844 m4 should say something useful about why an include()d file can't be opened
[unleashed.git] / usr / src / cmd / sgs / m4 / common / m4macs.c
blob4d86d7c449030cbc5fcd89f0808ef1588e5dc807
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 2011 Gary Mills
31 /* Copyright (c) 1988 AT&T */
32 /* All Rights Reserved */
34 #include <limits.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include "m4.h"
39 #define arg(n) (c < (n) ? nullstr: ap[n])
40 static void mkpid(char *);
41 static void def(wchar_t **, int, int);
42 static void dump(wchar_t *, wchar_t *);
43 static void incl(wchar_t **, int, int);
44 static int leftmatch(wchar_t *, wchar_t *);
46 static void
47 dochcom(wchar_t **ap, int c)
49 wchar_t *l = arg(1);
50 wchar_t *r = arg(2);
52 if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
53 error2(gettext(
54 "comment marker longer than %d chars"), MAXSYM);
55 (void) wcscpy(lcom, l);
56 (void) wcscpy(rcom, *r ? r : L"\n");
59 static void
60 docq(wchar_t **ap, int c)
62 wchar_t *l = arg(1);
63 wchar_t *r = arg(2);
65 if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
66 error2(gettext(
67 "quote marker longer than %d chars"), MAXSYM);
69 if (c <= 1 && !*l) {
70 l = L"`";
71 r = L"'";
72 } else if (c == 1) {
73 r = l;
76 (void) wcscpy(lquote, l);
77 (void) wcscpy(rquote, r);
80 static void
81 dodecr(wchar_t **ap, int c)
83 pbnum(ctol(arg(1))-1);
86 void
87 dodef(wchar_t **ap, int c)
89 def(ap, c, NOPUSH);
92 static void
93 def(wchar_t **ap, int c, int mode)
95 wchar_t *s;
97 if (c < 1)
98 return;
100 s = ap[1];
101 if (is_alpha(*s) || *s == '_') {
102 s++;
103 while (is_alnum(*s) || *s == '_')
104 s++;
106 if (*s || s == ap[1])
107 error(gettext("bad macro name"));
109 if ((ap[2] != NULL) && (wcscmp(ap[1], ap[2]) == 0))
110 error(gettext("macro defined as itself"));
112 install(ap[1], arg(2), mode);
115 static void
116 dodefn(wchar_t **ap, int c)
118 wchar_t *d;
120 while (c > 0)
121 if ((d = lookup(ap[c--])->def) != NULL) {
122 putbak(*rquote);
123 while (*d)
124 putbak(*d++);
125 putbak(*lquote);
129 static void
130 dodiv(wchar_t **ap, int c)
132 int f;
134 f = wstoi(arg(1));
135 if (f >= 10 || f < 0) {
136 cf = NULL;
137 ofx = f;
138 return;
140 tempfile[7] = 'a'+f;
141 if (ofile[f] || (ofile[f] = xfopen(tempfile, "w"))) {
142 ofx = f;
143 cf = ofile[f];
147 /* ARGSUSED */
148 static void
149 dodivnum(wchar_t **ap, int c)
151 pbnum((long)ofx);
154 /* ARGSUSED */
155 static void
156 dodnl(wchar_t **ap, int c)
158 wchar_t t;
160 while ((t = getchr()) != '\n' && t != WEOF)
164 static void
165 dodump(wchar_t **ap, int c)
167 struct nlist *np;
168 int i;
170 if (c > 0)
171 while (c--) {
172 if ((np = lookup(*++ap))->name != NULL)
173 dump(np->name, np->def);
175 else
176 for (i = 0; i < hshsize; i++)
177 for (np = hshtab[i]; np != NULL; np = np->next)
178 dump(np->name, np->def);
181 /*ARGSUSED*/
182 static void
183 dump(wchar_t *name, wchar_t *defnn)
185 wchar_t *s = defnn;
187 #if !defined(__lint) /* lint doesn't grok "%ws" */
188 (void) fprintf(stderr, "%ws:\t", name);
189 #endif
191 while (*s++)
193 --s;
195 while (s > defnn) {
196 --s;
197 if (is_builtin(*s)) {
198 #if !defined(__lint) /* lint doesn't grok "%ws" */
199 (void) fprintf(stderr, "<%ws>",
200 barray[builtin_idx(*s)].bname);
201 } else {
202 #endif
203 (void) fputwc(*s, stderr);
206 (void) fputc('\n', stderr);
209 /*ARGSUSED*/
210 static void
211 doerrp(wchar_t **ap, int c)
213 #if !defined(__lint) /* lint doesn't grok "%ws" */
214 if (c > 0)
215 (void) fprintf(stderr, "%ws", ap[1]);
216 #endif
219 long evalval; /* return value from yacc stuff */
220 wchar_t *pe; /* used by grammar */
222 static void
223 doeval(wchar_t **ap, int c)
225 int base = wstoi(arg(2));
226 int pad = wstoi(arg(3));
227 extern int yyparse(void);
229 evalval = 0;
230 if (c > 0) {
231 pe = ap[1];
232 if (yyparse() != 0)
233 error(gettext(
234 "invalid expression"));
236 pbnbr(evalval, base > 0 ? base:10, pad > 0 ? pad : 1);
240 * doexit
242 * Process m4exit macro.
244 static void
245 doexit(wchar_t **ap, int c)
247 delexit(wstoi(arg(1)), 1);
250 static void
251 doif(wchar_t **ap, int c)
253 if (c < 3)
254 return;
255 while (c >= 3) {
256 if (wcscmp(ap[1], ap[2]) == 0) {
257 pbstr(ap[3]);
258 return;
260 c -= 3;
261 ap += 3;
263 if (c > 0)
264 pbstr(ap[1]);
267 static void
268 doifdef(wchar_t **ap, int c)
270 if (c < 2)
271 return;
273 while (c >= 2) {
274 if (lookup(ap[1])->name != NULL) {
275 pbstr(ap[2]);
276 return;
278 c -= 2;
279 ap += 2;
282 if (c > 0)
283 pbstr(ap[1]);
286 static void
287 doincl(wchar_t **ap, int c)
289 incl(ap, c, 1);
292 static void
293 incl(wchar_t **ap, int c, int noisy)
295 if (c > 0 && wcslen(ap[1]) > 0) {
296 if (ifx >= 9)
297 error(gettext(
298 "input file nesting too deep (9)"));
299 if ((ifile[++ifx] = fopen(wstr2str(ap[1], 0), "r")) == NULL) {
300 --ifx;
301 if (noisy)
302 errorf(gettext("cannot open file: %s"),
303 strerror(errno));
304 } else {
305 ipstk[ifx] = ipflr = ip;
306 setfname(wstr2str(ap[1], 0));
311 static void
312 doincr(wchar_t **ap, int c)
314 pbnum(ctol(arg(1))+1);
317 static void
318 doindex(wchar_t **ap, int c)
320 wchar_t *subj = arg(1);
321 wchar_t *obj = arg(2);
322 int i;
324 for (i = 0; *subj; ++i)
325 if (leftmatch(subj++, obj)) {
326 pbnum((long)i);
327 return;
330 pbnum((long)-1);
333 static int
334 leftmatch(wchar_t *str, wchar_t *substr)
336 while (*substr)
337 if (*str++ != *substr++)
338 return (0);
340 return (1);
343 static void
344 dolen(wchar_t **ap, int c)
346 pbnum((long)wcslen(arg(1)));
349 static void
350 domake(wchar_t **ap, int c)
352 char *path;
354 if (c > 0) {
355 path = wstr2str(ap[1], 1);
356 mkpid(path);
357 pbstr(str2wstr(path, 0));
358 free(path);
362 static void
363 dopopdef(wchar_t **ap, int c)
365 int i;
367 for (i = 1; i <= c; ++i)
368 (void) undef(ap[i]);
371 static void
372 dopushdef(wchar_t **ap, int c)
374 def(ap, c, PUSH);
377 static void
378 doshift(wchar_t **ap, int c)
380 if (c <= 1)
381 return;
383 for (;;) {
384 pbstr(rquote);
385 pbstr(ap[c--]);
386 pbstr(lquote);
388 if (c <= 1)
389 break;
391 pbstr(L",");
395 static void
396 dosincl(wchar_t **ap, int c)
398 incl(ap, c, 0);
401 static void
402 dosubstr(wchar_t **ap, int c)
404 wchar_t *str;
405 int inlen, outlen;
406 int offset, ix;
408 inlen = wcslen(str = arg(1));
409 offset = wstoi(arg(2));
411 if (offset < 0 || offset >= inlen)
412 return;
414 outlen = c >= 3 ? wstoi(ap[3]) : inlen;
415 ix = min(offset+outlen, inlen);
417 while (ix > offset)
418 putbak(str[--ix]);
421 static void
422 dosyscmd(wchar_t **ap, int c)
424 sysrval = 0;
425 if (c > 0) {
426 (void) fflush(stdout);
427 sysrval = system(wstr2str(ap[1], 0));
431 /* ARGSUSED */
432 static void
433 dosysval(wchar_t **ap, int c)
435 pbnum((long)(sysrval < 0 ? sysrval :
436 (sysrval >> 8) & ((1 << 8) - 1)) |
437 ((sysrval & ((1 << 8) - 1)) << 8));
440 static void
441 dotransl(wchar_t **ap, int c)
443 wchar_t *sink, *fr, *sto;
444 wchar_t *source, *to;
446 if (c < 1)
447 return;
449 sink = ap[1];
450 fr = arg(2);
451 sto = arg(3);
453 for (source = ap[1]; *source; source++) {
454 wchar_t *i;
455 to = sto;
456 for (i = fr; *i; ++i) {
457 if (*source == *i)
458 break;
459 if (*to)
460 ++to;
462 if (*i) {
463 if (*to)
464 *sink++ = *to;
465 } else
466 *sink++ = *source;
468 *sink = EOS;
469 pbstr(ap[1]);
472 static void
473 dotroff(wchar_t **ap, int c)
475 struct nlist *np;
477 trace = 0;
479 while (c > 0)
480 if ((np = lookup(ap[c--]))->name)
481 np->tflag = 0;
484 static void
485 dotron(wchar_t **ap, int c)
487 struct nlist *np;
489 trace = !*arg(1);
491 while (c > 0)
492 if ((np = lookup(ap[c--]))->name)
493 np->tflag = 1;
496 void
497 doundef(wchar_t **ap, int c)
499 int i;
501 for (i = 1; i <= c; ++i)
502 while (undef(ap[i]))
507 undef(wchar_t *nam)
509 struct nlist *np, *tnp;
511 if ((np = lookup(nam))->name == NULL)
512 return (0);
513 tnp = hshtab[hshval]; /* lookup sets hshval */
514 if (tnp == np) /* it's in first place */
515 hshtab[hshval] = tnp->next;
516 else {
517 while (tnp->next != np)
518 tnp = tnp->next;
520 tnp->next = np->next;
522 free(np->name);
523 free(np->def);
524 free(np);
525 return (1);
528 static void
529 doundiv(wchar_t **ap, int c)
531 int i;
533 if (c <= 0)
534 for (i = 1; i < 10; i++)
535 undiv(i, OK);
536 else
537 while (--c >= 0)
538 undiv(wstoi(*++ap), OK);
542 * dowrap
544 * Process m4wrap macro.
546 static void
547 dowrap(wchar_t **ap, int c)
549 wchar_t *a = arg(1);
550 struct Wrap *wrapentry; /* entry for list of "m4wrap" strings */
552 wrapentry = xmalloc(sizeof (struct Wrap));
553 /* store m4wrap string */
554 wrapentry->wrapstr = wstrdup(a);
555 /* add this entry to the front of the list of Wrap entries */
556 wrapentry->nxt = wrapstart;
557 wrapstart = wrapentry;
560 static void
561 mkpid(char *as)
563 char *s = as;
564 char *l;
565 char *first_X;
566 unsigned xcnt = 0;
567 char my_pid[32];
568 int pid_len;
569 int i = 0;
572 * Count number of X.
574 l = &s[strlen(s)-1];
575 while (l != as) {
576 if (*l == 'X') {
577 first_X = l;
578 l--;
579 xcnt++;
580 } else if (xcnt == 0)
581 l--;
582 else {
583 break;
588 * 1) If there is no X in the passed string,
589 * then it just return the passed string.
590 * 2) If the length of the continuous right most X's of
591 * the string is shorter than the length of pid,
592 * then right most X's will be substitued with
593 * upper digits of pid.
594 * 3) If the length of the continuous right most X's of
595 * the string is equat to the length of pid,
596 * then X's will be replaced with pid.
597 * 4) If the lenght of the continuous right most X's of
598 * the string is longer than the length of pid,
599 * then X's will have leading 0 followed by
600 * pid.
604 * If there were no X, don't do anything.
606 if (xcnt == 0)
607 return;
610 * Get pid
612 (void) snprintf(my_pid, sizeof (my_pid), "%d", (int)getpid());
613 pid_len = strlen(my_pid);
615 if (pid_len > xcnt)
616 my_pid[xcnt] = 0;
617 else if (pid_len < xcnt) {
618 while (xcnt != pid_len) {
619 *first_X++ = '0';
620 xcnt--;
625 * Copy pid
627 while (i != xcnt)
628 *first_X++ = my_pid[i++];
631 struct bs barray[] = {
632 dochcom, L"changecom",
633 docq, L"changequote",
634 dodecr, L"decr",
635 dodef, L"define",
636 dodefn, L"defn",
637 dodiv, L"divert",
638 dodivnum, L"divnum",
639 dodnl, L"dnl",
640 dodump, L"dumpdef",
641 doerrp, L"errprint",
642 doeval, L"eval",
643 doexit, L"m4exit",
644 doif, L"ifelse",
645 doifdef, L"ifdef",
646 doincl, L"include",
647 doincr, L"incr",
648 doindex, L"index",
649 dolen, L"len",
650 domake, L"maketemp",
651 dopopdef, L"popdef",
652 dopushdef, L"pushdef",
653 doshift, L"shift",
654 dosincl, L"sinclude",
655 dosubstr, L"substr",
656 dosyscmd, L"syscmd",
657 dosysval, L"sysval",
658 dotransl, L"translit",
659 dotroff, L"traceoff",
660 dotron, L"traceon",
661 doundef, L"undefine",
662 doundiv, L"undivert",
663 dowrap, L"m4wrap",
664 0, 0