1 #include "mk.h" 2 3 char *infile; 4 int mkinline; 5 static int rhead(char *, Word **, Word **, int *, char **); 6 static char *rbody(Biobuf*); 7 extern Word *target1; 8 9 void 10 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 21 if(fd < 0){ 22 perror(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: "); 44 perror(p); 45 } else 46 parse(p, newfd, 0); 47 break; 48 case '|': 49 p = wtos(tail, ' '); 50 if(*p == 0){ 51 SYNERR(-1); 52 fprint(2, "missing include program name\n"); 53 Exit(); 54 } 55 execinit(); 56 pid=pipecmd(p, envy, &newfd); 57 if(newfd < 0){ 58 fprint(2, "warning: skipping missing program file: "); 59 perror(p); 60 } else 61 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 } 95 if(attr) 96 symlook(head->s, S_NOEXPORT, (void *)""); 97 break; 98 default: 99 SYNERR(hline); 100 fprint(2, "expected one of :<=\n"); 101 Exit(); 102 break; 103 } 104 } 105 close(fd); 106 freebuf(buf); 107 ipop(); 108 } 109 110 void 111 addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog) 112 { 113 Word *w; 114 115 assert("addrules args", head && body); 116 /* tuck away first non-meta rule as default target*/ 117 if(target1 == 0 && !(attr®EXP)){ 118 for(w = head; w; w = w->next) 119 if(charin(w->s, "%&")) 120 break; 121 if(w == 0) 122 target1 = wdup(head); 123 } 124 for(w = head; w; w = w->next) 125 addrule(w->s, tail, body, head, attr, hline, prog); 126 } 127 128 static int 129 rhead(char *line, Word **h, Word **t, int *attr, char **prog) 130 { 131 char *p; 132 char *pp; 133 int sep; 134 Rune r; 135 int n; 136 Word *w; 137 138 p = charin(line,":=<"); 139 if(p == 0) 140 return('?'); 141 sep = *p; 142 *p++ = 0; 143 if(sep == '<' && *p == '|'){ 144 sep = '|'; 145 p++; 146 } 147 *attr = 0; 148 *prog = 0; 149 if(sep == '='){ 150 pp = charin(p, termchars); /* termchars is shell-dependent */ 151 if (pp && *pp == '=') { 152 while (p != pp) { 153 n = chartorune(&r, p); 154 switch(r) 155 { 156 default: 157 SYNERR(-1); 158 fprint(2, "unknown attribute '%c'\n",*p); 159 Exit(); 160 case 'U': 161 *attr = 1; 162 break; 163 } 164 p += n; 165 } 166 p++; /* skip trailing '=' */ 167 } 168 } 169 if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){ 170 while (*p) { 171 n = chartorune(&r, p); 172 if (r == ':') 173 break; 174 p += n; 175 switch(r) 176 { 177 default: 178 SYNERR(-1); 179 fprint(2, "unknown attribute '%c'\n", p[-1]); 180 Exit(); 181 case 'D': 182 *attr |= DEL; 183 break; 184 case 'E': 185 *attr |= NOMINUSE; 186 break; 187 case 'n': 188 *attr |= NOVIRT; 189 break; 190 case 'N': 191 *attr |= NOREC; 192 break; 193 case 'P': 194 pp = utfrune(p, ':'); 195 if (pp == 0 || *pp == 0) 196 goto eos; 197 *pp = 0; 198 *prog = strdup(p); 199 *pp = ':'; 200 p = pp; 201 break; 202 case 'Q': 203 *attr |= QUIET; 204 break; 205 case 'R': 206 *attr |= REGEXP; 207 break; 208 case 'U': 209 *attr |= UPD; 210 break; 211 case 'V': 212 *attr |= VIR; 213 break; 214 } 215 } 216 if (*p++ != ':') { 217 eos: 218 SYNERR(-1); 219 fprint(2, "missing trailing :\n"); 220 Exit(); 221 } 222 } 223 *h = w = stow(line); 224 if(*w->s == 0 && sep != '<' && sep != '|') { 225 SYNERR(mkinline-1); 226 fprint(2, "no var on left side of assignment/rule\n"); 227 Exit(); 228 } 229 *t = stow(p); 230 return(sep); 231 } 232 233 static char * 234 rbody(Biobuf *in) 235 { 236 Bufblock *buf; 237 int r, lastr; 238 char *p; 239 240 lastr = '\n'; 241 buf = newbuf(); 242 for(;;){ 243 r = Bgetrune(in); 244 if (r < 0) 245 break; 246 if (lastr == '\n') { 247 if (r == '#') 248 rinsert(buf, r); 249 else if (r != ' ' && r != '\t') { 250 Bungetrune(in); 251 break; 252 } 253 } else 254 rinsert(buf, r); 255 lastr = r; 256 if (r == '\n') 257 mkinline++; 258 } 259 insert(buf, 0); 260 p = strdup(buf->start); 261 freebuf(buf); 262 return p; 263 } 264 265 struct input 266 { 267 char *file; 268 int line; 269 struct input *next; 270 }; 271 static struct input *inputs = 0; 272 273 void 274 ipush(void) 275 { 276 struct input *in, *me; 277 278 me = (struct input *)Malloc(sizeof(*me)); 279 me->file = infile; 280 me->line = mkinline; 281 me->next = 0; 282 if(inputs == 0) 283 inputs = me; 284 else { 285 for(in = inputs; in->next; ) 286 in = in->next; 287 in->next = me; 288 } 289 } 290 291 void 292 ipop(void) 293 { 294 struct input *in, *me; 295 296 assert("pop input list", inputs != 0); 297 if(inputs->next == 0){ 298 me = inputs; 299 inputs = 0; 300 } else { 301 for(in = inputs; in->next->next; ) 302 in = in->next; 303 me = in->next; 304 in->next = 0; 305 } 306 infile = me->file; 307 mkinline = me->line; 308 free((char *)me); 309 } 310