PageRenderTime 26ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/educational-vms/string_rewriting/m4/m4macs.c

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