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