# # initially generated by c2l # implement Mk; include "draw.m"; Mk: module { init: fn(nil: ref Draw->Context, argl: list of string); }; include "sys.m"; sys: Sys; include "bufio.m"; bufio: Bufio; Iobuf: import bufio; include "libc0.m"; libc0: Libc0; include "math.m"; math: Math; include "regex.m"; regex: Regex; include "ar.m"; ARMAG, SARMAG, ARFMAG, SARNAME, ar_hdr, SAR_HDR: import Ar; include "daytime.m"; daytime: Daytime; include "sh.m"; init(nil: ref Draw->Context, argl: list of string) { sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; libc0 = load Libc0 Libc0->PATH; math = load Math Math->PATH; regex = load Regex Regex->PATH; daytime = load Daytime Daytime->PATH; main(len argl, libc0->ls2aab(argl)); } NAMELEN: con 28; ERRLEN: con 64; PNPROC, PNGROUP : con iota; # function pointer enum for symtraverse ECOPY, PRINT1: con iota; Bufblock: adt{ next: cyclic ref Bufblock; start: array of byte; end: int; current: int; }; Word: adt{ s: array of byte; next: cyclic ref Word; }; Envy: adt{ name: array of byte; values: ref Word; }; Resub: adt{ sp: array of byte; ep: array of byte; }; Rule: adt{ target: array of byte; # one target tail: ref Word; # constituents of targets recipe: array of byte; # do it ! attr: int; # attributes line: int; # source line file: array of byte; # source file alltargets: ref Word; # all the targets rule: int; # rule number pat: Regex->Re; # reg exp goo prog: array of byte; # to use in out of date chain: cyclic ref Rule; # hashed per target next: cyclic ref Rule; }; # Rule.attr META, SEQ, UPD, QUIET, VIR, REGEXP, NOREC, DEL, NOVIRT: con 1< value , S_TARGET # target -> rule , S_TIME # file -> time , S_PID # pid -> products , S_NODE # target name -> node , S_AGG # aggregate -> time , S_BITCH # bitched about aggregate not there , S_NOEXPORT # var -> noexport , S_OVERRIDE # can't override , S_OUTOFDATE # n1\377n2 -> 2(outofdate) or 1(not outofdate) , S_MAKEFILE # target -> node , S_MAKEVAR # dumpable mk variable , S_EXPORTED # var -> current exported value , S_BULKED # we have bulked this dir , S_WESET # variable; we set in the mkfile # an internal mk variable (e.g., stem, target) , S_INTERNAL: con iota; NAMEBLOCK: con 1000; BIGBLOCK: con 20000; D_PARSE, D_GRAPH, D_EXEC: con 1<FD = sys->fildes(-1); tb: ref Iobuf; buf, whatif: ref Bufblock; # # * start with a copy of the current environment variables # * instead of sharing them # bout = bufio->fopen(sys->fildes(1), Sys->OWRITE); buf = newbuf(); whatif = nil; if(argc) ; for(argv = argv[1: ]; argv[0] != nil && argv[0][0] == byte '-'; argv = argv[1: ]){ bufcpy(buf, argv[0], libc0->strlen(argv[0])); insert(buf, ' '); case(int argv[0][1]){ 'a' => aflag = 1; 'd' => if(int (s = argv[0][2: ])[0]) while(int s[0]){ case(int s[0]){ 'p' => debug |= D_PARSE; 'g' => debug |= D_GRAPH; 'e' => debug |= D_EXEC; } s = s[1: ]; } else debug = 16rffff; 'e' => explain = argv[0][2: ]; 'f' => argv = argv[1: ]; if(argv[0] == nil) badusage(); f[0] = argv[0]; f = f[1: ]; bufcpy(buf, argv[0], libc0->strlen(argv[0])); insert(buf, ' '); 'i' => iflag = 1; 'k' => kflag = 1; 'n' => nflag = 1; 's' => sflag = 1; 't' => tflag = 1; 'u' => uflag = 1; 'w' => if(whatif == nil) whatif = newbuf(); else insert(whatif, ' '); if(int argv[0][2]) bufcpy(whatif, argv[0][2: ], libc0->strlen(argv[0][2: ])); else{ argv = argv[1: ]; if(argv[0] == nil) badusage(); bufcpy(whatif, argv[0][0: ], libc0->strlen(argv[0][0: ])); } * => badusage(); } } if(aflag) iflag = 1; usage(); syminit(); initenv(); initbind(); openwait(); usage(); # # assignment args become null strings # temp = nil; for(i = 0; argv[i] != nil; i++) if(libc0->strchr(argv[i], '=') != nil){ bufcpy(buf, argv[i], libc0->strlen(argv[i])); insert(buf, ' '); if(tfd == nil){ temp = maketmp(); if(temp == nil){ perrors("temp file"); Exit(); } sys->create(libc0->ab2s(temp), Sys->OWRITE, 8r600); if((tfd = sys->open(libc0->ab2s(temp), 2)) == nil){ perror(temp); Exit(); } tb = bufio->fopen(tfd, Sys->OWRITE); } tb.puts(sys->sprint("%s\n", libc0->ab2s(argv[i]))); argv[i][0] = byte 0; } if(tfd != nil){ tb.flush(); sys->seek(tfd, 0, 0); parse(libc0->s2ab("command line args"), tfd, 1); sys->remove(libc0->ab2s(temp)); } if(buf.current != 0){ buf.current--; insert(buf, 0); } symlookw(libc0->s2ab("MKFLAGS"), S_VAR, stow(buf.start)); buf.current = 0; for(i = 0; argv[i] != nil; i++){ if(argv[i][0] == byte 0) continue; if(i) insert(buf, ' '); bufcpy(buf, argv[i], libc0->strlen(argv[i])); } insert(buf, 0); symlookw(libc0->s2ab("MKARGS"), S_VAR, stow(buf.start)); freebuf(buf); if(f == files){ if(access(libc0->s2ab(MKFILE), Sys->OREAD) == 0) parse(libc0->s2ab(MKFILE), sys->open(MKFILE, 0), 0); } else for(ff = 0; ff < len files && files[ff] != nil; ff++) parse(files[ff], sys->open(libc0->ab2s(files[ff]), 0), 0); if(debug&D_PARSE){ dumpw(libc0->s2ab("default targets"), target1); dumpr(libc0->s2ab("rules"), rules); dumpr(libc0->s2ab("metarules"), metarules); dumpv(libc0->s2ab("variables")); } if(whatif != nil){ insert(whatif, 0); timeinit(whatif.start); freebuf(whatif); } execinit(); # skip assignment args while(argv[0] != nil && argv[0][0] == byte 0) argv = argv[1: ]; catchnotes(); if(argv[0] == nil){ if(target1 != nil) for(w = target1; w != nil; w = w.next) mk(w.s); else{ sys->fprint(sys->fildes(2), "mk: nothing to mk\n"); Exit(); } } else{ if(sflag){ for(; argv[0] != nil; argv = argv[1: ]) if(int argv[0][0]) mk(argv[0]); } else{ head, tail, t: ref Word; # fake a new rule with all the args as prereqs tail = nil; t = nil; for(; argv[0] != nil; argv = argv[1: ]) if(int argv[0][0]){ if(tail == nil) tail = t = newword(argv[0]); else{ t.next = newword(argv[0]); t = t.next; } } if(tail.next == nil) mk(tail.s); else{ head = newword(libc0->s2ab("command line arguments")); addrules(head, tail, libc0->strdup(libc0->s2ab("")), VIR, mkinline, nil); mk(head.s); } } } if(uflag) prusage(); bout.flush(); exit; } badusage() { sys->fprint(sys->fildes(2), "Usage: mk [-f file] [-n] [-a] [-e] [-t] [-k] [-i] [-d[egp]] [targets ...]\n"); Exit(); } assert(s: array of byte, n: int) { if(!n){ sys->fprint(sys->fildes(2), "mk: Assertion ``%s'' failed.\n", libc0->ab2s(s)); Exit(); } } regerror(s: array of byte) { if(patrule != nil) sys->fprint(sys->fildes(2), "mk: %s:%d: regular expression error; %s\n", libc0->ab2s(patrule.file), patrule.line, libc0->ab2s(s)); else sys->fprint(sys->fildes(2), "mk: %s:%d: regular expression error; %s\n", libc0->ab2s(infile), mkinline, libc0->ab2s(s)); Exit(); } perror(s: array of byte) { perrors(libc0->ab2s(s)); } perrors(s: string) { sys->fprint(sys->fildes(2), "mk: %s: %r\n", s); } access(s: array of byte, mode: int): int { fd := sys->open(libc0->ab2s(s), mode); if (fd == nil) return -1; fd = nil; return 0; } stob(buf: array of byte, s: string) { b := libc0->s2ab(s); libc0->strncpy(buf, b, len buf); } mktemp(t: array of byte) { x := libc0->strchr(t, 'X'); if(x == nil) return; pid := libc0->s2ab(string sys->pctl(0, nil)); for(i := 'a'; i <= 'z'; i++){ x[0] = byte i; x = x[1: ]; libc0->strncpy(x, pid, libc0->strlen(x)); (ok, nil) := sys->stat(libc0->ab2s(t)); if(ok >= 0) continue; } } postnote(t: int, pid: int, note: array of byte) { if(pid == 0) return; fd := sys->open("#p/" + string pid + "/ctl", Sys->OWRITE); if(fd == nil) return; s := libc0->ab2s(note); if(t == PNGROUP) s += "grp"; sys->fprint(fd, "%s", s); fd = nil; } map(s: array of byte, n: int): int { i := j := 0; ls := libc0->strlen(s); while(i < ls){ if(j == n) return i; (nil, l, nil) := sys->byte2char(s, i); i += l; j++; } return -1; } regadd(s: array of byte, m: array of (int, int), rm: array of Resub, n: int) { k := len m; for(i := 0; i < n; i++) rm[i].sp = rm[i].ep= nil; for(i = 0; i < k && i < n; i++){ (a, b) := m[i]; if(a >= 0 && b >= 0){ a = map(s, a); b = map(s, b); if(a >= 0 && b >= 0){ rm[i].sp = s[a: ]; rm[i].ep = s[b: ]; } } } } scopy(d: array of byte, j: int, m: array of Resub, k: int, n: int): int { if(k >= n) return 0; sp := m[k].sp; ep := m[k].ep; if(sp == nil || ep == nil) return 0; c := ep[0]; ep[0] = byte 0; libc0->strcpy(d[j: ], sp); ep[0] = c; return libc0->strlen(sp)-libc0->strlen(ep); } regsub(s: array of byte, d: array of byte, m: array of Resub, n: int) { # libc0->strncpy(d, s, libc0->strlen(d)); ls := libc0->strlen(s); j := 0; for(i := 0; i < ls; i++){ case(int s[i]){ '\\' => if(i+1 < ls && s[i+1] >= byte '0' && s[i+1] <= byte '9'){ k := int s[++i]-'0'; j += scopy(d, j, m, k, n); } else d[j++] = byte '\\'; '&' => j += scopy(d, j, m, 0, n); * => d[j++] = s[i]; } } d[j] = byte 0; } wpid := -1; wfd : ref Sys->FD; wprocs := 0; openwait() { pid := sys->pctl(0, nil); w := sys->sprint("#p/%d/wait", pid); fd := sys->open(w, Sys->OREAD); if(fd == nil){ perrors("fd == nil in wait"); return; } wpid = pid; wfd = fd; } addwait() { if(wpid == sys->pctl(0, nil)) wprocs++; } wait(): (int, array of byte) { n: int; if(wpid != -1 && wpid != sys->pctl(0, nil)){ perrors(sys->sprint("wait: pid %d != pid %d", wpid, sys->pctl(0, nil))); return (-1, nil); } if(wprocs == 0) return (-1, nil); buf := array[Sys->WAITLEN] of byte; status := ""; for(;;){ if((n = sys->read(wfd, buf, len buf))<0) perrors("bad read in wait"); status = string buf[0:n]; break; } s := ""; if(status[len status - 1] != ':') s = status; wprocs--; return (int status, libc0->s2ab(s)); } abort() { exit; } execl(sh: string, name: string, a1: string, a2: string, a3: string, a4: string) { # sys->print("execl %s : %s %s %s %s %s\n", sh, name, a1, a2, a3, a4); c := load Command sh; if(c == nil){ sys->fprint(sys->fildes(2), "x %s: %r\n", sh); return; } argl: list of string; if(a4 != nil) argl = a4 :: argl; if(a3 != nil) argl = a3 :: argl; if(a2 != nil) argl = a2 :: argl; if(a1 != nil) argl = a1 :: argl; # argl = "-x" :: argl; argl = name :: argl; # argl := list of { name, a1, a2, a3, a4 }; if(debug&D_EXEC) sys->fprint(sys->fildes(1), "executing %s with args (%s, %s, %s, %s, %s)\n", sh, name, a1, a2, a3, a4); c->init(nil, argl); } getuser(): string { fd := sys->open("/dev/user", sys->OREAD); if(fd == nil) return ""; buf := array[128] of byte; n := sys->read(fd, buf, len buf); if(n < 0) return ""; return string buf[0: n]; } initbind() { f := sys->sprint("/usr/%s/lib/mkbinds", getuser()); b := bufio->open(f, Bufio->OREAD); if(b == nil) b = bufio->open("/appl/cmd/mk/mkbinds", Bufio->OREAD); if(b == nil) return; while((s := b.gets('\n')) != nil){ m := len s; if(s[m-1] == '\n') s = s[0: m-1]; (n, l) := sys->tokenize(s, " \t"); if(n == 2) sys->bind(hd l, hd tl l, Sys->MREPL); } }