parse.c 5.2 KB

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