/* File: plab.c * * Contains: proc_symbol, add_symbol, load_symbol, locat * * This is the routine that will process labels inserting them * into the symbol table if they're new and it's pass 1. On * pass 2, it will additionally check to see if the address (value) * is the same between the two passes and indicate phase error if * they're not. */ #include "asm.h" extern int prtyes; int symnum; /* number of syms in table */ int start_count = 1; SYM *symend; SYM *insert_point; SYM *start_fp = 0; /*. ************************************************************************* * * * proc_symbol * * ----------- * * * * process symbol * * * * proc_symbol(c) * * * * char c * * opcode token * * * * returns no value * * * ************************************************************************* */ SYM *proc_symbol(c,i_SYM) char c; SYM *i_SYM; { register SYM *symbol; register int g_flag = 0; short value; #if DEBUG printf("proc_symbol\n"); #endif /* see if we're in a false conditional and exit if so */ if (false_condit || labflg) { #if DEBUG printf("proc_symbol: return because of false_condit=%d or labflg=%d\n",false_condit,labflg); #endif turn_off(AFGLAB); return(0); } labflg = 1; if (labbuf[0] == 0) { turn_off(AFGLAB); return(0); } if (is_on(AFENTS | AFEXTS)) value = 0; else value = adrefc[mode]; /* * see if it's a DEFL or EQU */ if (c == DEFLTK || c == EQUTOK) { gtod(linpnt); value = odint1; addisr = odint1 & (unsigned) 0xffff; turn_on(AFEQDL); mathfg |= MFEQDL; if (((opbyt1 & 0xf0) | ((opbyt2 >> 4) & 0xf)) != INTTOK) { dnops(); turn_off(AFGLAB); return(0); } } /* * if this is from get_label * reset flag * * if this is NOT a local label, and we processed a local label, * and this is not an equ/defl * * reset flag * ++local number */ if (is_on(AFGLAB)) { turn_off(AFGLAB); if (is_off(AFGLOC) && is_on(AFLOC) && is_off(AFEQDL)) { turn_off(AFLOC); ++locnum; } g_flag = 1; } /* * see if the label is a reserved word */ if (regtok(labbuf) || match(labbuf, "narg", 1)) { eror('W'); return(0); } /* * set the 'label being defined' bit */ turn_on(AFSYMB); /* * see if we've already defined this label */ if (g_flag && passno == 2) { if ((symbol = i_SYM) == 0) { eror('P'); return(0); } } else if ((symbol = loc_symbol(labbuf)) == 0) { if (passno == 1) { symbol = add_symbol(); load_symbol(symbol,value); return(symbol); } else { #if DEBUG printf("proc_symbol: symbol not found\n"); #endif eror('P'); return(0); } } /* * if symbol is not a relocatable symbol, the turn on abs symbol flag */ if ((symbol->s_flag1 & SYMREL) == 0) turn_on(AFABSL); if (symbol->s_flag1 & SYMDFL) { if (c == DEFLTK) { labrel(symbol); symbol->s_value = value; } else symbol->s_flag1 |= SYMMDF; } else if (passno == 1) { if ((symbol->s_flag1 & SYMUDF) == 0 && (symbol->s_flag2 & SLOCAL) == 0) { if (refflg) return(symbol); symbol->s_flag1 |= SYMMDF; } else if (g_flag) symbol->s_flag1 &= ~SYMUDF; } if (passno == 2) { /* * no reference to this symbol */ if (symbol->s_flag2 & PNOREF) refpno = '-'; /* * global symbol */ if (symbol->s_flag2 & PRTGBL) bglob = 'g'; if (prtyes || is_off(AFENTS | AFEXTS) && (symbol->s_flag2 & SLOCAL) == 0) reff_symbol(symbol,1); } /* * global, public, or entry symbol */ if (symbol->s_flag1 & SYMENT) { if (is_on(AFENTS) == 0) { symbol->s_psect = pdef; /* * turn on AFENTS flag since it is off */ turn_on(AFENTS); } labrel(symbol); if (passno == 1) symbol->s_value = value; else { (void) movbuf(labbuf, o4entb, slenth, -1); entadr = value; } } if (symbol->s_flag2 & MACLOC) { symbol->s_psect = pdef; symbol->s_flag1 &= ~(SYMMDF | SYMUDF); symbol->s_value = value; return(symbol); } /* * symbol multidefined */ if (symbol->s_flag1 & SYMMDF) eror('M'); if ((symbol->s_flag1 & SYMDFL) != SYMDFL) if (symbol->s_value != value) eror('P'); return(symbol); } /*. ************************************************************************* * * * labrel * * ------ * * * * set relocatable flags * * * * * * * ************************************************************************* */ void labrel(symbol) register SYM *symbol; { if (is_off(AFASEG) && mathfg & MFEQDL) { if ((mathfg & MFRLEM) == 0) symbol->s_flag1 &= ~SYMREL; else if ((symbol->s_flag1 & SYMREL) == 0) symbol->s_flag1 |= SYMREL; } } /*. ************************************************************************* * * * load_symbol * * ----- * * * * transfer label and value to symbol buffer * * * * * * * ************************************************************************* */ void load_symbol(sp,value) register SYM *sp; register short value; { register unsigned char *fp,*bp; #if DEBUG printf("lbysm: *%s* value=%d\n",labbuf,value); #endif fp = labbuf; bp = sp->s_name; while(*fp) *bp++ = *fp++; *bp = 0; #if DEBUG > 1 printf("load_symbol: name=*%s*\n",sp->s_name); #endif sp->s_flag1 = 0; sp->s_value = value; sp->s_flag2 = PNOREF; if(mode == DSEG) { sp->s_flag1 |= SYMENT; sp->s_flag2 |= SYDSEG; } /* set relocatable if it's that way */ if (is_off(AFASEG)) { if ((mathfg & MFEQDL) == 0 || mathfg & MFRLEM) sp->s_flag1 |= SYMREL; else sp->s_flag2 &= ~SYMREL; } /* set external if so */ if (is_on(AFEXTS)) { sp->s_flag1 |= (SYMEXT | SYMUDF); sp->s_flag1 &= ~SYMREL; } /* set entry if so */ if (is_on(AFENTS)) sp->s_flag1 |= (SYMENT | SYMUDF); /* set isect if so */ if (is_on(AFISEC)) { sp->s_flag1 &= ~SYMREL; sp->s_flag1 |= SYMSEC; } /* set defl if so */ if (*ortkbf == DEFLTK) sp->s_flag1 |= SYMDFL; /* set the isect number */ sp->s_isect = idef; sp->s_psect = pdef; if (refflg) sp->s_flag1 |= SYMREF; if (is_on(AFLOC | AFLOCL) == (AFLOC | AFLOCL)) { turn_off(AFLOCL); sp->s_flag2 |= SYMLOC; } if (is_on(AFGLOC | AFMLOC) == (AFGLOC | AFMLOC)) sp->s_flag2 |= MACLOC; sp->ref_beg = 0; sp->ref_end = 0; } /*. ************************************************************************* * * * loc_symbol * * ---------- * * * * lookup symbol in symbol table * * * * * * * ************************************************************************* */ SYM *loc_symbol(sp) register char *sp; { register SYM *fp; register int low,high,ptr,retcode; #if DEBUG printf("loc_symbol:*%s*\n", sp); printf("start address=%x name=*%s* count=%d \n",start_fp,start_fp->s_name,start_count); #endif fp = start_fp; symcnt = start_count; low = 0; high = symnum + 1; while ((ptr = (high-low)/2 + low) != low && ptr != high) { retcode = symcnt; while (ptr > retcode) { #if DEBUG printf("loc_symbol: down *%s*\n",fp->s_name); #endif fp = fp->rightptr; retcode++; } while (ptr < retcode) { #if DEBUG printf("loc_symbol: up *%s*\n",fp->s_name); #endif fp = fp->leftptr; retcode--; } symcnt = retcode; if ((retcode = check(sp,fp->s_name)) == TOO_HIGH) low = ptr; else if (retcode == TOO_LOW) high = ptr; else { if (fp->s_flag1 & SYMSEC) { isave2 = fp->s_isect; turn_on(AFUSPR); } #if DEBUG printf("\nfound: %s with value of %d\n", fp->s_name, fp->s_value); #endif return(fp); } } #if DEBUG printf("\n"); #endif if (retcode == TOO_HIGH) { if (fp->rightptr) insert_point = fp->rightptr; else insert_point = 0; symcnt++; } else insert_point = fp; return(0); } /*. ************************************************************************* * * * check * * ----- * * * * check to see if symbol (fp) is greater than symbol (bp) * * * * * * * ************************************************************************* */ int check(fp, bp) register char *fp, *bp; { #if DEBUG printf("check: *%s* *%s*\n",fp,bp); fflush(stdout); #endif while (*fp && *bp) { if (*fp > *bp) return(TOO_HIGH); else if (*fp < *bp) return(TOO_LOW); fp++; bp++; } /* * at this point, one string is at its end */ if (*fp) return(TOO_HIGH); if (*bp) return(TOO_LOW); return(MATCH); } /*. ************************************************************************* * * * add_symbol * * ------ * * * * insert a new symbol into the symbol table * * * * SYM *add_symbol() * * * * returns no value * * * ************************************************************************* */ SYM *add_symbol() { register SYM *new, *pnt; register int i; ++symnum; new = (SYM *) xalloc(SSIZE); if (symbeg == 0) { /* * symbol table is empty - enter first symbol */ symbeg = new; symend = new; start_fp = new; start_count = 1; new->leftptr = 0; new->rightptr = 0; return(new); } pnt = insert_point; if (pnt == 0) { /* * insert symbol at the end of the table */ pnt = symend; pnt->rightptr = new; new->leftptr = pnt; new->rightptr = 0; symend = new; return(new); } /* * insert symbol somewhere inside the table */ new->leftptr = pnt->leftptr; pnt->leftptr = new; new->rightptr = pnt; if (pnt == symbeg) symbeg = new; else { pnt = new->leftptr; pnt->rightptr = new; } #if DEBUG > 1 printf("add_symbol: symcnt=%d\n",symcnt); printf("add_symbol: symnum=%d\n",symnum); printf("add_symbol:start_fp *%s*\n",start_fp->s_name); printf("add_symbol:start_count =%d\n",start_count); #endif if (symcnt <= start_count) { start_count++; #if DEBUG > 1 printf("add_symbol:increase start_count\n"); #endif } i = (symnum+1)/2; while (i < start_count) { start_fp = start_fp->leftptr; start_count--; } while (i > start_count) { start_fp = start_fp->rightptr; start_count++; } #if DEBUG > 1 printf("add_symbol:start_fp %s\n",start_fp->s_name); printf("add_symbol:start_count =%d\n",start_count); #endif return(new); } /*. ************************************************************************* * * * gsym * * ---- * * * * * * * * * ************************************************************************* */ /* * This routine will search for a label in the line buffer, and * if one is found, will move it to LABBUF. The line pointer is * left pointing to the character after the label. */ #include unsigned char *gsym(fp, buff) register unsigned char *fp; register char *buff; { register int count; #if DEBUG printf("gsym\n"); #endif count = 0; while (alpha(fp) || (*fp >= '0' && *fp <= '9')) { if (count++ >= slenth) break; *buff++ = *fp++; } *buff = 0; while (alpha(fp) || (*fp >= '0' && *fp <= '9')) fp++; return(fp); }