/* @(#)comm4.c 1.6 */ /* * Micro processor assembler framework written by * Johan Stevenson, Vrije Universiteit, Amsterdam * modified by * Johan Stevenson, Han Schaminee and Hans de Vries * Philips S&I, T&M, PMDS, Eindhoven */ #include "comm0.h" #include "comm1.h" #include "y.tab.h" extern YYSTYPE yylval; /* ========== Machine independent C routines ========== */ stop() { #if DEBUG < 2 unlink(temppath); #ifdef LISTING unlink(listpath); #endif #endif exit(nerrors != 0); } main(argc, argv) char **argv; { register char *p; register i; static char sigs[] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM, 0 }; /* this test should be performed by the * preprocessor, but it cannot */ if ((S_ETC|S_COM|S_VAR|S_DOT) != S_ETC) fatal("incorrect type bits"); progname = *argv++; argc--; for (p = sigs; i = *p++; ) if (signal(i, SIG_IGN) != SIG_IGN) signal(i, stop); for (i = 0; i < argc; i++) { p = argv[i]; if (*p++ != '-') continue; switch (*p++) { case 'o': if (*p != NULL) { aoutpath = p; break; } argv[i] = 0; if (++i >= argc) fatal("-o needs filename"); aoutpath = argv[i]; break; case 'd': #ifdef LISTING dflag = 0; while (*p >= '0' && *p <= '7') dflag = (dflag << 3) + *p++ - '0'; if ((dflag & 0777) == 0) dflag |= 0700; dflag &= ~4; #endif break; case 's': sflag = 0; while (*p >= '0' && *p <= '7') sflag = (sflag << 3) + *p++ - '0'; break; case 'r': #ifdef RELOCATION #ifdef ASLD rflag = 1; #endif ASLD #endif RELOCATION break; case 'b': #ifdef THREE_PASS bflag = 1; #endif break; #ifndef ASLD case 'u': case '\0': uflag = 1; break; #endif default: continue; } argv[i] = 0; } #ifdef RELOCATION if (rflag) sflag |= SYM_SCT; #endif RELOCATION pass_1(argc, argv); #ifdef THREE_PASS pass_23(PASS_2); #endif pass_23(PASS_3); stop(); } /* ---------- pass 1: arguments, modules, archives ---------- */ pass_1(argc, argv) char **argv; { register i; register char *p; register item_t *ip; #ifdef ASLD char armagic[SZMAGIC]; #else register nfile = 0; #endif tempfile = fftemp(temppath, "asTXXXXXX"); #ifdef LISTING listmode = dflag; if (listmode & 0440) listfile = fftemp(listpath, "asLXXXXXX"); #endif for (ip = keytab; ip->i_type; ip++) item_insert(ip, H_KEY+hash(ip->i_name)); machstart(PASS_1); while (--argc >= 0) { p = *argv++; if (p == 0) continue; #ifdef ASLD if (p[0] == '-' && p[1] == '\0') { input = stdin; parse("STDIN"); continue; } #else if (nfile != 0) fatal("second source file %s", p); nfile++; #endif if ((input = fopen(p, "r")) == NULL) fatal("can't open %s", p); #ifdef ASLD if ( fread(armagic, SZMAGIC, 1, input) == 1 && strncmp(armagic, ARMAGIC, SZMAGIC) == 0 ) { archive(); fclose(input); continue; } rewind(input); #endif parse(p); fclose(input); } commfinish(); machfinish(PASS_1); #ifdef ASLD if (unresolved) { nerrors++; fflush(stdout); fprintf(stderr, "unresolved references:\n"); for (i = 0; i < H_SIZE; i++) { ip = hashtab[H_GLOBAL+i]; while (ip != 0) { if ((ip->i_type & (S_EXT|S_TYP)) == (S_EXT|S_UND)) fprintf(stderr, "\t%s\n", ip->i_name); ip = ip->i_next; } } } #else if (unresolved) outhead.oh_flags |= HF_LINK; if (nfile == 0) fatal("no source file"); #endif } #ifdef ASLD archive() { register long offset; register i; register long modsize; char modhead[SZMHEAD]; archmode++; offset = SZMAGIC; for (;;) { if (unresolved == 0) break; fseek(input, offset, 0); if (fread(modhead, SZMHEAD, 1, input) != 1) break; if ( strncmp(&modhead[OFF_BEG], STR_BEG, LEN_BEG) || strncmp(&modhead[OFF_END], STR_END, LEN_END) ) fatal("bad archive"); offset += SZMHEAD; modsize = atol(&modhead[OFF_SIZ]); archsize = modsize; if (needed()) { fseek(input, offset, 0); archsize = modsize; for (i = 0; i < LEN_NAM; i++) if (modhead[OFF_NAM+i] == ' ') break; modhead[OFF_NAM+i] = '\0'; parse(remember(&modhead[OFF_NAM])); } offset += modsize; } archmode = 0; } needed() { register c, first; register item_t *ip; register need; #ifdef LISTING register save; save = listflag; listflag = 0; #endif need = 0; peekc = -1; first = 1; for (;;) { c = nextchar(); if (c == '\n') { first = 1; continue; } if (c == ' ' || c == '\t' || c == ',') continue; if (ISALPHA(c) == 0) break; if ((ip = item_search(readident(c))) == 0) { if (first) break; continue; } if (first) { if (ip != &keytab[KEYDEFINE]) break; first = 0; } if ((ip->i_type & S_TYP) == S_UND) { need++; break; } } #ifdef LISTING listflag = save; #endif return(need); } #endif ASLD parse(s) char *s; { register i; register item_t *ip; register char *p; for (p = s; *p; ) if (*p++ == '/') s = p; #ifdef ASLD yylval.y_strp = s; putval(MODULE); #endif for (i = 0; i < FB_SIZE; i++) fb_ptr[FB_BACK+i] = 0; newmodule(s); peekc = -1; yyparse(); /* * Check for undefined symbols */ #ifdef ASLD for (i = 0; i < H_SIZE; i++) { while (ip = hashtab[H_LOCAL+i]) { /* * cleanup local queue */ hashtab[H_LOCAL+i] = ip->i_next; /* * make undefined references extern */ if ((ip->i_type & (S_VAR|S_TYP)) == S_UND) ip->i_type |= S_EXT; /* * relink externals in global queue */ if (ip->i_type & S_EXT) item_insert(ip, H_GLOBAL+i); } } #else for (i = 0; i < H_SIZE; i++) { for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) { if (ip->i_type & S_EXT) continue; if (ip->i_type != S_UND) continue; if (uflag == 0) serror("undefined symbol %s", ip->i_name); ip->i_type |= S_EXT; } } #endif /* * Check for undefined numeric labels */ for (i = 0; i < FB_SIZE; i++) { if ((ip = fb_ptr[FB_FORW+i]) == 0) continue; serror("undefined label %d", i); fb_ptr[FB_FORW+i] = 0; } } pass_23(n) { register i; #ifdef ASLD register addr_t base = 0; #endif register sect_t *sp; if (nerrors) stop(); pass = n; #ifdef LISTING listmode >>= 3; if (listmode & 4) ffreopen(listpath, listfile); listeoln = 1; #endif #ifdef THREE_PASS nbits = 0; #endif for (i = 0; i < FB_SIZE; i++) fb_ptr[FB_FORW+i] = fb_ptr[FB_HEAD+i]; outhead.oh_nemit = 0; for (sp = sect; sp < §[outhead.oh_nsect]; sp++) { #ifdef ASLD if (sp->s_flag & BASED) { base = sp->s_base; if (base % sp->s_lign) fatal("base not aligned"); } else { base += (sp->s_lign - 1); base -= (base % sp->s_lign); sp->s_base = base; } base += sp->s_size; base += sp->s_comm; #endif outhead.oh_nemit += sp->s_size - sp->s_zero; } if (pass == PASS_3) setupoutput(); for (sp = sect; sp < §[outhead.oh_nsect]; sp++) { sp->s_size = 0; sp->s_zero = 0; #ifdef THREE_PASS sp->s_gain = 0; #endif } machstart(n); #ifndef ASLD newmodule(modulename); #endif ASLD ffreopen(temppath, tempfile); yyparse(); commfinish(); machfinish(n); } newmodule(s) char *s; { switchsect(S_UND); modulename = s; lineno = 1; if ((sflag & (SYM_EXT|SYM_LOC|SYM_LAB)) && PASS_SYMB) newsymb(s, S_MOD, (short)0, (valu_t)0); #ifdef LISTING listtemp = 0; if (dflag & 01000) listtemp = listmode; listflag = listtemp; #endif } setupoutput() { register sect_t *sp; register long off; struct outsect outsect; #ifdef AOUTSEEK #define AOUTseek(p,o) {aoutseek[p]=o;} aoutfile = ffcreat(aoutpath); #else #define AOUTseek(p,o) {fseek(aoutfile[p],o,0);} aoutfile[PARTEMIT]=ffcreat(aoutpath); #ifdef RELOCATION aoutfile[PARTRELO]=ffcreat(aoutpath); #endif aoutfile[PARTNAME]=ffcreat(aoutpath); aoutfile[PARTCHAR]=ffcreat(aoutpath); #endif /* * header generation */ AOUTseek(PARTEMIT, 0); putofmt((char *)&outhead, SF_HEAD, PARTEMIT); /* * section table generation */ off = SZ_HEAD; off += (long)outhead.oh_nsect * SZ_SECT; for (sp = sect; sp < §[outhead.oh_nsect]; sp++) { sp->s_foff = off; outsect.os_base = SETBASE(sp); outsect.os_size = sp->s_size + sp->s_comm; outsect.os_foff = sp->s_foff; outsect.os_flen = sp->s_size - sp->s_zero; outsect.os_lign = sp->s_lign; off += outsect.os_flen; putofmt((char *)&outsect, SF_SECT, PARTEMIT); } #ifdef RELOCATION AOUTseek(PARTRELO, off); off += (long)outhead.oh_nrelo * SZ_RELO; #endif if (sflag == 0) return; AOUTseek(PARTNAME, off); off += (long)outhead.oh_nname * SZ_NAME; AOUTseek(PARTCHAR, off); outhead.oh_nchar = off; /* see newsymb() */ #undef AOUTseek } commfinish() { register i; register item_t *ip; register sect_t *sp; register valu_t addr; switchsect(S_UND); #ifdef ASLD /* * assign .comm labels and produce .comm symbol table entries */ for (i = 0; ii_next) { if ((ip->i_type & S_COM) == 0) continue; sp = §[(ip->i_type & S_TYP) - S_MIN]; if (pass == PASS_1) { addr = sp->s_size + sp->s_comm; sp->s_comm += ip->i_valu; ip->i_valu = addr; } #ifdef THREE_PASS if (pass == PASS_2) ip->i_valu -= sp->s_gain; #endif if ((sflag & SYM_EXT) && PASS_SYMB) newsymb( ip->i_name, ip->i_type & (S_EXT|S_TYP), (short)0, load(ip) ); } #endif if (PASS_SYMB == 0) return; #ifndef ASLD /* * produce symbol table entries for undefined's */ for (i = 0; ii_next) { if (ip->i_type != (S_EXT|S_UND)) continue; if (pass != PASS_3) /* * save symbol table index * for possible relocation */ ip->i_valu = outhead.oh_nname; if (sflag & SYM_SCT) newsymb( ip->i_name, S_EXT|S_UND, (short)0, (valu_t)0 ); } #endif ASLD /* * produce symbol table entries for sections */ if (sflag & SYM_SCT) for (sp = sect; sp < §[outhead.oh_nsect]; sp++) { ip = sp->s_item; newsymb( ip->i_name, (short)(ip->i_type | S_SCT), (short)0, load(ip) ); } }