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