|
|
1.1 root 1: static char *ID_pass0 = "@(#) pass0.c: 1.16 12/10/83";
2:
3: #include <stdio.h>
4: #include <signal.h>
5: #include <ctype.h>
6: #include <paths.h>
7: #include "systems.h"
8: #include "pass0.h"
9: #include "sgs.h"
10:
11: /*
12: *
13: * "pass0.c" is a file containing the source for the setup program
14: * for the SGS Assemblers. Routines in this file parse the
15: * arguments, determining the source and object file names, invent
16: * names for temporary files, and execute the first pass of the
17: * assembler.
18: *
19: * This program can be invoked with the command:
20: *
21: * as [flags] ifile [-o ofile]
22: *
23: * where [flags] are optional user-specified flags,
24: * "ifile" is the name of the assembly languge source file
25: * and "ofile" is the name of a file where the object program is
26: * to be written. If "ofile" is not specified on the command line,
27: * it is created from "ifile" by the following algorithm:
28: *
29: * 1. If the name "ifile" ends with the two characters ".s",
30: * these are replaced with the two characters ".o".
31: *
32: * 2. If the name "ifile" does not end with the two
33: * characters ".s" and is no more than 12 characters in
34: * length, the name "ofile" is created by appending the
35: * characters ".o" to the name "ifile".
36: *
37: * 3. If the name "ifile" does not end with the two
38: * characters ".s" and is greater than 12 characters in
39: * length, the name "ofile" is created by appending the
40: * characters ".o" to the first 12 characters of "ifile".
41: *
42: * The global variables "name1" through "name6" are used to store
43: * the six temporary file names. The variable "pid" is used to
44: * store a character version of the process ID number. This is
45: * used to make temporary file names unique.
46: *
47: */
48:
49: #define NO 0
50: #define YES 1
51: #define MAXFLAGS 15 - 9 /* sizeof(xargp)-num of args required for pass1 */
52: #ifndef P_tmpdir
53: #define P_tmpdir "/usr/tmp"
54: #endif
55:
56: #if ONEPROC
57: short passnbr = 0;
58:
59: extern short opt;
60: extern short workaround;
61:
62: extern short
63: tstlookup,
64: Oflag,
65: dlflag;
66:
67: extern char file[];
68:
69: extern char *filenames[];
70:
71: #if M4ON
72: extern short rflag;
73: #endif
74:
75: #if M32RSTFIX
76: extern short rstflag; /* Don't generate workaround for RESTORE chip bug */
77: #endif
78:
79: #endif
80:
81: char *infile;
82:
83: char outfile[80];
84:
85: char *tempnam();
86:
87: char
88: *name0,
89: *name1,
90: *name2,
91: *name3,
92: *name4,
93: *name5,
94: *name6,
95: #if MULTSECT
96: *name7,
97: *name8,
98: *name9,
99: *name10,
100: *name11,
101: *name12,
102: *name13;
103: #else
104: *name7;
105: #endif
106:
107: short transvec = NO,
108: argindex = 1,
109: flagindex = 0;
110:
111: #if !ONEPROC
112: static char
113: nextpass[15];
114:
115: static char
116: teststr[4] = {'-','t','\0','\0'};
117:
118: static char
119: *xargp[16];
120: #endif
121:
122: static char
123: flagstr[8][3];
124:
125: #if M4ON
126: static short
127: macro = MACRO;
128: #endif
129:
130: #if !ONEPROC
131: static short
132: testas = -2;
133: #endif
134:
135: extern char
136: *strcpy(),
137: *strcat(),
138: *strncat();
139:
140: #define max(A,B) (((A)<(B))?(B):(A))
141:
142: extern char *malloc(), *getenv(), *mktemp();
143: extern int access();
144:
145: static char *pcopy(), *seed="AAA";
146:
147: /*
148: *
149: * "tempnam" is the routine that allocates the temporary files needed
150: * by the assembler. It searches directories for enough space for the
151: * files, then assigns a (guaranteed) unique filename using the prefix
152: * in the function call.
153: *
154: */
155:
156: char *
157: tempnam(dir, pfx)
158: char *dir; /* use this directory please (if non-NULL) */
159: char *pfx; /* use this (if non-NULL) as filename prefix */
160: {
161: register char *p, *q, *tdir;
162: int x=0, y=0, z;
163:
164: z=strlen(P_tmpdir);
165: if((tdir = getenv("TMPDIR")) != NULL) {
166: x = strlen(tdir);
167: }
168: if(dir != NULL) {
169: y=strlen(dir);
170: }
171: if((p=malloc((unsigned)(max(max(x,y),z)+16))) == NULL)
172: return(NULL);
173: if(x > 0 && access(pcopy(p, tdir), 3) == 0)
174: goto OK;
175: if(y > 0 && access(pcopy(p, dir), 3) == 0)
176: goto OK;
177: if(access(pcopy(p, P_tmpdir), 3) == 0)
178: goto OK;
179: if(access(pcopy(p, "/tmp"), 3) != 0)
180: return(NULL);
181: OK:
182: (void)strcat(p, "/");
183: if(pfx) {
184: *(p+strlen(p)+5) = '\0';
185: (void)strncat(p, pfx, 5);
186: }
187: (void)strcat(p, seed);
188: (void)strcat(p, "XXXXXX");
189: q = seed;
190: while(*q == 'Z')
191: *q++ = 'A';
192: ++*q;
193: (void)mktemp(p);
194: if (*p == '\0')
195: return(NULL);
196: return(p);
197: }
198:
199: static char*
200: pcopy(space, arg)
201: register char *space, *arg;
202: {
203: register char *p;
204:
205: if(arg) {
206: (void)strcpy(space, arg);
207: p = space-1+strlen(space);
208: if(*p == '/')
209: *p = '\0';
210: }
211: return(space);
212: }
213:
214: /*
215: *
216: * "getargs" is a general purpose argument parsing routine.
217: * It locates flags (identified by a preceding minus sign ('-'))
218: * and initializes any associated flags for the assembler.
219: * If there are any file names in the argument list, then a
220: * pointer to the name is stored in a global variable for
221: * later use.
222: *
223: */
224:
225: getargs(xargc,xargv)
226: register int xargc;
227: register char **xargv;
228: {
229: register char ch;
230:
231: while (xargc-- > 0) {
232: if (**xargv == '-') {
233: while ((ch = *++*xargv) != '\0')
234: switch (ch) {
235: #if M4ON
236: case 'm':
237: macro = ! macro;
238: break;
239: #endif
240: case 'o':
241: strcpy(outfile,*(++xargv));
242: --xargc;
243: while (*++*xargv != '\0') ;
244: --*xargv;
245: break;
246: case 'd':
247: if (*++*xargv == 'l')
248: #if !ONEPROC
249: xargp[argindex++] = "-dl";
250: #else
251: dlflag = YES;
252: #endif
253: break;
254: #if TRANVEC || !ONEPROC
255: case 't':
256: ++*xargv;
257: #endif
258: #if TRANVEC
259: if (**xargv == 'v'){
260: transvec = YES;
261: #if !ONEPROC
262: xargp[argindex++] = "-tv";
263: #endif
264: break;
265: }
266: #endif
267: #if !ONEPROC
268: if (isdigit(**xargv)) {
269: testas = **xargv - '0' - 1;
270: if (testas > -1) {
271: teststr[2] = (char)(testas + '0');
272: }
273: }
274: else {
275: --*xargv;
276: testas += 2;
277: }
278: xargp[argindex++] = teststr;
279: break;
280: #endif
281: case 'V':
282: /* version flag */
283: fprintf(stderr,"%s: assembler - %s\n",
284: SGSNAME,RELEASE);
285: break;
286: #if ONEPROC
287: case 'n':
288: if (*++*xargv == 'f') { /* -nf option */
289: /* no frills; disable work-arounds */
290: workaround = NO;
291: #if M32RSTFIX
292: rstflag = NO;
293: #endif /* M32RSTFIX */
294: } else { /* -n option */
295: opt = NO;
296: *--*xargv;
297: }
298: break;
299: #if DEBUG
300: case 'O':
301: Oflag = YES;
302: break;
303: case 'T': {
304: switch (*++*xargv) {
305: case 'L' : {
306: tstlookup = YES;
307: break;
308: }
309: }
310: break;
311: }
312: #endif
313: #if M4ON
314: case 'R':
315: rflag = YES;
316: break;
317: #endif
318: #if M32RSTFIX
319: case 'r': /* Don't generate the workaround
320: * for the RESTORE chip bug.
321: */
322: rstflag = NO;
323: break;
324: #endif /* M32RSTFIX */
325: #endif
326: #if VAX
327: case 'j': /* invoke ljas instead of as */
328: if (strcmp(xargv[0],"ljas")) {
329: execvp("ljas",xargv);
330: aerror("cannot exec ljas");
331: };
332: break;
333: #endif
334: default:
335: #if ONEPROC
336: flags(ch);
337: #else
338: flagstr[flagindex][0] = '-';
339: flagstr[flagindex][1] = ch;
340: xargp[argindex++] = &(flagstr[flagindex++][0]);
341: #endif
342: break;
343: }
344: xargv++;
345: }
346: else {
347: infile = *xargv++;
348: }
349: }
350: }
351:
352: /*
353: *
354: * "main" is the main driver for the assembler. It calls "getargs"
355: * to parse the argument list, set flags, and stores pointers
356: * to any file names in the argument list .
357: * If the output file was not specified in the argument list
358: * then the output file name is generated. Next the temporary
359: * file names are generated and the first pass of the assembler
360: * is invoked.
361: *
362: */
363:
364: main(argc,argv)
365: int argc;
366: char **argv;
367: {
368: register short index, count;
369: #if !ONEPROC
370: register char *temp;
371: #endif
372: FILE *fd;
373:
374: argc--;
375: if (argc <= 0) {
376: fprintf(stderr,"Usage: %sas [options] file\n",SGS);
377: exit(1);
378: }
379: #if !ONEPROC
380: temp = *argv;
381: index = -1;
382: while (temp[++index] != '\0') ;
383: while (--index >= 0 && temp[index] != '/') ;
384: strcpy(nextpass,&temp[++index]);
385: nextpass[strlen(nextpass)] = '1';
386: #endif
387: argv++;
388: getargs(argc, argv);
389: /* Check to see if input file exits */
390: if ((fd = fopen(infile,"r")) != NULL)
391: fclose(fd);
392: else {
393: fprintf(stderr,"Nonexistent file\n");
394: exit(1);
395: }
396: if (outfile[0] == '\0') {
397: for(index=0,count=0;infile[index]!='\0';index++,count++)
398: if(infile[index]=='/')
399: count = -1;
400: strcpy(outfile,infile+index-count);
401: if(outfile[count-2]=='.' &&
402: outfile[count-1]=='s')
403: outfile[count-1]='o';
404: else
405: {
406: if(count>12)
407: count = 12;
408: strcpy(outfile+count,".o");
409: }
410: }
411:
412: name1 = tempnam(TMPDIR,TMPFILE1);
413: name2 = tempnam(TMPDIR,TMPFILE2);
414: name3 = tempnam(TMPDIR,TMPFILE3);
415: name4 = tempnam(TMPDIR,TMPFILE4);
416: name5 = tempnam(TMPDIR,TMPFILE5);
417: name6 = tempnam(TMPDIR,TMPFILE6);
418: name7 = tempnam(TMPDIR,TMPFILE7);
419: #if MULTSECT
420: name8 = tempnam(TMPDIR,TMPFILE8);
421: name9 = tempnam(TMPDIR,TMPFILE9);
422: name10 = tempnam(TMPDIR,TMPFILEA);
423: name11 = tempnam(TMPDIR,TMPFILEB);
424: name12 = tempnam(TMPDIR,TMPFILEC);
425: name13 = tempnam(TMPDIR,TMPFILED);
426: #endif
427: #if !ONEPROC
428: xargp[0] = nextpass;
429: #endif
430: #if M4ON
431: if (macro) {
432: /* tell pass1 to unlink its input when through */
433: #if ONEPROC
434: rflag = YES;
435: #else
436: xargp[argindex++] = "-R";
437: #endif
438: callm4();
439: }
440: #endif
441:
442: #if ONEPROC
443: strcpy(file,infile);
444: filenames[0] = infile;
445: filenames[1] = outfile;
446: filenames[2] = name1;
447: filenames[3] = name2;
448: filenames[4] = name3;
449: filenames[5] = name4;
450: filenames[6] = name5;
451: filenames[7] = name6;
452: filenames[8] = name7;
453: #if MULTSECT
454: filenames[9] = name8;
455: filenames[10] = name9;
456: filenames[11] = name10;
457: filenames[12] = name11;
458: filenames[13] = name12;
459: filenames[14] = name13;
460: #endif
461: exit(aspass1());
462: #else
463: if (argindex > MAXFLAGS) {
464: fprintf(stderr,"Too many flags\n");
465: exit (1);
466: }
467:
468: xargp[argindex++] = infile;
469: xargp[argindex++] = outfile;
470: xargp[argindex++] = name1;
471: xargp[argindex++] = name2;
472: xargp[argindex++] = name3;
473: xargp[argindex++] = name4;
474: xargp[argindex++] = name5;
475: xargp[argindex++] = name6;
476: xargp[argindex++] = name7;
477: #if MULTSECT
478: xargp[argindex++] = name8;
479: xargp[argindex++] = name9;
480: xargp[argindex++] = name10;
481: xargp[argindex++] = name11;
482: xargp[argindex++] = name12;
483: xargp[argindex++] = name13;
484: #endif
485: xargp[argindex] = 0;
486: if (testas != -1) {
487: if (testas > -1) {
488: execv(NAS1,xargp);
489: }
490: else
491: execv(AS1,xargp);
492: fprintf(stderr,"Assembler Error - Cannot Exec Pass 1\n");
493: exit(1);
494: }
495: #endif
496: } /* main */
497:
498: #if M4ON
499: callm4()
500: {
501: static char
502: *av[] = { "m4", 0, 0, 0};
503:
504: /*
505: * The following code had to be added with a 'u370' ifdef due
506: * to a MAXI bug concerning static pointers. We think it's fixed
507: * that is why the code is commented out. It can be deleted
508: * when this fact is verified.
509: *
510: * char *regdef, *tvdef;
511: * regdef = CM4DEFS;
512: * tvdef = CM4TVDEFS;
513: */
514:
515: #if !NODEFS
516: static char
517: *regdef = CM4DEFS
518: #if TRANVEC
519: ,
520: *tvdef = CM4TVDEFS
521: #endif
522: ;
523:
524: #if TRANVEC
525: av[1] = (transvec) ? tvdef : regdef;
526: av[2] = infile;
527: #else
528: av[1] = regdef;
529: av[2] = infile;
530: #endif
531: #else
532: av[1] = infile;
533: #endif
534: name0 = tempnam(TMPDIR,TMPFILE0); /* m4 output file */
535: if (callsys(M4, av, name0) != 0) {
536: unlink(name0);
537: fprintf(stderr,"Assembly inhibited\n");
538: exit(100);
539: }
540: infile = name0;
541: return;
542: } /* callm4 */
543:
544: callsys(f,v,o)
545: char f[], *v[];
546: char *o; /* file name, if any, for redirecting stdout */
547: {
548: int t, status;
549:
550: if ((t=fork())==0) {
551: if (o != NULL) { /* redirect stdout */
552: if (freopen(o, "w", stdout) == NULL) {
553: fprintf(stderr,"Can't open %s\n", o);
554: exit(100);
555: }
556: }
557: execv(f, v);
558: fprintf(stderr,"Can't find %s\n", f);
559: exit(100);
560: } else
561: if (t == -1) {
562: fprintf(stderr,"Try again\n");
563: return(100);
564: }
565: while(t!=wait(&status));
566: if ((t=(status&0377)) != 0) {
567: if (t!=SIGINT) /* interrupt */
568: {
569: fprintf(stderr,"status %o\n",status);
570: fprintf(stderr,"Fatal error in %s\n", f);
571: }
572: exit(100);
573: }
574: return((status>>8) & 0377);
575: } /* callsys */
576: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.