PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/cmd/cmd-inet/usr.bin/rdist/gram.y

https://bitbucket.org/illumos/illumos-gate/
Happy | 542 lines | 490 code | 52 blank | 0 comment | 0 complexity | 5e7de588785cd8bcafeefcb8c7f87661 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, AGPL-3.0, BSD-3-Clause, GPL-3.0, LGPL-2.1, BSD-2-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, 0BSD
  1. %{
  2. /*
  3. * Copyright (c) 1983 Regents of the University of California.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms are permitted
  7. * provided that the above copyright notice and this paragraph are
  8. * duplicated in all such forms and that any documentation,
  9. * advertising materials, and other materials related to such
  10. * distribution and use acknowledge that the software was developed
  11. * by the University of California, Berkeley. The name of the
  12. * University may not be used to endorse or promote products derived
  13. * from this software without specific prior written permission.
  14. *
  15. * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
  16. * Use is subject to license terms.
  17. */
  18. #pragma ident "%Z%%M% %I% %E% SMI"
  19. #include "defs.h"
  20. struct cmd *cmds = NULL;
  21. struct cmd *last_cmd;
  22. struct namelist *last_n;
  23. struct subcmd *last_sc;
  24. static void append(char *label, struct namelist *files, char *stamp,
  25. struct subcmd *subcmds);
  26. void yyerror(char *s);
  27. %}
  28. %term EQUAL 1
  29. %term LP 2
  30. %term RP 3
  31. %term SM 4
  32. %term ARROW 5
  33. %term COLON 6
  34. %term DCOLON 7
  35. %term NAME 8
  36. %term STRING 9
  37. %term INSTALL 10
  38. %term NOTIFY 11
  39. %term EXCEPT 12
  40. %term PATTERN 13
  41. %term SPECIAL 14
  42. %term OPTION 15
  43. %union {
  44. int intval;
  45. char *string;
  46. struct subcmd *subcmd;
  47. struct namelist *namel;
  48. }
  49. %type <intval> OPTION, options
  50. %type <string> NAME, STRING
  51. %type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
  52. %type <namel> namelist, names, opt_namelist
  53. %%
  54. file: /* VOID */
  55. | file command
  56. ;
  57. command: NAME EQUAL namelist = {
  58. (void) lookup($1, INSERT, $3);
  59. }
  60. | namelist ARROW namelist cmdlist = {
  61. insert(NULL, $1, $3, $4);
  62. }
  63. | NAME COLON namelist ARROW namelist cmdlist = {
  64. insert($1, $3, $5, $6);
  65. }
  66. | namelist DCOLON NAME cmdlist = {
  67. append(NULL, $1, $3, $4);
  68. }
  69. | NAME COLON namelist DCOLON NAME cmdlist = {
  70. append($1, $3, $5, $6);
  71. }
  72. | error
  73. ;
  74. namelist: NAME = {
  75. $$ = makenl($1);
  76. }
  77. | LP names RP = {
  78. $$ = $2;
  79. }
  80. ;
  81. names: /* VOID */ {
  82. $$ = last_n = NULL;
  83. }
  84. | names NAME = {
  85. if (last_n == NULL)
  86. $$ = last_n = makenl($2);
  87. else {
  88. last_n->n_next = makenl($2);
  89. last_n = last_n->n_next;
  90. $$ = $1;
  91. }
  92. }
  93. ;
  94. cmdlist: /* VOID */ {
  95. $$ = last_sc = NULL;
  96. }
  97. | cmdlist cmd = {
  98. if (last_sc == NULL)
  99. $$ = last_sc = $2;
  100. else {
  101. last_sc->sc_next = $2;
  102. last_sc = $2;
  103. $$ = $1;
  104. }
  105. }
  106. ;
  107. cmd: INSTALL options opt_namelist SM = {
  108. register struct namelist *nl;
  109. $1->sc_options = $2 | options;
  110. if ($3 != NULL) {
  111. nl = expand($3, E_VARS);
  112. if (nl && nl->n_next != NULL)
  113. yyerror("only one name allowed\n");
  114. $1->sc_name = nl ? nl->n_name: NULL;
  115. if (nl)
  116. free(nl);
  117. }
  118. $$ = $1;
  119. }
  120. | NOTIFY namelist SM = {
  121. if ($2 != NULL)
  122. $1->sc_args = expand($2, E_VARS);
  123. $$ = $1;
  124. }
  125. | EXCEPT namelist SM = {
  126. if ($2 != NULL)
  127. $1->sc_args = expand($2, E_ALL);
  128. $$ = $1;
  129. }
  130. | PATTERN namelist SM = {
  131. struct namelist *nl;
  132. char *cp, *re_comp();
  133. /*
  134. * We dup the namelist in $2 because expand()
  135. * destroys the list referred to in its first
  136. * argument.
  137. */
  138. for (nl = expand(dupnl($2), E_VARS); nl != NULL;
  139. nl = nl->n_next)
  140. if ((cp = re_comp(nl->n_name)) != NULL)
  141. yyerror(cp);
  142. $1->sc_args = expand($2, E_VARS);
  143. $$ = $1;
  144. }
  145. | SPECIAL opt_namelist STRING SM = {
  146. if ($2 != NULL)
  147. $1->sc_args = expand($2, E_ALL);
  148. $1->sc_name = $3;
  149. $$ = $1;
  150. }
  151. ;
  152. options: /* VOID */ = {
  153. $$ = 0;
  154. }
  155. | options OPTION = {
  156. $$ |= $2;
  157. }
  158. ;
  159. opt_namelist: /* VOID */ = {
  160. $$ = NULL;
  161. }
  162. | namelist = {
  163. $$ = $1;
  164. }
  165. ;
  166. %%
  167. int yylineno = 1;
  168. extern FILE *fin;
  169. int
  170. yylex()
  171. {
  172. static char yytext[INMAX];
  173. register int c;
  174. register char *cp1, *cp2;
  175. static char quotechars[] = "[]{}*?$";
  176. again:
  177. switch (c = getc(fin)) {
  178. case EOF: /* end of file */
  179. return(0);
  180. case '#': /* start of comment */
  181. while ((c = getc(fin)) != EOF && c != '\n')
  182. ;
  183. if (c == EOF)
  184. return(0);
  185. case '\n':
  186. yylineno++;
  187. case ' ':
  188. case '\t': /* skip blanks */
  189. goto again;
  190. case '=': /* EQUAL */
  191. return(EQUAL);
  192. case '(': /* LP */
  193. return(LP);
  194. case ')': /* RP */
  195. return(RP);
  196. case ';': /* SM */
  197. return(SM);
  198. case '-': /* -> */
  199. if ((c = getc(fin)) == '>')
  200. return(ARROW);
  201. ungetc(c, fin);
  202. c = '-';
  203. break;
  204. case '"': /* STRING */
  205. cp1 = yytext;
  206. cp2 = &yytext[INMAX - 1];
  207. for (;;) {
  208. if (cp1 >= cp2) {
  209. yyerror("command string too long\n");
  210. break;
  211. }
  212. c = getc(fin);
  213. if (c == EOF || c == '"')
  214. break;
  215. if (c == '\\') {
  216. if ((c = getc(fin)) == EOF) {
  217. *cp1++ = '\\';
  218. break;
  219. }
  220. }
  221. if (c == '\n') {
  222. yylineno++;
  223. c = ' '; /* can't send '\n' */
  224. }
  225. *cp1++ = c;
  226. }
  227. if (c != '"')
  228. yyerror("missing closing '\"'\n");
  229. *cp1 = '\0';
  230. yylval.string = makestr(yytext);
  231. return(STRING);
  232. case ':': /* : or :: */
  233. if ((c = getc(fin)) == ':')
  234. return(DCOLON);
  235. ungetc(c, fin);
  236. return(COLON);
  237. }
  238. cp1 = yytext;
  239. cp2 = &yytext[INMAX - 1];
  240. for (;;) {
  241. if (cp1 >= cp2) {
  242. yyerror("input line too long\n");
  243. break;
  244. }
  245. if (c == '\\') {
  246. if ((c = getc(fin)) != EOF) {
  247. if (any(c, quotechars))
  248. c |= QUOTE;
  249. } else {
  250. *cp1++ = '\\';
  251. break;
  252. }
  253. }
  254. *cp1++ = c;
  255. c = getc(fin);
  256. if (c == EOF || any(c, " \"'\t()=;:\n")) {
  257. ungetc(c, fin);
  258. break;
  259. }
  260. }
  261. *cp1 = '\0';
  262. if (yytext[0] == '-' && yytext[2] == '\0') {
  263. switch (yytext[1]) {
  264. case 'b':
  265. yylval.intval = COMPARE;
  266. return(OPTION);
  267. case 'R':
  268. yylval.intval = REMOVE;
  269. return(OPTION);
  270. case 'v':
  271. yylval.intval = VERIFY;
  272. return(OPTION);
  273. case 'w':
  274. yylval.intval = WHOLE;
  275. return(OPTION);
  276. case 'y':
  277. yylval.intval = YOUNGER;
  278. return(OPTION);
  279. case 'h':
  280. yylval.intval = FOLLOW;
  281. return(OPTION);
  282. case 'i':
  283. yylval.intval = IGNLNKS;
  284. return(OPTION);
  285. }
  286. }
  287. if (!strcmp(yytext, "install"))
  288. c = INSTALL;
  289. else if (!strcmp(yytext, "notify"))
  290. c = NOTIFY;
  291. else if (!strcmp(yytext, "except"))
  292. c = EXCEPT;
  293. else if (!strcmp(yytext, "except_pat"))
  294. c = PATTERN;
  295. else if (!strcmp(yytext, "special"))
  296. c = SPECIAL;
  297. else {
  298. yylval.string = makestr(yytext);
  299. return(NAME);
  300. }
  301. yylval.subcmd = makesubcmd(c);
  302. return(c);
  303. }
  304. int
  305. any(c, str)
  306. register int c;
  307. register char *str;
  308. {
  309. while (*str)
  310. if (c == *str++)
  311. return(1);
  312. return(0);
  313. }
  314. /*
  315. * Insert or append ARROW command to list of hosts to be updated.
  316. */
  317. void
  318. insert(label, files, hosts, subcmds)
  319. char *label;
  320. struct namelist *files, *hosts;
  321. struct subcmd *subcmds;
  322. {
  323. register struct cmd *c, *prev, *nc;
  324. register struct namelist *h, *oldh;
  325. files = expand(files, E_VARS|E_SHELL);
  326. hosts = expand(hosts, E_ALL);
  327. if (debug) {
  328. printf("insert: files = ");
  329. prnames(files);
  330. printf("insert: hosts = ");
  331. prnames(hosts);
  332. if (cmds)
  333. prcmd(cmds);
  334. else
  335. printf("insert: cmds NULL\n");
  336. }
  337. for (h = hosts; h != NULL; oldh = h, h = h->n_next, free(oldh)) {
  338. /*
  339. * Search command list for an update to the same host.
  340. */
  341. for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) {
  342. if (strcmp(c->c_name, h->n_name) == 0) {
  343. do {
  344. prev = c;
  345. c = c->c_next;
  346. } while (c != NULL &&
  347. strcmp(c->c_name, h->n_name) == 0);
  348. break;
  349. }
  350. }
  351. /*
  352. * Insert new command to update host.
  353. */
  354. nc = ALLOC(cmd);
  355. if (nc == NULL)
  356. fatal("ran out of memory\n");
  357. nc->c_type = ARROW;
  358. nc->c_name = h->n_name;
  359. nc->c_label = label;
  360. nc->c_files = files;
  361. nc->c_cmds = subcmds;
  362. nc->c_next = c;
  363. if (prev == NULL)
  364. cmds = nc;
  365. else
  366. prev->c_next = nc;
  367. /* update last_cmd if appending nc to cmds */
  368. if (c == NULL)
  369. last_cmd = nc;
  370. }
  371. }
  372. /*
  373. * Append DCOLON command to the end of the command list since these are always
  374. * executed in the order they appear in the distfile.
  375. */
  376. static void
  377. append(label, files, stamp, subcmds)
  378. char *label;
  379. struct namelist *files;
  380. char *stamp;
  381. struct subcmd *subcmds;
  382. {
  383. register struct cmd *c;
  384. c = ALLOC(cmd);
  385. if (c == NULL)
  386. fatal("ran out of memory\n");
  387. c->c_type = DCOLON;
  388. c->c_name = stamp;
  389. c->c_label = label;
  390. c->c_files = expand(files, E_ALL);
  391. c->c_cmds = subcmds;
  392. c->c_next = NULL;
  393. if (cmds == NULL)
  394. cmds = last_cmd = c;
  395. else {
  396. last_cmd->c_next = c;
  397. last_cmd = c;
  398. }
  399. }
  400. /*
  401. * Error printing routine in parser.
  402. */
  403. void
  404. yyerror(s)
  405. char *s;
  406. {
  407. extern int yychar;
  408. nerrs++;
  409. fflush(stdout);
  410. fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
  411. }
  412. /*
  413. * Return a copy of the string.
  414. */
  415. char *
  416. makestr(str)
  417. char *str;
  418. {
  419. register char *cp, *s;
  420. str = cp = malloc(strlen(s = str) + 1);
  421. if (cp == NULL)
  422. fatal("ran out of memory\n");
  423. while (*cp++ = *s++)
  424. ;
  425. return(str);
  426. }
  427. /*
  428. * Allocate a namelist structure.
  429. */
  430. struct namelist *
  431. makenl(name)
  432. char *name;
  433. {
  434. register struct namelist *nl;
  435. nl = ALLOC(namelist);
  436. if (nl == NULL)
  437. fatal("ran out of memory\n");
  438. nl->n_name = name;
  439. nl->n_next = NULL;
  440. return(nl);
  441. }
  442. /*
  443. * Duplicate an existing namelist structure. Only used by the PATTERN
  444. * code, and then only because expand() is destructive.
  445. */
  446. struct namelist *
  447. dupnl(old)
  448. struct namelist *old;
  449. {
  450. struct namelist *n;
  451. struct namelist *new, *newhead = (struct namelist *) NULL;
  452. struct namelist *prev = (struct namelist *) NULL;
  453. for (n = old; n; n = n->n_next) {
  454. new = ALLOC(namelist);
  455. if (new == (struct namelist *) NULL)
  456. fatal("ran out of memory\n");
  457. if (newhead == (struct namelist *) NULL)
  458. newhead = new;
  459. if (n->n_name) {
  460. if ((new->n_name = strdup(n->n_name)) == (char *) NULL)
  461. fatal("ran out of memory\n");
  462. } else
  463. new->n_name = (char *) NULL;
  464. if (prev)
  465. prev->n_next = new;
  466. prev = new;
  467. }
  468. if (prev)
  469. prev->n_next = (struct namelist *) NULL;
  470. return (newhead);
  471. }
  472. /*
  473. * Make a sub command for lists of variables, commands, etc.
  474. */
  475. struct subcmd *
  476. makesubcmd(type, name)
  477. int type;
  478. register char *name;
  479. {
  480. register char *cp;
  481. register struct subcmd *sc;
  482. sc = ALLOC(subcmd);
  483. if (sc == NULL)
  484. fatal("ran out of memory\n");
  485. sc->sc_type = type;
  486. sc->sc_args = NULL;
  487. sc->sc_next = NULL;
  488. sc->sc_name = NULL;
  489. return(sc);
  490. }