Blob
1 #include "mk.h"3 char *infile;4 int mkinline;5 static int rhead(char *, Word **, Word **, int *, char **);6 static char *rbody(Biobuf*);7 extern Word *target1;9 void10 parse(char *f, int fd, int varoverride)11 {12 int hline;13 char *body;14 Word *head, *tail;15 int attr, set, pid;16 char *prog, *p;17 int newfd;18 Biobuf in;19 Bufblock *buf;20 char *err;22 if(fd < 0){23 fprint(2, "open %s: %r\n", f);24 Exit();25 }26 pushshell();27 ipush();28 infile = strdup(f);29 mkinline = 1;30 Binit(&in, fd, OREAD);31 buf = newbuf();32 while(assline(&in, buf)){33 hline = mkinline;34 switch(rhead(buf->start, &head, &tail, &attr, &prog))35 {36 case '<':37 p = wtos(tail, ' ');38 if(*p == 0){39 SYNERR(-1);40 fprint(2, "missing include file name\n");41 Exit();42 }43 newfd = open(p, OREAD);44 if(newfd < 0){45 fprint(2, "warning: skipping missing include file %s: %r\n", p);46 } else47 parse(p, newfd, 0);48 break;49 case '|':50 p = wtos(tail, ' ');51 if(*p == 0){52 SYNERR(-1);53 fprint(2, "missing include program name\n");54 Exit();55 }56 execinit();57 pid=pipecmd(p, envy, &newfd, shellt, shellcmd);58 if(newfd < 0){59 fprint(2, "warning: skipping missing program file %s: %r\n", p);60 } else61 parse(p, newfd, 0);62 while(waitup(-3, &pid) >= 0)63 ;64 if(pid != 0){65 fprint(2, "bad include program status\n");66 Exit();67 }68 break;69 case ':':70 body = rbody(&in);71 addrules(head, tail, body, attr, hline, prog);72 break;73 case '=':74 if(head->next){75 SYNERR(-1);76 fprint(2, "multiple vars on left side of assignment\n");77 Exit();78 }79 if(symlook(head->s, S_OVERRIDE, 0)){80 set = varoverride;81 } else {82 set = 1;83 if(varoverride)84 symlook(head->s, S_OVERRIDE, (void *)"");85 }86 if(set){87 /*88 char *cp;89 dumpw("tail", tail);90 cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);91 */92 setvar(head->s, (void *) tail);93 symlook(head->s, S_WESET, (void *)"");94 if(strcmp(head->s, "MKSHELL") == 0){95 if((err = setshell(tail)) != nil){96 SYNERR(hline);97 fprint(2, "%s\n", err);98 Exit();99 break;100 }101 }102 }103 if(attr)104 symlook(head->s, S_NOEXPORT, (void *)"");105 break;106 default:107 SYNERR(hline);108 fprint(2, "expected one of :<=\n");109 Exit();110 break;111 }112 }113 close(fd);114 freebuf(buf);115 ipop();116 popshell();117 }119 void120 addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog)121 {122 Word *w;124 assert("addrules args", head && body);125 /* tuck away first non-meta rule as default target*/126 if(target1 == 0 && !(attr®EXP)){127 for(w = head; w; w = w->next)128 if(shellt->charin(w->s, "%&"))129 break;130 if(w == 0)131 target1 = wdup(head);132 }133 for(w = head; w; w = w->next)134 addrule(w->s, tail, body, head, attr, hline, prog);135 }137 static int138 rhead(char *line, Word **h, Word **t, int *attr, char **prog)139 {140 char *p;141 char *pp;142 int sep;143 Rune r;144 int n;145 Word *w;147 p = shellt->charin(line,":=<");148 if(p == 0)149 return('?');150 sep = *p;151 *p++ = 0;152 if(sep == '<' && *p == '|'){153 sep = '|';154 p++;155 }156 *attr = 0;157 *prog = 0;158 if(sep == '='){159 pp = shellt->charin(p, shellt->termchars); /* termchars is shell-dependent */160 if (pp && *pp == '=') {161 while (p != pp) {162 n = chartorune(&r, p);163 switch(r)164 {165 default:166 SYNERR(-1);167 fprint(2, "unknown attribute '%c'\n",*p);168 Exit();169 case 'U':170 *attr = 1;171 break;172 }173 p += n;174 }175 p++; /* skip trailing '=' */176 }177 }178 if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){179 while (*p) {180 n = chartorune(&r, p);181 if (r == ':')182 break;183 p += n;184 switch(r)185 {186 default:187 SYNERR(-1);188 fprint(2, "unknown attribute '%c'\n", p[-1]);189 Exit();190 case 'D':191 *attr |= DEL;192 break;193 case 'E':194 *attr |= NOMINUSE;195 break;196 case 'n':197 *attr |= NOVIRT;198 break;199 case 'N':200 *attr |= NOREC;201 break;202 case 'P':203 pp = utfrune(p, ':');204 if (pp == 0 || *pp == 0)205 goto eos;206 *pp = 0;207 *prog = strdup(p);208 *pp = ':';209 p = pp;210 break;211 case 'Q':212 *attr |= QUIET;213 break;214 case 'R':215 *attr |= REGEXP;216 break;217 case 'U':218 *attr |= UPD;219 break;220 case 'V':221 *attr |= VIR;222 break;223 }224 }225 if (*p++ != ':') {226 eos:227 SYNERR(-1);228 fprint(2, "missing trailing :\n");229 Exit();230 }231 }232 *h = w = stow(line);233 if(*w->s == 0 && sep != '<' && sep != '|' && sep != 'S') {234 SYNERR(mkinline-1);235 fprint(2, "no var on left side of assignment/rule\n");236 Exit();237 }238 *t = stow(p);239 return(sep);240 }242 static char *243 rbody(Biobuf *in)244 {245 Bufblock *buf;246 int r, lastr;247 char *p;249 lastr = '\n';250 buf = newbuf();251 for(;;){252 r = Bgetrune(in);253 if (r < 0)254 break;255 if (lastr == '\n') {256 if (r == '#')257 rinsert(buf, r);258 else if (r != ' ' && r != '\t') {259 Bungetrune(in);260 break;261 }262 } else263 rinsert(buf, r);264 lastr = r;265 if (r == '\n')266 mkinline++;267 }268 insert(buf, 0);269 p = strdup(buf->start);270 freebuf(buf);271 return p;272 }274 struct input275 {276 char *file;277 int line;278 struct input *next;279 };280 static struct input *inputs = 0;282 void283 ipush(void)284 {285 struct input *in, *me;287 me = (struct input *)Malloc(sizeof(*me));288 me->file = infile;289 me->line = mkinline;290 me->next = 0;291 if(inputs == 0)292 inputs = me;293 else {294 for(in = inputs; in->next; )295 in = in->next;296 in->next = me;297 }298 }300 void301 ipop(void)302 {303 struct input *in, *me;305 assert("pop input list", inputs != 0);306 if(inputs->next == 0){307 me = inputs;308 inputs = 0;309 } else {310 for(in = inputs; in->next->next; )311 in = in->next;312 me = in->next;313 in->next = 0;314 }315 infile = me->file;316 mkinline = me->line;317 free((char *)me);318 }