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]
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 */
36 #include <sys/types.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 *);
47 dochcom(wchar_t **ap
, int c
)
52 if (wcslen(l
) > MAXSYM
|| wcslen(r
) > MAXSYM
)
54 "comment marker longer than %d chars"), MAXSYM
);
55 (void) wcscpy(lcom
, l
);
56 (void) wcscpy(rcom
, *r
? r
: L
"\n");
60 docq(wchar_t **ap
, int c
)
65 if (wcslen(l
) > MAXSYM
|| wcslen(r
) > MAXSYM
)
67 "quote marker longer than %d chars"), MAXSYM
);
76 (void) wcscpy(lquote
, l
);
77 (void) wcscpy(rquote
, r
);
81 dodecr(wchar_t **ap
, int c
)
83 pbnum(ctol(arg(1))-1);
87 dodef(wchar_t **ap
, int c
)
93 def(wchar_t **ap
, int c
, int mode
)
101 if (is_alpha(*s
) || *s
== '_') {
103 while (is_alnum(*s
) || *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
);
116 dodefn(wchar_t **ap
, int c
)
121 if ((d
= lookup(ap
[c
--])->def
) != NULL
) {
130 dodiv(wchar_t **ap
, int c
)
135 if (f
>= 10 || f
< 0) {
141 if (ofile
[f
] || (ofile
[f
] = xfopen(tempfile
, "w"))) {
149 dodivnum(wchar_t **ap
, int c
)
156 dodnl(wchar_t **ap
, int c
)
160 while ((t
= getchr()) != '\n' && t
!= WEOF
)
165 dodump(wchar_t **ap
, int c
)
172 if ((np
= lookup(*++ap
))->name
!= NULL
)
173 dump(np
->name
, np
->def
);
176 for (i
= 0; i
< hshsize
; i
++)
177 for (np
= hshtab
[i
]; np
!= NULL
; np
= np
->next
)
178 dump(np
->name
, np
->def
);
183 dump(wchar_t *name
, wchar_t *defnn
)
187 (void) fprintf(stderr
, "%ws:\t", name
);
195 if (is_builtin(*s
)) {
196 (void) fprintf(stderr
, "<%ws>",
197 barray
[builtin_idx(*s
)].bname
);
199 (void) fputwc(*s
, stderr
);
202 (void) fputc('\n', stderr
);
207 doerrp(wchar_t **ap
, int c
)
210 (void) fprintf(stderr
, "%ws", ap
[1]);
213 long evalval
; /* return value from yacc stuff */
214 wchar_t *pe
; /* used by grammar */
217 doeval(wchar_t **ap
, int c
)
219 int base
= wstoi(arg(2));
220 int pad
= wstoi(arg(3));
221 extern int yyparse(void);
228 "invalid expression"));
230 pbnbr(evalval
, base
> 0 ? base
:10, pad
> 0 ? pad
: 1);
236 * Process m4exit macro.
239 doexit(wchar_t **ap
, int c
)
241 delexit(wstoi(arg(1)), 1);
245 doif(wchar_t **ap
, int c
)
250 if (wcscmp(ap
[1], ap
[2]) == 0) {
262 doifdef(wchar_t **ap
, int c
)
268 if (lookup(ap
[1])->name
!= NULL
) {
281 doincl(wchar_t **ap
, int c
)
287 incl(wchar_t **ap
, int c
, int noisy
)
289 if (c
> 0 && wcslen(ap
[1]) > 0) {
292 "input file nesting too deep (9)"));
293 if ((ifile
[++ifx
] = fopen(wstr2str(ap
[1], 0), "r")) == NULL
) {
296 errorf(gettext("cannot open file: %s"),
299 ipstk
[ifx
] = ipflr
= ip
;
300 setfname(wstr2str(ap
[1], 0));
306 doincr(wchar_t **ap
, int c
)
308 pbnum(ctol(arg(1))+1);
312 doindex(wchar_t **ap
, int c
)
314 wchar_t *subj
= arg(1);
315 wchar_t *obj
= arg(2);
318 for (i
= 0; *subj
; ++i
)
319 if (leftmatch(subj
++, obj
)) {
328 leftmatch(wchar_t *str
, wchar_t *substr
)
331 if (*str
++ != *substr
++)
338 dolen(wchar_t **ap
, int c
)
340 pbnum((long)wcslen(arg(1)));
344 domake(wchar_t **ap
, int c
)
349 path
= wstr2str(ap
[1], 1);
351 pbstr(str2wstr(path
, 0));
357 dopopdef(wchar_t **ap
, int c
)
361 for (i
= 1; i
<= c
; ++i
)
366 dopushdef(wchar_t **ap
, int c
)
372 doshift(wchar_t **ap
, int c
)
390 dosincl(wchar_t **ap
, int c
)
396 dosubstr(wchar_t **ap
, int c
)
402 inlen
= wcslen(str
= arg(1));
403 offset
= wstoi(arg(2));
405 if (offset
< 0 || offset
>= inlen
)
408 outlen
= c
>= 3 ? wstoi(ap
[3]) : inlen
;
409 ix
= min(offset
+outlen
, inlen
);
416 dosyscmd(wchar_t **ap
, int c
)
420 (void) fflush(stdout
);
421 sysrval
= system(wstr2str(ap
[1], 0));
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));
435 dotransl(wchar_t **ap
, int c
)
437 wchar_t *sink
, *fr
, *sto
;
438 wchar_t *source
, *to
;
447 for (source
= ap
[1]; *source
; source
++) {
450 for (i
= fr
; *i
; ++i
) {
467 dotroff(wchar_t **ap
, int c
)
474 if ((np
= lookup(ap
[c
--]))->name
)
479 dotron(wchar_t **ap
, int c
)
486 if ((np
= lookup(ap
[c
--]))->name
)
491 doundef(wchar_t **ap
, int c
)
495 for (i
= 1; i
<= c
; ++i
)
503 struct nlist
*np
, *tnp
;
505 if ((np
= lookup(nam
))->name
== NULL
)
507 tnp
= hshtab
[hshval
]; /* lookup sets hshval */
508 if (tnp
== np
) /* it's in first place */
509 hshtab
[hshval
] = tnp
->next
;
511 while (tnp
->next
!= np
)
514 tnp
->next
= np
->next
;
523 doundiv(wchar_t **ap
, int c
)
528 for (i
= 1; i
< 10; i
++)
532 undiv(wstoi(*++ap
), OK
);
538 * Process m4wrap macro.
541 dowrap(wchar_t **ap
, int c
)
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
;
574 } else if (xcnt
== 0)
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
598 * If there were no X, don't do anything.
606 (void) snprintf(my_pid
, sizeof (my_pid
), "%d", (int)getpid());
607 pid_len
= strlen(my_pid
);
611 else if (pid_len
< xcnt
) {
612 while (xcnt
!= pid_len
) {
622 *first_X
++ = my_pid
[i
++];
625 struct bs barray
[] = {
626 dochcom
, L
"changecom",
627 docq
, L
"changequote",
646 dopushdef
, L
"pushdef",
648 dosincl
, L
"sinclude",
652 dotransl
, L
"translit",
653 dotroff
, L
"traceoff",
655 doundef
, L
"undefine",
656 doundiv
, L
"undivert",