1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453 |
- #define Extern
- #include "limbo.h"
- #include "y.tab.h"
- enum
- {
- Leof = -1,
- Linestart = 0,
- Mlower = 1,
- Mupper = 2,
- Munder = 4,
- Malpha = Mupper|Mlower|Munder,
- Mdigit = 8,
- Msign = 16,
- Mexp = 32,
- Mhex = 64,
- Mradix = 128,
- HashSize = 1024,
- MaxPath = 4096
- };
- typedef struct Keywd Keywd;
- struct Keywd
- {
- char *name;
- int token;
- };
- File **files; /* files making up the module, sorted by absolute line */
- int nfiles;
- static int lenfiles;
- static int lastfile; /* index of last file looked up */
- static char *incpath[MaxIncPath];
- static Sym *symbols[HashSize];
- static Sym *strings[HashSize];
- static char map[256];
- static Biobuf *bin;
- static Line linestack[MaxInclude];
- static int lineno;
- static int linepos;
- static int bstack;
- static int ineof;
- static int lasttok;
- static YYSTYPE lastyylval;
- static char srcdir[MaxPath];
- static Keywd keywords[] =
- {
- "adt", Ladt,
- "alt", Lalt,
- "array", Larray,
- "big", Ltid,
- "break", Lbreak,
- "byte", Ltid,
- "case", Lcase,
- "chan", Lchan,
- "con", Lcon,
- "continue", Lcont,
- "cyclic", Lcyclic,
- "do", Ldo,
- "dynamic", Ldynamic,
- "else", Lelse,
- "exception", Lexcept,
- "exit", Lexit,
- "fixed", Lfix,
- "fn", Lfn,
- "for", Lfor,
- "hd", Lhd,
- "if", Lif,
- "implement", Limplement,
- "import", Limport,
- "include", Linclude,
- "int", Ltid,
- "len", Llen,
- "list", Llist,
- "load", Lload,
- "module", Lmodule,
- "nil", Lnil,
- "of", Lof,
- "or", Lor,
- "pick", Lpick,
- "raise", Lraise,
- "raises", Lraises,
- "real", Ltid,
- "ref", Lref,
- "return", Lreturn,
- "self", Lself,
- "spawn", Lspawn,
- "string", Ltid,
- "tagof", Ltagof,
- "tl", Ltl,
- "to", Lto,
- "type", Ltype,
- "while", Lwhile,
- 0,
- };
- static Keywd tokwords[] =
- {
- "&=", Landeq,
- "|=", Loreq,
- "^=", Lxoreq,
- "<<=", Llsheq,
- ">>=", Lrsheq,
- "+=", Laddeq,
- "-=", Lsubeq,
- "*=", Lmuleq,
- "/=", Ldiveq,
- "%=", Lmodeq,
- "**=", Lexpeq,
- ":=", Ldeclas,
- "||", Loror,
- "&&", Landand,
- "::", Lcons,
- "==", Leq,
- "!=", Lneq,
- "<=", Lleq,
- ">=", Lgeq,
- "<<", Llsh,
- ">>", Lrsh,
- "<-", Lcomm,
- "++", Linc,
- "--", Ldec,
- "->", Lmdot,
- "=>", Llabs,
- "**", Lexp,
- "EOF", Leof,
- "eof", Beof,
- 0,
- };
- void
- lexinit(void)
- {
- Keywd *k;
- int i;
- for(i = 0; i < 256; i++){
- if(i == '_' || i > 0xa0)
- map[i] |= Munder;
- if(i >= 'A' && i <= 'Z')
- map[i] |= Mupper;
- if(i >= 'a' && i <= 'z')
- map[i] |= Mlower;
- if(i >= 'A' && i <= 'F' || i >= 'a' && i <= 'f')
- map[i] |= Mhex;
- if(i == 'e' || i == 'E')
- map[i] |= Mexp;
- if(i == 'r' || i == 'R')
- map[i] |= Mradix;
- if(i == '-' || i == '+')
- map[i] |= Msign;
- if(i >= '0' && i <= '9')
- map[i] |= Mdigit;
- }
- memset(escmap, -1, sizeof(escmap));
- escmap['\''] = '\'';
- unescmap['\''] = '\'';
- escmap['"'] = '"';
- unescmap['"'] = '"';
- escmap['\\'] = '\\';
- unescmap['\\'] = '\\';
- escmap['a'] = '\a';
- unescmap['\a'] = 'a';
- escmap['b'] = '\b';
- unescmap['\b'] = 'b';
- escmap['f'] = '\f';
- unescmap['\f'] = 'f';
- escmap['n'] = '\n';
- unescmap['\n'] = 'n';
- escmap['r'] = '\r';
- unescmap['\r'] = 'r';
- escmap['t'] = '\t';
- unescmap['\t'] = 't';
- escmap['v'] = '\v';
- unescmap['\v'] = 'v';
- escmap['0'] = '\0';
- unescmap['\0'] = '0';
- for(k = keywords; k->name != nil; k++)
- enter(k->name, k->token);
- }
- int
- cmap(int c)
- {
- if(c<0)
- return 0;
- if(c<256)
- return map[c];
- return Mlower;
- }
- void
- lexstart(char *in)
- {
- char *p;
- ineof = 0;
- bstack = 0;
- nfiles = 0;
- lastfile = 0;
- addfile(mkfile(strdup(in), 1, 0, -1, nil, 0, -1));
- bin = bins[bstack];
- lineno = 1;
- linepos = Linestart;
- secpy(srcdir, srcdir+MaxPath, in);
- p = strrchr(srcdir, '/');
- if(p == nil)
- srcdir[0] = '\0';
- else
- p[1] = '\0';
- }
- static int
- Getc(void)
- {
- int c;
- if(ineof)
- return Beof;
- c = BGETC(bin);
- if(c == Beof)
- ineof = 1;
- linepos++;
- return c;
- }
- static void
- unGetc(void)
- {
- if(ineof)
- return;
- Bungetc(bin);
- linepos--;
- }
- static int
- getrune(void)
- {
- int c;
- if(ineof)
- return Beof;
- c = Bgetrune(bin);
- if(c == Beof)
- ineof = 1;
- linepos++;
- return c;
- }
- static void
- ungetrune(void)
- {
- if(ineof)
- return;
- Bungetrune(bin);
- linepos--;
- }
- void
- addinclude(char *s)
- {
- int i;
- for(i = 0; i < MaxIncPath; i++){
- if(incpath[i] == 0){
- incpath[i] = s;
- return;
- }
- }
- fatal("out of include path space");
- }
- File*
- mkfile(char *name, int abs, int off, int in, char *act, int actoff, int sbl)
- {
- File *f;
- f = allocmem(sizeof *f);
- f->name = name;
- f->abs = abs;
- f->off = off;
- f->in = in;
- f->act = act;
- f->actoff = actoff;
- f->sbl = sbl;
- return f;
- }
- int
- addfile(File *f)
- {
- if(nfiles >= lenfiles){
- lenfiles = nfiles+32;
- files = reallocmem(files, lenfiles*sizeof(File*));
- }
- files[nfiles] = f;
- return nfiles++;
- }
- void
- includef(Sym *file)
- {
- Biobuf *b;
- char *p, buf[MaxPath];
- int i;
- linestack[bstack].line = lineno;
- linestack[bstack].pos = linepos;
- bstack++;
- if(bstack >= MaxInclude)
- fatal("%L: include file depth too great", curline());
- p = "";
- if(file->name[0] != '/')
- p = srcdir;
- seprint(buf, buf+sizeof(buf), "%s%s", p, file->name);
- b = Bopen(buf, OREAD);
- for(i = 0; b == nil && i < MaxIncPath && incpath[i] != nil && file->name[0] != '/'; i++){
- seprint(buf, buf+sizeof(buf), "%s/%s", incpath[i], file->name);
- b = Bopen(buf, OREAD);
- }
- bins[bstack] = b;
- if(bins[bstack] == nil){
- yyerror("can't include %s: %r", file->name);
- bstack--;
- }else{
- addfile(mkfile(strdup(buf), lineno+1, -lineno, lineno, nil, 0, -1));
- lineno++;
- linepos = Linestart;
- }
- bin = bins[bstack];
- }
- /*
- * we hit eof in the current file
- * revert to the file which included it.
- */
- static void
- popinclude(void)
- {
- Fline fl;
- File *f;
- int oline, opos, ln;
- ineof = 0;
- bstack--;
- bin = bins[bstack];
- oline = linestack[bstack].line;
- opos = linestack[bstack].pos;
- fl = fline(oline);
- f = fl.file;
- ln = fl.line;
- lineno++;
- linepos = opos;
- addfile(mkfile(f->name, lineno, ln-lineno, f->in, f->act, f->actoff, -1));
- }
- /*
- * convert an absolute Line into a file and line within the file
- */
- Fline
- fline(int absline)
- {
- Fline fl;
- int l, r, m, s;
- if(absline < files[lastfile]->abs
- || lastfile+1 < nfiles && absline >= files[lastfile+1]->abs){
- lastfile = 0;
- l = 0;
- r = nfiles - 1;
- while(l <= r){
- m = (r + l) / 2;
- s = files[m]->abs;
- if(s <= absline){
- l = m + 1;
- lastfile = m;
- }else
- r = m - 1;
- }
- }
- fl.file = files[lastfile];
- fl.line = absline + files[lastfile]->off;
- return fl;
- }
- /*
- * read a comment
- */
- static int
- lexcom(void)
- {
- File *f;
- char buf[StrSize], *s, *t, *act;
- int i, n, c, actline;
- i = 0;
- while((c = Getc()) != '\n'){
- if(c == Beof)
- return -1;
- if(i < sizeof(buf)-1)
- buf[i++] = c;
- }
- buf[i] = 0;
- lineno++;
- linepos = Linestart;
- if(strncmp(buf, "line ", 5) != 0 && strncmp(buf, "line\t", 5) != 0)
- return 0;
- for(s = buf+5; *s == ' ' || *s == '\t'; s++)
- ;
- if(!(cmap(*s) & Mdigit))
- return 0;
- n = 0;
- for(; cmap(c = *s) & Mdigit; s++)
- n = n * 10 + c - '0';
- for(; *s == ' ' || *s == '\t'; s++)
- ;
- if(*s != '"')
- return 0;
- s++;
- t = strchr(s, '"');
- if(t == nil || t[1] != '\0')
- return 0;
- *t = '\0';
- f = files[nfiles - 1];
- if(n == f->off+lineno && strcmp(s, f->name) == 0)
- return 1;
- act = f->name;
- actline = lineno + f->off;
- if(f->act != nil){
- actline += f->actoff;
- act = f->act;
- }
- addfile(mkfile(strdup(s), lineno, n-lineno, f->in, act, actline - n, -1));
- return 1;
- }
- Line
- curline(void)
- {
- Line line;
- line.line = lineno;
- line.pos = linepos;
- return line;
- }
- int
- lineconv(Fmt *f)
- {
- Fline fl;
- File *file;
- Line inl, line;
- char buf[StrSize], *s;
- line = va_arg(f->args, Line);
- if(line.line < 0)
- return fmtstrcpy(f, "<noline>");
- fl = fline(line.line);
- file = fl.file;
- s = seprint(buf, buf+sizeof(buf), "%s:%d", file->name, fl.line);
- if(file->act != nil)
- s = seprint(s, buf+sizeof(buf), " [ %s:%d ]", file->act, file->actoff+fl.line);
- if(file->in >= 0){
- inl.line = file->in;
- inl.pos = 0;
- seprint(s, buf+sizeof(buf), ": %L", inl);
- }
- return fmtstrcpy(f, buf);
- }
- static char*
- posconv(char *s, char *e, Line line)
- {
- Fline fl;
- if(line.line < 0)
- return secpy(s, e, "nopos");
- fl = fline(line.line);
- return seprint(s, e, "%s:%d.%d", fl.file->name, fl.line, line.pos);
- }
- int
- srcconv(Fmt *f)
- {
- Src src;
- char buf[StrSize], *s;
- src = va_arg(f->args, Src);
- s = posconv(buf, buf+sizeof(buf), src.start);
- s = secpy(s, buf+sizeof(buf), ",");
- posconv(s, buf+sizeof(buf), src.stop);
- return fmtstrcpy(f, buf);
- }
- int
- lexid(int c)
- {
- Sym *sym;
- char id[StrSize*UTFmax+1], *p;
- Rune r;
- int i, t;
- p = id;
- i = 0;
- for(;;){
- if(i < StrSize){
- if(c < Runeself)
- *p++ = c;
- else{
- r = c;
- p += runetochar(p, &r);
- }
- i++;
- }
- c = getrune();
- if(c == Beof
- || !(cmap(c) & (Malpha|Mdigit))){
- ungetrune();
- break;
- }
- }
- *p = '\0';
- sym = enter(id, Lid);
- t = sym->token;
- if(t == Lid || t == Ltid)
- yylval.tok.v.idval = sym;
- return t;
- }
- Long
- strtoi(char *t, int base)
- {
- char *s;
- Long v;
- int c, neg, ck;
- neg = 0;
- if(t[0] == '-'){
- neg = 1;
- t++;
- }else if(t[0] == '+')
- t++;
- v = 0;
- for(s = t; c = *s; s++){
- ck = cmap(c);
- if(ck & Mdigit)
- c -= '0';
- else if(ck & Mlower)
- c = c - 'a' + 10;
- else if(ck & Mupper)
- c = c - 'A' + 10;
- if(c >= base){
- yyerror("digit '%c' not radix %d", *s, base);
- return -1;
- }
- v = v * base + c;
- }
- if(neg)
- return -v;
- return v;
- }
- static int
- digit(int c, int base)
- {
- int cc, ck;
- cc = c;
- ck = cmap(c);
- if(ck & Mdigit)
- c -= '0';
- else if(ck & Mlower)
- c = c - 'a' + 10;
- else if(ck & Mupper)
- c = c - 'A' + 10;
- else if(ck & Munder)
- {}
- else
- return -1;
- if(c >= base)
- yyerror("digit '%c' not radix %d", cc, base);
- return c;
- }
- double
- strtodb(char *t, int base)
- {
- double num, dem;
- int neg, eneg, dig, exp, c, d;
- num = 0;
- neg = 0;
- dig = 0;
- exp = 0;
- eneg = 0;
- c = *t++;
- if(c == '-' || c == '+'){
- if(c == '-')
- neg = 1;
- c = *t++;
- }
- while((d = digit(c, base)) >= 0){
- num = num*base + d;
- c = *t++;
- }
- if(c == '.')
- c = *t++;
- while((d = digit(c, base)) >= 0){
- num = num*base + d;
- dig++;
- c = *t++;
- }
- if(c == 'e' || c == 'E'){
- c = *t++;
- if(c == '-' || c == '+'){
- if(c == '-'){
- dig = -dig;
- eneg = 1;
- }
- c = *t++;
- }
- while((d = digit(c, base)) >= 0){
- exp = exp*base + d;
- c = *t++;
- }
- }
- exp -= dig;
- if(exp < 0){
- exp = -exp;
- eneg = !eneg;
- }
- dem = rpow(base, exp);
- if(eneg)
- num /= dem;
- else
- num *= dem;
- if(neg)
- return -num;
- return num;
- }
- /*
- * parse a numeric identifier
- * format [0-9]+(r[0-9A-Za-z]+)?
- * or ([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][+-]?[0-9]+)?
- */
- int
- lexnum(int c)
- {
- char buf[StrSize], *base;
- enum { Int, Radix, RadixSeen, Frac, ExpSeen, ExpSignSeen, Exp, FracB } state;
- double d;
- Long v;
- int i, ck;
- i = 0;
- buf[i++] = c;
- state = Int;
- if(c == '.')
- state = Frac;
- base = nil;
- for(;;){
- c = Getc();
- if(c == Beof){
- yyerror("end of file in numeric constant");
- return Leof;
- }
- ck = cmap(c);
- switch(state){
- case Int:
- if(ck & Mdigit)
- break;
- if(ck & Mexp){
- state = ExpSeen;
- break;
- }
- if(ck & Mradix){
- base = &buf[i];
- state = RadixSeen;
- break;
- }
- if(c == '.'){
- state = Frac;
- break;
- }
- goto done;
- case RadixSeen:
- case Radix:
- if(ck & (Mdigit|Malpha)){
- state = Radix;
- break;
- }
- if(c == '.'){
- state = FracB;
- break;
- }
- goto done;
- case Frac:
- if(ck & Mdigit)
- break;
- if(ck & Mexp)
- state = ExpSeen;
- else
- goto done;
- break;
- case FracB:
- if(ck & (Mdigit|Malpha))
- break;
- goto done;
- case ExpSeen:
- if(ck & Msign){
- state = ExpSignSeen;
- break;
- }
- /* fall through */
- case ExpSignSeen:
- case Exp:
- if(ck & Mdigit){
- state = Exp;
- break;
- }
- goto done;
- }
- if(i < StrSize-1)
- buf[i++] = c;
- }
- done:
- buf[i] = 0;
- unGetc();
- switch(state){
- default:
- yyerror("malformed numerical constant '%s'", buf);
- yylval.tok.v.ival = 0;
- return Lconst;
- case Radix:
- *base++ = '\0';
- v = strtoi(buf, 10);
- if(v < 0)
- break;
- if(v < 2 || v > 36){
- yyerror("radix '%s' must be between 2 and 36", buf);
- break;
- }
- v = strtoi(base, v);
- break;
- case Int:
- v = strtoi(buf, 10);
- break;
- case Frac:
- case Exp:
- d = strtod(buf, nil);
- yylval.tok.v.rval = d;
- return Lrconst;
- case FracB:
- *base++ = '\0';
- v = strtoi(buf, 10);
- if(v < 0)
- break;
- if(v < 2 || v > 36){
- yyerror("radix '%s' must be between 2 and 36", buf);
- break;
- }
- d = strtodb(base, v);
- yylval.tok.v.rval = d;
- return Lrconst;
- }
- yylval.tok.v.ival = v;
- return Lconst;
- }
- int
- escchar(void)
- {
- char buf[4+1];
- int c, i;
- c = getrune();
- if(c == Beof)
- return Beof;
- if(c == 'u'){
- for(i = 0; i < 4; i++){
- c = getrune();
- if(c == Beof || !(cmap(c) & (Mdigit|Mhex))){
- yyerror("malformed \\u escape sequence");
- ungetrune();
- break;
- }
- buf[i] = c;
- }
- buf[i] = 0;
- return strtoul(buf, 0, 16);
- }
- if(c < 256 && (i = escmap[c]) >= 0)
- return i;
- yyerror("unrecognized escape \\%C", c);
- return c;
- }
- void
- lexstring(int israw)
- {
- char *str;
- int c, t, startlno;
- Rune r;
- int len, alloc;
- alloc = 32;
- len = 0;
- str = allocmem(alloc * sizeof(str));
- startlno = lineno;
- for(;;){
- c = getrune();
- if(israw){
- switch(c){
- case '`':
- yylval.tok.v.idval = enterstring(str, len);
- return;
- case '\n':
- lineno++;
- linepos = Linestart;
- break;
- case Beof:
- t = lineno;
- lineno = startlno;
- yyerror("end of file in raw string constant");
- lineno = t;
- yylval.tok.v.idval = enterstring(str, len);
- return;
- }
- }else{
- switch(c){
- case '\\':
- c = escchar();
- if(c != Beof)
- break;
- /* fall through */
- case Beof:
- yyerror("end of file in string constant");
- yylval.tok.v.idval = enterstring(str, len);
- return;
- case '\n':
- yyerror("newline in string constant");
- lineno++;
- linepos = Linestart;
- yylval.tok.v.idval = enterstring(str, len);
- return;
- case '"':
- yylval.tok.v.idval = enterstring(str, len);
- return;
- }
- }
- while(len+UTFmax+1 >= alloc){
- alloc += 32;
- str = reallocmem(str, alloc * sizeof(str));
- }
- r = c;
- len += runetochar(&str[len], &r);
- str[len] = '\0';
- }
- }
- static int
- lex(void)
- {
- int c;
- loop:
- yylval.tok.src.start.line = lineno;
- yylval.tok.src.start.pos = linepos;
- c = getrune(); /* ehg: outside switch() to avoid bug in VisualC++5.0 */
- switch(c){
- case Beof:
- Bterm(bin);
- if(bstack == 0)
- return Leof;
- popinclude();
- break;
- case '#':
- if(lexcom() < 0){
- Bterm(bin);
- if(bstack == 0)
- return Leof;
- popinclude();
- }
- break;
- case '\n':
- lineno++;
- linepos = Linestart;
- goto loop;
- case ' ':
- case '\t':
- case '\r':
- case '\v':
- case '\f':
- goto loop;
- case '"':
- lexstring(0);
- return Lsconst;
- case '`':
- lexstring(1);
- return Lsconst;
- case '\'':
- c = getrune();
- if(c == '\\')
- c = escchar();
- if(c == Beof){
- yyerror("end of file in character constant");
- return Beof;
- }else
- yylval.tok.v.ival = c;
- c = Getc();
- if(c != '\'') {
- yyerror("missing closing '");
- unGetc();
- }
- return Lconst;
- case '(':
- case ')':
- case '[':
- case ']':
- case '{':
- case '}':
- case ',':
- case ';':
- case '~':
- return c;
- case ':':
- c = Getc();
- if(c == ':')
- return Lcons;
- if(c == '=')
- return Ldeclas;
- unGetc();
- return ':';
- case '.':
- c = Getc();
- unGetc();
- if(c != Beof && (cmap(c) & Mdigit))
- return lexnum('.');
- return '.';
- case '|':
- c = Getc();
- if(c == '=')
- return Loreq;
- if(c == '|')
- return Loror;
- unGetc();
- return '|';
- case '&':
- c = Getc();
- if(c == '=')
- return Landeq;
- if(c == '&')
- return Landand;
- unGetc();
- return '&';
- case '^':
- c = Getc();
- if(c == '=')
- return Lxoreq;
- unGetc();
- return '^';
- case '*':
- c = Getc();
- if(c == '=')
- return Lmuleq;
- if(c == '*'){
- c = Getc();
- if(c == '=')
- return Lexpeq;
- unGetc();
- return Lexp;
- }
- unGetc();
- return '*';
- case '/':
- c = Getc();
- if(c == '=')
- return Ldiveq;
- unGetc();
- return '/';
- case '%':
- c = Getc();
- if(c == '=')
- return Lmodeq;
- unGetc();
- return '%';
- case '=':
- c = Getc();
- if(c == '=')
- return Leq;
- if(c == '>')
- return Llabs;
- unGetc();
- return '=';
- case '!':
- c = Getc();
- if(c == '=')
- return Lneq;
- unGetc();
- return '!';
- case '>':
- c = Getc();
- if(c == '=')
- return Lgeq;
- if(c == '>'){
- c = Getc();
- if(c == '=')
- return Lrsheq;
- unGetc();
- return Lrsh;
- }
- unGetc();
- return '>';
- case '<':
- c = Getc();
- if(c == '=')
- return Lleq;
- if(c == '-')
- return Lcomm;
- if(c == '<'){
- c = Getc();
- if(c == '=')
- return Llsheq;
- unGetc();
- return Llsh;
- }
- unGetc();
- return '<';
- case '+':
- c = Getc();
- if(c == '=')
- return Laddeq;
- if(c == '+')
- return Linc;
- unGetc();
- return '+';
- case '-':
- c = Getc();
- if(c == '=')
- return Lsubeq;
- if(c == '-')
- return Ldec;
- if(c == '>')
- return Lmdot;
- unGetc();
- return '-';
- case '1': case '2': case '3': case '4': case '5':
- case '0': case '6': case '7': case '8': case '9':
- return lexnum(c);
- default:
- if(cmap(c) & Malpha)
- return lexid(c);
- yyerror("unknown character %c", c);
- break;
- }
- goto loop;
- }
- int
- yylex(void)
- {
- int t;
- t = lex();
- yylval.tok.src.stop.line = lineno;
- yylval.tok.src.stop.pos = linepos;
- lasttok = t;
- lastyylval = yylval;
- return t;
- }
- static char*
- toksp(int t)
- {
- Keywd *k;
- static char buf[256];
- switch(t){
- case Lconst:
- snprint(buf, sizeof(buf), "%lld", lastyylval.tok.v.ival);
- return buf;
- case Lrconst:
- snprint(buf, sizeof(buf), "%f", lastyylval.tok.v.rval);
- return buf;
- case Lsconst:
- snprint(buf, sizeof(buf), "\"%s\"", lastyylval.tok.v.idval->name);
- return buf;
- case Ltid:
- case Lid:
- return lastyylval.tok.v.idval->name;
- }
- for(k = keywords; k->name != nil; k++)
- if(t == k->token)
- return k->name;
- for(k = tokwords; k->name != nil; k++)
- if(t == k->token)
- return k->name;
- if(t < 0 || t > 255)
- fatal("bad token %d in toksp()", t);
- buf[0] = t;
- buf[1] = '\0';
- return buf;
- }
- Sym*
- enterstring(char *str, int n)
- {
- Sym *s;
- char *p, *e;
- ulong h;
- int c, c0;
- e = str + n;
- h = 0;
- for(p = str; p < e; p++){
- c = *p;
- c ^= c << 6;
- h += (c << 11) ^ (c >> 1);
- c = *p;
- h ^= (c << 14) + (c << 7) + (c << 4) + c;
- }
- c0 = str[0];
- h %= HashSize;
- for(s = strings[h]; s != nil; s = s->next){
- if(s->name[0] == c0 && s->len == n && memcmp(s->name, str, n) == 0){
- free(str);
- return s;
- }
- }
- if(n == 0)
- return enter("", 0);
- s = allocmem(sizeof(Sym));
- memset(s, 0, sizeof(Sym));
- s->name = str;
- s->len = n;
- s->next = strings[h];
- strings[h] = s;
- return s;
- }
- int
- symcmp(Sym *s, Sym *t)
- {
- int n, c;
- n = s->len;
- if(n > t->len)
- n = t->len;
- c = memcmp(s->name, t->name, n);
- if(c == 0)
- return s->len - t->len;
- return c;
- }
- Sym*
- stringcat(Sym *s, Sym *t)
- {
- char *str;
- int n;
- n = s->len + t->len;
- str = allocmem(n+1);
- memmove(str, s->name, s->len);
- memmove(str+s->len, t->name, t->len);
- str[n] = '\0';
- return enterstring(str, n);
- }
- Sym*
- enter(char *name, int token)
- {
- Sym *s;
- char *p;
- ulong h;
- int c0, c, n;
- c0 = name[0];
- h = 0;
- for(p = name; c = *p; p++){
- c ^= c << 6;
- h += (c << 11) ^ (c >> 1);
- c = *p;
- h ^= (c << 14) + (c << 7) + (c << 4) + c;
- }
- n = p - name;
- h %= HashSize;
- for(s = symbols[h]; s != nil; s = s->next)
- if(s->name[0] == c0 && strcmp(s->name, name) == 0)
- return s;
- s = allocmem(sizeof(Sym));
- memset(s, 0, sizeof(Sym));
- s->hash = h;
- s->name = allocmem(n+1);
- memmove(s->name, name, n+1);
- if(token == 0)
- token = Lid;
- s->token = token;
- s->next = symbols[h];
- s->len = n;
- symbols[h] = s;
- return s;
- }
- char*
- stringpr(char *buf, char *end, Sym *sym)
- {
- char sb[30], *s, *p;
- int i, c, n;
- s = sym->name;
- n = sym->len;
- if(n > 10)
- n = 10;
- p = sb;
- *p++ = '"';
- for(i = 0; i < n; i++){
- c = s[i];
- switch(c){
- case '\\':
- case '"':
- case '\n':
- case '\r':
- case '\t':
- case '\b':
- case '\a':
- case '\v':
- case '\0':
- *p++ = '\\';
- *p++ = unescmap[c];
- break;
- default:
- *p++ = c;
- break;
- }
- }
- if(n != sym->len){
- *p++ = '.';
- *p++ = '.';
- *p++ = '.';
- }
- *p++ = '"';
- *p = 0;
- return secpy(buf, end, sb);
- }
- void
- warn(Line line, char *fmt, ...)
- {
- char buf[4096];
- va_list arg;
- if(errors || !dowarn)
- return;
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%L: warning: %s\n", line, buf);
- }
- void
- nwarn(Node *n, char *fmt, ...)
- {
- char buf[4096];
- va_list arg;
- if(errors || !dowarn)
- return;
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%L: warning: %s\n", n->src.start, buf);
- }
- void
- error(Line line, char *fmt, ...)
- {
- char buf[4096];
- va_list arg;
- errors++;
- if(errors >= maxerr){
- if(errors == maxerr)
- fprint(2, "too many errors, stopping\n");
- return;
- }
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%L: %s\n", line, buf);
- }
- void
- nerror(Node *n, char *fmt, ...)
- {
- char buf[4096];
- va_list arg;
- errors++;
- if(errors >= maxerr){
- if(errors == maxerr)
- fprint(2, "too many errors, stopping\n");
- return;
- }
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%L: %s\n", n->src.start, buf);
- }
- void
- yyerror(char *fmt, ...)
- {
- char buf[4096];
- va_list arg;
- errors++;
- if(errors >= maxerr){
- if(errors == maxerr)
- fprint(2, "too many errors, stopping\n");
- return;
- }
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- if(lasttok != 0)
- fprint(2, "%L: near ` %s ` : %s\n", curline(), toksp(lasttok), buf);
- else
- fprint(2, "%L: %s\n", curline(), buf);
- }
- void
- fatal(char *fmt, ...)
- {
- char buf[4096];
- va_list arg;
- if(errors == 0 || isfatal){
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "fatal limbo compiler error: %s\n", buf);
- }
- if(bout != nil)
- remove(outfile);
- if(bsym != nil)
- remove(symfile);
- if(isfatal)
- abort();
- exits(buf);
- }
- int
- gfltconv(Fmt *f)
- {
- double d;
- char buf[32];
- d = va_arg(f->args, double);
- g_fmt(buf, d, 'e');
- return fmtstrcpy(f, buf);
- }
- char*
- secpy(char *p, char *e, char *s)
- {
- int c;
- if(p == e){
- p[-1] = '\0';
- return p;
- }
- for(; c = *s; s++){
- *p++ = c;
- if(p == e){
- p[-1] = '\0';
- return p;
- }
- }
- *p = '\0';
- return p;
- }
- char*
- seprint(char *buf, char *end, char *fmt, ...)
- {
- va_list arg;
- if(buf == end)
- return buf;
- va_start(arg, fmt);
- buf = vseprint(buf, end, fmt, arg);
- va_end(arg);
- return buf;
- }
- void*
- allocmem(ulong n)
- {
- void *p;
- p = malloc(n);
- if(p == nil)
- fatal("out of memory");
- return p;
- }
- void*
- reallocmem(void *p, ulong n)
- {
- if(p == nil)
- p = malloc(n);
- else
- p = realloc(p, n);
- if(p == nil)
- fatal("out of memory");
- return p;
- }
|