lotus

previous page: 9.1: What programs/utilities should I have to port UNIX source code to GNO?
  
page up: comp.sys.apple2. gno FAQ
  
next page: 9.3: Are there any other recommendations for porting programs?

9.2: What are the common problems encountered when porting UNIX sourceto GNO?




Description

This article is from the Apple II GNO FAQ, by Devin Reade with numerous contributions by others.

9.2: What are the common problems encountered when porting UNIX sourceto GNO?

    A#9.2:	The first thing to watch for is known compiler and library bugs.
Soenke Behrens maintains the current ORCA/C bug report list.
You should keep the contents of this list in mind when examining
the target source code.  The ORCA/C bug report list may be found at

	http://www.arrowweb.com/sbehrens/obugs.htm

This list has been considerably shorted since the release of
ORCA/C v2.1.0.  If you have an earlier version of ORCA/C, you
should seriously consider an upgrade.

The following items should be watched for, in no particular order.
Since UNIX source is usually in C, that language is assumed for
the rest of this section, where relevant:

sizeof(int)
	The size of the type "int" is implementation-defined.
	While most modern C compilers use 32 bits, ORCA/C still
	uses 16 bits since this is the "natural" integer size of
	the 65816.  This also results in more effective code
	generation.

	While the size of an int shouldn't make a difference to
	any well-written code, there is some available source code
	that assumes that ints are 32 bits.  You should watch for
	this in any code that does bit manipulations.  You should
	also watch for code that freely converts between integers
	and pointers.  GNU (Free Software Foundation) software
	is often bad for this.

recursion
	When possible, recursion should be avoided when programming
	on the Apple IIgs.  This is because recursion invariably
	causes stack growth and the stack can only exist in bank
	zero.  This means that the maximum space available for
	the stack is 64k.  In practise, it is much smaller.

	This problem is exacerbated under GNO where all processes
	must share the available stack space (each process has its
	own stack, though).

	Any program that uses recursion can be rewritten to use
	iteration instead.  You should try to do this when possible.
	If you do use recursion, don't allocate a huge stack;
	this will keep other programs from executing.  Also, you
	should leave in stack checking and stack repair (if
	programming with ORCA/C) to ensure that your recursion
	does not crash the machine if it goes too far.

reference to absolute file descriptors
	True UNIX machines invariably use the file descriptors 0, 1,
	and 2 for standard input, standard output, and standard error,
	respectively.  Under GNO, the file descriptors used are 1,
	2, and 3.

	This causes a problem when source code is written to use
	these descriptors directly.  You should search your code
	for references to these descriptors, typically in calls
	to open, close, read, write, dup, dup2, and fcntl.

	Instead of replacing these digits with other digits though,
	you should use the macros STDIN_FILENO, STDOUT_FILENO, and
	STDERR_FILENO defined in <unistd.h>.  This will ensure
	that your source is kept portable.

fork
	Because of problems that are discussed in the fork(2) man
	page and the kernel reference, the fork system call under
	GNO is different than other versions of UNIX.  Besides
	having a different prototype, the parent and child process
	share the same address space.  In this respect, GNO is less
	a multitasking environment than it is a multithreading 
	environment.

	Search for calls to fork; you will have to rewrite these
	sections of code.  See also the man page for fork2(2); it
	may be more suited to your purposes.

	Also note than when compiling routines that make a call
	to fork, you should turn off ORCA/C's stack repair code.
	This means that you should be using an optimization level
	of at least 8.

read/write of newline character
	Most UNIX systems use LF (ASCII 0x0a) as the line delimiter.
	Both Apple II and Macintosh computers use CR (ASCII 0x0d)
	as the line delimiter.  The C newline character is '\n';
	ASCII 0x0a.

	While the stdio routines (fprintf(3), fread(3), etc) usually
	make this difference unnoticable by doing CR-->LF translation
	on input and LF-->CR translation on output, no such
	translation is done on files accessed through read(2) and
	write(2).  Specifically, the GNO open(2) does not recognize
	the ORCA/C O_BINARY bit in it's second argument.

	Therefore, if the program you are porting makes calls to
	read(2) and write(2), watch for the '\n' character in your
	code.  You may have to change this to '\r'.  Don't do it
	blindly, because many programs will use both stdio and
	operations on the bare file descriptors.

	One suggestion is to modify your programs low-level I/O
	routines to modify the I/O buffer prior to calling write(2)
	and after calling read(2).

variadic functions
	Some (poorly written) UNIX programs have variadic functions
	where the number of provided arguments don't match the 
	number of arguments expected by the called routine.  Even
	though this is in some cases legal ANSI/C, versions of
	ORCA/C prior to v2.1 would puke magnificently when encountering
	such code.  Some of these cases are now handled in a more
	robust fashion by ORCA/C v2.1 and later.

	If you are defining (as opposed to using) variadic functions,
	you must turn off stack repair code around the definitions
	of those functions.

	The ORCA/C manual (and especially the release notes for
	v2.1) have important and detailed information on this topic.
	See the sections on the optimize and debug #pragmas.

