1 char rcsid[] = "$Header: perly.c,v 1.0.1.2 88/01/24 00:06:03 root Exp $";
4 * Revision 1.0.1.2 88/01/24 00:06:03 root
5 * patch 2: s/(abc)/\1/ grandfathering didn't work right.
7 * Revision 1.0.1.1 88/01/21 21:25:57 root
8 * Now uses CPP and CPPMINUS symbols from config.h.
10 * Revision 1.0 87/12/18 15:53:31 root
15 bool preprocess = FALSE;
16 bool assume_n = FALSE;
17 bool assume_p = FALSE;
18 bool doswitches = FALSE;
20 char *e_tmpname = "/tmp/perl-eXXXXXX";
33 linestr = str_new(80);
34 str = str_make("-I/usr/lib/perl "); /* first used for -I flags */
35 for (argc--,argv++; argc; argc--,argv++) {
36 if (argv[0][0] != '-' || !argv[0][1])
42 debug = atoi(argv[0]+2);
44 yydebug = (debug & 1);
51 e_fp = fopen(e_tmpname,"w");
59 inplace = savestr(argv[0]+2);
60 argvoutstab = stabent("ARGVOUT",TRUE);
73 strcpy(argv[0], argv[0]+1);
77 strcpy(argv[0], argv[0]+1);
81 strcpy(argv[0], argv[0]+1);
85 strcpy(argv[0], argv[0]+1);
96 fatal("Unrecognized switch: %s\n",argv[0]);
107 str_set(&str_yes,Yes);
112 if (argv[0] == Nullch)
114 filename = savestr(argv[0]);
115 if (strEQ(filename,"-"))
119 /bin/sed -e '/^[^#]/b' \
120 -e '/^#[ ]*include[ ]/b' \
121 -e '/^#[ ]*define[ ]/b' \
122 -e '/^#[ ]*if[ ]/b' \
123 -e '/^#[ ]*ifdef[ ]/b' \
125 -e '/^#[ ]*endif/b' \
128 argv[0], CPP, str_get(str), CPPMINUS);
129 rsfp = popen(buf,"r");
134 rsfp = fopen(argv[0],"r");
136 fatal("Perl script \"%s\" doesn't seem to exist.\n",filename);
137 str_free(str); /* free -I directories */
139 defstab = stabent("_",TRUE);
143 bufptr = str_get(linestr);
145 /* now parse the report spec */
148 fatal("Execution aborted due to compilation errors.\n");
154 argc--,argv++; /* skip name of script */
156 for (; argc > 0 && **argv == '-'; argc--,argv++) {
157 if (argv[0][1] == '-') {
161 str_numset(stabent(argv[0]+1,TRUE)->stab_val,(double)1.0);
164 if (argvstab = stabent("ARGV",FALSE)) {
165 for (; argc > 0; argc--,argv++) {
166 apush(argvstab->stab_array,str_make(argv[0]));
169 if (envstab = stabent("ENV",FALSE)) {
170 for (; *env; env++) {
171 if (!(s = index(*env,'=')))
175 str->str_link.str_magic = envstab;
176 hstore(envstab->stab_hash,*env,str);
180 sigstab = stabent("SIG",FALSE);
182 magicalize("!#?^~=-%0123456789.+&*(),\\/[|");
184 (tmpstab = stabent("0",FALSE)) && str_set(STAB_STR(tmpstab),filename);
185 (tmpstab = stabent("$",FALSE)) &&
186 str_numset(STAB_STR(tmpstab),(double)getpid());
188 tmpstab = stabent("stdin",TRUE);
189 tmpstab->stab_io = stio_new();
190 tmpstab->stab_io->fp = stdin;
192 tmpstab = stabent("stdout",TRUE);
193 tmpstab->stab_io = stio_new();
194 tmpstab->stab_io->fp = stdout;
195 defoutstab = tmpstab;
196 curoutstab = tmpstab;
198 tmpstab = stabent("stderr",TRUE);
199 tmpstab->stab_io = stio_new();
200 tmpstab->stab_io->fp = stderr;
202 setjmp(top_env); /* sets goto_targ on longjump */
206 dump_cmd(main_root,Nullcmd);
208 fprintf(stderr,"\nEXECUTING...\n\n");
213 (void) cmd_exec(main_root);
216 fatal("Can't find label \"%s\"--aborting.\n",goto_targ);
227 while (*sym = *list++) {
228 if (stab = stabent(sym,FALSE)) {
229 stab->stab_flags = SF_VMAGIC;
230 stab->stab_val->str_link.str_magic = stab;
235 #define RETURN(retval) return (bufptr = s,retval)
236 #define OPERATOR(retval) return (expectterm = TRUE,bufptr = s,retval)
237 #define TERM(retval) return (expectterm = FALSE,bufptr = s,retval)
238 #define LOOPX(f) return (yylval.ival = f,expectterm = FALSE,bufptr = s,LOOPEX)
239 #define UNI(f) return (yylval.ival = f,expectterm = TRUE,bufptr = s,UNIOP)
240 #define FUN0(f) return (yylval.ival = f,expectterm = FALSE,bufptr = s,FUNC0)
241 #define FUN1(f) return (yylval.ival = f,expectterm = FALSE,bufptr = s,FUNC1)
242 #define FUN2(f) return (yylval.ival = f,expectterm = FALSE,bufptr = s,FUNC2)
243 #define FUN3(f) return (yylval.ival = f,expectterm = FALSE,bufptr = s,FUNC3)
244 #define SFUN(f) return (yylval.ival = f,expectterm = FALSE,bufptr = s,STABFUN)
248 register char *s = bufptr;
251 static bool in_format = FALSE;
252 static bool firstline = TRUE;
258 fprintf(stderr,"Tokener at %s",s);
260 fprintf(stderr,"Tokener at %s\n",s);
265 "Unrecognized character %c in file %s line %d--ignoring.\n",
269 s = str_get(linestr);
271 if (firstline && (assume_n || assume_p)) {
273 str_set(linestr,"while (<>) {");
274 s = str_get(linestr);
280 yylval.formval = load_format(); /* leaves . in buffer */
282 s = str_get(linestr);
286 if ((s = str_gets(linestr, rsfp)) == Nullch) {
289 else if (rsfp != stdin)
292 if (assume_n || assume_p) {
293 str_set(linestr,assume_p ? "}continue{print;" : "");
294 str_cat(linestr,"}");
295 s = str_get(linestr);
298 s = str_get(linestr);
302 else if (firstline) {
314 if (preprocess && s == str_get(linestr) &&
315 s[1] == ' ' && isdigit(s[2])) {
317 for (s += 2; isdigit(*s); s++) ;
318 while (*s && isspace(*s)) s++;
321 s[strlen(s)-1] = '\0'; /* wipe out newline */
322 filename = savestr(s);
323 s = str_get(linestr);
413 while (isalpha(*s) || isdigit(*s) || *s == '_') \
419 if (s[1] == '#' && (isalpha(s[2]) || s[2] == '_')) {
421 s = scanreg(s,tokenbuf);
422 yylval.stabval = aadd(stabent(tokenbuf,TRUE));
425 s = scanreg(s,tokenbuf);
426 yylval.stabval = stabent(tokenbuf,TRUE);
430 s = scanreg(s,tokenbuf);
431 yylval.stabval = aadd(stabent(tokenbuf,TRUE));
434 case '/': /* may either be division or pattern */
435 case '?': /* may either be conditional or pattern */
444 if (!expectterm || !isdigit(s[1])) {
453 case '0': case '1': case '2': case '3': case '4':
454 case '5': case '6': case '7': case '8': case '9':
455 case '\'': case '"': case '`':
461 yylval.cval = savestr(d);
465 yylval.cval = savestr(d);
469 yylval.cval = savestr(d);
473 if (strEQ(d,"continue"))
475 if (strEQ(d,"chdir"))
477 if (strEQ(d,"close"))
479 if (strEQ(d,"crypt"))
483 if (strEQ(d,"chmod")) {
484 yylval.ival = O_CHMOD;
487 if (strEQ(d,"chown")) {
488 yylval.ival = O_CHOWN;
491 yylval.cval = savestr(d);
499 yylval.cval = savestr(d);
505 if (strEQ(d,"elsif"))
507 if (strEQ(d,"eq") || strEQ(d,"EQ"))
517 if (strEQ(d,"exec")) {
518 yylval.ival = O_EXEC;
521 yylval.cval = savestr(d);
527 if (strEQ(d,"format")) {
533 yylval.cval = savestr(d);
537 if (strEQ(d,"gt") || strEQ(d,"GT"))
539 if (strEQ(d,"ge") || strEQ(d,"GE"))
543 if (strEQ(d,"gmtime"))
545 yylval.cval = savestr(d);
551 yylval.cval = savestr(d);
557 if (strEQ(d,"index"))
561 yylval.cval = savestr(d);
567 yylval.cval = savestr(d);
573 if (strEQ(d,"kill")) {
574 yylval.ival = O_KILL;
577 yylval.cval = savestr(d);
583 if (strEQ(d,"length"))
585 if (strEQ(d,"lt") || strEQ(d,"LT"))
587 if (strEQ(d,"le") || strEQ(d,"LE"))
589 if (strEQ(d,"localtime"))
595 yylval.cval = savestr(d);
603 yylval.cval = savestr(d);
609 if (strEQ(d,"ne") || strEQ(d,"NE"))
611 yylval.cval = savestr(d);
621 yylval.cval = savestr(d);
625 if (strEQ(d,"print")) {
626 yylval.ival = O_PRINT;
629 if (strEQ(d,"printf")) {
630 yylval.ival = O_PRTF;
633 if (strEQ(d,"push")) {
634 yylval.ival = O_PUSH;
639 yylval.cval = savestr(d);
643 yylval.cval = savestr(d);
647 if (strEQ(d,"reset"))
651 if (strEQ(d,"rename"))
653 yylval.cval = savestr(d);
661 if (strEQ(d,"shift"))
663 if (strEQ(d,"split"))
665 if (strEQ(d,"substr"))
667 if (strEQ(d,"sprintf"))
671 if (strEQ(d,"select"))
679 if (strEQ(d,"sleep"))
681 if (strEQ(d,"system")) {
682 yylval.ival = O_SYSTEM;
685 yylval.cval = savestr(d);
697 if (strEQ(d,"times"))
699 yylval.cval = savestr(d);
703 if (strEQ(d,"using"))
705 if (strEQ(d,"until"))
707 if (strEQ(d,"unless"))
709 if (strEQ(d,"umask"))
711 if (strEQ(d,"unshift")) {
712 yylval.ival = O_UNSHIFT;
715 if (strEQ(d,"unlink")) {
716 yylval.ival = O_UNLINK;
719 yylval.cval = savestr(d);
723 if (strEQ(d,"values"))
725 yylval.cval = savestr(d);
729 if (strEQ(d,"write"))
731 if (strEQ(d,"while"))
733 yylval.cval = savestr(d);
737 if (!expectterm && strEQ(d,"x"))
739 yylval.cval = savestr(d);
747 yylval.cval = savestr(d);
751 yylval.cval = savestr(d);
763 for (stab = stab_index[*name]; stab; stab = stab->stab_next) {
764 if (strEQ(name,stab->stab_name))
768 /* no entry--should we add one? */
771 stab = (STAB *) safemalloc(sizeof(STAB));
772 bzero((char*)stab, sizeof(STAB));
773 stab->stab_name = savestr(name);
774 stab->stab_val = str_new(0);
775 stab->stab_next = stab_index[*name];
776 stab_index[*name] = stab;
785 STIO *stio = (STIO *) safemalloc(sizeof(STIO));
787 bzero((char*)stio, sizeof(STIO));
801 while (isalpha(*s) || isdigit(*s) || *s == '_')
809 while (*s && *s != '}')
819 if (*d == '^' && !isspace(*s))
828 register STR *retstr;
832 if (index(string,'|')) {
835 retstr = str_make(string);
839 case '.': case '[': case '$': case '(': case ')': case '|':
843 if (index("wWbB0123456789",d[1])) {
864 if (d[1] == '*' || d[1] == '+' || d[1] == '?') {
875 retstr->str_cur = strlen(retstr->str_ptr); /* XXX cheating here */
883 register SPAT *spat = (SPAT *) safemalloc(sizeof (SPAT));
886 bzero((char *)spat, sizeof(SPAT));
887 spat->spat_next = spat_root; /* link into spat list */
889 init_compex(&spat->spat_compex);
898 spat->spat_flags |= SPAT_USE_ONCE;
901 fatal("Search pattern not found:\n%s",str_get(linestr));
903 s = cpytill(tokenbuf,s,s[-1]);
905 fatal("Search pattern not terminated:\n%s",str_get(linestr));
907 if (*tokenbuf == '^') {
908 spat->spat_first = scanconst(tokenbuf+1);
909 if (spat->spat_first) {
910 spat->spat_flen = strlen(spat->spat_first->str_ptr);
911 if (spat->spat_flen == strlen(tokenbuf+1))
912 spat->spat_flags |= SPAT_SCANALL;
916 spat->spat_flags |= SPAT_SCANFIRST;
917 spat->spat_first = scanconst(tokenbuf);
918 if (spat->spat_first) {
919 spat->spat_flen = strlen(spat->spat_first->str_ptr);
920 if (spat->spat_flen == strlen(tokenbuf))
921 spat->spat_flags |= SPAT_SCANALL;
924 if (d = compile(&spat->spat_compex,tokenbuf,TRUE,FALSE))
926 yylval.arg = make_match(O_MATCH,stab_to_arg(A_STAB,defstab),spat);
934 register SPAT *spat = (SPAT *) safemalloc(sizeof (SPAT));
937 bzero((char *)spat, sizeof(SPAT));
938 spat->spat_next = spat_root; /* link into spat list */
940 init_compex(&spat->spat_compex);
942 s = cpytill(tokenbuf,s+1,*s);
944 fatal("Substitution pattern not terminated:\n%s",str_get(linestr));
945 for (d=tokenbuf; *d; d++) {
946 if (*d == '$' && d[1] && d[-1] != '\\' && d[1] != '|') {
949 spat->spat_runtime = arg = op_new(1);
950 arg->arg_type = O_ITEM;
951 arg[1].arg_type = A_DOUBLE;
952 arg[1].arg_ptr.arg_str = str_make(tokenbuf);
953 goto get_repl; /* skip compiling for now */
956 if (*tokenbuf == '^') {
957 spat->spat_first = scanconst(tokenbuf+1);
958 if (spat->spat_first)
959 spat->spat_flen = strlen(spat->spat_first->str_ptr);
962 spat->spat_flags |= SPAT_SCANFIRST;
963 spat->spat_first = scanconst(tokenbuf);
964 if (spat->spat_first)
965 spat->spat_flen = strlen(spat->spat_first->str_ptr);
967 if (d = compile(&spat->spat_compex,tokenbuf,TRUE,FALSE))
972 fatal("Substitution replacement not terminated:\n%s",str_get(linestr));
973 spat->spat_repl = yylval.arg;
976 spat->spat_flags &= ~SPAT_USE_ONCE;
979 spat->spat_flags |= SPAT_USE_ONCE;
980 yylval.arg = make_match(O_SUBST,stab_to_arg(A_STAB,defstab),spat);
989 if (arg->arg_type != O_MATCH) {
990 register SPAT *spat = (SPAT *) safemalloc(sizeof (SPAT));
993 bzero((char *)spat, sizeof(SPAT));
994 spat->spat_next = spat_root; /* link into spat list */
996 init_compex(&spat->spat_compex);
998 spat->spat_runtime = arg;
999 arg = make_match(O_MATCH,stab_to_arg(A_STAB,defstab),spat);
1001 arg->arg_type = O_SPLIT;
1002 arg[2].arg_ptr.arg_spat->spat_repl = stab_to_arg(A_STAB,aadd(stab));
1011 register char *d = t;
1015 if (s[1] == '-' && s[2]) {
1016 for (i = s[0]; i <= s[2]; i++)
1032 l(make_op(O_TRANS,2,stab_to_arg(A_STAB,defstab),Nullarg,Nullarg,0));
1035 register char *tbl = safemalloc(256);
1038 arg[2].arg_type = A_NULL;
1039 arg[2].arg_ptr.arg_cval = tbl;
1040 for (i=0; i<256; i++)
1044 fatal("Translation pattern not terminated:\n%s",str_get(linestr));
1045 t = expand_charset(str_get(yylval.arg[1].arg_ptr.arg_str));
1046 free_arg(yylval.arg);
1049 fatal("Translation replacement not terminated:\n%s",str_get(linestr));
1050 r = expand_charset(str_get(yylval.arg[1].arg_ptr.arg_str));
1051 free_arg(yylval.arg);
1057 for (i = 0; t[i]; i++) {
1060 tbl[t[i] & 0377] = r[i];
1072 if (tail == Nullcmd) {
1075 return tail->c_head;
1079 append_line(head,tail)
1083 if (tail == Nullcmd)
1085 if (!tail->c_head) /* make sure tail is well formed */
1086 tail->c_head = tail;
1087 if (head != Nullcmd) {
1088 tail = tail->c_head; /* get to start of tail list */
1090 head->c_head = head; /* start a new head list */
1091 while (head->c_next) {
1092 head->c_next->c_head = head->c_head;
1093 head = head->c_next; /* get to end of head list */
1095 head->c_next = tail; /* link to end of old list */
1096 tail->c_head = head->c_head; /* propagate head pointer */
1098 while (tail->c_next) {
1099 tail->c_next->c_head = tail->c_head;
1100 tail = tail->c_next;
1106 make_acmd(type,stab,cond,arg)
1112 register CMD *cmd = (CMD *) safemalloc(sizeof (CMD));
1114 bzero((char *)cmd, sizeof(CMD));
1116 cmd->ucmd.acmd.ac_stab = stab;
1117 cmd->ucmd.acmd.ac_expr = arg;
1121 cmd->c_flags |= CF_COND;
1127 make_ccmd(type,arg,cblock)
1130 struct compcmd cblock;
1132 register CMD *cmd = (CMD *) safemalloc(sizeof (CMD));
1134 bzero((char *)cmd, sizeof(CMD));
1137 cmd->ucmd.ccmd.cc_true = cblock.comp_true;
1138 cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
1141 cmd->c_flags |= CF_COND;
1147 opt_arg(cmd,fliporflop)
1155 char *tmps; /* for True macro */
1156 int context = 0; /* 0 = normal, 1 = before &&, 2 = before || */
1157 int flp = fliporflop;
1163 /* Turn "if (!expr)" into "unless (expr)" */
1165 while (arg->arg_type == O_NOT && arg[1].arg_type == A_EXPR) {
1166 cmd->c_flags ^= CF_INVERT; /* flip sense of cmd */
1167 cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
1169 arg = cmd->c_expr; /* here we go again */
1172 if (!arg->arg_len) { /* sanity check */
1173 cmd->c_flags |= opt;
1177 /* for "cond .. cond" we set up for the initial check */
1179 if (arg->arg_type == O_FLIP)
1182 /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
1184 if (arg->arg_type == O_AND)
1186 else if (arg->arg_type == O_OR)
1188 if (context && arg[flp].arg_type == A_EXPR) {
1189 arg = arg[flp].arg_ptr.arg_arg;
1193 if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
1194 cmd->c_flags |= opt;
1195 return; /* side effect, can't optimize */
1198 if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
1199 arg->arg_type == O_AND || arg->arg_type == O_OR) {
1200 if (arg[flp].arg_type == A_SINGLE) {
1201 opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
1202 cmd->c_first = arg[flp].arg_ptr.arg_str;
1205 else if (arg[flp].arg_type == A_STAB || arg[flp].arg_type == A_LVAL) {
1206 cmd->c_stab = arg[flp].arg_ptr.arg_stab;
1209 if (!context) { /* no && or ||? */
1211 cmd->c_expr = Nullarg;
1214 cmd->c_flags |= CF_EQSURE;
1216 cmd->c_flags |= CF_NESURE;
1219 else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
1220 arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
1221 if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
1222 arg[2].arg_type == A_SPAT &&
1223 arg[2].arg_ptr.arg_spat->spat_first ) {
1224 cmd->c_stab = arg[1].arg_ptr.arg_stab;
1225 cmd->c_first = arg[2].arg_ptr.arg_spat->spat_first;
1226 cmd->c_flen = arg[2].arg_ptr.arg_spat->spat_flen;
1227 if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANALL &&
1228 (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
1229 sure |= CF_EQSURE; /* (SUBST must be forced even */
1230 /* if we know it will work.) */
1231 arg[2].arg_ptr.arg_spat->spat_first = Nullstr;
1232 arg[2].arg_ptr.arg_spat->spat_flen = 0; /* only one chk */
1233 sure |= CF_NESURE; /* normally only sure if it fails */
1234 if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
1235 cmd->c_flags |= CF_FIRSTNEG;
1236 if (context & 1) { /* only sure if thing is false */
1237 if (cmd->c_flags & CF_FIRSTNEG)
1242 else if (context & 2) { /* only sure if thing is true */
1243 if (cmd->c_flags & CF_FIRSTNEG)
1248 if (sure & (CF_EQSURE|CF_NESURE)) { /* if we know anything*/
1249 if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
1253 if (sure == (CF_EQSURE|CF_NESURE) /* really sure? */
1254 && arg->arg_type == O_MATCH
1256 && fliporflop == 1) {
1257 arg[2].arg_type = A_SINGLE; /* don't do twice */
1258 arg[2].arg_ptr.arg_str = &str_yes;
1260 cmd->c_flags |= sure;
1264 else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
1265 arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
1266 if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
1267 if (arg[2].arg_type == A_SINGLE) {
1268 cmd->c_stab = arg[1].arg_ptr.arg_stab;
1269 cmd->c_first = arg[2].arg_ptr.arg_str;
1270 cmd->c_flen = 30000;
1271 switch (arg->arg_type) {
1272 case O_SLT: case O_SGT:
1274 cmd->c_flags |= CF_FIRSTNEG;
1277 cmd->c_flags |= CF_FIRSTNEG;
1280 sure |= CF_NESURE|CF_EQSURE;
1283 if (context & 1) { /* only sure if thing is false */
1284 if (cmd->c_flags & CF_FIRSTNEG)
1289 else if (context & 2) { /* only sure if thing is true */
1290 if (cmd->c_flags & CF_FIRSTNEG)
1295 if (sure & (CF_EQSURE|CF_NESURE)) {
1297 cmd->c_flags |= sure;
1302 else if (arg->arg_type == O_ASSIGN &&
1303 (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
1304 arg[1].arg_ptr.arg_stab == defstab &&
1305 arg[2].arg_type == A_EXPR ) {
1306 arg2 = arg[2].arg_ptr.arg_arg;
1307 if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
1309 cmd->c_stab = arg2[1].arg_ptr.arg_stab;
1310 if (!(arg2[1].arg_ptr.arg_stab->stab_io->flags & IOF_ARGV)) {
1313 cmd->c_expr = Nullarg;
1317 else if (arg->arg_type == O_CHOP &&
1318 (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
1320 cmd->c_stab = arg[1].arg_ptr.arg_stab;
1322 cmd->c_expr = Nullarg;
1326 cmd->c_flags |= opt;
1328 if (cmd->c_flags & CF_FLIP) {
1329 if (fliporflop == 1) {
1330 arg = cmd->c_expr; /* get back to O_FLIP arg */
1331 arg[3].arg_ptr.arg_cmd = (CMD*)safemalloc(sizeof(CMD));
1332 bcopy((char *)cmd, (char *)arg[3].arg_ptr.arg_cmd, sizeof(CMD));
1333 arg[4].arg_ptr.arg_cmd = (CMD*)safemalloc(sizeof(CMD));
1334 bcopy((char *)cmd, (char *)arg[4].arg_ptr.arg_cmd, sizeof(CMD));
1335 opt_arg(arg[4].arg_ptr.arg_cmd,2);
1336 arg->arg_len = 2; /* this is a lie */
1339 if ((opt & CF_OPTIMIZE) == CFT_EVAL)
1340 cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
1346 mod_match(type,left,pat)
1351 register SPAT *spat;
1352 register ARG *newarg;
1354 if ((pat->arg_type == O_MATCH ||
1355 pat->arg_type == O_SUBST ||
1356 pat->arg_type == O_TRANS ||
1357 pat->arg_type == O_SPLIT
1359 pat[1].arg_ptr.arg_stab == defstab ) {
1360 switch (pat->arg_type) {
1362 newarg = make_op(type == O_MATCH ? O_MATCH : O_NMATCH,
1364 left,Nullarg,Nullarg,0);
1367 newarg = l(make_op(type == O_MATCH ? O_SUBST : O_NSUBST,
1369 left,Nullarg,Nullarg,0));
1372 newarg = l(make_op(type == O_MATCH ? O_TRANS : O_NTRANS,
1374 left,Nullarg,Nullarg,0));
1377 newarg = make_op(type == O_MATCH ? O_SPLIT : O_SPLIT,
1379 left,Nullarg,Nullarg,0);
1382 if (pat->arg_len >= 2) {
1383 newarg[2].arg_type = pat[2].arg_type;
1384 newarg[2].arg_ptr = pat[2].arg_ptr;
1385 newarg[2].arg_flags = pat[2].arg_flags;
1386 if (pat->arg_len >= 3) {
1387 newarg[3].arg_type = pat[3].arg_type;
1388 newarg[3].arg_ptr = pat[3].arg_ptr;
1389 newarg[3].arg_flags = pat[3].arg_flags;
1392 safefree((char*)pat);
1395 spat = (SPAT *) safemalloc(sizeof (SPAT));
1396 bzero((char *)spat, sizeof(SPAT));
1397 spat->spat_next = spat_root; /* link into spat list */
1399 init_compex(&spat->spat_compex);
1401 spat->spat_runtime = pat;
1402 newarg = make_op(type,2,left,Nullarg,Nullarg,0);
1403 newarg[2].arg_type = A_SPAT;
1404 newarg[2].arg_ptr.arg_spat = spat;
1405 newarg[2].arg_flags = AF_SPECIAL;
1428 cmd->c_flags |= CF_COND;
1439 cmd->c_flags |= CF_COND|CF_LOOP;
1440 if (cmd->c_type == C_BLOCK)
1441 cmd->c_flags &= ~CF_COND;
1443 arg = cmd->ucmd.acmd.ac_expr;
1444 if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
1445 cmd->c_flags &= ~CF_COND; /* "do {} while" happens at least once */
1446 if (arg && arg->arg_type == O_SUBR)
1447 cmd->c_flags &= ~CF_COND; /* likewise for "do subr() while" */
1456 cmd->c_flags ^= CF_INVERT;
1464 char *tname = tmpbuf;
1467 tname = tokename[yychar-256];
1468 if (strEQ(tname,"word"))
1469 strcpy(tname,tokenbuf);
1470 else if (strEQ(tname,"register"))
1471 sprintf(tname,"$%s",tokenbuf);
1472 else if (strEQ(tname,"array_length"))
1473 sprintf(tname,"$#%s",tokenbuf);
1476 strcpy(tname,"EOF");
1477 else if (yychar < 32)
1478 sprintf(tname,"^%c",yychar+64);
1479 else if (yychar == 127)
1482 sprintf(tname,"%c",yychar);
1483 printf("%s in file %s at line %d, next token \"%s\"\n",
1484 s,filename,line,tname);
1494 register bool makesingle = FALSE;
1495 char *leave = "\\$nrtfb0123456789"; /* which backslash sequences to keep */
1499 arg->arg_type = O_ITEM;
1502 default: /* a substitution replacement */
1503 arg[1].arg_type = A_DOUBLE;
1504 makesingle = TRUE; /* maybe disable runtime scanning */
1514 arg[1].arg_type = A_SINGLE;
1519 else if (s[1] == '.')
1530 fatal("Illegal octal digit at line %d",line);
1532 case '0': case '1': case '2': case '3': case '4':
1533 case '5': case '6': case '7':
1537 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1538 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1542 i += (*s++ & 7) + 9;
1547 sprintf(tokenbuf,"%d",i);
1548 arg[1].arg_ptr.arg_str = str_make(tokenbuf);
1551 case '1': case '2': case '3': case '4': case '5':
1552 case '6': case '7': case '8': case '9': case '.':
1554 arg[1].arg_type = A_SINGLE;
1556 while (isdigit(*s) || *s == '_')
1558 if (*s == '.' && index("0123456789eE",s[1]))
1560 while (isdigit(*s) || *s == '_')
1562 if (index("eE",*s) && index("+-0123456789",s[1]))
1564 if (*s == '+' || *s == '-')
1569 arg[1].arg_ptr.arg_str = str_make(tokenbuf);
1572 arg[1].arg_type = A_SINGLE;
1578 arg[1].arg_type = A_READ;
1579 s = cpytill(tokenbuf,s+1,'>');
1581 strcpy(tokenbuf,"ARGV");
1584 if (rsfp == stdin && strEQ(tokenbuf,"stdin"))
1585 fatal("Can't get both program and data from <stdin>\n");
1586 arg[1].arg_ptr.arg_stab = stabent(tokenbuf,TRUE);
1587 arg[1].arg_ptr.arg_stab->stab_io = stio_new();
1588 if (strEQ(tokenbuf,"ARGV")) {
1589 aadd(arg[1].arg_ptr.arg_stab);
1590 arg[1].arg_ptr.arg_stab->stab_io->flags |= IOF_ARGV|IOF_START;
1594 arg[1].arg_type = A_DOUBLE;
1595 makesingle = TRUE; /* maybe disable runtime scanning */
1599 arg[1].arg_type = A_BACKTICK;
1607 tmpstr = str_new(strlen(s));
1608 s = str_append_till(tmpstr,s+1,term,leave);
1609 while (!*s) { /* multiple line string? */
1610 s = str_gets(linestr, rsfp);
1612 fatal("EOF in string at line %d\n",sqstart);
1614 s = str_append_till(tmpstr,s,term,leave);
1618 arg[1].arg_ptr.arg_str = tmpstr;
1622 s = d = tmpstr->str_ptr; /* assuming shrinkage only */
1624 if (*s == '$' && s[1]) {
1625 makesingle = FALSE; /* force interpretation */
1626 if (!isalpha(s[1])) { /* an internal register? */
1629 len = scanreg(s,tokenbuf) - s;
1630 stabent(tokenbuf,TRUE); /* make sure it's created */
1636 else if (*s == '\\' && s[1]) {
1641 if (!leave || index(leave,*s))
1645 case '0': case '1': case '2': case '3':
1646 case '4': case '5': case '6': case '7':
1648 if (index("01234567",*s)) {
1652 else if (!index("`\"",term)) { /* oops, a subpattern */
1656 if (index("01234567",*s)) {
1684 if (arg[1].arg_type == A_DOUBLE) {
1686 arg[1].arg_type = A_SINGLE; /* now we can optimize on it */
1689 for (d = s = tmpstr->str_ptr; *s; *d++ = *s++) {
1690 if (*s == '\\' && (!leave || index(leave,s[1])))
1695 tmpstr->str_cur = d - tmpstr->str_ptr; /* XXX cheat */
1696 arg[1].arg_ptr.arg_str = tmpstr;
1705 make_op(type,newlen,arg1,arg2,arg3,dolist)
1717 arg = op_new(newlen);
1718 arg->arg_type = type;
1719 doarg = opargs[type];
1722 arg[1].arg_flags |= AF_SPECIAL;
1724 arg[1].arg_flags |= AF_NUMERIC;
1725 if (chld->arg_type == O_ITEM &&
1726 (hoistable[chld[1].arg_type] || chld[1].arg_type == A_LVAL) ) {
1727 arg[1].arg_type = chld[1].arg_type;
1728 arg[1].arg_ptr = chld[1].arg_ptr;
1729 arg[1].arg_flags |= chld[1].arg_flags;
1733 arg[1].arg_type = A_EXPR;
1734 arg[1].arg_ptr.arg_arg = chld;
1736 if (chld->arg_type == O_LIST) {
1737 if (newlen == 1) { /* we can hoist entire list */
1738 chld->arg_type = type;
1743 arg[1].arg_flags |= AF_SPECIAL;
1746 else if (chld->arg_type == O_ARRAY && chld->arg_len == 1)
1747 arg[1].arg_flags |= AF_SPECIAL;
1753 arg[2].arg_flags |= AF_SPECIAL;
1755 arg[2].arg_flags |= AF_NUMERIC;
1756 if (chld->arg_type == O_ITEM &&
1757 (hoistable[chld[1].arg_type] ||
1758 (type == O_ASSIGN &&
1759 (chld[1].arg_type == A_READ ||
1760 chld[1].arg_type == A_DOUBLE ||
1761 chld[1].arg_type == A_BACKTICK ) ) ) ) {
1762 arg[2].arg_type = chld[1].arg_type;
1763 arg[2].arg_ptr = chld[1].arg_ptr;
1767 arg[2].arg_type = A_EXPR;
1768 arg[2].arg_ptr.arg_arg = chld;
1770 (chld->arg_type == O_LIST ||
1771 (chld->arg_type == O_ARRAY && chld->arg_len == 1) ))
1772 arg[2].arg_flags |= AF_SPECIAL;
1777 arg[3].arg_flags |= AF_SPECIAL;
1779 arg[3].arg_flags |= AF_NUMERIC;
1780 if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type]) {
1781 arg[3].arg_type = chld[1].arg_type;
1782 arg[3].arg_ptr = chld[1].arg_ptr;
1786 arg[3].arg_type = A_EXPR;
1787 arg[3].arg_ptr.arg_arg = chld;
1789 (chld->arg_type == O_LIST ||
1790 (chld->arg_type == O_ARRAY && chld->arg_len == 1) ))
1791 arg[3].arg_flags |= AF_SPECIAL;
1796 fprintf(stderr,"%lx <= make_op(%s",arg,opname[arg->arg_type]);
1798 fprintf(stderr,",%s=%lx",
1799 argname[arg[1].arg_type],arg[1].arg_ptr.arg_arg);
1801 fprintf(stderr,",%s=%lx",
1802 argname[arg[2].arg_type],arg[2].arg_ptr.arg_arg);
1804 fprintf(stderr,",%s=%lx",
1805 argname[arg[3].arg_type],arg[3].arg_ptr.arg_arg);
1806 fprintf(stderr,")\n");
1809 evalstatic(arg); /* see if we can consolidate anything */
1813 /* turn 123 into 123 == $. */
1819 if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_SINGLE) {
1820 arg = (ARG*)saferealloc((char*)arg,3*sizeof(ARG));
1821 arg->arg_type = O_EQ;
1823 arg[2].arg_type = A_STAB;
1824 arg[2].arg_flags = 0;
1825 arg[2].arg_ptr.arg_stab = stabent(".",TRUE);
1837 double value; /* must not be register */
1838 register char *tmps;
1840 double exp(), log(), sqrt(), modf();
1843 if (!arg || !arg->arg_len)
1846 if (arg[1].arg_type == A_SINGLE &&
1847 (arg->arg_len == 1 || arg[2].arg_type == A_SINGLE) ) {
1849 s1 = arg[1].arg_ptr.arg_str;
1850 if (arg->arg_len > 1)
1851 s2 = arg[2].arg_ptr.arg_str;
1854 switch (arg->arg_type) {
1857 str = Nullstr; /* can't be evaluated yet */
1864 i = (int)str_gnum(s2);
1869 value = str_gnum(s1);
1870 str_numset(str,value * str_gnum(s2));
1873 value = str_gnum(s1);
1874 str_numset(str,value / str_gnum(s2));
1877 value = str_gnum(s1);
1878 str_numset(str,(double)(((long)value) % ((long)str_gnum(s2))));
1881 value = str_gnum(s1);
1882 str_numset(str,value + str_gnum(s2));
1885 value = str_gnum(s1);
1886 str_numset(str,value - str_gnum(s2));
1889 value = str_gnum(s1);
1890 str_numset(str,(double)(((long)value) << ((long)str_gnum(s2))));
1893 value = str_gnum(s1);
1894 str_numset(str,(double)(((long)value) >> ((long)str_gnum(s2))));
1897 value = str_gnum(s1);
1898 str_numset(str,(double)(value < str_gnum(s2)));
1901 value = str_gnum(s1);
1902 str_numset(str,(double)(value > str_gnum(s2)));
1905 value = str_gnum(s1);
1906 str_numset(str,(double)(value <= str_gnum(s2)));
1909 value = str_gnum(s1);
1910 str_numset(str,(double)(value >= str_gnum(s2)));
1913 value = str_gnum(s1);
1914 str_numset(str,(double)(value == str_gnum(s2)));
1917 value = str_gnum(s1);
1918 str_numset(str,(double)(value != str_gnum(s2)));
1921 value = str_gnum(s1);
1922 str_numset(str,(double)(((long)value) & ((long)str_gnum(s2))));
1925 value = str_gnum(s1);
1926 str_numset(str,(double)(((long)value) ^ ((long)str_gnum(s2))));
1929 value = str_gnum(s1);
1930 str_numset(str,(double)(((long)value) | ((long)str_gnum(s2))));
1934 str = str_make(str_get(s2));
1936 str = str_make(str_get(s1));
1940 str = str_make(str_get(s1));
1942 str = str_make(str_get(s2));
1945 if (arg[3].arg_type != A_SINGLE) {
1950 str = str_make(str_get(str_true(s1) ? s2 : arg[3].arg_ptr.arg_str));
1951 str_free(arg[3].arg_ptr.arg_str);
1955 str_numset(str,(double)(-str_gnum(s1)));
1958 str_numset(str,(double)(!str_true(s1)));
1961 str_numset(str,(double)(~(long)str_gnum(s1)));
1964 str_numset(str, (double)str_len(s1));
1967 if (arg[3].arg_type != A_SINGLE || stabent("[",FALSE)) {
1968 str_free(str); /* making the fallacious assumption */
1969 str = Nullstr; /* that any $[ occurs before substr()*/
1973 int len = (int)str_gnum(s2);
1976 for (beg = str_get(s1); *beg && len > 0; beg++,len--) ;
1977 len = (int)str_gnum(arg[3].arg_ptr.arg_str);
1978 str_free(arg[3].arg_ptr.arg_str);
1979 if (len > (tmp = strlen(beg)))
1981 str_nset(str,beg,len);
1986 str_numset(str,(double)(strLT(tmps,str_get(s2))));
1990 str_numset(str,(double)(strGT(tmps,str_get(s2))));
1994 str_numset(str,(double)(strLE(tmps,str_get(s2))));
1998 str_numset(str,(double)(strGE(tmps,str_get(s2))));
2002 str_numset(str,(double)(strEQ(tmps,str_get(s2))));
2006 str_numset(str,(double)(strNE(tmps,str_get(s2))));
2010 str_set(str,crypt(tmps,str_get(s2)));
2013 str_numset(str,exp(str_gnum(s1)));
2016 str_numset(str,log(str_gnum(s1)));
2019 str_numset(str,sqrt(str_gnum(s1)));
2022 modf(str_gnum(s1),&value);
2023 str_numset(str,value);
2026 str_numset(str,(double)(*str_get(s1)));
2030 arg->arg_type = O_ITEM; /* note arg1 type is already SINGLE */
2033 arg[1].arg_ptr.arg_str = str;
2045 arg->arg_flags |= AF_COMMON; /* XXX should cross-match */
2047 /* see if it's an array reference */
2049 if (arg[1].arg_type == A_EXPR) {
2050 arg1 = arg[1].arg_ptr.arg_arg;
2052 if (arg1->arg_type == O_LIST && arg->arg_type != O_ITEM) {
2053 /* assign to list */
2054 arg[1].arg_flags |= AF_SPECIAL;
2055 arg[2].arg_flags |= AF_SPECIAL;
2056 for (i = arg1->arg_len; i >= 1; i--) {
2057 switch (arg1[i].arg_type) {
2058 case A_STAB: case A_LVAL:
2059 arg1[i].arg_type = A_LVAL;
2061 case A_EXPR: case A_LEXPR:
2062 arg1[i].arg_type = A_LEXPR;
2063 if (arg1[i].arg_ptr.arg_arg->arg_type == O_ARRAY)
2064 arg1[i].arg_ptr.arg_arg->arg_type = O_LARRAY;
2065 else if (arg1[i].arg_ptr.arg_arg->arg_type == O_HASH)
2066 arg1[i].arg_ptr.arg_arg->arg_type = O_LHASH;
2067 if (arg1[i].arg_ptr.arg_arg->arg_type == O_LARRAY)
2069 if (arg1[i].arg_ptr.arg_arg->arg_type == O_LHASH)
2074 "Illegal item (%s) as lvalue",argname[arg1[i].arg_type]);
2079 else if (arg1->arg_type == O_ARRAY) {
2080 if (arg1->arg_len == 1 && arg->arg_type != O_ITEM) {
2081 /* assign to array */
2082 arg[1].arg_flags |= AF_SPECIAL;
2083 arg[2].arg_flags |= AF_SPECIAL;
2086 arg1->arg_type = O_LARRAY; /* assign to array elem */
2088 else if (arg1->arg_type == O_HASH)
2089 arg1->arg_type = O_LHASH;
2092 "Illegal expression (%s) as lvalue",opname[arg1->arg_type]);
2095 arg[1].arg_type = A_LEXPR;
2098 fprintf(stderr,"lval LEXPR\n");
2103 /* not an array reference, should be a register name */
2105 if (arg[1].arg_type != A_STAB && arg[1].arg_type != A_LVAL) {
2107 "Illegal item (%s) as lvalue",argname[arg[1].arg_type]);
2110 arg[1].arg_type = A_LVAL;
2113 fprintf(stderr,"lval LVAL\n");
2119 addflags(i,flags,arg)
2122 arg[i].arg_flags |= flags;
2130 if (arg->arg_type == O_ARRAY)
2131 return make_op(O_ITEM,1,arg,Nullarg,Nullarg,0);
2141 register ARG *nxtnode;
2147 arg->arg_type = O_LIST;
2149 if (arg->arg_type != O_COMMA) {
2150 arg->arg_flags |= AF_LISTISH; /* see listish() below */
2153 for (i = 2, node = arg; ; i++) {
2154 if (node->arg_len < 2)
2156 if (node[2].arg_type != A_EXPR)
2158 node = node[2].arg_ptr.arg_arg;
2159 if (node->arg_type != O_COMMA)
2165 tmpstr = arg->arg_ptr.arg_str;
2166 *arg = *node; /* copy everything except the STR */
2167 arg->arg_ptr.arg_str = tmpstr;
2175 nxtnode = node[2].arg_ptr.arg_arg;
2180 arg->arg_type = O_LIST;
2185 /* turn a single item into a list */
2191 if (arg->arg_flags & AF_LISTISH)
2192 arg = make_op(O_LIST,1,arg,Nullarg,Nullarg,0);
2197 stab_to_arg(atype,stab)
2199 register STAB *stab;
2204 arg->arg_type = O_ITEM;
2205 arg[1].arg_type = atype;
2206 arg[1].arg_ptr.arg_stab = stab;
2212 register char *cval;
2217 arg->arg_type = O_ITEM;
2218 arg[1].arg_type = A_SINGLE;
2219 arg[1].arg_ptr.arg_str = str_make(cval);
2230 arg = (ARG*)safemalloc((numargs + 1) * sizeof (ARG));
2231 bzero((char *)arg, (numargs + 1) * sizeof (ARG));
2232 arg->arg_ptr.arg_str = str_new(0);
2233 arg->arg_len = numargs;
2241 str_free(arg->arg_ptr.arg_str);
2242 safefree((char*)arg);
2246 make_match(type,expr,spat)
2253 arg = make_op(type,2,expr,Nullarg,Nullarg,0);
2255 arg[2].arg_type = A_SPAT;
2256 arg[2].arg_ptr.arg_spat = spat;
2259 fprintf(stderr,"make_match SPAT=%lx\n",spat);
2262 if (type == O_SUBST || type == O_NSUBST) {
2263 if (arg[1].arg_type != A_STAB)
2264 yyerror("Illegal lvalue");
2265 arg[1].arg_type = A_LVAL;
2277 arg->arg_type = O_ITEM;
2278 arg[1].arg_type = A_CMD;
2279 arg[1].arg_ptr.arg_cmd = cmd;
2288 register ARG *arg = cmd->c_expr;
2289 char *tmps; /* used by True macro */
2291 /* hoist "while (<channel>)" up into command block */
2293 if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
2294 cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
2295 cmd->c_flags |= CFT_GETS; /* and set it to do the input */
2296 cmd->c_stab = arg[1].arg_ptr.arg_stab;
2297 if (arg[1].arg_ptr.arg_stab->stab_io->flags & IOF_ARGV) {
2298 cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$_ =" */
2299 stab_to_arg(A_LVAL,defstab), arg, Nullarg,1 ));
2303 cmd->c_expr = Nullarg;
2307 /* First find the end of the true list */
2309 if (cmd->ucmd.ccmd.cc_true == Nullcmd)
2311 for (tail = cmd->ucmd.ccmd.cc_true; tail->c_next; tail = tail->c_next) ;
2313 /* if there's a continue block, link it to true block and find end */
2315 if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
2316 tail->c_next = cmd->ucmd.ccmd.cc_alt;
2317 for ( ; tail->c_next; tail = tail->c_next) ;
2320 /* Here's the real trick: link the end of the list back to the beginning,
2321 * inserting a "last" block to break out of the loop. This saves one or
2322 * two procedure calls every time through the loop, because of how cmd_exec
2323 * does tail recursion.
2326 tail->c_next = (CMD *) safemalloc(sizeof (CMD));
2327 tail = tail->c_next;
2328 if (!cmd->ucmd.ccmd.cc_alt)
2329 cmd->ucmd.ccmd.cc_alt = tail; /* every loop has a continue now */
2331 bcopy((char *)cmd, (char *)tail, sizeof(CMD));
2332 tail->c_type = C_EXPR;
2333 tail->c_flags ^= CF_INVERT; /* turn into "last unless" */
2334 tail->c_next = tail->ucmd.ccmd.cc_true; /* loop directly back to top */
2335 tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg,0);
2336 tail->ucmd.acmd.ac_stab = Nullstab;
2345 register FCMD *fprev = &froot;
2346 register FCMD *fcmd;
2349 register char tmpchar;
2352 while ((s = str_gets(linestr,rsfp)) != Nullch) {
2354 if (strEQ(s,".\n")) {
2356 return froot.f_next;
2360 flinebeg = Nullfcmd;
2363 fcmd = (FCMD *)safemalloc(sizeof (FCMD));
2364 bzero((char*)fcmd, sizeof (FCMD));
2365 fprev->f_next = fcmd;
2367 for (t=s; *t && *t != '@' && *t != '^'; t++) {
2375 fcmd->f_pre = savestr(s);
2376 fcmd->f_presize = strlen(s);
2381 fcmd->f_flags |= FC_NOBLANK;
2385 flinebeg = fcmd; /* start values here */
2387 fcmd->f_flags |= FC_CHOP; /* for doing text filling */
2390 fcmd->f_type = F_LINES;
2394 fcmd->f_type = F_LEFT;
2399 fcmd->f_type = F_RIGHT;
2404 fcmd->f_type = F_CENTER;
2409 fcmd->f_type = F_LEFT;
2412 if (fcmd->f_flags & FC_CHOP && *s == '.') {
2413 fcmd->f_flags |= FC_MORE;
2421 if ((bufptr = str_gets(linestr ,rsfp)) == Nullch)
2424 if (strEQ(bufptr,".\n")) {
2425 yyerror("Missing values line");
2426 return froot.f_next;
2430 lex_newlines = TRUE;
2431 while (flinebeg || *bufptr) {
2434 yyerror("Bad value in format");
2439 yyerror("Missing value in format");
2443 yylval.arg = stab_to_arg(A_LVAL,yylval.stabval);
2447 yyerror("Extra value in format");
2449 flinebeg->f_expr = yylval.arg;
2451 flinebeg = flinebeg->f_next;
2452 } while (flinebeg && flinebeg->f_size == 0);
2459 lex_newlines = FALSE;
2463 bufptr = str_get(linestr);
2464 yyerror("Format not terminated");
2465 return froot.f_next;