/* asmain.c */ /* * (C) Copyright 1989 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 */ #include #include #include "asm.h" VOID main(argc, argv) char *argv[]; { register char *p; register c, i; struct area *ap; FILE *afile(); inpfil = -1; for (i=1; ia_fuzz = 0; ap->a_size = 0; ap = ap->a_ap; } fuzz = 0; dot->s_addr = 0; dot->s_area = dca; symp = dot; minit(); while (getline()) { ++line; cp = cb; ep = eb; ip = ib; if (setjmp(jump_env) == 0) asmbl(); if (pass == 2) { diag(); list(); } } newdot(dot->s_area); /* Flush area info */ if (flevel || tlevel) err('i'); } if (oflag) outchk(HUGE, HUGE); /* Flush */ if (sflag) { lstsym(tfp); } else if (lflag) { lstsym(lfp); } } VOID asmbl() { register struct mne *mp; register struct sym *sp; register struct tsym *tp; register c; struct area *ap; struct expr e1; char id[NCPS]; char opt[NCPS]; char fn[FILSPC]; char *p; int d, n, uaf, uf; laddr = dot->s_addr; lmode = SLIST; loop: if ((c=endline()) == 0) { return; } if (ctype[c] == DIGIT) { if (flevel) return; n = 0; while ((d = digit(c, 10)) >= 0) { n = 10*n + d; c = get(); } if (c != '$' || get() != ':') qerr(); tp = symp->s_tsym; if (pass == 0) { while (tp) { if (n == tp->t_num) { tp->t_flg |= S_MDF; break; } tp = tp->t_lnk; } if (tp == NULL) { tp=(struct tsym *) new (sizeof(struct tsym)); tp->t_lnk = symp->s_tsym; tp->t_num = n; tp->t_area = dot->s_area; tp->t_addr = dot->s_addr; symp->s_tsym = tp; } } else { while (tp) { if (n == tp->t_num) { break; } tp = tp->t_lnk; } if (tp) { if (pass == 1) { fuzz = tp->t_addr - dot->s_addr; tp->t_area = dot->s_area; tp->t_addr = dot->s_addr; } else { phase(tp->t_area, tp->t_addr); if (tp->t_flg & S_MDF) err('m'); } } else { err('u'); } } goto loop; } if (ctype[c] != LETTER) if (flevel) { return; } else { qerr(); } getid(id, c); c = getnb(); if (c == ':') { if (flevel) return; if ((c = get()) != ':') { unget(c); c = 0; } symp = lookup(id); if (symp == dot) err('.'); if (pass == 0) if (symp->s_type != S_NEW && (symp->s_flag & S_ASG) == 0) symp->s_flag |= S_MDF; if (pass != 2) { fuzz = symp->s_addr - dot->s_addr; symp->s_type = S_USER; symp->s_area = dot->s_area; symp->s_addr = dot->s_addr; } else { if (symp->s_flag & S_MDF) err('m'); phase(symp->s_area, symp->s_addr); } if (c) { symp->s_flag |= S_GBL; } lmode = ALIST; goto loop; } if (c == '=') { if (flevel) return; if ((c = get()) != '=') { unget(c); c = 0; } expr(&e1, 0); sp = lookup(id); if (sp == dot) { outall(); if (e1.e_flag || e1.e_base.e_ap != dot->s_area) err('.'); } else if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { err('m'); } sp->s_type = S_USER; sp->s_area = e1.e_base.e_ap; sp->s_addr = laddr = e1.e_addr; sp->s_flag |= S_ASG; if (c) { sp->s_flag |= S_GBL; } lmode = ALIST; goto loop; } unget(c); lmode = flevel ? SLIST : CLIST; if ((mp = mlookup(id)) == NULL) { if (!flevel) err('o'); return; } switch (mp->m_type) { case S_IF: n = absexpr(); if (tlevel < MAXIF) { ++tlevel; ifcnd[tlevel] = n; iflvl[tlevel] = flevel; if (n == 0) { ++flevel; } } else { err('i'); } lmode = ALIST; laddr = n; return; case S_ELSE: if (ifcnd[tlevel]) { if (++flevel > (iflvl[tlevel]+1)) { err('i'); } } else { if (--flevel < iflvl[tlevel]) { err('i'); } } lmode = SLIST; return; case S_ENDIF: if (tlevel) { flevel = iflvl[tlevel--]; } else { err('i'); } lmode = SLIST; return; case S_PAGE: lop = NLPP; lmode = NLIST; return; default: break; } if (flevel) return; switch (mp->m_type) { case S_EVEN: outall(); dot->s_addr = (dot->s_addr + 1) & ~1; lmode = SLIST; break; case S_ODD: outall(); dot->s_addr |= 1; lmode = SLIST; break; case S_BYTE: case S_WORD: do { expr(&e1, 0); if (mp->m_type == S_BYTE) { outrb(&e1, 0); } else { outrw(&e1, 0); } } while ((c = getnb()) == ','); unget(c); break; case S_ASCII: case S_ASCIZ: if ((d = getnb()) == '\0') qerr(); while ((c = getmap(d)) >= 0) outab(c); if (mp->m_type == S_ASCIZ) outab(0); break; case S_BLK: expr(&e1, 0); outall(); dot->s_addr += e1.e_addr*mp->m_valu; break; case S_TITLE: p = tb; if (c = getnb()) { do { if (p < &tb[NTITL-1]) *p++ = c; } while (c = get()); } *p = 0; unget(c); lmode = SLIST; break; case S_SBTL: p = stb; if (c = getnb()) { do { if (p < &stb[NSBTL-1]) *p++ = c; } while (c = get()); } *p = 0; unget(c); lmode = SLIST; break; case S_MODUL: getid(id, -1); if (pass == 0) { if (module[0]) err('m'); strncpy(module, id, NCPS); } lmode = SLIST; break; case S_GLOBL: do { getid(id, -1); sp = lookup(id); sp->s_flag |= S_GBL; } while ((c = getnb()) == ','); unget(c); lmode = SLIST; break; case S_DAREA: getid(id, -1); uaf = 0; uf = A_CON|A_REL; if ((c = getnb()) == '(') { do { getid(opt, -1); mp = mlookup(opt); if (mp && mp->m_type == S_ATYP) { ++uaf; uf |= mp->m_valu; } else { err('u'); } } while ((c = getnb()) == ','); if (c != ')') qerr(); } else { unget(c); } if (ap = alookup(id)) { if (uaf && uf != ap->a_flag) err('m'); } else { ap = (struct area *) new (sizeof(struct area)); ap->a_ap = areap; strncpy(ap->a_id, id, NCPS); ap->a_ref = areap->a_ref + 1; ap->a_flag = uaf ? uf : (A_CON|A_REL); areap = ap; } newdot(ap); lmode = SLIST; break; case S_ORG: if (dot->s_area->a_flag & A_ABS) { outall(); dot->s_addr = absexpr(); } else { err('o'); } lmode = SLIST; break; case S_RADIX: if (more()) { switch (getnb()) { case 'b': case 'B': radix = 2; break; case '@': case 'o': case 'O': case 'q': case 'Q': radix = 8; break; case 'd': case 'D': radix = 10; break; case 'h': case 'H': case 'x': case 'X': radix = 16; break; default: qerr(); radix = 10; break; } } else { radix = 10; } lmode = SLIST; break; case S_INCL: d = getnb(); p = fn; while ((c = get()) != d) { if (p < &fn[FILSPC-1]) { *p++ = c; } else { break; } } *p = 0; if (++incfil == MAXINC || (ifp[incfil] = fopen(fn, "r")) == NULL) { --incfil; err('i'); lmode = SLIST; } else { lop = NLPP; lmode = NLIST; } break; default: machine(mp); } goto loop; } FILE * afile(fn, ft, wf) char *fn; char *ft; { register char *p1, *p2, *p3; register c; FILE *fp; char fb[FILSPC]; p1 = fn; p2 = fb; p3 = ft; while ((c = *p1++) && c != '.') { if (p2 < &fb[FILSPC-4]) *p2++ = c; } *p2++ = '.'; if (*p3 == 0) { if (c == '.') { p3 = p1; } else { p3 = dsft; } } while (c = *p3++) { if (p2 < &fb[FILSPC-1]) *p2++ = c; } *p2++ = 0; if ((fp = fopen(fb, wf?"w":"r")) == NULL) { fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open"); exit(1); } return (fp); } VOID newdot(nap) register struct area *nap; { register struct area *oap; oap = dot->s_area; oap->a_fuzz = fuzz; oap->a_size = dot->s_addr; fuzz = nap->a_fuzz; dot->s_area = nap; dot->s_addr = nap->a_size; outall(); } VOID phase(ap, a) struct area *ap; addr_t a; { if (ap != dot->s_area || a != dot->s_addr) err('p'); } char *usetxt[] = { "Usage: [-dqxgalos] file1 [file2 file3 ...]", " d decimal listing", " q octal listing", " x hex listing (default)", " g undefined symbols made global", " a all user symbols made global", " l create list output file1.lst", " o create object output file1.rel", " s create symbol output file1.sym", "", 0 }; VOID usage() { register char **dp; fprintf(stderr, "\nAssembler (%s)\n\n", cpu); for (dp = usetxt; *dp; dp++) fprintf(stderr, "%s\n", *dp); exit(1); }