open, chmod, fchmod, creat, st_mode, stat, fstat, lstat
	In general, the bits in the mode parameter of these
	functions do not directly map between UNIX and GNO
	implementations.  If your application is using macros
	such as S_IREAD or S_IWRITE for the mode parameters, and
	those macros are taken from the system header file
	<sys/stat.h>, then you probably don't need to modify your
	application.

	If, on the other hand, your application is using its own
	constants for the mode parameter, you should convert it
	to use the standard macros.  Failure to do so may result
	in files with strange GS/OS flags set, or file tests failing
	in your program.

/dev
	One of the UNIX philosophies is that "everything is a file".
	The /dev directory on UNIX systems contain device special
	files.  Accessing these files is the way to access the
	relevant hardware.

	For GNO programs, you should not access devices in the
	/dev directory.  For example, opening "/dev/console" for
	writing will not have the expected effect.  Instead you
	should open the corresponding GS/OS device, ".ttyco".

	The portable (and suggested) method of handling these cases
	is not to change the value of the string (in this example)
	from "/dev/console" to ".ttyco".  Instead, use the macros
	defined in the file <paths.h>.  For this example, one would
	use the macro _PATH_CONSOLE.

standard path assumptions
	This one is closely tied in with the "/dev" description
	above.  The <paths.h> file contains macros for various
	standard paths.  The macros, instead of the actual paths,
	should be used to maximize portability.

signal handlers
	When a signal handler is called, the data bank register
	may not have an expected value.  If your program references
	global scalars, it may crash.  To avoid this, all functions
	used as signal handlers should have their definition
	preceded by
		#pragma databank 1
	and followed by
		#pragma databank 0

validity of pathnames
	Most programs make assumptions about what constitutes
	a valid file name.  For most modern Unices, a valid
	file name follows the POSIX portable filename character
	set:  The characters a-z and A-Z, the digits 0-9, and
	'.', '_', and '-'.  The '-' is not used as the first
	character of a file name, and '/' is the directory
	separator character.  The maximum filename length is
	at least 14 characters, and the maximum pathname length
	is at least 255 characters.

	Now this is different from what is available under GNO.
	The ProDOS FST provides only a subset of the above.  The
	HFS FST provides a superset, but HFS is too slow, too
	buggy, and too unmaintainable for many users.

	The problem is also compounded by the fact that under
	GS/OS, the ':' is a directory separator.  '/' may be used
	but it is mapped internally to ':'.

	Unfortunately, there is no general consensus on how to
	handle pathnames under GNO.  Here are some opinions, all
	of which refer to user code; the GNO kernel treats pathnames
	the same way that GS/OS does:

	- the ':' character should be mapped to '/'.  This prohibits
	  the use of '/' in file names.  It also provides the
	  highest degree of "UNIX compatibility"; or

	- the '/' character should be mapped to ':'.  This is more
	  in line with GS/OS, but can require extensive rewrites
	  of ported UNIX programs; or

	- use dynamic directory delimiters.  The ':' character is
	  always considered to be a directory separator.  The '/'
	  character is considered to be a directory separator unless
	  it was preceded at some point by a ':', in which case it
	  is part of the file name.  Having a '/' appear before ':'
	  in a pathname is illegal.  This is the closest to GS/OS,
	  but also has some problems  with POSIX compliance.  For
	  example, the PATH environment variable is supposed to
	  be a list of pathnames delimited by the ':' character.
	  This implies that one cannot use the ':' as a directory
	  delimiter when defining PATH, and that directories in
	  PATH must not contain '/' as a regular character.

	Regardless of which method you use to do filename, pathname,
	and directory separator mapping, you should verify that
	the pathname is legal for your target filesystem.  GS/OS
	provides a mechanism to do this through the JudgeName
	system call.

	Also watch out for references to the root partition.  For
	other UNIXs, this is the pathname "/", which is a not legal
	directory under GS/OS (and therefore GNO).  Hopefully the
	context of your program will give you an idea how to handle
	such a directory reference in a sensible manner.

unlink
	Many UNIX programs unlink (delete) files while they still
	have them open.  Under true UNIX systems, this means that
	the file will be deleted as soon as it is closed.  This is
	is not done under GNO, and attempting to unlink an open file
	will fail, and the file will remain on the file system after
	it is closed.  If your program relies on this behavior, you
	will have to find a work-around.  One partial solution is
	to register a clean-up function via atexit(3) that deletes
	your files for you.  [This method is not suitable for 
	daemons or other long-running programs.]
    

 

Continue to:













TOP
previous page: 9.1: What programs/utilities should I have to port UNIX source code to GNO?
  
page up: comp.sys.apple2. gno FAQ
  
next page: 9.3: Are there any other recommendations for porting programs?