1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
|
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define import_spp
#define import_error
#include <iraf.h>
#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 <sfname> or <mkobj_command> is
* replaced by <stname>.
*/
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;
}
}
|