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 #if !defined(__lint) /* lint doesn't grok "%ws" */
188 (void) fprintf(stderr
, "%ws:\t", name
);
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
);
203 (void) fputwc(*s
, stderr
);
206 (void) fputc('\n', stderr
);
211 doerrp(wchar_t **ap
, int c
)
213 #if !defined(__lint) /* lint doesn't grok "%ws" */
215 (void) fprintf(stderr
, "%ws", ap
[1]);
219 long evalval
; /* return value from yacc stuff */
220 wchar_t *pe
; /* used by grammar */
223 doeval(wchar_t **ap
, int c
)
225 int base
= wstoi(arg(2));
226 int pad
= wstoi(arg(3));
227 extern int yyparse(void);
234 "invalid expression"));
236 pbnbr(evalval
, base
> 0 ? base
:10, pad
> 0 ? pad
: 1);
242 * Process m4exit macro.
245 doexit(wchar_t **ap
, int c
)
247 delexit(wstoi(arg(1)), 1);
251 doif(wchar_t **ap
, int c
)
256 if (wcscmp(ap
[1], ap
[2]) == 0) {
268 doifdef(wchar_t **ap
, int c
)
274 if (lookup(ap
[1])->name
!= NULL
) {
287 doincl(wchar_t **ap
, int c
)
293 incl(wchar_t **ap
, int c
, int noisy
)
295 if (c
> 0 && wcslen(ap
[1]) > 0) {
298 "input file nesting too deep (9)"));
299 if ((ifile
[++ifx
] = fopen(wstr2str(ap
[1], 0), "r")) == NULL
) {
302 errorf(gettext("cannot open file: %s"),
305 ipstk
[ifx
] = ipflr
= ip
;
306 setfname(wstr2str(ap
[1], 0));
312 doincr(wchar_t **ap
, int c
)
314 pbnum(ctol(arg(1))+1);
318 doindex(wchar_t **ap
, int c
)
320 wchar_t *subj
= arg(1);
321 wchar_t *obj
= arg(2);
324 for (i
= 0; *subj
; ++i
)
325 if (leftmatch(subj
++, obj
)) {
334 leftmatch(wchar_t *str
, wchar_t *substr
)
337 if (*str
++ != *substr
++)
344 dolen(wchar_t **ap
, int c
)
346 pbnum((long)wcslen(arg(1)));
350 domake(wchar_t **ap
, int c
)
355 path
= wstr2str(ap
[1], 1);
357 pbstr(str2wstr(path
, 0));
363 dopopdef(wchar_t **ap
, int c
)
367 for (i
= 1; i
<= c
; ++i
)
372 dopushdef(wchar_t **ap
, int c
)
378 doshift(wchar_t **ap
, int c
)
396 dosincl(wchar_t **ap
, int c
)
402 dosubstr(wchar_t **ap
, int c
)
408 inlen
= wcslen(str
= arg(1));
409 offset
= wstoi(arg(2));
411 if (offset
< 0 || offset
>= inlen
)
414 outlen
= c
>= 3 ? wstoi(ap
[3]) : inlen
;
415 ix
= min(offset
+outlen
, inlen
);
422 dosyscmd(wchar_t **ap
, int c
)
426 (void) fflush(stdout
);
427 sysrval
= system(wstr2str(ap
[1], 0));
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));
441 dotransl(wchar_t **ap
, int c
)
443 wchar_t *sink
, *fr
, *sto
;
444 wchar_t *source
, *to
;
453 for (source
= ap
[1]; *source
; source
++) {
456 for (i
= fr
; *i
; ++i
) {
473 dotroff(wchar_t **ap
, int c
)
480 if ((np
= lookup(ap
[c
--]))->name
)
485 dotron(wchar_t **ap
, int c
)
492 if ((np
= lookup(ap
[c
--]))->name
)
497 doundef(wchar_t **ap
, int c
)
501 for (i
= 1; i
<= c
; ++i
)
509 struct nlist
*np
, *tnp
;
511 if ((np
= lookup(nam
))->name
== NULL
)
513 tnp
= hshtab
[hshval
]; /* lookup sets hshval */
514 if (tnp
== np
) /* it's in first place */
515 hshtab
[hshval
] = tnp
->next
;
517 while (tnp
->next
!= np
)
520 tnp
->next
= np
->next
;
529 doundiv(wchar_t **ap
, int c
)
534 for (i
= 1; i
< 10; i
++)
538 undiv(wstoi(*++ap
), OK
);
544 * Process m4wrap macro.
547 dowrap(wchar_t **ap
, int c
)
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
;
580 } else if (xcnt
== 0)
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
604 * If there were no X, don't do anything.
612 (void) snprintf(my_pid
, sizeof (my_pid
), "%d", (int)getpid());
613 pid_len
= strlen(my_pid
);
617 else if (pid_len
< xcnt
) {
618 while (xcnt
!= pid_len
) {
628 *first_X
++ = my_pid
[i
++];
631 struct bs barray
[] = {
632 dochcom
, L
"changecom",
633 docq
, L
"changequote",
652 dopushdef
, L
"pushdef",
654 dosincl
, L
"sinclude",
658 dotransl
, L
"translit",
659 dotroff
, L
"traceoff",
661 doundef
, L
"undefine",
662 doundiv
, L
"undivert",