From: Eric Backus Subject: Re: porting To: kok AT CS DOT ColoState DOT EDU Date: Fri, 22 Jan 93 13:03:34 PST Cc: djgpp AT sun DOT soe DOT clarkson DOT edu (djgpp) Mailer: Elm [revision: 66.25] > I have been interested in porting various FSF code and other UNIX code > to MSDOS, but each time I have tried, the task has seemed daunting. Some > scripts would probably help. > > Before anyone can write scripts, it is necesary to have an idea of what > things need to be done to port the code. Could those who have experience > porting provide some documentation on what things commonly need to be done, > or provide pointers to some documentation? > > In order for the documentation and associated scripts to be useful to as > many people as possible, the docs and scripts should be organized according > to the generality of the tasks, for example: > 1) porting code from UNIX workstations to PCs > 2) porting FSF code > 3a) porting to MSDOS > 3b) porting to OS-2 > 3c) porting to DesqView > 4) porting specific programs, such as gcc, emacs, etc. > > I guess I'm volunteering to collect and organize any docs and scripts that > people may contribute. I'm also familiar with awk, so I may be able to > write some scripts, if I know what's needed. > > Cheers, > - Jan Kok > kok AT cs DOT colostate DOT edu I have ported many of the FSF utilities to DJGPP on MS-DOS. My impression is that it will be nearly impossible to automate this process. The process of porting FSF code is fairly easy, because the FSF has already spent a great deal of effort making their code portable across a wide variety of computer systems. Other code may be more difficult, but it all depends on what the code does. Pure number crunching should port with no effort. One of the problems with porting to MS-DOS is the lack of a good shell and make program. The best (i.e. closest to UNIX) shell I've found is MS_SH200, which is available on SIMTEL20 and its mirrors. This is a bourne-shell-like shell; it will do filename globbing (expand '*' and '?') and understands how to create "response files" to pass long command-lines to programs. You'll have to read the documentation closely and play around a little to get this working correctly. The best make program I've found is GNUish make, also available on SIMTEL20. This is a port of GNU make to MS-DOS. It has a few quirks, but most can be worked around. Once you have a good shell and make program, it also helps to have a collection of unix-like tools around, since may Makefiles assume that things like "cp", "mv", or "install" exist. One good choice is the collection of FSF utilities that I ported, which are available on twok.ods.com in ~ftp/pub/gnu-dos. Another good choice is the GNUish collection of FSF utilites available on SIMTEL20. When porting FSF code, I try to check the following things: 1. Most FSF code uses a configure script to create the Makefile. This works great on UNIX but fails on MS-DOS. So, I had to create the Makefile by hand, to handle the quirks of MS-DOS, MS_SH200, and GNUish make. a. Create a .exe target, like this: .exe: aout2exe $< b. If the Makefile doesn't already define the SHELL variable, add "SHELL=/bin/sh" to the Makefile, since GNUish make defaults to using COMMAND.COM. c. If the Makefile doesn't already define an explicit ".c.o:" target, define one like: .c.o: $(CC) $(CFLAGS) -c $< This is because GNUish make doesn't have this implicit rule built in. d. Often, the command-line that "make" wants to pass to gcc is too long to fit in MS-DOS's 128 character limit. Often, the same is true of the command-line that "make" want to pass to "rm". To work around this, add this to the Makefile: LONGARGS = gcc:rm This requires GNUish make, and it requires that you have an "rm" program that understand the GNUish method of passing long command lines. GNUish rm will work, or you can get a DJGPP version of rm ported from the FSF sources, since all GO32 programs understand the GNUish method. e. If the Makefile uses lex and/or yacc, change them to flex and/or bison. The Makefile probably also assumes the name of the output file from flex and/or bison, and the assumption probably has more than one "." in the filename and is therefore wrong on MS-DOS. You'll have to fix this appropriately. f. Usually there is a "clean:" target. Modify it to remove MS-DOS specific files like .exe files. 2. Search the source code you're porting for "/dev/tty", which you'll have to replace with "/dev/con". Similarly, search for "/dev/null" and replace it with "/dev/nul". 3. Search for all calls to open() and fopen(). Be default, these functions will open the file in text mode. This is fine for a text utility, but fails miserably on anything that tries to do binary stuff on a file. Any call to open() that must open the file in binary mode must bitwise-or "O_BINARY" into the "mode" parameter, which is the third parameter. Any call to fopen() that must open the file in binary mode must include a "b" in the string that is the second parameter. An alternative to changing the open() or fopen() is too call "setmode(fildes, O_BINARY)" after the open() or "setmode(fileno(fp), O_BINARY)" after the fopen(). 4. Similarly, stdin and stdout (and stderr for that matter) are in text mode by default. If the program must work with stdin and stdout in binary mode, you must include "setmode(fileno(stdin), O_BINARY)" and "setmode(fileno(stdout), O_BINARY)" somewhere in the program. 5. Look for source filenames that are not unique when truncated to MS-DOS's "filename.ext" format. If you run into this problem, you'll have to change the name of at least one of the files. Make sure you change all references to this file in the Makefile and the source code. In particular, if you change the name of an include file, make sure you find all the "#include" lines that use it. 6. Look for the creation of temporary files. Make sure that the filenames for temporary files will be unique when truncated to MS-DOS's "filename.ext" format. Often, the program will assume that something like "sprintf(filename, "temp%6d", getpid() + count++)" is unique, but it won't be on MS-DOS. Also make sure the code doesn't try to put more than one "." into the filename. 7. Look for calls to fstat(). I've had trouble with fstat() before, and haven't gotten around to fixing it. On the other hand, stat() works great, so try to replace the fstat() with stat() if you can. 8. Look for anything that uses ioctl(), and do your best to work around it since it won't work with DJGPP. If the purpose of the ioctl() is to turn off echo while prompting for a password, consider using getpass() or getlongpass(), which handle this problem. 9. Look for anything which tries to fork(), exec(), or use pipe(). Hope that you don't find any of them. 10. Watch out for code that has previously been ported to MS-DOS using the Borland or Microsoft compilers. Some of the "#ifdef MSDOS" in the code will be appropriate (like if it works around inherent DOS limits), but others will NOT be appropriate (like if it works around 16-bit limitations). You'll probably have to un-ifdef some of the ifdefs. Note that DJGPP defines MSDOS and __MSDOS__ (in common with Borland and Microsoft compilers), but also defines __GNUC__. You can use this to #ifdef the code so that it works for all combinations. 11. Search the source code for dirname() or basename() functions, or any similar place where assumptions are made about the form of pathnames. You'll have to modify these functions to understand that ":" is a separator, and you'll have to modify them to understand both kinds of slashes, since MS-DOS allows both. 12. I think the fnmatch() function provided with DJGPP is not compatible with versions of this function elsewhere. If your sourcecode provides and uses this function, make sure you don't link in the libc.a version instead. -- Eric Backus ericb AT lsid DOT hp DOT com (206) 335-2495