parse.c 5.6 KB

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