dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / m4 / common / m4macs.c
blob00aa03615cefb4e862c592a53aae8a2bf4bfd94b
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 (void) fprintf(stderr, "%ws:\t", name);
189 while (*s++)
191 --s;
193 while (s > defnn) {
194 --s;
195 if (is_builtin(*s)) {
196 (void) fprintf(stderr, "<%ws>",
197 barray[builtin_idx(*s)].bname);
198 } else {
199 (void) fputwc(*s, stderr);
202 (void) fputc('\n', stderr);
205 /*ARGSUSED*/
206 static void
207 doerrp(wchar_t **ap, int c)
209 if (c > 0)
210 (void) fprintf(stderr, "%ws", ap[1]);
213 long evalval; /* return value from yacc stuff */
214 wchar_t *pe; /* used by grammar */
216 static void
217 doeval(wchar_t **ap, int c)
219 int base = wstoi(arg(2));
220 int pad = wstoi(arg(3));
221 extern int yyparse(void);
223 evalval = 0;
224 if (c > 0) {
225 pe = ap[1];
226 if (yyparse() != 0)
227 error(gettext(
228 "invalid expression"));
230 pbnbr(evalval, base > 0 ? base:10, pad > 0 ? pad : 1);
234 * doexit
236 * Process m4exit macro.
238 static void
239 doexit(wchar_t **ap, int c)
241 delexit(wstoi(arg(1)), 1);
244 static void
245 doif(wchar_t **ap, int c)
247 if (c < 3)
248 return;
249 while (c >= 3) {
250 if (wcscmp(ap[1], ap[2]) == 0) {
251 pbstr(ap[3]);
252 return;
254 c -= 3;
255 ap += 3;
257 if (c > 0)
258 pbstr(ap[1]);
261 static void
262 doifdef(wchar_t **ap, int c)
264 if (c < 2)
265 return;
267 while (c >= 2) {
268 if (lookup(ap[1])->name != NULL) {
269 pbstr(ap[2]);
270 return;
272 c -= 2;
273 ap += 2;
276 if (c > 0)
277 pbstr(ap[1]);
280 static void
281 doincl(wchar_t **ap, int c)
283 incl(ap, c, 1);
286 static void
287 incl(wchar_t **ap, int c, int noisy)
289 if (c > 0 && wcslen(ap[1]) > 0) {
290 if (ifx >= 9)
291 error(gettext(
292 "input file nesting too deep (9)"));
293 if ((ifile[++ifx] = fopen(wstr2str(ap[1], 0), "r")) == NULL) {
294 --ifx;
295 if (noisy)
296 errorf(gettext("cannot open file: %s"),
297 strerror(errno));
298 } else {
299 ipstk[ifx] = ipflr = ip;
300 setfname(wstr2str(ap[1], 0));
305 static void
306 doincr(wchar_t **ap, int c)
308 pbnum(ctol(arg(1))+1);
311 static void
312 doindex(wchar_t **ap, int c)
314 wchar_t *subj = arg(1);
315 wchar_t *obj = arg(2);
316 int i;
318 for (i = 0; *subj; ++i)
319 if (leftmatch(subj++, obj)) {
320 pbnum((long)i);
321 return;
324 pbnum((long)-1);
327 static int
328 leftmatch(wchar_t *str, wchar_t *substr)
330 while (*substr)
331 if (*str++ != *substr++)
332 return (0);
334 return (1);
337 static void
338 dolen(wchar_t **ap, int c)
340 pbnum((long)wcslen(arg(1)));
343 static void
344 domake(wchar_t **ap, int c)
346 char *path;
348 if (c > 0) {
349 path = wstr2str(ap[1], 1);
350 mkpid(path);
351 pbstr(str2wstr(path, 0));
352 free(path);
356 static void
357 dopopdef(wchar_t **ap, int c)
359 int i;
361 for (i = 1; i <= c; ++i)
362 (void) undef(ap[i]);
365 static void
366 dopushdef(wchar_t **ap, int c)
368 def(ap, c, PUSH);
371 static void
372 doshift(wchar_t **ap, int c)
374 if (c <= 1)
375 return;
377 for (;;) {
378 pbstr(rquote);
379 pbstr(ap[c--]);
380 pbstr(lquote);
382 if (c <= 1)
383 break;
385 pbstr(L",");
389 static void
390 dosincl(wchar_t **ap, int c)
392 incl(ap, c, 0);
395 static void
396 dosubstr(wchar_t **ap, int c)
398 wchar_t *str;
399 int inlen, outlen;
400 int offset, ix;
402 inlen = wcslen(str = arg(1));
403 offset = wstoi(arg(2));
405 if (offset < 0 || offset >= inlen)
406 return;
408 outlen = c >= 3 ? wstoi(ap[3]) : inlen;
409 ix = min(offset+outlen, inlen);
411 while (ix > offset)
412 putbak(str[--ix]);
415 static void
416 dosyscmd(wchar_t **ap, int c)
418 sysrval = 0;
419 if (c > 0) {
420 (void) fflush(stdout);
421 sysrval = system(wstr2str(ap[1], 0));
425 /* ARGSUSED */
426 static void
427 dosysval(wchar_t **ap, int c)
429 pbnum((long)(sysrval < 0 ? sysrval :
430 (sysrval >> 8) & ((1 << 8) - 1)) |
431 ((sysrval & ((1 << 8) - 1)) << 8));
434 static void
435 dotransl(wchar_t **ap, int c)
437 wchar_t *sink, *fr, *sto;
438 wchar_t *source, *to;
440 if (c < 1)
441 return;
443 sink = ap[1];
444 fr = arg(2);
445 sto = arg(3);
447 for (source = ap[1]; *source; source++) {
448 wchar_t *i;
449 to = sto;
450 for (i = fr; *i; ++i) {
451 if (*source == *i)
452 break;
453 if (*to)
454 ++to;
456 if (*i) {
457 if (*to)
458 *sink++ = *to;
459 } else
460 *sink++ = *source;
462 *sink = EOS;
463 pbstr(ap[1]);
466 static void
467 dotroff(wchar_t **ap, int c)
469 struct nlist *np;
471 trace = 0;
473 while (c > 0)
474 if ((np = lookup(ap[c--]))->name)
475 np->tflag = 0;
478 static void
479 dotron(wchar_t **ap, int c)
481 struct nlist *np;
483 trace = !*arg(1);
485 while (c > 0)
486 if ((np = lookup(ap[c--]))->name)
487 np->tflag = 1;
490 void
491 doundef(wchar_t **ap, int c)
493 int i;
495 for (i = 1; i <= c; ++i)
496 while (undef(ap[i]))
501 undef(wchar_t *nam)
503 struct nlist *np, *tnp;
505 if ((np = lookup(nam))->name == NULL)
506 return (0);
507 tnp = hshtab[hshval]; /* lookup sets hshval */
508 if (tnp == np) /* it's in first place */
509 hshtab[hshval] = tnp->next;
510 else {
511 while (tnp->next != np)
512 tnp = tnp->next;
514 tnp->next = np->next;
516 free(np->name);
517 free(np->def);
518 free(np);
519 return (1);
522 static void
523 doundiv(wchar_t **ap, int c)
525 int i;
527 if (c <= 0)
528 for (i = 1; i < 10; i++)
529 undiv(i, OK);
530 else
531 while (--c >= 0)
532 undiv(wstoi(*++ap), OK);
536 * dowrap
538 * Process m4wrap macro.
540 static void
541 dowrap(wchar_t **ap, int c)
543 wchar_t *a = arg(1);
544 struct Wrap *wrapentry; /* entry for list of "m4wrap" strings */
546 wrapentry = xmalloc(sizeof (struct Wrap));
547 /* store m4wrap string */
548 wrapentry->wrapstr = wstrdup(a);
549 /* add this entry to the front of the list of Wrap entries */
550 wrapentry->nxt = wrapstart;
551 wrapstart = wrapentry;
554 static void
555 mkpid(char *as)
557 char *s = as;
558 char *l;
559 char *first_X;
560 unsigned xcnt = 0;
561 char my_pid[32];
562 int pid_len;
563 int i = 0;
566 * Count number of X.
568 l = &s[strlen(s)-1];
569 while (l != as) {
570 if (*l == 'X') {
571 first_X = l;
572 l--;
573 xcnt++;
574 } else if (xcnt == 0)
575 l--;
576 else {
577 break;
582 * 1) If there is no X in the passed string,
583 * then it just return the passed string.
584 * 2) If the length of the continuous right most X's of
585 * the string is shorter than the length of pid,
586 * then right most X's will be substitued with
587 * upper digits of pid.
588 * 3) If the length of the continuous right most X's of
589 * the string is equat to the length of pid,
590 * then X's will be replaced with pid.
591 * 4) If the lenght of the continuous right most X's of
592 * the string is longer than the length of pid,
593 * then X's will have leading 0 followed by
594 * pid.
598 * If there were no X, don't do anything.
600 if (xcnt == 0)
601 return;
604 * Get pid
606 (void) snprintf(my_pid, sizeof (my_pid), "%d", (int)getpid());
607 pid_len = strlen(my_pid);
609 if (pid_len > xcnt)
610 my_pid[xcnt] = 0;
611 else if (pid_len < xcnt) {
612 while (xcnt != pid_len) {
613 *first_X++ = '0';
614 xcnt--;
619 * Copy pid
621 while (i != xcnt)
622 *first_X++ = my_pid[i++];
625 struct bs barray[] = {
626 dochcom, L"changecom",
627 docq, L"changequote",
628 dodecr, L"decr",
629 dodef, L"define",
630 dodefn, L"defn",
631 dodiv, L"divert",
632 dodivnum, L"divnum",
633 dodnl, L"dnl",
634 dodump, L"dumpdef",
635 doerrp, L"errprint",
636 doeval, L"eval",
637 doexit, L"m4exit",
638 doif, L"ifelse",
639 doifdef, L"ifdef",
640 doincl, L"include",
641 doincr, L"incr",
642 doindex, L"index",
643 dolen, L"len",
644 domake, L"maketemp",
645 dopopdef, L"popdef",
646 dopushdef, L"pushdef",
647 doshift, L"shift",
648 dosincl, L"sinclude",
649 dosubstr, L"substr",
650 dosyscmd, L"syscmd",
651 dosysval, L"sysval",
652 dotransl, L"translit",
653 dotroff, L"traceoff",
654 dotron, L"traceon",
655 doundef, L"undefine",
656 doundiv, L"undivert",
657 dowrap, L"m4wrap",
658 0, 0