📄 smal32.c
字号:
if (lim - pos > ttlbuflen - 3) lim = pos + ttlbuflen - 3; for (i = pos - 1; i < lim; i++) { (*len)++; buf[*len - 1] = line[i]; }}static void newpage(){ /* force listing to the start of a new page */ inbufptr i; if (!permitlisting) return; if (lineonpg <= 1) return; putc('\f', o); /* formfeed character */ /* note that instead of using a formfeed, this routine could be written to simply output blank lines and count them with lineonpg until the count was high enough to push the listing to a new page */ lineonpg = 1; pagenum++; /* write title to listing file */ fputs("SMAL32, rev 6/98. ", o); for (i = 0; i < titlelen; i++) putc(titlebuf[i], o); for (i = titlelen; i <= ttlbuflen; i++) putc(' ', o); fputs(timestr, o); fputs(" Page ", o); writedec(o, pagenum, 1); putc('\n', o); /* linefeed character */ fputs(" ", o); for (i = 0; i < sbttllen; i++) putc(sbttlbuf[i], o); for (i = sbttllen; i <= ttlbuflen; i++) putc(' ', o); fputs( datestr, o ); putc('\n', o); /* linefeed character */ putc('\n', o);}static void listline(){ /* list one line, including generated code. if there are any errors, list the error messages */ inbufptr i; ermsg msg; int col; int nextcol = 0; /* column on output listing */ int codepos; /* more permanent buffer ptr */ if (!permitlisting) return; lineonpg++; if (lineonpg >= linesper) newpage(); col = 1; codepos = codelen + 1; /* in case we don't make any code.. */ if (codelen > 0) { /* list generated code */ if (codeloc.base == abssym) putc(' ', o); else putc('+', o); writehex(o, codeloc.offset, 6L); putc(':', o); col = 9; i = 0; while (i < codelen) { /* list each code item */ _REC_codebuf *WITH; long width; i++; WITH = &codebuf[i - 1]; width = WITH->form * 2; nextcol = col + width + 2; if (nextcol > (listcol + 1)) { codepos = i; i = codelen; } else { if (WITH->val.base != abssym) putc('+', o); else putc(' ', o); writehex(o, WITH->val.offset, width); putc(' ', o); col = nextcol; } } } for (; col <= listcol; col++) putc(' ', o); writedec(o, lineno, 6); /* text starts in column listcol + 1 */ fputs(" ", o); for (i = 0; i < length; i++) putc(line[i], o); /* check for extended code listing */ /* list ALL generated code */ while (codepos <= codelen) { _REC_codebuf *WITH = &codebuf[codepos - 1]; long width = WITH->form * 2; nextcol += (width + 2); if (nextcol > (listcol+1)) { putc('\n', o); lineonpg++; if (lineonpg > linesper) newpage(); fputs(" ", o); nextcol = 9 + width + 2; } if (WITH->val.base != abssym) putc('+', o); else putc(' ', o); writehex(o, WITH->val.offset, width); putc(' ', o); codepos++; } codelen = 0; /* reset record of listed code */ /* write out all accumulated error messages */ if (erset != 0) { /* if */ for (msg = minermsg; (long)msg <= (long)maxermsg; msg++) { if (((1L << ((long)msg)) & erset) != 0) { /* put message into listing */ putc('\n', o); lineonpg++; if (lineonpg > linesper) newpage(); fputs( errormsgs[ msg ], o ); for (col = 26; col <= listcol + 7; col++) putc(' ', o); for (i = 0; i < ermax; i++) putc(erbuf[i], o); ermax = 0; /* put message to stderr also */ writedec(stderr, lineno, 6); fputs(" ", stderr); fputs(errormsgs[ msg ], stderr); { int l = length; if ((l + 26) > 79) l = 79 - 26; for (i = 0; i < l; i++) { putc(line[i], stderr); } } putc('\n', stderr); } } } putc('\n', o);}static void putobj(form, offset, base)int form;long offset;poolref base;{ /* store value (offset,base) in current loc. (base=abssym is used for absolute values; typically, relocatable values will come from loc.base and loc.offset or expr.base and expr.offset.) use format form (.25, .5 or 1 word), save information for listing */ if (allowlist) { /* first assure that code gets loaded in right loc */ if (objloc.offset != loc.offset || objloc.base != loc.base) { objloc = loc; fputs(".=", obj); genval( 4L, loc.offset, loc.base); } /* save appropriate listing data */ if (codelen == 0) codeloc = loc; if (codelen < listcodes) { codelen++; codebuf[codelen - 1].val.offset = offset; codebuf[codelen - 1].val.base = base; codebuf[codelen - 1].form = form; } /* then generate correct object code */ switch (form) { case 1: putc('B', obj); break; case 2: putc('H', obj); break; case 4: putc('W', obj); break; } genval( form, offset, base); objloc.offset = add(objloc.offset, form); } loc.offset = add(loc.offset, form);}static void putascii(pos, lim)inbufptr pos, lim;{ /* generate object code for ascii string */ inbufptr i; for (i = pos; i < lim; i++) { putobj(1L, line[i - 1], abssym); }}/* procedures used only by nextlex */static long number(radix)long radix;{ long acch,accl; /* accumulates the value */ long digit; /* the value of one digit */ /* assume initially that ch is a valid digit */ acch = 0; accl = 0; do { if (charclass[ch] & isdigit) digit = ch - '0'; else if (charclass[ch] & isupper) digit = (ch - 'A') + 10; else digit = (ch - 'a') + 10; if (digit >= radix) { acch = 65536L; } else { pos++; ch = line[pos - 1]; accl = accl * radix + digit; acch = acch * radix + accl / 65536L; accl %= 65536L; } } while ((charclass[ch] & isalphanum) && (acch < 65536L)); if (digit >= radix) { errmsg(baddig, pos, pos + 1); while (charclass[ch] & isalphanum) { pos++; ch = line[pos - 1]; } return 0; } else if (acch >= 65536L) { while (charclass[ch] & isalphanum) { pos++; ch = line[pos - 1]; } errmsg(bounds, next.pos, pos); return 0; } else if (acch >= 32768L) return ((acch - 32768L) * 65536L - maxposint + accl - 1); else return (acch * 65536L + accl);}/* inside smal32.onepass, lexical analysis routines */static void nextlex(){ /* save the next lexeme information in the current lexeme variable, then read a new next one from the input line */ lex = next; while (line[pos - 1] == ' ') pos++; ch = line[pos - 1]; next.pos = pos; if (ch == ';') next.typ = eol; else if (charclass[ch] & ispunc) { switch (ch) { /* case */ case ':': next.typ = colon; break; case '.': next.typ = dot; break; case ',': next.typ = comma; break; case '=': next.typ = eq; break; case '>': next.typ = gt; break; case '<': next.typ = lt; break; case '+': next.typ = plus; break; case '-': next.typ = minus; break; case '\\': next.typ = notsym; break; case '&': next.typ = andsym; break; case '!': next.typ = orsym; break; case '(': next.typ = bpar; break; case ')': next.typ = epar; break; } pos++; } else if (charclass[ch] & isdigit) { next.typ = num; next.UU.val = number(10L); if (ch == '#') { if (next.UU.val > 36 || next.UU.val < 2) { next.UU.val = 36; errmsg(badrad, next.pos, pos); } pos++; ch = line[pos - 1]; if (charclass[ch] & isalphanum) next.UU.val = number(next.UU.val); else errmsg(baddig, next.pos, pos); } } else if (charclass[ch] & isalpha) { next.typ = id; do { pos++; ch = line[pos - 1]; } while (charclass[ch] & isalphanum); } else if (ch == '#') { pos++; ch = line[pos - 1]; if (charclass[ch] & isalphanum) { next.typ = num; next.UU.val = number(16L); } else /* if */ next.typ = junk; } else if (charclass[ch] & isquote) { char mark = ch; next.typ = quote; do { pos++; } while (line[pos - 1] != mark && pos <= length); if (pos <= length) pos++; else errmsg(misquo, next.pos, next.pos + 1); } else { do { pos++; ch = line[pos - 1]; } while ((charclass[ch] & isvalid) == 0); next.typ = junk; } next.lim = pos; /* invalid lexeme */}static void startup(){ /* setup for processing one line of input */ getline(); /* read input line */ nextlex(); /* read first lexeme */ nextlex(); /* read second lexeme (allow lookahead) */ /* start parsing by looking for valid start of line */ while ( (lex.typ != id) && (lex.typ != eol) && (lex.typ != dot) ) { errmsg(notlab, lex.pos, lex.lim); nextlex(); }}/* inside smal32.onepass, string pool and symbol table management */static void putch(ch)char ch;{ /* put one char into permanent end of stringpool */ if (poolsp > poolpos) { /* there is room in pool */ poolpos++; strpool[poolpos - relsym] = ch; } else /* there isn't room */ poolfull = true;}static poolref putpool_(pos, lim)inbufptr pos, lim;{ /* put the string between pos and lim-1 on the current line into the string pool, returning it's index in the pool. the string delimiter is appended to the string in the pool. it is assumed that the string will fit (the caller must guarantee this) */ poolref Result; inbufptr i; poolpos++; Result = poolpos; for (i = pos - 1; i <= lim - 2; i++) { strpool[poolpos - relsym] = line[i]; poolpos++; } strpool[poolpos - relsym] = pooldel; return Result;}static boolean poolfit(pos, lim)inbufptr pos, lim;{ /* check to see if text between pos and lim will fit in stringpool */ /* poolfit */ return (poolsp - poolpos > lim - pos);}static boolean poolcmp(poolpos, pos, lim)poolref poolpos;inbufptr pos, lim;{ /* compare the string starting at poolpos in the stringpool with that between pos and lim on the current line, return true if they are the same; this relies on the fact that the string delimiter in the stringpool will never occur in the line */ while (strpool[poolpos - relsym] == line[pos - 1]) { poolpos++; pos++; } return (strpool[poolpos - relsym] == pooldel && pos == lim);}static long hash_(pos, lim, modulus)inbufptr pos, lim;long modulus;{ /* compute hash of lexeme between pos and lim, return a value between 1 and modulus (inclusive) this hash function must match that in "opinit" */ long acc; inbufptr p; /* hash */ acc = 1; for (p = pos - 1; p <= lim - 2; p++) { acc = (acc * 5 + line[p]) % modulus + 1; } return acc;}static symptr lookup(pos, lim)inbufptr pos, lim;{ /* find the symbol between pos and lim on the current line in the symbol table, return the index into the table where it was found or inserted; if it could not be inserted, return zero */ symptr Result, s, olds; association *WITH; /* lookup */ s = hash_(pos, lim, (long)symsize); olds = s; Result = 0; /* default return value */ do { WITH = &symtab[s - 1]; if (WITH->id != 0) { /* with */ if (poolcmp(WITH->id, pos, lim)) { Result = s; s = olds; /* terminate loop */ } else { if (s < symsize) s++; else s = 1; if (s == olds) symfull = true; } } else { /* found unused table entry */ if (poolfit(pos, lim)) { /* put the symbol in the pool and table */ WITH->id = putpool_(pos, lim); Result = s; } else /* no room in pool for sym */ poolfull = true; s = olds; /* terminate loop */ } } while (s != olds); return Result;}static void symdump(){ /* dump entire contents of symbol table */ symptr i; association *WITH; for (i = 0; i < symsize; i++) { WITH = &symtab[i]; if (WITH->id != 0) { /* have nonblank entry */ writesym(dmp, WITH->id); putc('=', dmp); putc('\t', dmp); /* sort field delimiter */ /* could use following */ /* genval(..., 4L, WITH->val.offset, WITH->val.base);*/ /* instead, we do it locally to get sortable format */ if (WITH->val.base != abssym) { if (WITH->val.base = relsym) { fputs("REL(0)", dmp); } else { writesym(dmp, WITH->val.base); } putc('+', dmp); } putc('\t', dmp); putc('#', dmp); writehex(dmp, WITH->val.offset, 8); putc('\n', dmp); } }}static opptr oplookup(pos, lim)inbufptr pos, lim;{ /* find the symbol between pos and lim on the current line in the opcode table, return the index into the table where it was found or should be put; return 0 if it isn't found and the table is full */ opptr Result, s, olds; _REC_optab *WITH; s = hash_(pos, lim, (long)opcodes); olds = s; Result = 0; /* default return value */ do { WITH = &optab[s - 1]; if (WITH->id != 0) /* with */ { /* have nonblank entry */ if (poolcmp(WITH->id, pos, lim)) { /* found it */ Result = s; s = olds; /* terminate loop */ } else { if (s < opcodes) s++; else s = 1; } } else { /* found vacancy */ Result = s; s = olds; /* terminate loop */ } } while (s != olds); return Result;}/* inside smal32.onepass, utility parsing procedures */static void getcomma(){ /* skip the comma, complain if there isn't one */ if (lex.typ == comma) nextlex(); else errmsg(comexp, lex.pos, lex.lim);}static void skipbal(){ /* skip to maching end paren when given begin paren */ long nest; lexeme par;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -