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 (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 #define tempfree(a) {if (istemp(a)) {xfree(a->sval); a->tval = 0; }}
41 #define RECSIZE BUFSIZ
52 extern CELL
*execute(), *nodetoobj(), *fieldel(), *dopa2(), *gettemp();
55 int pairstack
[PA2NUM
], paircnt
;
60 static CELL truecell
={ OBOOL
, BTRUE
, 0, 0, 0.0, NUM
, 0 };
61 CELL
*true = &truecell
;
62 static CELL falsecell
={ OBOOL
, BFALSE
, 0, 0, 0.0, NUM
, 0 };
63 CELL
*false = &falsecell
;
64 static CELL breakcell
={ OJUMP
, JBREAK
, 0, 0, 0.0, NUM
, 0 };
65 CELL
*jbreak
= &breakcell
;
66 static CELL contcell
={ OJUMP
, JCONT
, 0, 0, 0.0, NUM
, 0 };
67 CELL
*jcont
= &contcell
;
68 static CELL nextcell
={ OJUMP
, JNEXT
, 0, 0, 0.0, NUM
, 0 };
69 CELL
*jnext
= &nextcell
;
70 static CELL exitcell
={ OJUMP
, JEXIT
, 0, 0, 0.0, NUM
, 0 };
71 CELL
*jexit
= &exitcell
;
72 static CELL tempcell
={ OCELL
, CTEMP
, 0, 0, 0.0, NUM
, 0 };
74 static void redirprint(wchar_t *s
, int a
, NODE
*b
);
76 void freesymtab(CELL
*ap
);
85 /* Wait for children to complete if output to a pipe. */
86 for (i
=0; i
<FILENUM
; i
++)
87 if (files
[i
].fp
&& files
[i
].type
== '|')
101 for (a
= u
; /* dummy */; a
= a
->nnext
) {
103 return (nodetoobj(a
));
104 if (notlegal(a
->nobj
))
105 error(FATAL
, "illegal statement %o", a
);
106 proc
= proctab
[a
->nobj
-FIRSTTOKEN
];
107 x
= (*proc
)(a
->narg
, a
->nobj
);
112 /* a statement, goto next statement */
115 if (a
->nnext
== (NODE
*)NULL
)
125 program(NODE
**a
, int n
)
134 error(FATAL
, "unexpected break, continue or next");
147 if (isbreak(x
) || isnext(x
) || iscont(x
))
148 error(FATAL
, "unexpected break, continue or next");
163 setfval(x
, (awkfloat
) getrec());
171 array(NODE
**a
, int n
)
174 extern CELL
*arrayel();
177 y
= arrayel(a
[0], x
);
186 arrayel(NODE
*a
, CELL
*b
)
195 if (!(x
->tval
&ARR
)) {
199 x
->sval
= (wchar_t *) makesymtab();
201 y
= setsymtab(s
, tostring(L_NULL
), 0.0, STR
|NUM
, x
->sval
);
208 matchop(NODE
**a
, int n
)
218 if (n
== MATCH
&& i
== 1 || n
== NOTMATCH
&& i
== 0)
228 boolop(NODE
**a
, int n
)
241 if (i
) return (true);
245 if (i
) return (true);
248 if (!i
) return (false);
252 if (i
) return (true);
255 if (i
) return (false);
258 error(FATAL
, "unknown boolean operator %d", n
);
267 relop(NODE
**a
, int n
)
279 if (x
->tval
&NUM
&& y
->tval
&NUM
) {
280 j
= x
->fval
- y
->fval
;
281 i
= j
<0? -1: (j
>0? 1: 0);
293 case LT
: if (i
<0) return (true);
295 case LE
: if (i
<=0) return (true);
297 case NE
: if (i
!=0) return (true);
299 case EQ
: if (i
== 0) return (true);
301 case GE
: if (i
>=0) return (true);
303 case GT
: if (i
>0) return (true);
306 error(FATAL
, "unknown relational operator %d", n
);
327 for (i
=0; i
<MAXTMP
; i
++)
328 if (tmps
[i
].tval
== 0)
331 error(FATAL
, "out of temporaries in gettemp");
341 indirect(NODE
**a
, int n
)
360 substr(NODE
**a
, int nnn
)
392 dprintf("substr: m=%d, n=%d, s=%ws\n", m
, n
, s
);
395 s
[n
+m
-1] = (wchar_t)0x0;
396 setsval(x
, s
+ m
- 1);
406 sindex(NODE
**a
, int nnn
)
409 wchar_t *s1
, *s2
, *p1
, *p2
, *q
;
419 for (p1
= s1
; *p1
!= (wchar_t)0x0; p1
++) {
420 for (q
=p1
, p2
=s2
; *p2
!= (wchar_t)0x0 && *q
== *p2
; q
++, p2
++)
422 if (*p2
== (wchar_t)0x0) {
423 setfval(x
, (awkfloat
) (p1
- s1
+ 1)); /* origin 1 */
435 format(wchar_t *s
, NODE
*a
)
437 wchar_t *buf
, *ep
, *str
;
441 wchar_t tbuf
[2*RECSIZE
];
448 p
= buf
= (wchar_t *)malloc(RECSIZE
* sizeof (wchar_t));
451 error(FATAL
, "out of space in format");
463 for (t
=fmt
; *s
!= '\0'; s
++)
465 if (*s
== 's' || *s
== 'c')
468 if (*s
>= 'a' && *s
<= 'z' && *s
!= 'l')
473 "not enough arguments in printf(%ws) or sprintf(%ws)",
478 sprintf(t
-1, "%d", (int) getfval(x
));
479 t
= fmt
+ strlen(fmt
);
485 if (t
>= fmt
+ sizeof (fmt
))
486 error(FATAL
, "format item %.20ws... too long", os
);
488 case 'f': case 'e': case 'g':
493 if (*(s
-1) == 'l') break;
499 flag
= *(s
-1) == 'l' ? 2 : 3;
512 wsprintf(p
, "%s", fmt
);
518 "not enough arguments in printf(%ws) or sprintf(%ws)", os
, os
);
524 * Get the string to check length; %s is the usual problem;
525 * other conversions can cause overrun if they occur when
526 * the buffer is almost filled.
528 if (flag
== 4) { /* watch out for converting to numbers! */
533 if (flag
== 1) wsprintf(tbuf
, fmt
, xf
);
534 else if (flag
== 2) wsprintf(tbuf
, fmt
, (long)xf
);
535 else if (flag
== 3) wsprintf(tbuf
, fmt
, (int)xf
);
536 if (wslen(tbuf
) >= RECSIZE
)
537 error(FATAL
, "formatted item %s... too long",
542 * If string overruns the buffer, reallocate;
543 * consider length of format string
545 if (p
+ wslen(str
) + wslen(s
) + 1 >= ep
) {
549 /* Add RECSIZE for additional space */
550 newlen
= oldlen
+ wslen(str
) + RECSIZE
;
551 buf
= realloc(buf
, (unsigned) newlen
* sizeof(wchar_t));
553 error(FATAL
, "out of format space");
557 /* Transfer string to buffer */
559 wsprintf(p
, fmt
, str
);
566 error(FATAL
, "formatted string too long");
575 a_sprintf(NODE
**a
, int n
)
583 s
= format(getsval(x
), y
);
593 arith(NODE
**a
, int n
)
619 error(FATAL
, "division by zero");
624 error(FATAL
, "division by zero");
625 i
= i
- j
*(long)(i
/j
);
631 error(FATAL
, "illegal arithmetic operator %d", n
);
641 incrdecr(NODE
**a
, int n
)
649 k
= (n
== PREINCR
|| n
== POSTINCR
) ? 1 : -1;
650 if (n
== PREINCR
|| n
== PREDECR
) {
664 assign(NODE
**a
, int n
)
674 if (n
== ASSIGN
) { /* ordinary assignment */
675 if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
680 } else if (y
->tval
& STR
)
682 else if (y
->tval
& NUM
)
701 error(FATAL
, "division by zero");
706 error(FATAL
, "division by zero");
707 xf
= xf
- yf
*(long)(xf
/yf
);
710 error(FATAL
, "illegal assignment operator %d", n
);
737 if ((s
= (wchar_t *) malloc((n1
+ n2
+ 1) * sizeof (wchar_t))) == NULL
)
738 error(FATAL
, "out of space in cat");
740 wscpy(s
+n1
, y
->sval
);
753 pastat(NODE
**a
, int n
)
775 dopa2(NODE
**a
, int n
)
784 if (pairstack
[pair
] == 0) {
790 if (pairstack
[pair
] == 1) {
805 aprintf(NODE
**a
, int n
)
814 printf("%ws", x
->sval
);
818 redirprint(x
->sval
, (int)a
[1], a
[2]);
826 split(NODE
**a
, int nnn
)
831 wchar_t *t
, temp
, num
[5];
850 dprintf("split: s=|%ws|, a=%ws, sep=|%wc|\n", s
, ap
->nval
, sep
);
853 ap
->sval
= (wchar_t *) makesymtab();
860 for (n
= 0; /* dummy */; /* dummy */) {
862 while (iswblank(c
) || c
== '\t' || c
== '\n')
870 while (! iswblank(c
) && c
!= '\t' &&
871 c
!= '\n' && c
!= '\0');
874 wsprintf(num
, "%d", n
);
876 setsymtab(num
, tostring(t
),
877 watof(t
), STR
|NUM
, ap
->sval
);
879 setsymtab(num
, tostring(t
), 0.0, STR
, ap
->sval
);
888 while ((c
= *s
) != sep
&& c
!= '\n' && c
!= '\0')
892 wsprintf(num
, "%d", n
);
894 setsymtab(num
, tostring(t
),
895 watof(t
), STR
|NUM
, ap
->sval
);
897 setsymtab(num
, tostring(t
), 0.0, STR
, ap
->sval
);
912 ifstat(NODE
**a
, int n
)
924 } else if (a
[2] != 0) {
935 whilestat(NODE
**a
, int n
)
944 if (!istrue(x
)) return (x
);
951 if (isnext(x
) || isexit(x
))
961 forstat(NODE
**a
, int n
)
974 if (!istrue(x
)) return (x
);
978 if (isbreak(x
)) { /* turn off break */
982 if (isnext(x
) || isexit(x
))
994 instat(NODE
**a
, int n
)
996 CELL
*vp
, *arrayp
, *cp
, **tp
;
1004 arrayp
= (CELL
*) a
[1];
1005 if (!(arrayp
->tval
& ARR
))
1006 error(FATAL
, "%ws is not an array", arrayp
->nval
);
1007 tp
= (CELL
**) arrayp
->sval
;
1008 for (i
= 0; i
< MAXSYM
; i
++) { /* this routine knows too much */
1009 for (cp
= tp
[i
]; cp
!= NULL
; cp
= cp
->nextval
) {
1010 setsval(vp
, cp
->nval
);
1016 if (isnext(x
) || isexit(x
))
1028 jump(NODE
**a
, int n
)
1039 errorflag
= getfval(y
);
1049 error(FATAL
, "illegal jump type %d", n
);
1058 fncn(NODE
**a
, int n
)
1068 u
= (awkfloat
) wslen(getsval(x
));
1070 u
= log(getfval(x
));
1072 u
= (awkfloat
) (long) getfval(x
);
1074 u
= exp(getfval(x
));
1075 else if (t
== FSQRT
)
1076 u
= sqrt(getfval(x
));
1078 error(FATAL
, "illegal function type %d", t
);
1089 print(NODE
**a
, int n
)
1094 wchar_t *ss
, *bp
, *ep
, *os
;
1095 size_t blen
, newlen
, sslen
, orslen
, ofslen
, oslen
;
1102 orslen
= wcslen(*ORS
);
1103 ofslen
= wcslen(*OFS
);
1105 for (x
= a
[0]; x
!= NULL
; x
= x
->nnext
) {
1109 /* total new length will be */
1111 if (x
->nnext
== NULL
) {
1118 newlen
= blen
+ sslen
+ oslen
;
1120 /* allocate larger buffer if needed */
1121 if (ep
< (bp
+ newlen
+ 1)) {
1122 wchar_t *oldbp
= bp
;
1126 bp
= realloc(bp
, sizeof (wchar_t) * (newlen
+ 1));
1128 error(FATAL
, "out of space in print");
1129 ep
= bp
+ newlen
+ 1;
1131 (void) wmemcpy(bp
, oldbp
, blen
);
1133 (void) wmemcpy(bp
+ blen
, ss
, sslen
);
1134 (void) wmemcpy(bp
+ blen
+ sslen
, os
, oslen
);
1140 (void) printf("%ws", bp
);
1146 redirprint(bp
, (int)a
[1], a
[2]);
1167 x
= (CELL
*) a
->nobj
;
1169 x
->csub
= a
->subtype
;
1176 redirprint(wchar_t *s
, int a
, NODE
*b
)
1183 for (i
=0; i
<FILENUM
; i
++)
1184 if (files
[i
].fname
&& wscmp(x
->sval
, files
[i
].fname
) == 0)
1186 for (i
=0; i
<FILENUM
; i
++)
1187 if (files
[i
].fp
== 0)
1190 error(FATAL
, "too many output files %d", i
);
1191 if (a
== '|') /* a pipe! */
1192 files
[i
].fp
= popen(toeuccode(x
->sval
), "w");
1193 else if (a
== APPEND
)
1194 files
[i
].fp
= fopen(toeuccode(x
->sval
), "a");
1196 files
[i
].fp
= fopen(toeuccode(x
->sval
), "w");
1198 error(FATAL
, "illegal redirection near line %lld", lineno
);
1199 if (files
[i
].fp
== NULL
)
1200 error(FATAL
, "can't open file %ws", x
->sval
);
1201 files
[i
].fname
= tostring(x
->sval
);
1204 fprintf(files
[i
].fp
, "%ws", s
);
1206 fflush(files
[i
].fp
); /* in case someone is waiting for the output */