# # initially generated by c2l # infile: array of byte; mkinline: int; parse(f: array of byte, fd: ref Sys->FD, varoverride: int) { hline, v: int; body: array of byte; head, tail: ref Word; attr, set, pid: int; prog, p: array of byte; newfd: ref Sys->FD; in: ref Iobuf; buf: ref Bufblock; if(fd == nil){ perror(f); Exit(); } ipush(); infile = libc0->strdup(f); mkinline = 1; in = bufio->fopen(fd, Sys->OREAD); buf = newbuf(); while(assline(in, buf)){ hline = mkinline; (v, head, tail, attr, prog) = rhead(buf.start); case(v){ '<' => p = wtos(tail, ' '); if(p[0] == byte 0){ if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "missing include file name\n"); Exit(); } newfd = sys->open(libc0->ab2s(p), Sys->OREAD); if(newfd == nil){ sys->fprint(sys->fildes(2), "warning: skipping missing include file: "); perror(p); } else parse(p, newfd, 0); '|' => p = wtos(tail, ' '); if(p[0] == byte 0){ if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "missing include program name\n"); Exit(); } execinit(); anewfd := array[1] of ref Sys->FD; anewfd[0] = newfd; pid = pipecmd(p, envy, anewfd); newfd = anewfd[0]; if(newfd == nil){ sys->fprint(sys->fildes(2), "warning: skipping missing program file: "); perror(p); } else parse(p, newfd, 0); apid := array[1] of int; apid[0] = pid; while(waitup(-3, apid) >= 0) ; pid = apid[0]; if(pid != 0){ sys->fprint(sys->fildes(2), "bad include program status\n"); Exit(); } ':' => body = rbody(in); addrules(head, tail, body, attr, hline, prog); '=' => if(head.next != nil){ if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "multiple vars on left side of assignment\n"); Exit(); } if(symlooki(head.s, S_OVERRIDE, 0) != nil){ set = varoverride; } else{ set = 1; if(varoverride) symlooks(head.s, S_OVERRIDE, libc0->s2ab("")); } if(set){ # # char *cp; # dumpw("tail", tail); # cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp); # setvar(head.s, tail); symlooks(head.s, S_WESET, libc0->s2ab("")); } if(attr) symlooks(head.s, S_NOEXPORT, libc0->s2ab("")); * => if(hline >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), hline); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "expected one of :<=\n"); Exit(); } } fd = nil; freebuf(buf); ipop(); } addrules(head: ref Word, tail: ref Word, body: array of byte, attr: int, hline: int, prog: array of byte) { w: ref Word; assert(libc0->s2ab("addrules args"), head != nil && body != nil); # tuck away first non-meta rule as default target if(target1 == nil && !(attr®EXP)){ for(w = head; w != nil; w = w.next) if(charin(w.s, libc0->s2ab("%&")) != nil) break; if(w == nil) target1 = wdup(head); } for(w = head; w != nil; w = w.next) addrule(w.s, tail, body, head, attr, hline, prog); } rhead(line: array of byte): (int, ref Word, ref Word, int, array of byte) { h, t: ref Word; attr: int; prog: array of byte; p, pp: array of byte; sep: int; r: int; n: int; w: ref Word; p = charin(line, libc0->s2ab(":=<")); if(p == nil) return ('?', nil, nil, 0, nil); sep = int p[0]; p[0] = byte 0; p = p[1: ]; if(sep == '<' && p[0] == byte '|'){ sep = '|'; p = p[1: ]; } attr = 0; prog = nil; if(sep == '='){ pp = charin(p, termchars); # termchars is shell-dependent if(pp != nil && pp[0] == byte '='){ while(p != pp){ (r, n, nil) = sys->byte2char(p, 0); case(r){ * => if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "unknown attribute '%c'\n", int p[0]); Exit(); 'U' => attr = 1; } p = p[n: ]; } p = p[1: ]; # skip trailing '=' } } if(sep == ':' && int p[0] && p[0] != byte ' ' && p[0] != byte '\t'){ while(int p[0]){ (r, n, nil) = sys->byte2char(p, 0); if(r == ':') break; ea := p[n-1]; p = p[n: ]; case(r){ * => if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "unknown attribute '%c'\n", int ea); Exit(); 'D' => attr |= DEL; 'E' => attr |= NOMINUSE; 'n' => attr |= NOVIRT; 'N' => attr |= NOREC; 'P' => pp = libc0->strchr(p, ':'); if(pp == nil || pp[0] == byte 0){ if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "missing trailing :\n"); Exit(); } pp[0] = byte 0; prog = libc0->strdup(p); pp[0] = byte ':'; p = pp; 'Q' => attr |= QUIET; 'R' => attr |= REGEXP; 'U' => attr |= UPD; 'V' => attr |= VIR; } } if(p[0] != byte ':'){ if(-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), -1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "missing trailing :\n"); Exit(); } p = p[1: ]; } h = w = stow(line); if(w.s[0] == byte 0 && sep != '<' && sep != '|'){ if(mkinline-1 >= 0) sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline-1); else sys->fprint(sys->fildes(2), "mk: %s:%d: syntax error; ", libc0->ab2s(infile), mkinline); sys->fprint(sys->fildes(2), "no var on left side of assignment/rule\n"); Exit(); } t = stow(p); return (sep, h, t, attr, prog); } rbody(in: ref Iobuf): array of byte { buf: ref Bufblock; r, lastr: int; p: array of byte; lastr = '\n'; buf = newbuf(); for(;;){ r = in.getc(); if(r < 0) break; if(lastr == '\n'){ if(r == '#') rinsert(buf, r); else if(r != ' ' && r != '\t'){ in.ungetc(); break; } } else rinsert(buf, r); lastr = r; if(r == '\n') mkinline++; } insert(buf, 0); p = libc0->strdup(buf.start); freebuf(buf); return p; } input: adt{ file: array of byte; line: int; next: cyclic ref input; }; inputs: ref input = nil; ipush() { in, me: ref input; me = ref input; me.file = infile; me.line = mkinline; me.next = nil; if(inputs == nil) inputs = me; else{ for(in = inputs; in.next != nil;) in = in.next; in.next = me; } } ipop() { in, me: ref input; assert(libc0->s2ab("pop input list"), inputs != nil); if(inputs.next == nil){ me = inputs; inputs = nil; } else{ for(in = inputs; in.next.next != nil;) in = in.next; me = in.next; in.next = nil; } infile = me.file; mkinline = me.line; me = nil; }