From 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 Mon Sep 17 00:00:00 2001 From: Joe Hunkeler Date: Tue, 11 Aug 2015 16:51:37 -0400 Subject: Repatch (from linux) of OSX IRAF --- unix/boot/mkpkg/sflist.c | 321 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 unix/boot/mkpkg/sflist.c (limited to 'unix/boot/mkpkg/sflist.c') diff --git a/unix/boot/mkpkg/sflist.c b/unix/boot/mkpkg/sflist.c new file mode 100644 index 00000000..e487df77 --- /dev/null +++ b/unix/boot/mkpkg/sflist.c @@ -0,0 +1,321 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include +#include +#include + +#define import_spp +#define import_error +#include + +#include "mkpkg.h" +#include "extern.h" +#include "../bootProto.h" + + +/* + * SFLIST.C -- Special file list package. The special file list is a list of + * library module list source files which need special processing on a given + * host system. Examples of such files are files which have been optimized in + * a machine dependent way, e.g., in assembler or C, or files which must be + * compiled in a nonstandard way due to host compiler bugs. The special file + * list makes this special processing possible without having to modify the + * mkpkg files in the portable system in a host dependent way, concentrating + * all knowledge of those parts of the system which have been tailored for the + * local host into a single, easily modifiable table file stored in HLIB. + * + * External functions: + * + * sf_scanlist (cx) # parse $special file list + * sflist = sf_dirsearch (dirname) # lookup directory in sflist + * sfp = sf_filesearch (sflist, filename) # lookup file in dir file list + * sf_prune (cp) # free space in string buffer + * + * where + * + * struct context *cx; + * struct sfile *sflist, *sfp; + * char *filename, *dirname; + * + * The special file list is organized by source directory to speed searches + * (most directories will not contain any files needing special processing, + * eliminating the need to lookup the files in module lists in that directory) + * and to reduce storage requirements for the list. The special file database + * thus consists of a list of directories containing special files, and for + * each directory, a pointer to a linked list of special file entries, one + * for each special file in the directory. Since the organization by directory + * tends to produce a database consisting of very short file lists, we use a + * linked list rather than a hash table for the file lists. + * + * For each special file we record the standard file name, the pathname of + * the special file to be used, and a command to be pushed back into the MKPKG + * command input stream to generate the object file for the module. + * The special file name may be the same as the standard file name, e.g, if + * the standard file only needs to be compiled in a nonstandard way. If the + * mkobj string is null the special file name will simply be returned in the + * module list, and compiled with XC using the default compile flags. + */ + +static int sf_ndirs = 0; /* no. of directories */ +static int sf_nfiles = 0; /* no. of special files */ +static char *sf_dirs[MAX_SFDIRS]; /* source directories */ +static struct sfile *sf_flist[MAX_SFDIRS]; /* directory file lists */ +static struct sfile sf_files[MAX_SFFILES]; /* special file list */ +static char nullstr[] = ""; + + +/* SF_SCANLIST -- Called when the $special macro preprocessor directive is + * encountered to parse a special file list, entering each file listed into + * the special file list database. The syntax of a $special special file + * list directive is as follows: + * + * $special dirname: + * stname1 sfname1 mkobj_command1 + * stname2 sfname2 mkobj_command2 + * ... + * stnameN sfnameN mkobj_commandN + * ; + * + * where any string value may optionally be quoted, and the mkobj command + * strings are optional. The token "&" in or is + * replaced by . + */ +int +sf_scanlist ( + struct context *cx /* current mkpkg context */ +) +{ + register struct sfile *sfp; + register char *ip, *op, *tp; + + char dirname[SZ_PATHNAME+1]; + char stname[SZ_PATHNAME+1]; + char sfname[SZ_PATHNAME+1]; + char mkobj[SZ_CMD+SZ_PATHNAME+1]; + char token[SZ_CMD+1]; + struct sfile *head, *tail; + int tok, nfiles, eol=0; + char *old_cp; + + old_cp = cp; /* mark position in sbuf */ + nfiles = 0; + + /* Get the directory name. */ + if (gettok (cx, token, SZ_LINE) != TOK_FNAME) { + warns ("missing directory name in special file list", ""); + goto err; + } else + os_fpathname (token, dirname, SZ_PATHNAME); + + if (debug) { + printf ("scan special file list for directory %s\n", + debug > 1 ? dirname : token); + fflush (stdout); + } + + /* Advance to the start of the module list. */ + while ((tok = gettok (cx, token, SZ_LINE)) != TOK_BEGIN) + if (tok == EOF || tok == TOK_END) + goto err; + + /* Get a pointer to the last element in the special file list for + * the named directory. If this is the first entry for the named + * directory, enter the name in the symbol table and set the sflist + * pointer to NULL. + */ + if ((head = sf_dirsearch (dirname)) == NULL) { + sf_dirs[sf_ndirs++] = putstr (dirname); + if (sf_ndirs >= MAX_SFDIRS) + fatals ("too many special file list directories: %s", dirname); + tail = NULL; + } else { + for (tail=sfp=head; sfp; sfp=sfp->sf_next) + tail = sfp; + } + + /* Read successive entries from the special file list for the named + * directory, entering each file at the tail of the list. + */ + while (!eol && (tok = gettok (cx, token, SZ_LINE)) != TOK_END) { + if (tok == EOF || tok == TOK_END) + break; + + /* Get standard file name (module name). */ + if (tok == TOK_NEWLINE) + continue; /* blank line */ + else if (tok != TOK_FNAME) + goto badline; + else + strcpy (stname, token); + + /* Get the special file name. */ + if ((tok = gettok (cx, sfname, SZ_PATHNAME)) == TOK_END) + eol++; + if (tok != TOK_FNAME) + goto badline; + + /* Get the mkobj command string, if any. */ + if ((tok = gettok (cx, token, SZ_LINE)) == TOK_NEWLINE) { + mkobj[0] = EOS; + } else if (tok == TOK_END) { + mkobj[0] = EOS; + eol++; + } else if (tok != TOK_FNAME) { + goto badline; + } else { + /* Extract the command string, expanding any "&" filename + * references therein. + */ + for (ip=token, op=mkobj; (*op = *ip++); op++) + if (*op == '&') { + for (tp=stname; (*op = *tp++); op++) + ; + --op; + } + } + + if (debug) + printf ("file %s -> %s, mkobj = `%s'\n", + stname, (sfname[0] == '&') ? stname : sfname, mkobj); + + /* Add the file to the tail of the file list. */ + nfiles++; + sfp = &sf_files[sf_nfiles++]; + if (sf_nfiles >= MAX_SFFILES) + fatals ("too many special files: %s", stname); + + sfp->sf_stname = putstr (stname); + sfp->sf_sfname = (sfname[0]=='&') ? sfp->sf_stname : putstr(sfname); + sfp->sf_mkobj = mkobj[0] ? putstr(mkobj) : nullstr; + sfp->sf_next = NULL; + + if (tail) { + tail->sf_next = sfp; + tail = sfp; + } else + sf_flist[sf_ndirs-1] = head = tail = sfp; + + continue; +badline: + /* Print message and discard rest of line, but do not quit. */ + warns ("bad token `%s' in special file list", token); + while (!eol && (tok = gettok (cx, token, SZ_LINE)) != TOK_NEWLINE) + if (tok == TOK_END) + break; + else if (tok == EOF) + goto err; + } + + if (debug) { + printf ("%d special files added; total ndirs=%d, nfiles=%d\n", + nfiles, sf_ndirs, sf_nfiles); + fflush (stdout); + } + + if (nfiles == 0) { + warns ("empty special file list for %s", dirname); + sf_prune (cp = old_cp); + return (ERR); + } else + return (OK); + +err: + /* Discard rest of directive. */ + while (!eol && (tok = gettok (cx, token, SZ_LINE)) != TOK_END) + if (tok == EOF || tok == TOK_END) + break; + + /* Return memory and sfile database space. */ + sf_prune ((cp = old_cp)); + + return (ERR); +} + + +/* SF_DIRSEARCH -- Search the special file database for the named directory, + * returning a pointer to the special file list for that directory if the + * directory is found, else NULL. Note that directory names are stored as + * host system pathnames (so that any equivalent form of reference may be used + * in the mkpkg files), and we assume that we are called with the directory + * pathname already resolved. + */ +struct sfile * +sf_dirsearch ( + char *dirname /* host pathname of directory */ +) +{ + register int i; + + if (debug) { + printf ("search sflist for directory %s\n", dirname); + fflush (stdout); + } + + for (i=0; i < sf_ndirs; i++) + if (h_direq (sf_dirs[i], dirname)) + return (sf_flist[i]); + + return (NULL); +} + + +/* SF_FILESEARCH -- Search the special file list for a directory for the named + * file. File names are stored in the list by the name given in the library + * module list in the mkpkg file. If the named file is found a pointer to the + * special file descriptor for that file is returned, otherwise NULL is + * returned. Note that "file*" is a prefix match, whereas "file" requires an + * exact match. + */ +struct sfile * +sf_filesearch ( + struct sfile *sflist, /* special file list */ + char *stname /* standard file name */ +) +{ + register struct sfile *sfp; + register char *p1, *p2; + + for (sfp=sflist; sfp; sfp=sfp->sf_next) { + for (p1=sfp->sf_stname, p2=stname; *p1 && *p1 == *p2; p1++, p2++) + ; + if ((*p1 == EOS && *p2 == EOS) || *p1 == '*') + return (sfp); + } + + return (NULL); +} + + +/* SF_PRUNE -- Prune the special file database back to the given point in the + * string buffer. + */ +void +sf_prune ( + register char *cp /* lop off everything here and above */ +) +{ + register struct sfile *sfp, *sf_top; + register int i; + + /* Prune the directory list. */ + for (i=0; i < sf_ndirs; i++) + if (sf_dirs[i] >= cp || sf_flist[i]->sf_stname >= cp) { + sf_ndirs = i; + break; + } + + /* Prune the global file list. */ + for (i=0; i < sf_nfiles; i++) + if (sf_files[i].sf_stname >= cp) { + sf_nfiles = i; + break; + } + + /* Prune the individual directory file lists. */ + for (i=0, sf_top = &sf_files[sf_nfiles]; i < sf_nfiles; i++) { + sfp = &sf_files[i]; + if (sfp->sf_next >= sf_top) + sfp->sf_next = NULL; + } +} -- cgit