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 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
39 int donefld
; /* 1 = implies rec broken into fields */
40 int donerec
; /* 1 = record is valid (no flds have changed) */
42 static struct fldtab_chunk
{
43 struct fldtab_chunk
*next
;
44 Cell fields
[FLD_INCR
];
45 } *fldtab_head
, *fldtab_tail
;
47 static size_t fldtab_maxidx
;
49 static FILE *infile
= NULL
;
50 static uchar
*file
= (uchar
*) "";
52 static size_t fields_size
= LINE_INCR
;
54 static int maxfld
= 0; /* last used field */
55 static int argno
= 1; /* current input argument number */
57 static uchar
*getargv(int);
58 static void cleanfld(int, int);
59 static int refldbld(uchar
*, uchar
*);
60 static void bcheck2(int, int, int);
61 static void eprint(void);
62 static void bclass(int);
70 for (i
= 1; i
< *ARGC
; i
++) {
71 if (!isclvar(p
= getargv(i
))) /* find 1st real filename */
73 setclvar(p
); /* a commandline assignment before filename */
76 infile
= stdin
; /* no filenames, so use stdin */
77 /* *FILENAME = file = (uchar*) "-"; */
81 getrec(uchar
**bufp
, size_t *bufsizep
)
84 static int firsttime
= 1;
92 dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
93 *RS
, *FS
, *ARGC
, *FILENAME
));
96 while (argno
< *ARGC
|| infile
== stdin
) {
97 dprintf(("argno=%d, file=|%s|\n", argno
, file
));
98 if (infile
== NULL
) { /* have to open a new file */
99 file
= getargv(argno
);
100 if (*file
== '\0') { /* it's been zapped */
104 if (isclvar(file
)) { /* a var=value arg */
110 dprintf(("opening file %s\n", file
));
111 if (*file
== '-' && *(file
+1) == '\0')
113 else if ((infile
= fopen((char *)file
, "r")) == NULL
)
114 ERROR
"can't open file %s", file FATAL
;
115 (void) setfval(fnrloc
, 0.0);
117 c
= readrec(&nbuf
, &len
, infile
);
118 expand_buf(bufp
, bufsizep
, len
);
120 (void) memcpy(buf
, nbuf
, len
);
124 if (c
!= 0 || buf
[0] != '\0') { /* normal record */
125 if (bufp
== &record
) {
126 if (!(recloc
->tval
& DONTFREE
))
128 recloc
->sval
= record
;
129 recloc
->tval
= REC
| STR
| DONTFREE
;
130 if (is_number(recloc
->sval
)) {
132 atof((const char *)recloc
->sval
);
136 (void) setfval(nrloc
, nrloc
->fval
+1);
137 (void) setfval(fnrloc
, fnrloc
->fval
+1);
140 /* EOF arrived on this file; set up next */
142 (void) fclose(infile
);
146 return (0); /* true end of file */
150 readrec(uchar
**bufp
, size_t *sizep
, FILE *inf
) /* read one record into buf */
157 init_buf(&buf
, &bufsize
, LINE_INCR
);
158 if ((sep
= **RS
) == 0) {
160 /* skip leading \n's */
161 while ((c
= getc(inf
)) == '\n' && c
!= EOF
)
164 (void) ungetc(c
, inf
);
168 while ((c
= getc(inf
)) != sep
&& c
!= EOF
) {
169 expand_buf(&buf
, &bufsize
, count
);
172 if (**RS
== sep
|| c
== EOF
)
174 if ((c
= getc(inf
)) == '\n' || c
== EOF
) /* 2 in a row */
176 expand_buf(&buf
, &bufsize
, count
+ 1);
181 dprintf(("readrec saw <%s>, returns %d\n",
182 buf
, c
== EOF
&& count
== 0 ? 0 : 1));
185 return (c
== EOF
&& count
== 0 ? 0 : 1);
194 extern Array
*ARGVtab
;
196 (void) sprintf((char *)temp
, "%d", n
);
197 x
= setsymtab(temp
, (uchar
*)"", 0.0, STR
, ARGVtab
);
199 dprintf(("getargv(%d) returns |%s|\n", n
, s
));
204 setclvar(uchar
*s
) /* set var=value from s */
209 for (p
= s
; *p
!= '='; p
++)
212 p
= qstring(p
, '\0');
213 q
= setsymtab(s
, p
, 0.0, STR
, symtab
);
214 (void) setsval(q
, p
);
215 if (is_number(q
->sval
)) {
216 q
->fval
= atof((const char *)q
->sval
);
219 dprintf(("command line set %s to |%s|\n", s
, p
));
233 if (!(recloc
->tval
& STR
))
234 (void) getsval(recloc
);
235 r
= recloc
->sval
; /* was record! */
237 /* make sure fields is always allocated */
238 adjust_buf(&fields
, fields_size
);
241 * make sure fields has enough size. We don't expand the buffer
242 * in the middle of the loop, since p->sval has already pointed
243 * the address in the fields.
245 len
= strlen((char *)r
) + 1;
246 expand_buf(&fields
, &fields_size
, len
);
249 i
= 0; /* number of fields accumulated here */
250 if (strlen((char *)*FS
) > 1) { /* it's a regular expression */
251 i
= refldbld(r
, *FS
);
252 } else if ((sep
= **FS
) == ' ') {
254 while (*r
== ' ' || *r
== '\t' || *r
== '\n')
260 if (!(p
->tval
& DONTFREE
))
263 p
->tval
= FLD
| STR
| DONTFREE
;
266 while (*r
!= ' ' && *r
!= '\t' && *r
!= '\n' &&
272 } else if (*r
!= 0) { /* if 0, it's a null field */
276 if (!(p
->tval
& DONTFREE
))
279 p
->tval
= FLD
| STR
| DONTFREE
;
280 /* \n always a separator */
281 while (*r
!= sep
&& *r
!= '\n' && *r
!= '\0')
289 /* clean out junk from previous record */
293 for (i
= 1; i
<= maxfld
; i
++) {
295 if (is_number(p
->sval
)) {
296 p
->fval
= atof((const char *)p
->sval
);
301 (void) setfval(nfloc
, (Awkfloat
) maxfld
);
303 for (i
= 0; i
<= maxfld
; i
++) {
305 (void) printf("field %d: |%s|\n", i
, p
->sval
);
311 cleanfld(int n1
, int n2
) /* clean out fields n1..n2 inclusive */
313 static uchar
*nullstat
= (uchar
*) "";
317 for (i
= n2
; i
> n1
; i
--) {
319 if (!(p
->tval
& DONTFREE
))
321 p
->tval
= FLD
| STR
| DONTFREE
;
327 newfld(int n
) /* add field n (after end) */
330 ERROR
"accessing invalid field", record FATAL
;
334 (void) setfval(nfloc
, (Awkfloat
) n
);
338 * allocate field table. We don't reallocate the table since there
339 * might be somewhere recording the address of the table.
345 struct fldtab_chunk
*fldcp
;
348 if ((fldcp
= calloc(sizeof (struct fldtab_chunk
), 1)) == NULL
)
349 ERROR
"out of space in morefld" FATAL
;
351 newfld
= &fldcp
->fields
[0];
352 for (i
= 0; i
< FLD_INCR
; i
++) {
353 newfld
[i
].ctype
= OCELL
;
354 newfld
[i
].csub
= CFLD
;
355 newfld
[i
].nval
= NULL
;
356 newfld
[i
].sval
= (uchar
*)"";
357 newfld
[i
].fval
= 0.0;
358 newfld
[i
].tval
= FLD
|STR
|DONTFREE
;
359 newfld
[i
].cnext
= NULL
;
362 * link this field chunk
364 if (fldtab_head
== NULL
)
367 fldtab_tail
->next
= fldcp
;
371 fldtab_maxidx
+= FLD_INCR
;
377 struct fldtab_chunk
*fldcp
;
381 ERROR
"trying to access field %d", idx FATAL
;
382 while (idx
>= fldtab_maxidx
)
385 for (fldcp
= fldtab_head
; fldcp
!= NULL
; fldcp
= fldcp
->next
) {
386 if (idx
< (cbase
+ FLD_INCR
))
387 return (&fldcp
->fields
[idx
- cbase
]);
390 /* should never happen */
391 ERROR
"trying to access invalid field %d", idx FATAL
;
398 struct fldtab_chunk
*fldcp
;
403 for (fldcp
= fldtab_head
; fldcp
!= NULL
; fldcp
= fldcp
->next
) {
404 tbl
= &fldcp
->fields
[0];
405 if (vp
>= tbl
&& vp
< (tbl
+ FLD_INCR
))
406 return (cbase
+ (vp
- tbl
));
409 /* should never happen */
410 ERROR
"trying to access unknown field" FATAL
;
415 refldbld(uchar
*rec
, uchar
*fs
) /* build fields from reg expr in FS */
423 /* make sure fields is allocated */
424 adjust_buf(&fields
, fields_size
);
430 len
= strlen((char *)rec
) + 1;
431 expand_buf(&fields
, &fields_size
, len
);
434 pfa
= makedfa(fs
, 1);
435 dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec
, fs
));
436 tempstat
= pfa
->initstat
;
439 if (!(p
->tval
& DONTFREE
))
441 p
->tval
= FLD
| STR
| DONTFREE
;
443 dprintf(("refldbld: i=%d\n", i
));
444 if (nematch(pfa
, rec
)) {
446 dprintf(("match %s (%d chars)\n", patbeg
, patlen
));
447 (void) strncpy((char *)fr
, (char *)rec
, patbeg
-rec
);
448 fr
+= patbeg
- rec
+ 1;
450 rec
= patbeg
+ patlen
;
452 dprintf(("no match %s\n", rec
));
453 (void) strcpy((char *)fr
, (char *)rec
);
454 pfa
->initstat
= tempstat
;
466 size_t cnt
, len
, olen
;
471 olen
= strlen((char *)*OFS
);
472 for (i
= 1; i
<= *NF
; i
++) {
473 p
= getsval(getfld(i
));
474 len
= strlen((char *)p
);
475 expand_buf(&record
, &record_size
, cnt
+ len
+ olen
);
476 (void) memcpy(&record
[cnt
], p
, len
);
479 (void) memcpy(&record
[cnt
], *OFS
, olen
);
484 dprintf(("in recbld FS=%o, recloc=%p\n", **FS
, (void *)recloc
));
485 if (!(recloc
->tval
& DONTFREE
))
487 recloc
->tval
= REC
| STR
| DONTFREE
;
488 recloc
->sval
= record
;
489 dprintf(("in recbld FS=%o, recloc=%p\n", **FS
, (void *)recloc
));
490 dprintf(("recbld = |%s|\n", record
));
498 ERROR
"trying to access field %d", n FATAL
;
508 extern uchar
*cmdname
, *curfname
;
509 static int been_here
= 0;
513 (void) fprintf(stderr
, "%s: %s", cmdname
, s
);
514 (void) fprintf(stderr
, gettext(" at source line %lld"), lineno
);
515 if (curfname
!= NULL
)
516 (void) fprintf(stderr
, gettext(" in function %s"), curfname
);
517 (void) fprintf(stderr
, "\n");
526 ERROR
"floating point exception" FATAL
;
529 extern int bracecnt
, brackcnt
, parencnt
;
535 static int beenhere
= 0;
539 while ((c
= input()) != EOF
&& c
!= '\0')
541 bcheck2(bracecnt
, '{', '}');
542 bcheck2(brackcnt
, '[', ']');
543 bcheck2(parencnt
, '(', ')');
548 bcheck2(int n
, int c1
, int c2
)
551 (void) fprintf(stderr
, gettext("\tmissing %c\n"), c2
);
553 (void) fprintf(stderr
, gettext("\t%d missing %c's\n"), n
, c2
);
555 (void) fprintf(stderr
, gettext("\textra %c\n"), c2
);
557 (void) fprintf(stderr
, gettext("\t%d extra %c's\n"), -n
, c2
);
561 error(int f
, char *s
)
563 extern Node
*curnode
;
564 extern uchar
*cmdname
;
566 (void) fflush(stdout
);
567 (void) fprintf(stderr
, "%s: ", cmdname
);
568 (void) fprintf(stderr
, "%s", s
);
569 (void) fprintf(stderr
, "\n");
570 if (compile_time
!= 2 && NR
&& *NR
> 0) {
571 (void) fprintf(stderr
,
572 gettext(" input record number %g"), *FNR
);
573 if (strcmp((char *)*FILENAME
, "-") != 0)
574 (void) fprintf(stderr
, gettext(", file %s"), *FILENAME
);
575 (void) fprintf(stderr
, "\n");
577 if (compile_time
!= 2 && curnode
)
578 (void) fprintf(stderr
, gettext(" source line number %lld\n"),
580 else if (compile_time
!= 2 && lineno
) {
581 (void) fprintf(stderr
,
582 gettext(" source line number %lld\n"), lineno
);
593 eprint(void) /* try to print context around error */
597 static int been_here
= 0;
598 extern uchar ebuf
[300], *ep
;
600 if (compile_time
== 2 || compile_time
== 0 || been_here
++ > 0)
603 if (p
> ebuf
&& *p
== '\n')
605 for (; p
> ebuf
&& *p
!= '\n' && *p
!= '\0'; p
--)
609 (void) fprintf(stderr
, gettext(" context is\n\t"));
610 for (q
= ep
-1; q
>= p
&& *q
!= ' ' && *q
!= '\t' && *q
!= '\n'; q
--)
614 (void) putc(*p
, stderr
);
615 (void) fprintf(stderr
, " >>> ");
618 (void) putc(*p
, stderr
);
619 (void) fprintf(stderr
, " <<< ");
621 while ((c
= input()) != '\n' && c
!= '\0' && c
!= EOF
) {
622 (void) putc(c
, stderr
);
625 (void) putc('\n', stderr
);
633 case '{': bracecnt
++; break;
634 case '}': bracecnt
--; break;
635 case '[': brackcnt
++; break;
636 case ']': brackcnt
--; break;
637 case '(': parencnt
++; break;
638 case ')': parencnt
--; break;
643 errcheck(double x
, char *s
)
649 ERROR
"%s argument out of domain", s WARNING
;
651 } else if (errno
== ERANGE
) {
653 ERROR
"%s result out of range", s WARNING
;
662 dprintf(("%s\n", s
));
666 isclvar(uchar
*s
) /* is s of form var=something? */
670 /* Must begin with an underscore or alphabetic character */
671 if (isalpha(*s
) || (*s
== '_')) {
675 * followed by a sequence of underscores,
676 * digits, and alphabetics
678 if (!(isalnum(*s
) || *s
== '_')) {
682 return (*s
== '=' && *(s
+ 1) != '=');
689 #define MAXEXPON 38 /* maximum exponent for fp number */
697 extern char radixpoint
;
700 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
703 return (0); /* empty stuff isn't number */
704 if (*s
== '+' || *s
== '-')
706 if (!isdigit(*s
) && *s
!= radixpoint
)
712 } while (isdigit(*s
));
715 return (0); /* too many digits to convert */
716 if (*s
== radixpoint
) {
724 } while (isdigit(*s
));
726 if (!(d1
|| point
&& d2
))
728 if (*s
== 'e' || *s
== 'E') {
730 if (*s
== '+' || *s
== '-')
737 } while (isdigit(*s
));
740 } else if (s
- es
== 2 &&
741 (int)(10 * (*es
-'0') + *(es
+1)-'0') >= MAXEXPON
) {
745 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
754 init_buf(uchar
**optr
, size_t *sizep
, size_t amt
)
758 if ((nptr
= malloc(amt
)) == NULL
)
759 ERROR
"out of space in init_buf" FATAL
;
760 /* initial buffer should have NULL terminated */
768 r_expand_buf(uchar
**optr
, size_t *sizep
, size_t req
)
771 size_t amt
, size
= *sizep
;
773 if (size
!= 0 && req
< (size
- 1))
775 amt
= req
+ 1 - size
;
776 amt
= (amt
/ LINE_INCR
+ 1) * LINE_INCR
;
778 if ((nptr
= realloc(*optr
, size
+ amt
)) == NULL
)
779 ERROR
"out of space in expand_buf" FATAL
;
780 /* initial buffer should have NULL terminated */
788 adjust_buf(uchar
**optr
, size_t size
)
792 if ((nptr
= realloc(*optr
, size
)) == NULL
)
793 ERROR
"out of space in adjust_buf" FATAL
;