Leof: con -1;Linestart: con 0; Mlower,Mupper,Munder,Mdigit,Msign,Mexp,Mhex,Mradix: con byte 1 << iota;Malpha: con Mupper|Mlower|Munder; HashSize: con 1024; Keywd: adt{ name: string; token: int;}; ## internals#savec: int;files: array of ref File; # files making up the module, sorted by absolute linenfiles: int;lastfile := 0; # index of last file looked upincpath := array[MaxIncPath] of string;symbols := array[HashSize] of ref Sym;strings := array[HashSize] of ref Sym;map := array[256] of byte;bins := array [MaxInclude] of ref Iobuf;bin: ref Iobuf;linestack := array[MaxInclude] of (int, int);lineno: int;linepos: int;bstack: int;lasttok: int;lastyylval: YYSTYPE;dowarn: int;maxerr: int;dosym: int;toterrors: int;fabort: int;srcdir: string;outfile: string;stderr: ref Sys->FD;dontinline: int; escmap := array[256] of{ '\'' => '\'', '"' => '"', '\\' => '\\', 'a' => '\a', 'b' => '\b', 'f' => '\f', 'n' => '\n', 'r' => '\r', 't' => '\t', 'v' => '\v', '0' => '\u0000', * => -1};unescmap := array[256] of { '\'' => '\'', '"' => '"', '\\' => '\\', '\a' => 'a', '\b' => 'b', '\f' => 'f', '\n' => 'n', '\r' => 'r', '\t' => 't', '\v' => 'v', '\u0000' => '0', * => 0}; keywords := array [] of{ Keywd("adt", Ladt), Keywd("alt", Lalt), Keywd("array", Larray), Keywd("big", Ltid), Keywd("break", Lbreak), Keywd("byte", Ltid), Keywd("case", Lcase), Keywd("chan", Lchan), Keywd("con", Lcon), Keywd("continue", Lcont), Keywd("cyclic", Lcyclic), Keywd("do", Ldo), Keywd("dynamic", Ldynamic), Keywd("else", Lelse), Keywd("exception", Lexcept), Keywd("exit", Lexit), Keywd("fixed", Lfix), Keywd("fn", Lfn), Keywd("for", Lfor), Keywd("hd", Lhd), Keywd("if", Lif), Keywd("implement", Limplement), Keywd("import", Limport), Keywd("include", Linclude), Keywd("int", Ltid), Keywd("len", Llen), Keywd("list", Llist), Keywd("load", Lload), Keywd("module", Lmodule), Keywd("nil", Lnil), Keywd("of", Lof), Keywd("or", Lor), Keywd("pick", Lpick), Keywd("raise", Lraise), Keywd("raises", Lraises), Keywd("real", Ltid), Keywd("ref", Lref), Keywd("return", Lreturn), Keywd("self", Lself), Keywd("spawn", Lspawn), Keywd("string", Ltid), Keywd("tagof", Ltagof), Keywd("tl", Ltl), Keywd("to", Lto), Keywd("type", Ltype), Keywd("while", Lwhile),}; tokwords := array[] of{ Keywd("&=", Landeq), Keywd("|=", Loreq), Keywd("^=", Lxoreq), Keywd("<<=", Llsheq), Keywd(">>=", Lrsheq), Keywd("+=", Laddeq), Keywd("-=", Lsubeq), Keywd("*=", Lmuleq), Keywd("/=", Ldiveq), Keywd("%=", Lmodeq), Keywd("**=", Lexpeq), Keywd(":=", Ldeclas), Keywd("||", Loror), Keywd("&&", Landand), Keywd("::", Lcons), Keywd("==", Leq), Keywd("!=", Lneq), Keywd("<=", Lleq), Keywd(">=", Lgeq), Keywd("<<", Llsh), Keywd(">>", Lrsh), Keywd("<-", Lcomm), Keywd("++", Linc), Keywd("--", Ldec), Keywd("->", Lmdot), Keywd("=>", Llabs), Keywd("**", Lexp), Keywd("EOF", Leof),}; lexinit(){ for(i := 0; i < 256; i++){ map[i] = byte 0; if(i == '_' || i > 16ra0) 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; } for(i = 0; i < len keywords; i++) enter(keywords[i].name, keywords[i].token);} cmap(c: int): byte{ if(c<0) return byte 0; if(c<256) return map[c]; return Mlower;} lexstart(in: string){ savec = 0; bstack = 0; nfiles = 0; addfile(ref File(in, 1, 0, -1, nil, 0, -1)); bin = bins[bstack]; lineno = 1; linepos = Linestart; (srcdir, nil) = str->splitr(in, "/");} getc(): int{ if(c := savec){ if(savec >= 0){ linepos++; savec = 0; } return c; } c = bin.getc(); if(c < 0){ savec = -1; return savec; } linepos++; return c;} ## dumps '\u0000' chararcters#ungetc(c: int){ if(c > 0) linepos--; savec = c;} addinclude(s: string){ for(i := 0; i < MaxIncPath; i++){ if(incpath[i] == nil){ incpath[i] = s; return; } } fatal("out of include path space");} addfile(f: ref File): int{ if(lastfile >= nfiles) lastfile = 0; if(nfiles >= len files){ nf := array[nfiles+32] of ref File; nf[0:] = files; files = nf; } files[nfiles] = f; return nfiles++;} ## include a new file#includef(file: ref Sym){ linestack[bstack] = (lineno, linepos); bstack++; if(bstack >= MaxInclude) fatal(lineconv(lineno<<PosBits)+": include file depth too great"); buf := file.name; if(buf[0] != '/') buf = srcdir+buf; b := bufio->open(buf, Bufio->OREAD); for(i := 0; b == nil && i < MaxIncPath && incpath[i] != nil && file.name[0] != '/'; i++){ buf = incpath[i] + "/" + file.name; b = bufio->open(buf, Bufio->OREAD); } bins[bstack] = b; if(bins[bstack] == nil){ yyerror("can't include "+file.name+": "+sprint("%r")); bstack--; }else{ addfile(ref File(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.#popinclude(){ savec = 0; bstack--; bin = bins[bstack]; (oline, opos) := linestack[bstack]; (f, ln) := fline(oline); lineno++; linepos = opos; addfile(ref File(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(absline: int): (ref File, int){ 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; } } return (files[lastfile], absline + files[lastfile].off);} ## read a comment; process #line file renamings#lexcom(): int{ i := 0; buf := ""; while((c := getc()) != '\n'){ if(c == Bufio->EOF) return -1; buf[i++] = c; } lineno++; linepos = Linestart; if(len buf < 6 || buf[len buf - 1] != '"' || buf[:5] != "line " && buf[:5] != "line\t") return 0; for(s := 5; buf[s] == ' ' || buf[s] == '\t'; s++) ; if((cmap(buf[s]) & Mdigit) == byte 0) return 0; n := 0; for(; (cmap(c = buf[s]) & Mdigit) != byte 0; s++) n = n * 10 + c - '0'; for(; buf[s] == ' ' || buf[s] == '\t'; s++) ; if(buf[s++] != '"') return 0; buf = buf[s:len buf - 1]; f := files[nfiles - 1]; if(n == f.off+lineno && buf == f.name) return 1; act := f.name; actline := lineno + f.off; if(f.act != nil){ actline += f.actoff; act = f.act; } addfile(ref File(buf, lineno, n-lineno, f.in, act, actline - n, -1)); return 1;} curline(): Line{ return (lineno << PosBits) | (linepos & PosMask);} lineconv(line: Line): string{ line >>= PosBits; if(line < 0) return "<noline>"; (f, ln) := fline(line); s := ""; if(f.in >= 0){ s = ": " + lineconv(f.in << PosBits); } if(f.act != nil) s = " [ " + f.act + ":" + string(f.actoff+ln) + " ]" + s; return f.name + ":" + string ln + s;} posconv(s: Line): string{ if(s < 0) return "nopos"; spos := s & PosMask; s >>= PosBits; (f, ln) := fline(s); return f.name + ":" + string ln + "." + string spos;} srcconv(src: Src): string{ s := posconv(src.start); s[len s] = ','; s += posconv(src.stop); return s;} lexid(c: int): int{ id := ""; i := 0; for(;;){ if(i < StrSize) id[i++] = c; c = getc(); if(c == Bufio->EOF || (cmap(c) & (Malpha|Mdigit)) == byte 0){ ungetc(c); break; } } sym := enter(id, Lid); t := sym.token; if(t == Lid || t == Ltid) yyctxt.lval.tok.v.idval = sym; return t;} maxfast := array[37] of{ 2 => 31, 4 => 15, 8 => 10, 10 => 9, 16 => 7, 32 => 6, * => 0,}; strtoi(t: string, bbase: big): big{ # # do the first part in ints # v := 0; bv: big; base := int bbase; n := maxfast[base]; neg := 0; i := 0; if(i < len t && t[i] == '-'){ neg = 1; i++; }else if(i < len t && t[i] == '+') i++; for(; i < len t; i++){ c := t[i]; if(c >= '0' && c <= '9') c -= '0'; else if(c >= 'a' && c <= 'z') c -= 'a' - 10; else c -= 'A' - 10; if(c >= base){ yyerror("digit '"+t[i:i+1]+"' is not radix "+string base); return big -1; } if(i < n) v = v * base + c; else{ if(i == n) bv = big v; bv = bv * bbase + big c; } } if(i <= n) bv = big v; if(neg) return -bv; return bv;} digit(c: int, base: int): int{ ck: byte; cc: int; cc = c;Lines 1–500 of 1178. Load more
Leof: con -1; Linestart: con 0; Mlower, Mupper, Munder, Mdigit, Msign, Mexp, Mhex, Mradix: con byte 1 << iota; Malpha: con Mupper|Mlower|Munder; HashSize: con 1024; Keywd: adt { name: string; token: int; }; # # internals # savec: int; files: array of ref File; # files making up the module, sorted by absolute line nfiles: int; lastfile := 0; # index of last file looked up incpath := array[MaxIncPath] of string; symbols := array[HashSize] of ref Sym; strings := array[HashSize] of ref Sym; map := array[256] of byte; bins := array [MaxInclude] of ref Iobuf; bin: ref Iobuf; linestack := array[MaxInclude] of (int, int); lineno: int; linepos: int; bstack: int; lasttok: int; lastyylval: YYSTYPE; dowarn: int; maxerr: int; dosym: int; toterrors: int; fabort: int; srcdir: string; outfile: string; stderr: ref Sys->FD; dontinline: int; escmap := array[256] of { '\'' => '\'', '"' => '"', '\\' => '\\', 'a' => '\a', 'b' => '\b', 'f' => '\f', 'n' => '\n', 'r' => '\r', 't' => '\t', 'v' => '\v', '0' => '\u0000', * => -1 }; unescmap := array[256] of { '\'' => '\'', '"' => '"', '\\' => '\\', '\a' => 'a', '\b' => 'b', '\f' => 'f', '\n' => 'n', '\r' => 'r', '\t' => 't', '\v' => 'v', '\u0000' => '0', * => 0 }; keywords := array [] of { Keywd("adt", Ladt), Keywd("alt", Lalt), Keywd("array", Larray), Keywd("big", Ltid), Keywd("break", Lbreak), Keywd("byte", Ltid), Keywd("case", Lcase), Keywd("chan", Lchan), Keywd("con", Lcon), Keywd("continue", Lcont), Keywd("cyclic", Lcyclic), Keywd("do", Ldo), Keywd("dynamic", Ldynamic), Keywd("else", Lelse), Keywd("exception", Lexcept), Keywd("exit", Lexit), Keywd("fixed", Lfix), Keywd("fn", Lfn), Keywd("for", Lfor), Keywd("hd", Lhd), Keywd("if", Lif), Keywd("implement", Limplement), Keywd("import", Limport), Keywd("include", Linclude), Keywd("int", Ltid), Keywd("len", Llen), Keywd("list", Llist), Keywd("load", Lload), Keywd("module", Lmodule), Keywd("nil", Lnil), Keywd("of", Lof), Keywd("or", Lor), Keywd("pick", Lpick), Keywd("raise", Lraise), Keywd("raises", Lraises), Keywd("real", Ltid), Keywd("ref", Lref), Keywd("return", Lreturn), Keywd("self", Lself), Keywd("spawn", Lspawn), Keywd("string", Ltid), Keywd("tagof", Ltagof), Keywd("tl", Ltl), Keywd("to", Lto), Keywd("type", Ltype), Keywd("while", Lwhile), }; tokwords := array[] of { Keywd("&=", Landeq), Keywd("|=", Loreq), Keywd("^=", Lxoreq), Keywd("<<=", Llsheq), Keywd(">>=", Lrsheq), Keywd("+=", Laddeq), Keywd("-=", Lsubeq), Keywd("*=", Lmuleq), Keywd("/=", Ldiveq), Keywd("%=", Lmodeq), Keywd("**=", Lexpeq), Keywd(":=", Ldeclas), Keywd("||", Loror), Keywd("&&", Landand), Keywd("::", Lcons), Keywd("==", Leq), Keywd("!=", Lneq), Keywd("<=", Lleq), Keywd(">=", Lgeq), Keywd("<<", Llsh), Keywd(">>", Lrsh), Keywd("<-", Lcomm), Keywd("++", Linc), Keywd("--", Ldec), Keywd("->", Lmdot), Keywd("=>", Llabs), Keywd("**", Lexp), Keywd("EOF", Leof), }; lexinit() { for(i := 0; i < 256; i++){ map[i] = byte 0; if(i == '_' || i > 16ra0) 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; } for(i = 0; i < len keywords; i++) enter(keywords[i].name, keywords[i].token); } cmap(c: int): byte { if(c<0) return byte 0; if(c<256) return map[c]; return Mlower; } lexstart(in: string) { savec = 0; bstack = 0; nfiles = 0; addfile(ref File(in, 1, 0, -1, nil, 0, -1)); bin = bins[bstack]; lineno = 1; linepos = Linestart; (srcdir, nil) = str->splitr(in, "/"); } getc(): int { if(c := savec){ if(savec >= 0){ linepos++; savec = 0; } return c; } c = bin.getc(); if(c < 0){ savec = -1; return savec; } linepos++; return c; } # # dumps '\u0000' chararcters # ungetc(c: int) { if(c > 0) linepos--; savec = c; } addinclude(s: string) { for(i := 0; i < MaxIncPath; i++){ if(incpath[i] == nil){ incpath[i] = s; return; } } fatal("out of include path space"); } addfile(f: ref File): int { if(lastfile >= nfiles) lastfile = 0; if(nfiles >= len files){ nf := array[nfiles+32] of ref File; nf[0:] = files; files = nf; } files[nfiles] = f; return nfiles++; } # # include a new file # includef(file: ref Sym) { linestack[bstack] = (lineno, linepos); bstack++; if(bstack >= MaxInclude) fatal(lineconv(lineno<<PosBits)+": include file depth too great"); buf := file.name; if(buf[0] != '/') buf = srcdir+buf; b := bufio->open(buf, Bufio->OREAD); for(i := 0; b == nil && i < MaxIncPath && incpath[i] != nil && file.name[0] != '/'; i++){ buf = incpath[i] + "/" + file.name; b = bufio->open(buf, Bufio->OREAD); } bins[bstack] = b; if(bins[bstack] == nil){ yyerror("can't include "+file.name+": "+sprint("%r")); bstack--; }else{ addfile(ref File(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. # popinclude() { savec = 0; bstack--; bin = bins[bstack]; (oline, opos) := linestack[bstack]; (f, ln) := fline(oline); lineno++; linepos = opos; addfile(ref File(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(absline: int): (ref File, int) { 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; } } return (files[lastfile], absline + files[lastfile].off); } # # read a comment; process #line file renamings # lexcom(): int { i := 0; buf := ""; while((c := getc()) != '\n'){ if(c == Bufio->EOF) return -1; buf[i++] = c; } lineno++; linepos = Linestart; if(len buf < 6 || buf[len buf - 1] != '"' || buf[:5] != "line " && buf[:5] != "line\t") return 0; for(s := 5; buf[s] == ' ' || buf[s] == '\t'; s++) ; if((cmap(buf[s]) & Mdigit) == byte 0) return 0; n := 0; for(; (cmap(c = buf[s]) & Mdigit) != byte 0; s++) n = n * 10 + c - '0'; for(; buf[s] == ' ' || buf[s] == '\t'; s++) ; if(buf[s++] != '"') return 0; buf = buf[s:len buf - 1]; f := files[nfiles - 1]; if(n == f.off+lineno && buf == f.name) return 1; act := f.name; actline := lineno + f.off; if(f.act != nil){ actline += f.actoff; act = f.act; } addfile(ref File(buf, lineno, n-lineno, f.in, act, actline - n, -1)); return 1; } curline(): Line { return (lineno << PosBits) | (linepos & PosMask); } lineconv(line: Line): string { line >>= PosBits; if(line < 0) return "<noline>"; (f, ln) := fline(line); s := ""; if(f.in >= 0){ s = ": " + lineconv(f.in << PosBits); } if(f.act != nil) s = " [ " + f.act + ":" + string(f.actoff+ln) + " ]" + s; return f.name + ":" + string ln + s; } posconv(s: Line): string { if(s < 0) return "nopos"; spos := s & PosMask; s >>= PosBits; (f, ln) := fline(s); return f.name + ":" + string ln + "." + string spos; } srcconv(src: Src): string { s := posconv(src.start); s[len s] = ','; s += posconv(src.stop); return s; } lexid(c: int): int { id := ""; i := 0; for(;;){ if(i < StrSize) id[i++] = c; c = getc(); if(c == Bufio->EOF || (cmap(c) & (Malpha|Mdigit)) == byte 0){ ungetc(c); break; } } sym := enter(id, Lid); t := sym.token; if(t == Lid || t == Ltid) yyctxt.lval.tok.v.idval = sym; return t; } maxfast := array[37] of { 2 => 31, 4 => 15, 8 => 10, 10 => 9, 16 => 7, 32 => 6, * => 0, }; strtoi(t: string, bbase: big): big { # # do the first part in ints # v := 0; bv: big; base := int bbase; n := maxfast[base]; neg := 0; i := 0; if(i < len t && t[i] == '-'){ neg = 1; i++; }else if(i < len t && t[i] == '+') i++; for(; i < len t; i++){ c := t[i]; if(c >= '0' && c <= '9') c -= '0'; else if(c >= 'a' && c <= 'z') c -= 'a' - 10; else c -= 'A' - 10; if(c >= base){ yyerror("digit '"+t[i:i+1]+"' is not radix "+string base); return big -1; } if(i < n) v = v * base + c; else{ if(i == n) bv = big v; bv = bv * bbase + big c; } } if(i <= n) bv = big v; if(neg) return -bv; return bv; } digit(c: int, base: int): int { ck: byte; cc: int; cc = c;