#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,}; voidlexinit(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);} intcmap(int c){ if(c<0) return 0; if(c<256) return map[c]; return Mlower;} voidlexstart(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 intGetc(void){ int c; if(ineof) return Beof; c = BGETC(bin); if(c == Beof) ineof = 1; linepos++; return c;} static voidunGetc(void){ if(ineof) return; Bungetc(bin); linepos--;} static intgetrune(void){ int c; if(ineof) return Beof; c = Bgetrune(bin); if(c == Beof) ineof = 1; linepos++; return c;} static voidungetrune(void){ if(ineof) return; Bungetrune(bin); linepos--;} voidaddinclude(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;} intaddfile(File *f){ if(nfiles >= lenfiles){ lenfiles = nfiles+32; files = reallocmem(files, lenfiles*sizeof(File*)); } files[nfiles] = f; return nfiles++;} voidincludef(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 voidpopinclude(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 */Flinefline(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 intlexcom(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;} Linecurline(void){ Line line; line.line = lineno; line.pos = linepos; return line;} intlineconv(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);} intsrcconv(Fmt *f){ Src src;Lines 1–500 of 1430. Load more
#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;