📄 cc2.c
字号:
/*** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix** Copyright 1998 H T Walheim** All rights reserved.*/#include <stdio.h>#include "cc.h"extern char*symtab, *macn, *macq, *pline, *mline, optimize, alarm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3, *locptr, msname[NAMESIZE], pause, quote[2];extern int*wq, ccode, ch, csp, eof, errflag, iflevel, input, input2, listfp, macptr, nch, nxtlab, op[16], opindex, opsize, output, pptr, skiplevel, *wqptr;/********************** input functions **********************/preprocess(){ int k; char c; if (ccode) { line = mline; ifline(); if (eof) return; } else { zinline(); return; } pptr = -1; while (ch != NEWLINE && ch) { if (white()) { keepch(' '); while (white()) gch(); } else if (ch == '"') { keepch(ch); gch(); while (ch != '"' || (*(lptr - 1) == 92 && *(lptr - 2) != 92)) { if (ch == NULL) { error("no quote"); break; } keepch(gch()); } gch(); keepch('"'); } else if (ch == 39) { keepch(39); gch(); while (ch != 39 || (*(lptr - 1) == 92 && *(lptr - 2) != 92)) { if (ch == NULL) { error("no apostrophe"); break; } keepch(gch()); } gch(); keepch(39); } else if (ch == '/' && nch == '*') { bump(2); while ((ch == '*' && nch == '/') == 0) { if (ch) bump(1); else { ifline(); if (eof) break; } } bump(2); } else if (ch == '/' && nch == '/') { bump(2); while (ch != NEWLINE) { if (ch) bump(1); else { if (eof) break; } } bump(1); } else if (an(ch)) { k = 0; while (an(ch) && k < NAMEMAX) { msname[k++] = ch; gch(); } msname[k] = NULL; if (search(msname, macn, NAMESIZE + 2, MACNEND, MACNBR, 0)) { k = getint(cptr + NAMESIZE, 2 /*INTSIZE*/); while (c = macq[k++]) keepch(c); while (an(ch)) gch(); } else { k = 0; while (c = msname[k++]) keepch(c); } } else keepch(gch()); } if (pptr >= LINEMAX) error("line too long"); keepch(NULL); line = pline; bump(0);}keepch(c)char c;{ if (pptr < LINEMAX) pline[++pptr] = c;}ifline(){ while (1) { zinline(); if (eof) return; if (match("#ifdef")) { ++iflevel; if (skiplevel) continue; symname(msname); if (search(msname, macn, NAMESIZE + 2, MACNEND, MACNBR, 0) == 0) skiplevel = iflevel; continue; } if (match("#ifndef")) { ++iflevel; if (skiplevel) continue; symname(msname); if (search(msname, macn, NAMESIZE + 2, MACNEND, MACNBR, 0)) skiplevel = iflevel; continue; } if (match("#else")) { if (iflevel) { if (skiplevel == iflevel) skiplevel = 0; else if (skiplevel == 0) skiplevel = iflevel; } else noiferr(); continue; } if (match("#endif")) { if (iflevel) { if (skiplevel == iflevel) skiplevel = 0; --iflevel; } else noiferr(); continue; } if (skiplevel) continue; if (ch == 0) continue; break; }}zinline(){ /* numerous revisions */ int k, unit; if (input == EOF) openfile(); if (eof) return; if ((unit = input2) == EOF) unit = input; if (fgets(line, LINEMAX, unit) == NULL) { fclose(unit); if (input2 != EOF) input2 = EOF; else input = EOF; *line = NULL; } else if (listfp) { if (listfp == output) fputc(';', output); fputs(line, listfp); }#ifdef __GNUC__ else { fputc(';', output); fputs(line, output); }#endif bump(0);}inbyte(){ while (ch == 0) { if (eof) return 0; preprocess(); } return gch();}/********************* scanning functions ********************//*** test if next input string is legal symbol name*/symname(sname)char *sname;{ int k; char c; blanks(); if (alpha(ch) == 0) return (*sname = 0); k = 0; while (an(ch)) { sname[k] = gch(); if (k < NAMEMAX) ++k; } sname[k] = 0; return 1;}need(str)char *str;{ if (match(str) == 0) error("missing token");}ns(){ if (match(";") == 0) error("no semicolon"); else errflag = 0;}match(lit)char *lit;{ int k; blanks(); if (k = streq(lptr, lit)) { bump(k); return 1; } return 0;}streq(str1, str2)char str1[], str2[];{ int k; k = 0; while (str2[k]) { if (str1[k] != str2[k]) return 0; ++k; } return k;}amatch(lit, len)char *lit;int len;{ int k; blanks(); if (k = astreq(lptr, lit, len)) { bump(k); return 1; } return 0;}astreq(str1, str2, len)char str1[], str2[];int len;{ int k; k = 0; while (k < len) { if (str1[k] != str2[k]) break; /* ** must detect end of symbol table names terminated by ** symbol length in binary */ if (str2[k] < ' ') break; if (str1[k] < ' ') break; ++k; } if (an(str1[k]) || an(str2[k])) return 0; return k;}nextop(list)char *list;{ char op[4]; opindex = 0; blanks(); while (1) { opsize = 0; while (*list > ' ') op[opsize++] = *list++; op[opsize] = 0; if (opsize = streq(lptr, op)) if (*(lptr + opsize) != '=' && *(lptr + opsize) != *(lptr + opsize - 1)) return 1; if (*list) { ++list; ++opindex; } else return 0; }}blanks(){ while (1) { while (ch) { if (white()) gch(); else return; } if (line == mline) return; preprocess(); if (eof) break; }}white(){ return (*lptr <= ' ' && *lptr);}gch(){ int c; if (c = ch) bump(1); return c;}bump(n)int n;{ if (n) lptr += n; else lptr = line; if (ch = nch = *lptr) nch = *(lptr + 1);}kill(){ *line = 0; bump(0);}skip(){ if (an(inbyte())) while (an(ch)) gch(); else while (an(ch) == 0) { if (ch == 0) break; gch(); } blanks();}endst(){ blanks(); return (streq(lptr, ";") || ch == 0);}/*********** symbol table management functions ***********/addsym(sname, id, type, size, value, lgpp, class)char *sname, id, type;int size, value, *lgpp, class;{ if (lgpp == &glbptr) { if (cptr2 = findglb(sname)) return cptr2; if (cptr == 0) { error("global symbol table overflow"); return 0; } } else { if (locptr > (ENDLOC - SYMMAX)) { error("local symbol table overflow"); exit(ERRCODE); } cptr = *lgpp; } cptr[IDENT] = id; cptr[TYPE] = type; cptr[CLASS] = class; putint(size, cptr + SIZE, INTSIZE); putint(value, cptr + OFFSET, INTSIZE); cptr3 = cptr2 = cptr + NAME; while (an(*sname)) *cptr2++ = *sname++; if (lgpp == &locptr) { *cptr2 = cptr2 - cptr3; /* set length */ *lgpp = ++cptr2; } return cptr;}/*** search for symbol match** on return cptr points to slot found or empty slot*/search(sname, buf, len, end, max, off)char *sname, *buf, *end;int len, max, off;{ cptr = cptr2 = buf + ((hash(sname) % (max - 1)) * len); while (*cptr != NULL) { if (astreq(sname, cptr + off, NAMEMAX)) return 1; if ((cptr = cptr + len) >= end) cptr = buf; if (cptr == cptr2) return (cptr = 0); } return 0;}hash(sname)char *sname;{ int i, c; i = 0; while (c = *sname++) i = (i << 1) + c; return i;}findglb(sname)char *sname;{ if (search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME)) return cptr; return 0;}findloc(sname)char *sname;{ cptr = locptr - 1; /* search backward for block locals */ while (cptr > STARTLOC) { cptr = cptr - *cptr; if (astreq(sname, cptr, NAMEMAX)) return (cptr - NAME); cptr = cptr - NAME - 1; } return 0;}nextsym(entry)char *entry;{ entry = entry + NAME; while (*entry++ >= ' '); /* find length byte */ return entry;}/******** while queue management functions *********/addwhile(ptr)int ptr[];{ int k; ptr[WQSP] = csp; /* and stk ptr */ ptr[WQLOOP] = getlabel(); /* and looping label */ ptr[WQEXIT] = getlabel(); /* and exit label */ if (wqptr == WQMAX) { error("control statement nesting limit"); exit(ERRCODE); } k = 0; while (k < WQSIZ) *wqptr++ = ptr[k++];}readwhile(ptr)int *ptr;{ if (ptr <= wq) { error("out of context"); return 0; } else return (ptr - WQSIZ);}delwhile(){ if (wqptr > wq) wqptr -= WQSIZ;}/****************** utility functions ********************//*** test if c is alphabetic*/alpha(c)char c;{ return (isalpha(c) || c == '_');}/*** test if given character is alphanumeric*/an(c)char c;{ return (alpha(c) || isdigit(c));}/*** return next avail internal label number*/getlabel(){ return (nxtlab++);}/*** get integer of length len from address addr** (byte sequence set by "putint")*/getint(addr, len)char *addr;int len;{ int i; i = *(addr + --len); /* high order byte sign extended */ while (len--) i = (i << 8) | *(addr + len) & 255; return i;}/*** put integer i of length len into address addr** (low byte first)*/putint(i, addr, len)char *addr;int i, len;{ while (len--) { *addr++ = i; i = i >> 8; }}lout(line, fd)char *line;int fd;{ fputs(line, fd); fputc(NEWLINE, fd);}/******************* error functions *********************/illname(){ error("illegal symbol"); skip();}multidef(sname)char *sname;{ error("already defined");}needlval(){ error("must be lvalue");}noiferr(){ error("no matching #if..."); errflag = 0;}error(msg)char msg[];{ if (errflag) return; else errflag = 1; lout(line, stderr); errout(msg, stderr); if (alarm) fputc(7, stderr); if (pause) while (fgetc(stderr) != NEWLINE); if (listfp > 0) errout(msg, listfp);}errout(msg, fp)char msg[];int fp;{ int k; k = line + 2; while (k++ <= lptr) fputc(' ', fp); lout("/\\", fp); fputs("**** ", fp); lout(msg, fp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -