Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / as / comm4.c
1 /* $Id: comm4.c,v 2.18 1994/06/24 13:22:05 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /* @(#)comm4.c  1.6 */
7 /*
8  * Micro processor assembler framework written by
9  *      Johan Stevenson, Vrije Universiteit, Amsterdam
10  * modified by
11  *      Johan Stevenson, Han Schaminee and Hans de Vries
12  *              Philips S&I, T&M, PMDS, Eindhoven
13  */
14
15 #include        "comm0.h"
16 #include        "comm1.h"
17 #include        "y.tab.h"
18
19 extern YYSTYPE  yylval;
20
21 /* ========== Machine independent C routines ========== */
22
23 stop() {
24 #if DEBUG < 2
25         unlink(temppath);
26 #ifdef LISTING
27         unlink(listpath);
28 #endif
29 #endif
30         exit(nerrors != 0);
31 }
32
33 main(argc, argv)
34 char **argv;
35 {
36         register char *p;
37         register i;
38         static char sigs[] = {
39                 SIGHUP, SIGINT, SIGQUIT, SIGTERM, 0
40         };
41
42         /* the next test should be performed by the
43          * preprocessor, but it cannot, so it is performed by the compiler.
44          */
45
46         switch(0) {
47         case 1: break;
48         case (S_ETC|S_COM|S_VAR|S_DOT) != S_ETC : break;
49         }
50
51         progname = *argv++; argc--;
52         for (p = sigs; i = *p++; )
53                 if (signal(i, SIG_IGN) != SIG_IGN)
54                         signal(i, stop);
55         for (i = 0; i < argc; i++) {
56                 p = argv[i];
57                 if (*p++ != '-')
58                         continue;
59                 switch (*p++) {
60                 case 'o':
61                         if (*p != '\0') {
62                                 aoutpath = p;
63                                 break;
64                         }
65                         argv[i] = 0;
66                         if (++i >= argc)
67                                 fatal("-o needs filename");
68                         aoutpath = argv[i];
69                         break;
70                 case 'T':
71                         if (*p != '\0') {
72                                 extern char *tmp_dir;
73
74                                 tmp_dir = p;
75                         }
76                         break;
77                 case 'd':
78 #ifdef LISTING
79                         dflag = 0;
80                         while (*p >= '0' && *p <= '7')
81                                 dflag = (dflag << 3) + *p++ - '0';
82                         if ((dflag & 0777) == 0)
83                                 dflag |= 0700;
84                         dflag &= ~4;
85 #endif
86                         break;
87                 case 's':
88                         sflag = 0;
89                         while (*p >= '0' && *p <= '7')
90                                 sflag = (sflag << 3) + *p++ - '0';
91                         break;
92                 case 'r':
93 #ifdef RELOCATION
94 #ifdef ASLD
95                         rflag = 1;
96 #endif /* ASLD */
97 #endif /* RELOCATION */
98                         break;
99                 case 'b':
100 #ifdef THREE_PASS
101                         bflag = 1;
102 #endif
103                         break;
104 #ifndef ASLD
105                 case 'u':
106                 case '\0':
107                         uflag = 1;
108                         break;
109 #endif
110                 default:
111                         continue;
112                 }
113                 argv[i] = 0;
114         }
115 #ifdef RELOCATION
116         if (rflag)
117                 sflag |= SYM_SCT;
118 #endif /* RELOCATION */
119         pass_1(argc, argv);
120 #ifdef THREE_PASS
121         pass_23(PASS_2);
122 #endif
123         pass_23(PASS_3);
124         wr_close();
125         stop();
126 }
127
128 /* ---------- pass 1: arguments, modules, archives ---------- */
129
130 pass_1(argc, argv)
131 char **argv;
132 {
133         register char *p;
134         register item_t *ip;
135 #ifdef ASLD
136         char armagic[2];
137 #else
138         register nfile = 0;
139 #endif
140
141 #ifdef THREE_PASS
142         bitindex = -1;
143         nbits = BITCHUNK;
144 #endif
145
146         tempfile = fftemp(temppath, "asTXXXXXX");
147 #ifdef LISTING
148         listmode = dflag;
149         if (listmode & 0440)
150                 listfile = fftemp(listpath, "asLXXXXXX");
151 #endif
152         for (ip = keytab; ip->i_type; ip++)
153                 item_insert(ip, H_KEY+hash(ip->i_name));
154         machstart(PASS_1);
155         while (--argc >= 0) {
156                 p = *argv++;
157                 if (p == 0)
158                         continue;
159 #ifndef ASLD
160                 if (nfile != 0)
161                         fatal("second source file %s", p);
162                 nfile++;
163 #else
164                 if (p[0] == '-' && p[1] == '\0') {
165                         input = stdin;
166                         parse("STDIN");
167                         continue;
168                 }
169 #endif
170                 if ((input = fopen(p, "r")) == NULL)
171                         fatal("can't open %s", p);
172 #ifdef ASLD
173                 if (
174                         fread(armagic, 2, 1, input) == 1
175                         &&
176                         ((armagic[0]&0377) |
177                          ((unsigned)(armagic[1]&0377)<<8)) == ARMAG
178                 ) {
179                         archive();
180                         fclose(input);
181                         continue;
182                 }
183                 rewind(input);
184 #endif
185                 parse(p);
186                 fclose(input);
187         }
188 #ifndef ASLD
189         if (nfile == 0) {
190                 input = stdin;
191                 parse("STDIN");
192         }
193 #endif
194         commfinish();
195         machfinish(PASS_1);
196 #ifdef ASLD
197         if (unresolved) {
198                 register int i;
199
200                 nerrors++;
201                 fflush(stdout);
202                 fprintf(stderr, "unresolved references:\n");
203                 for (i = 0; i < H_SIZE; i++) {
204                         ip = hashtab[H_GLOBAL+i];
205                         while (ip != 0) {
206                                 if ((ip->i_type & (S_EXT|S_TYP)) == (S_EXT|S_UND))
207                                         fprintf(stderr, "\t%s\n", ip->i_name);
208                                 ip = ip->i_next;
209                         }
210                 }
211         }
212 #else
213         if (unresolved)
214                 outhead.oh_flags |= HF_LINK;
215         /*
216         if (nfile == 0)
217                 fatal("no source file");
218         */
219 #endif
220 }
221
222 #ifdef ASLD
223
224 archive() {
225         register long offset;
226         struct ar_hdr header;
227         char getsize[AR_TOTAL];
228
229         archmode++;
230         offset = 2;
231         for (;;) {
232                 if (unresolved == 0)
233                         break;
234                 fseek(input,offset,0);
235                 if (fread(getsize,AR_TOTAL,1,input) != 1)
236                         break;
237                 offset += AR_TOTAL;
238                 strncpy(header.ar_name,getsize,sizeof header.ar_name) ;
239                 header.ar_size= (((((long) (getsize[AR_SIZE+1]&0377))<<8)+
240                                 ((long) (getsize[AR_SIZE  ]&0377))<<8)+
241                                 ((long) (getsize[AR_SIZE+3]&0377))<<8)+
242                                 ((long) (getsize[AR_SIZE+2]&0377)) ;
243                 archsize = header.ar_size;
244                 if (needed()) {
245                         fseek(input,offset,0);
246                         archsize = header.ar_size;
247                         header.ar_name[14] = '\0';
248                         parse(remember(header.ar_name));
249                 }
250                 offset += header.ar_size;
251                 while (offset % 2)
252                         offset++;
253         }
254         archmode = 0;
255 }
256
257 needed()
258 {
259         register c, first;
260         register item_t *ip;
261         register need;
262
263 #ifdef LISTING
264         register save;
265
266         save = listflag; listflag = 0;
267 #endif
268         need = 0;
269         peekc = -1;
270         first = 1;
271         for (;;) {
272                 c = nextchar();
273                 if (c == '\n') {
274                         first = 1;
275                         continue;
276                 }
277                 if (c == ' ' || c == '\t' || c == ',')
278                         continue;
279                 if (ISALPHA(c) == 0)
280                         break;
281                 if ((ip = item_search(readident(c))) == 0) {
282                         if (first)
283                                 break;
284                         continue;
285                 }
286                 if (first) {
287                         if (ip == &keytab[KEYSECT]) {
288                                 while ((c = nextchar()) != '\n')
289                                         ;
290                                 continue;
291                         }
292
293                         if (ip != &keytab[KEYDEFINE])
294                                 break;
295                         first = 0;
296                 }
297                 if ((ip->i_type & S_TYP) == S_UND) {
298                         need++;
299                         break;
300                 }
301         }
302 #ifdef LISTING
303         listflag = save;
304 #endif
305         return(need);
306 }
307 #endif /* ASLD */
308
309 parse(s)
310 char *s;
311 {
312         register i;
313         register item_t *ip;
314         register char *p;
315
316         for (p = s; *p; )
317                 if (*p++ == '/')
318                         s = p;
319 #ifdef ASLD
320         yylval.y_strp = s;
321         putval(MODULE);
322 #endif
323         for (i = 0; i < FB_SIZE; i++)
324                 fb_ptr[FB_BACK+i] = 0;
325         newmodule(s);
326         peekc = -1;
327         yyparse();
328         /*
329          * Check for undefined symbols
330          */
331 #ifdef ASLD
332         for (i = 0; i < H_SIZE; i++) {
333                 while (ip = hashtab[H_LOCAL+i]) {
334                         /*
335                          * cleanup local queue
336                          */
337                         hashtab[H_LOCAL+i] = ip->i_next;
338                         /*
339                          * make undefined references extern
340                          */
341                         if ((ip->i_type & (S_VAR|S_TYP)) == S_UND) 
342                                 ip->i_type |= S_EXT;
343                         /*
344                          * relink externals in global queue
345                          */
346                         if (ip->i_type & S_EXT)
347                                 item_insert(ip, H_GLOBAL+i);
348                 }
349         }
350 #else
351         for (i = 0; i < H_SIZE; i++) {
352                 for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
353                         if (ip->i_type & S_EXT)
354                                 continue;
355                         if (ip->i_type != S_UND)
356                                 continue;
357                         if (uflag == 0)
358                                 serror("undefined symbol %s", ip->i_name);
359                         ip->i_type |= S_EXT;
360                 }
361         }
362 #endif
363         /*
364          * Check for undefined numeric labels
365          */
366         for (i = 0; i < FB_SIZE; i++) {
367                 if ((ip = fb_ptr[FB_FORW+i]) == 0)
368                         continue;
369                 serror("undefined label %d", i);
370                 fb_ptr[FB_FORW+i] = 0;
371         }
372 }
373
374 pass_23(n)
375 {
376         register i;
377 #ifdef ASLD
378         register ADDR_T base = 0;
379 #endif
380         register sect_t *sp;
381
382         if (nerrors)
383                 stop();
384         pass = n;
385 #ifdef LISTING
386         listmode >>= 3;
387         if (listmode & 4)
388                 ffreopen(listpath, listfile);
389         listeoln = 1;
390 #endif
391 #ifdef THREE_PASS
392         bitindex = -1;
393         nbits = BITCHUNK;
394 #endif
395         for (i = 0; i < FB_SIZE; i++)
396                 fb_ptr[FB_FORW+i] = fb_ptr[FB_HEAD+i];
397         outhead.oh_nemit = 0;
398         for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
399 #ifdef ASLD
400                 if (sp->s_flag & BASED) {
401                         base = sp->s_base;
402                         if (base % sp->s_lign)
403                                 fatal("base not aligned");
404                 } else {
405                         base += (sp->s_lign - 1);
406                         base -= (base % sp->s_lign);
407                         sp->s_base = base;
408                 }
409                 base += sp->s_size;
410                 base += sp->s_comm;
411 #endif
412                 outhead.oh_nemit += sp->s_size - sp->s_zero;
413         }
414         if (pass == PASS_3) 
415                 setupoutput();
416         for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
417                 sp->s_size = 0;
418                 sp->s_zero = 0;
419 #ifdef THREE_PASS
420                 sp->s_gain = 0;
421 #endif
422         }
423         machstart(n);
424 #ifndef ASLD
425         newmodule(modulename);
426 #endif /* ASLD */
427         ffreopen(temppath, tempfile);
428         yyparse();
429         commfinish();
430         machfinish(n);
431 }
432
433 newmodule(s)
434 char *s;
435 {
436         static char nmbuf[STRINGMAX];
437
438         switchsect(S_UND);
439         if (s && s != modulename) {
440                 strncpy(nmbuf, s, STRINGMAX-1);
441                 modulename = nmbuf;
442         }
443         else modulename = s;
444         lineno = 1;
445 #ifdef NEEDED
446         /*
447          * problem: it shows the name of the tempfile, not any name
448          * the user is familiar with. Moreover, it is not reproducable.
449          */
450         if ((sflag & (SYM_EXT|SYM_LOC|SYM_LAB)) && PASS_SYMB)
451                 newsymb(s, S_MOD, 0, (valu_t)0);
452 #endif
453 #ifdef LISTING
454         listtemp = 0;
455         if (dflag & 01000)
456                 listtemp = listmode;
457         listflag = listtemp;
458 #endif
459 }
460
461 setupoutput()
462 {
463         register sect_t *sp;
464         register long off;
465         struct outsect outsect;
466         register struct outsect *pos = &outsect;
467
468         if (! wr_open(aoutpath)) {
469                 fatal("can't create %s", aoutpath);
470         }
471         wr_ohead(&outhead);
472         /*
473          * section table generation
474          */
475         off = SZ_HEAD;
476         off += (long)outhead.oh_nsect * SZ_SECT;
477         for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
478                 sp->s_foff = off;
479                 pos->os_base = SETBASE(sp);
480                 pos->os_size = sp->s_size + sp->s_comm;
481                 pos->os_foff = sp->s_foff;
482                 pos->os_flen = sp->s_size - sp->s_zero;
483                 pos->os_lign = sp->s_lign;
484                 off += pos->os_flen;
485                 wr_sect(pos, 1);
486         }
487 #ifdef RELOCATION
488         off += (long)outhead.oh_nrelo * SZ_RELO;
489 #endif
490         if (sflag == 0)
491                 return;
492         off += (long)outhead.oh_nname * SZ_NAME;
493         outhead.oh_nchar = off; /* see newsymb() */
494 }
495
496 commfinish()
497 {
498 #ifndef ASLD
499         register int i;
500 #endif
501         register struct common_t *cp;
502         register item_t *ip;
503         register sect_t *sp;
504         register valu_t addr;
505
506         switchsect(S_UND);
507         /*
508          * assign .comm labels and produce .comm symbol table entries
509          */
510         for (cp = commons; cp; cp = cp->c_next) {
511                 ip = cp->c_it;
512 #ifndef ASLD
513                 if (!( ip->i_type & S_EXT)) {
514 #endif
515                         sp = &sect[(ip->i_type & S_TYP) - S_MIN];
516                         if (pass == PASS_1) {
517                                 addr = sp->s_size + sp->s_comm;
518                                 sp->s_comm += ip->i_valu;
519                                 ip->i_valu = addr;
520 #ifndef ASLD
521                                 ip->i_type &= ~S_COM;
522 #endif
523                         }
524 #ifdef ASLD
525 #ifdef THREE_PASS
526                         if (pass == PASS_2) {
527                                 ip->i_valu -= sp->s_gain;
528                         }
529 #endif
530                         if ((sflag & SYM_EXT) && PASS_SYMB)
531                                 newsymb(
532                                         ip->i_name,
533                                         ip->i_type & (S_EXT|S_TYP),
534                                         0,
535                                         load(ip)
536                                 );
537 #else /* not ASLD */
538 #ifdef THREE_PASS
539                         if (pass == PASS_2) {
540                                 cp->c_size -= sp->s_gain;
541                         }
542 #endif /* THREE_PASS */
543                 }
544                 if (pass == PASS_1) cp->c_size = ip->i_valu;
545                 if (PASS_SYMB) {
546                         if (pass != PASS_3 && (ip->i_type & S_EXT)) {
547                                 ip->i_valu = outhead.oh_nname;
548                         }
549                         newsymb(
550                                 ip->i_name,
551                                 ip->i_type,
552                                 0,
553                                 cp->c_size
554                         );
555                 }
556 #endif /* not ASLD */
557         }
558         if (PASS_SYMB == 0)
559                 return;
560 #ifndef ASLD
561         /*
562          * produce symbol table entries for undefined's
563          */
564         for (i = 0; i<H_SIZE; i++)
565                 for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
566                         if (ip->i_type != (S_EXT|S_UND))
567                                 continue;
568                         if (pass != PASS_3)
569                                 /*
570                                  * save symbol table index
571                                  * for possible relocation
572                                  */
573                                 ip->i_valu = outhead.oh_nname;
574                         newsymb(
575                                 ip->i_name,
576                                 S_EXT|S_UND,
577                                 0,
578                                 (valu_t)0
579                         );
580                 }
581 #endif /* not ASLD */
582         /*
583          * produce symbol table entries for sections
584          */
585         if (sflag & SYM_SCT)
586                 for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
587                         ip = sp->s_item;
588                         newsymb(
589                                 ip->i_name,
590                                 (ip->i_type | S_SCT),
591                                 0,
592                                 load(ip)
593                         );
594                 }
595 }