PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/cmd/sgs/m4/common/m4macs.c

https://bitbucket.org/dilos/onarm-gate
C | 655 lines | 493 code | 93 blank | 69 comment | 122 complexity | 13e65da3654b6ff7db733c69e70224ec MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, AGPL-3.0, MIT, Apache-2.0, 0BSD, GPL-2.0, LGPL-2.0, AGPL-1.0, BSD-3-Clause, LGPL-3.0, BSD-3-Clause-No-Nuclear-License-2014
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License, Version 1.0 only
  6. * (the "License"). You may not use this file except in compliance
  7. * with the License.
  8. *
  9. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10. * or http://www.opensolaris.org/os/licensing.
  11. * See the License for the specific language governing permissions
  12. * and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL HEADER in each
  15. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16. * If applicable, add the following below this CDDL HEADER, with the
  17. * fields enclosed by brackets "[]" replaced with your own identifying
  18. * information: Portions Copyright [yyyy] [name of copyright owner]
  19. *
  20. * CDDL HEADER END
  21. */
  22. /*
  23. * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
  24. * Use is subject to license terms.
  25. */
  26. /* Copyright (c) 1988 AT&T */
  27. /* All Rights Reserved */
  28. #pragma ident "%Z%%M% %I% %E% SMI"
  29. #include <limits.h>
  30. #include <unistd.h>
  31. #include <sys/types.h>
  32. #include "m4.h"
  33. #define arg(n) (c < (n) ? nullstr: ap[n])
  34. static void mkpid(char *);
  35. static void def(wchar_t **, int, int);
  36. static void dump(wchar_t *, wchar_t *);
  37. static void incl(wchar_t **, int, int);
  38. static int leftmatch(wchar_t *, wchar_t *);
  39. static void
  40. dochcom(wchar_t **ap, int c)
  41. {
  42. wchar_t *l = arg(1);
  43. wchar_t *r = arg(2);
  44. if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
  45. error2(gettext(
  46. "comment marker longer than %d chars"), MAXSYM);
  47. (void) wcscpy(lcom, l);
  48. (void) wcscpy(rcom, *r ? r : L"\n");
  49. }
  50. static void
  51. docq(wchar_t **ap, int c)
  52. {
  53. wchar_t *l = arg(1);
  54. wchar_t *r = arg(2);
  55. if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
  56. error2(gettext(
  57. "quote marker longer than %d chars"), MAXSYM);
  58. if (c <= 1 && !*l) {
  59. l = L"`";
  60. r = L"'";
  61. } else if (c == 1) {
  62. r = l;
  63. }
  64. (void) wcscpy(lquote, l);
  65. (void) wcscpy(rquote, r);
  66. }
  67. static void
  68. dodecr(wchar_t **ap, int c)
  69. {
  70. pbnum(ctol(arg(1))-1);
  71. }
  72. void
  73. dodef(wchar_t **ap, int c)
  74. {
  75. def(ap, c, NOPUSH);
  76. }
  77. static void
  78. def(wchar_t **ap, int c, int mode)
  79. {
  80. wchar_t *s;
  81. if (c < 1)
  82. return;
  83. s = ap[1];
  84. if (is_alpha(*s) || *s == '_') {
  85. s++;
  86. while (is_alnum(*s) || *s == '_')
  87. s++;
  88. }
  89. if (*s || s == ap[1])
  90. error(gettext("bad macro name"));
  91. if ((ap[2] != NULL) && (wcscmp(ap[1], ap[2]) == 0))
  92. error(gettext("macro defined as itself"));
  93. install(ap[1], arg(2), mode);
  94. }
  95. static void
  96. dodefn(wchar_t **ap, int c)
  97. {
  98. wchar_t *d;
  99. while (c > 0)
  100. if ((d = lookup(ap[c--])->def) != NULL) {
  101. putbak(*rquote);
  102. while (*d)
  103. putbak(*d++);
  104. putbak(*lquote);
  105. }
  106. }
  107. static void
  108. dodiv(wchar_t **ap, int c)
  109. {
  110. int f;
  111. f = wstoi(arg(1));
  112. if (f >= 10 || f < 0) {
  113. cf = NULL;
  114. ofx = f;
  115. return;
  116. }
  117. tempfile[7] = 'a'+f;
  118. if (ofile[f] || (ofile[f] = xfopen(tempfile, "w"))) {
  119. ofx = f;
  120. cf = ofile[f];
  121. }
  122. }
  123. /* ARGSUSED */
  124. static void
  125. dodivnum(wchar_t **ap, int c)
  126. {
  127. pbnum((long)ofx);
  128. }
  129. /* ARGSUSED */
  130. static void
  131. dodnl(wchar_t **ap, int c)
  132. {
  133. wchar_t t;
  134. while ((t = getchr()) != '\n' && t != WEOF)
  135. ;
  136. }
  137. static void
  138. dodump(wchar_t **ap, int c)
  139. {
  140. struct nlist *np;
  141. int i;
  142. if (c > 0)
  143. while (c--) {
  144. if ((np = lookup(*++ap))->name != NULL)
  145. dump(np->name, np->def);
  146. }
  147. else
  148. for (i = 0; i < hshsize; i++)
  149. for (np = hshtab[i]; np != NULL; np = np->next)
  150. dump(np->name, np->def);
  151. }
  152. static void
  153. dump(wchar_t *name, wchar_t *defnn)
  154. {
  155. wchar_t *s = defnn;
  156. (void) fprintf(stderr, "%ws:\t", name);
  157. while (*s++);
  158. --s;
  159. while (s > defnn) {
  160. --s;
  161. if (is_builtin(*s))
  162. (void) fprintf(stderr, "<%ws>",
  163. barray[builtin_idx(*s)].bname);
  164. else {
  165. (void) fputwc(*s, stderr);
  166. }
  167. }
  168. (void) fputc('\n', stderr);
  169. }
  170. static void
  171. doerrp(wchar_t **ap, int c)
  172. {
  173. if (c > 0)
  174. (void) fprintf(stderr, "%ws", ap[1]);
  175. }
  176. long evalval; /* return value from yacc stuff */
  177. wchar_t *pe; /* used by grammar */
  178. static void
  179. doeval(wchar_t **ap, int c)
  180. {
  181. int base = wstoi(arg(2));
  182. int pad = wstoi(arg(3));
  183. extern int yyparse(void);
  184. evalval = 0;
  185. if (c > 0) {
  186. pe = ap[1];
  187. if (yyparse() != 0)
  188. error(gettext(
  189. "invalid expression"));
  190. }
  191. pbnbr(evalval, base > 0 ? base:10, pad > 0 ? pad : 1);
  192. }
  193. /*
  194. * doexit
  195. *
  196. * Process m4exit macro.
  197. */
  198. static void
  199. doexit(wchar_t **ap, int c)
  200. {
  201. delexit(wstoi(arg(1)), 1);
  202. }
  203. static void
  204. doif(wchar_t **ap, int c)
  205. {
  206. if (c < 3)
  207. return;
  208. while (c >= 3) {
  209. if (wcscmp(ap[1], ap[2]) == 0) {
  210. pbstr(ap[3]);
  211. return;
  212. }
  213. c -= 3;
  214. ap += 3;
  215. }
  216. if (c > 0)
  217. pbstr(ap[1]);
  218. }
  219. static void
  220. doifdef(wchar_t **ap, int c)
  221. {
  222. if (c < 2)
  223. return;
  224. while (c >= 2) {
  225. if (lookup(ap[1])->name != NULL) {
  226. pbstr(ap[2]);
  227. return;
  228. }
  229. c -= 2;
  230. ap += 2;
  231. }
  232. if (c > 0)
  233. pbstr(ap[1]);
  234. }
  235. static void
  236. doincl(wchar_t **ap, int c)
  237. {
  238. incl(ap, c, 1);
  239. }
  240. static void
  241. incl(wchar_t **ap, int c, int noisy)
  242. {
  243. if (c > 0 && wcslen(ap[1]) > 0) {
  244. if (ifx >= 9)
  245. error(gettext(
  246. "input file nesting too deep (9)"));
  247. if ((ifile[++ifx] = fopen(wstr2str(ap[1], 0), "r")) == NULL) {
  248. --ifx;
  249. if (noisy)
  250. error(gettext(
  251. "can't open file"));
  252. } else {
  253. ipstk[ifx] = ipflr = ip;
  254. setfname(wstr2str(ap[1], 0));
  255. }
  256. }
  257. }
  258. static void
  259. doincr(wchar_t **ap, int c)
  260. {
  261. pbnum(ctol(arg(1))+1);
  262. }
  263. static void
  264. doindex(wchar_t **ap, int c)
  265. {
  266. wchar_t *subj = arg(1);
  267. wchar_t *obj = arg(2);
  268. int i;
  269. for (i = 0; *subj; ++i)
  270. if (leftmatch(subj++, obj)) {
  271. pbnum((long)i);
  272. return;
  273. }
  274. pbnum((long)-1);
  275. }
  276. static int
  277. leftmatch(wchar_t *str, wchar_t *substr)
  278. {
  279. while (*substr)
  280. if (*str++ != *substr++)
  281. return (0);
  282. return (1);
  283. }
  284. static void
  285. dolen(wchar_t **ap, int c)
  286. {
  287. pbnum((long)wcslen(arg(1)));
  288. }
  289. static void
  290. domake(wchar_t **ap, int c)
  291. {
  292. char *path;
  293. if (c > 0) {
  294. path = wstr2str(ap[1], 1);
  295. mkpid(path);
  296. pbstr(str2wstr(path, 0));
  297. free(path);
  298. }
  299. }
  300. static void
  301. dopopdef(wchar_t **ap, int c)
  302. {
  303. int i;
  304. for (i = 1; i <= c; ++i)
  305. (void) undef(ap[i]);
  306. }
  307. static void
  308. dopushdef(wchar_t **ap, int c)
  309. {
  310. def(ap, c, PUSH);
  311. }
  312. static void
  313. doshift(wchar_t **ap, int c)
  314. {
  315. if (c <= 1)
  316. return;
  317. for (;;) {
  318. pbstr(rquote);
  319. pbstr(ap[c--]);
  320. pbstr(lquote);
  321. if (c <= 1)
  322. break;
  323. pbstr(L",");
  324. }
  325. }
  326. static void
  327. dosincl(wchar_t **ap, int c)
  328. {
  329. incl(ap, c, 0);
  330. }
  331. static void
  332. dosubstr(wchar_t **ap, int c)
  333. {
  334. wchar_t *str;
  335. int inlen, outlen;
  336. int offset, ix;
  337. inlen = wcslen(str = arg(1));
  338. offset = wstoi(arg(2));
  339. if (offset < 0 || offset >= inlen)
  340. return;
  341. outlen = c >= 3 ? wstoi(ap[3]) : inlen;
  342. ix = min(offset+outlen, inlen);
  343. while (ix > offset)
  344. putbak(str[--ix]);
  345. }
  346. static void
  347. dosyscmd(wchar_t **ap, int c)
  348. {
  349. sysrval = 0;
  350. if (c > 0) {
  351. (void) fflush(stdout);
  352. sysrval = system(wstr2str(ap[1], 0));
  353. }
  354. }
  355. /* ARGSUSED */
  356. static void
  357. dosysval(wchar_t **ap, int c)
  358. {
  359. pbnum((long)(sysrval < 0 ? sysrval :
  360. (sysrval >> 8) & ((1 << 8) - 1)) |
  361. ((sysrval & ((1 << 8) - 1)) << 8));
  362. }
  363. static void
  364. dotransl(wchar_t **ap, int c)
  365. {
  366. wchar_t *sink, *fr, *sto;
  367. wchar_t *source, *to;
  368. if (c < 1)
  369. return;
  370. sink = ap[1];
  371. fr = arg(2);
  372. sto = arg(3);
  373. for (source = ap[1]; *source; source++) {
  374. wchar_t *i;
  375. to = sto;
  376. for (i = fr; *i; ++i) {
  377. if (*source == *i)
  378. break;
  379. if (*to)
  380. ++to;
  381. }
  382. if (*i) {
  383. if (*to)
  384. *sink++ = *to;
  385. } else
  386. *sink++ = *source;
  387. }
  388. *sink = EOS;
  389. pbstr(ap[1]);
  390. }
  391. static void
  392. dotroff(wchar_t **ap, int c)
  393. {
  394. struct nlist *np;
  395. trace = 0;
  396. while (c > 0)
  397. if ((np = lookup(ap[c--]))->name)
  398. np->tflag = 0;
  399. }
  400. static void
  401. dotron(wchar_t **ap, int c)
  402. {
  403. struct nlist *np;
  404. trace = !*arg(1);
  405. while (c > 0)
  406. if ((np = lookup(ap[c--]))->name)
  407. np->tflag = 1;
  408. }
  409. void
  410. doundef(wchar_t **ap, int c)
  411. {
  412. int i;
  413. for (i = 1; i <= c; ++i)
  414. while (undef(ap[i]))
  415. ;
  416. }
  417. int
  418. undef(wchar_t *nam)
  419. {
  420. struct nlist *np, *tnp;
  421. if ((np = lookup(nam))->name == NULL)
  422. return (0);
  423. tnp = hshtab[hshval]; /* lookup sets hshval */
  424. if (tnp == np) /* it's in first place */
  425. hshtab[hshval] = tnp->next;
  426. else {
  427. while (tnp->next != np)
  428. tnp = tnp->next;
  429. tnp->next = np->next;
  430. }
  431. free(np->name);
  432. free(np->def);
  433. free(np);
  434. return (1);
  435. }
  436. static void
  437. doundiv(wchar_t **ap, int c)
  438. {
  439. int i;
  440. if (c <= 0)
  441. for (i = 1; i < 10; i++)
  442. undiv(i, OK);
  443. else
  444. while (--c >= 0)
  445. undiv(wstoi(*++ap), OK);
  446. }
  447. /*
  448. * dowrap
  449. *
  450. * Process m4wrap macro.
  451. */
  452. static void
  453. dowrap(wchar_t **ap, int c)
  454. {
  455. wchar_t *a = arg(1);
  456. struct Wrap *wrapentry; /* entry for list of "m4wrap" strings */
  457. wrapentry = xmalloc(sizeof (struct Wrap));
  458. /* store m4wrap string */
  459. wrapentry->wrapstr = wstrdup(a);
  460. /* add this entry to the front of the list of Wrap entries */
  461. wrapentry->nxt = wrapstart;
  462. wrapstart = wrapentry;
  463. }
  464. static void
  465. mkpid(char *as)
  466. {
  467. char *s = as;
  468. char *l;
  469. char *first_X;
  470. unsigned xcnt = 0;
  471. char my_pid[32];
  472. int pid_len;
  473. int i = 0;
  474. /*
  475. * Count number of X.
  476. */
  477. l = &s[strlen(s)-1];
  478. while (l != as) {
  479. if (*l == 'X') {
  480. first_X = l;
  481. l--;
  482. xcnt++;
  483. } else if (xcnt == 0)
  484. l--;
  485. else {
  486. break;
  487. }
  488. }
  489. /*
  490. * 1) If there is no X in the passed string,
  491. * then it just return the passed string.
  492. * 2) If the length of the continuous right most X's of
  493. * the string is shorter than the length of pid,
  494. * then right most X's will be substitued with
  495. * upper digits of pid.
  496. * 3) If the length of the continuous right most X's of
  497. * the string is equat to the length of pid,
  498. * then X's will be replaced with pid.
  499. * 4) If the lenght of the continuous right most X's of
  500. * the string is longer than the length of pid,
  501. * then X's will have leading 0 followed by
  502. * pid.
  503. */
  504. /*
  505. * If there were no X, don't do anything.
  506. */
  507. if (xcnt == 0)
  508. return;
  509. /*
  510. * Get pid
  511. */
  512. (void) snprintf(my_pid, sizeof (my_pid), "%d", (int)getpid());
  513. pid_len = strlen(my_pid);
  514. if (pid_len > xcnt)
  515. my_pid[xcnt] = 0;
  516. else if (pid_len < xcnt) {
  517. while (xcnt != pid_len) {
  518. *first_X++ = '0';
  519. xcnt--;
  520. }
  521. }
  522. /*
  523. * Copy pid
  524. */
  525. while (i != xcnt)
  526. *first_X++ = my_pid[i++];
  527. }
  528. struct bs barray[] = {
  529. dochcom, L"changecom",
  530. docq, L"changequote",
  531. dodecr, L"decr",
  532. dodef, L"define",
  533. dodefn, L"defn",
  534. dodiv, L"divert",
  535. dodivnum, L"divnum",
  536. dodnl, L"dnl",
  537. dodump, L"dumpdef",
  538. doerrp, L"errprint",
  539. doeval, L"eval",
  540. doexit, L"m4exit",
  541. doif, L"ifelse",
  542. doifdef, L"ifdef",
  543. doincl, L"include",
  544. doincr, L"incr",
  545. doindex, L"index",
  546. dolen, L"len",
  547. domake, L"maketemp",
  548. dopopdef, L"popdef",
  549. dopushdef, L"pushdef",
  550. doshift, L"shift",
  551. dosincl, L"sinclude",
  552. dosubstr, L"substr",
  553. dosyscmd, L"syscmd",
  554. dosysval, L"sysval",
  555. dotransl, L"translit",
  556. dotroff, L"traceoff",
  557. dotron, L"traceon",
  558. doundef, L"undefine",
  559. doundiv, L"undivert",
  560. dowrap, L"m4wrap",
  561. 0, 0
  562. };