September 9, 2000
By

Kelvin Sherlock

Introduction

Ask most people which programming language is most associated with Unix, and the most common answer (aside from a vacant stare) is “C.” And for good reason — developed concurrently by Bell Labs in the late ’60s and early ’70s, each influenced the design of the other.

Although most unix kernels and utilites are written predominantly in C, Pascal users aren’t left out in the cold. True, in most Unix environments, no Pascal compiler is available, or if one is, it most likely is virtually unusable. However, GNO/ME users are blessed with ORCA/Pascal, a commercial-quality, ISO-compliant, GNO/ME compatible Pascal compiler available from the Byte Works, Inc.

Setting Things Up

This information assumes that you are following the recommended directory layout as described in the GNO/ME FAQ.

These files should be present:

FileDescription
/lang/orca/languages/Pascal(the compiler)
/lang/orca/languages/Linker(the linker)
/lib/PasLib(run-time pascal libraries)
/lib/SysLib(run-time C + Pascal libraries)
/lib/SysFloat(run-time C + Pascal libraries)
/lib/OrcaPascalDefs/*.int(compiled tool interface definitions)

Due to library dependencies, Paslib must come before SysLib and SysFloat to prevent unresolved references. Use the ORCA/Shell Sort and Compress routines or Prosel-16 to change the directory order. Also refer to the GNO/ME FAQ for more information.

Using The Compiler

Compiling Pascal source code under GNO/ME is not substantially different from compiling Pascal source code under ORCA/Shell. There are a couple caveats, though.

Under ORCA/Shell, the current language stamp is changed via Pascal, CC, ASM65816, et cetera. GNO/ME does not currently honor the language stamp. Before compiling your code, you should manually change the language of the file with chtyp -l pascal file.pas

Using GNO/ME features

Even though the GNO/ME libraries and syscalls are mainly for the benefit of C and assembly programmers, ORCA/Pascal can make use of most of them, either directly, or indirectly, via three options.

System calls (which are handled entirely by the kernel) are implemented in terms of user tools, which ORCA/Pascal can access directly with UserTool. The complete list of system calls is listed in /usr/include/gno/kerntool.h, and are described in various man pages.

Examples:

(ORCA/Pascal)

function Kgetpid: integer;
	UserTool($03, $09);

function Kfork(subr: ProcPtr; var errno: integer): integer;
	UserTool($03, $0B);

For standard IIGS tools (like the Memory Manager), returned errors are accessible via the ToolError function. For GNO/ME system calls, though, the ToolErrorfunction is not a reliable indicator of an error. For some calls (such as Kgetpid) no error is possible (as long as GNO/ME is active). Other calls (which take a var errnoparameter) will set the variable to an error (as described in /usr/include/sys/errno.h) if the returned value indicates an error (usually -1, but see the appropriate man page for more information).

For library calls (code in libc, et cetera), ORCA/M (or ORCA/C) stubs can be written to call the C library routine. Please keep in mind that C is case sensitive (Pascal is not), and that C pushes its parameters in reverse order (unless you use the “pascal” qualifier).

Examples:

(ORCA/Pascal)

function isatty(fd: integer): integer; extern;
funtion Errno: integer; extern;


(ORCA/M)
	case on
;
; int isatty(int fd);
;
; because there is only one parameter, we can jml to the C entry point
; if there were more, we would need to set up a stack frame, push the
; arguments in reverse order, and then tear down the stack frame.
;
ISATTY	START
	jml isatty
	END

ERRNO	START
	lda >errno
	rtl
	END
		
ORCA/C

/*
 * "pascal" makes it handle the parameter's in pascal's order
 *
 */
pascal int ISATTY(int fd)
{
	return isatty(fd);
}

pascal int ERRNO(void)
{
	return errno;
}

If a library call fails, it will usually set the errno variable, which is inaccessable to Pascal due to case sensitivity. Unlike the ToolError function, the Errno function (rather, the errno variable) is only set on failure, and not reset to 0 on success.

Functions which take a variable number of parameters (such as fork2 and fprintf) are not easily convertible since Pascal functions and procedures must have a fixed number of parameters.

The third method is to rewrite the C function in Pascal. This option requires much more work and is generally a bad idea, as new bugs can be introduced and fixes or enhancements to the C libraries won’t be incorporated immediately, as they would be with the C stubs.

An Example Program

This example program doesn’t do much. Basically, it creates a new process, and prints a couple lines (one from the child and one from the parent). However, it does make use of some GNO/ME system calls and shows how to create a new process and one way to synchronize parent/child code via semaphores.