vm: include no-caching bits in PTF_ALLFLAGS for flags sanity check.
[minix.git] / commands / awk.old / r.c
blobe9630252f4291d4cc653047f587d15bee6f1105c
1 /*
2 * a small awk clone
4 * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
6 * Absolutely no warranty. Use this software with your own risk.
8 * Permission to use, copy, modify and distribute this software for any
9 * purpose and without fee is hereby granted, provided that the above
10 * copyright and disclaimer notice.
12 * This program was written to fit into 64K+64K memory of the Minix 1.2.
16 #include <stdio.h>
17 #include <ctype.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #ifdef DOS
22 #include <process.h>
23 #endif
24 #include "awk.h"
25 #include "regexp.h"
27 #define MAXFLD 100
29 extern char **FS, **RS, **OFS, **ORS, **FILENAME;
30 extern double *NF, *NR;
31 extern double *FNR;
32 extern double *ARGC;
33 extern SYMBOL *argtab[];
34 extern CELL *getvar();
36 char *strsave(), *strcpy(), *getsval(), *jStrchr(), *strchr();
37 double getfval(), atof();
38 CELL *mkcell(), *mktmp(), *execute(), *patexec();
39 FILE *efopen();
41 extern CELL truecell, falsecell;
43 extern int pateval;
45 int infileno = 1;
46 FILE *ifp;
47 char record[BUFSIZ];
48 CELL *field[MAXFLD];
50 char *fs_str;
51 regexp *fs_pat;
53 CELL *
54 Getline(p) NODE *p;
56 CELL *u;
57 char *fnam, *s, str[BUFSIZ];
58 int i;
59 FILE *fp, *getfp();
61 if ((int) p->n_arg[0]) /* read into var */
62 s = str;
63 else
64 s = NULL;
65 if ((int) p->n_arg[1]) { /* file name */
66 u = execute(p->n_arg[1]);
67 fnam = getsval(u);
68 fp = getfp(fnam, (int) p->n_arg[2]);
69 c_free(u);
70 i = get1rec(s, fp);
72 else
73 i = Getrec(s);
74 if (s == str) {
75 u = execute(p->n_arg[0]);
76 setsval(u, str);
78 return mktmp(NUM, NULL, (double) i);
81 static
82 get1rec(buf, fp) char *buf; FILE *fp;
84 register int c;
85 register char rs, *s;
86 int mflg;
88 if (buf == NULL)
89 buf = record;
90 if ((rs = **RS) == '\0') { /* multi line record */
91 mflg = 1;
92 rs = '\n';
94 else
95 mflg = 0;
97 if (feof(fp) || (c = getc(fp)) == EOF)
98 return 0;
99 for (s = buf; ; ) {
100 for ( ; c != rs && c != EOF; c = getc(fp)) {
101 if (isKanji(c)) {
102 *s++ = c; c = getc(fp);
104 *s++ = c;
106 if (mflg) {
107 if ((c = getc(fp)) == '\n' || c == EOF)
108 break;
109 *s++ = '\n';
111 else
112 break;
114 *s = '\0';
115 #if 1
116 if (buf == record) {
117 #else
118 if (buf == record && c != EOF) {
119 #endif
120 mkfld(record, *FS, field);
121 (*NR)++;
122 (*FNR)++;
124 return s > buf || c != EOF ? 1 : 0;
127 Getrec(s) char *s;
129 CELL *u;
130 char *file, str[8];
132 while (ifp == stdin || infileno < (int)*ARGC) {
133 if (ifp == NULL) {
134 *FNR = 0.0;
135 if (infileno == (int)*ARGC)
136 break;
137 sprintf(str, "%d", infileno);
138 u = getvar(str, argtab);
139 file = getsval(u);
140 if (strchr(file, '=') != NULL) {
141 setvar(file);
142 infileno++;
143 continue;
145 else if (strcmp(file, "") == 0) {
147 if (infileno == (int)*ARGC - 1)
148 ifp = stdin;
150 infileno++;
151 continue;
153 else {
154 if (strcmp(file, "-") == 0)
155 ifp = stdin;
156 else
157 ifp = efopen(file, "r");
158 *FILENAME = file;
161 if (get1rec(s, ifp))
162 return 1;
163 else {
164 if (ifp != stdin)
165 fclose(ifp);
166 ifp = NULL;
167 infileno++;
170 ifp = stdin; /* for further "getline" */
171 *FILENAME = "-";
172 return 0; /* EOF */
175 mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
177 char *s, *t;
178 char str[BUFSIZ];
179 int i, j, n;
180 int skip = 0;
182 if (strlen(sep) > 1)
183 return r_mkfld(rec, sep, fld);
185 if (*sep == ' ' || *sep == '\0') {
186 sep = " \t\n"; skip++;
188 for (i = 1, n = (int) *NF; i <= n; i++) {
189 sfree(fld[i]->c_sval);
190 sfree(fld[i]);
191 fld[i] = NULL;
193 for (i = 0, s = rec; ; ) {
194 t = str;
195 if (skip) {
196 while (*s && strchr(" \t\n", *s))
197 s++;
198 if (*s == '\0')
199 break;
201 while (*s && !jStrchr(sep, *s)) {
202 if (isKanji(*s))
203 *t++ = *s++;
204 *t++ = *s++;
206 *t = '\0';
207 if (isnum(str))
208 fld[++i] = mkcell(FLD|STR|NUM, str, atof(str));
209 else
210 fld[++i] = mkcell(FLD|STR, str, 0.0);
211 if (*s)
212 s++;
213 else
214 break;
216 *NF = (double) i;
217 return i;
220 static
221 r_mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
223 char *s, *t;
224 char str[BUFSIZ];
225 int i, n;
226 regexp *mkpat();
227 extern int r_start, r_length;
229 if (strcmp(*FS, fs_str) != 0) {
230 sfree(fs_str); sfree(fs_pat);
231 fs_str = strsave(*FS);
232 fs_pat = mkpat(fs_str);
234 for (i = 1, n = (int) *NF; i <= n; i++) {
235 sfree(fld[i]->c_sval);
236 sfree(fld[i]);
237 fld[i] = NULL;
239 for (i = 0, s = rec, t = str; *s; ) {
240 if (match(fs_pat, s)) {
241 for (n = r_start; --n > 0; )
242 *t++ = *s++;
244 else {
245 while (*s)
246 *t++ = *s++;
248 *t = '\0';
249 t = str;
250 fld[++i] = mkcell(FLD|STR, str, 0.0);
251 if (*s)
252 s += r_length;
254 *NF = (double) i;
255 return i;
258 mkrec(u) CELL *u;
260 register char *s, *t;
261 register int i, j;
263 for (j = (int)*NF, i = 1; i <= j; i++)
264 if (field[i] == u)
265 break;
266 if (i > j) {
267 for ( ; i < MAXFLD; i++)
268 if (field[i] == u)
269 break;
270 if (i == MAXFLD)
271 error("too many field (%d)", i);
272 *NF = (double)i;
274 for (t = record, i = 1, j = (int) *NF; i <= j; i++) {
275 if (i > 1)
276 *t++ = **OFS;
277 for (s = getsval(field[i]); *s; )
278 *t++ = *s++;
280 *t++ = '\0';
283 CELL *
284 Field(p) NODE *p;
286 CELL *u;
287 int i, j;
289 u = execute(p->n_arg[0]);
290 i = (int) getfval(u);
291 c_free(u);
292 j = (int)*NF;
293 if (i > j)
294 for (++j; j <= i; j++) {
295 if (field[j] == NULL)
296 field[j] = mkcell(FLD|STR, "", 0.0);
298 return field[i];
301 CELL *
302 P1stat(p) NODE *p;
304 CELL *u;
305 double x;
307 pateval++;
308 u = execute(p->n_arg[0]);
309 pateval = 0;
310 x = getfval(u);
311 c_free(u);
312 if (x != 0.0)
313 u = execute(p->n_arg[1]);
314 else
315 u = &truecell;
316 return u;
319 CELL *
320 P2stat(p) NODE *p;
322 static stat = 0;
323 CELL *u, *v;
324 double x;
326 switch (stat) {
327 case 0:
328 pateval++;
329 u = execute(p->n_arg[0]);
330 pateval = 0;
331 x = getfval(u);
332 c_free(u);
333 if (x == 0.0) {
334 u = &truecell; break;
336 else
337 stat++;
338 /* fall through */
339 case 1:
340 u = execute(p->n_arg[2]);
341 c_free(u);
342 pateval++;
343 u = execute(p->n_arg[1]);
344 pateval = 0;
345 x = getfval(u);
346 if (x != 0.0)
347 stat = 0;
348 break;
349 default:
350 u = &truecell;
351 break;
353 return u;
356 CELL *
357 Print0()
360 int i, j;
361 char *s, str[BUFSIZ];
363 for (*str = '\0', i = 1, j = (int) *NF; i <= j; i++) {
364 if (i > 1)
365 strcat(str, *OFS);
366 s = getsval(field[i]);
367 strcat(str, s);
369 strcat(str, *ORS);
370 fputs(str, stdout);
372 fprintf(stdout, "%s%s", record, *ORS);
373 return &truecell;
376 char *
377 format(t, p) char *t; NODE *p;
379 CELL *u, *v;
380 char *r, *s, *s0, fmt[BUFSIZ];
381 double x;
382 int i;
384 u = execute(p->n_arg[2]);
385 s = s0 = getsval(u);
387 printf("fmt(%s)\n", s);
389 for (i = 3; *s; s++) {
390 if (isKanji(*s)) {
391 *t++ = *s++; *t++ = *s; continue;
393 if (*s != '%') {
394 *t++ = *s; continue;
396 else if (*(s + 1) == '%') {
397 *t++ = *s++; continue;
399 for (r = fmt, *r++ = *s++; *r++ = *s; s++) {
400 if (strchr("%cdefgosux", *s))
401 break;
403 *r = '\0';
404 if (p->n_arg[i] == NULL)
405 error("not enough args in printf(%s)", s0);
406 v = execute(p->n_arg[i++]);
407 if (*s == 's')
408 r = getsval(v);
409 else
410 x = getfval(v);
412 printf("val(%d)(%s)\n", v->c_type, v->c_sval);
414 switch (*s) {
415 case 'c':
416 sprintf(t, fmt, (int) x);
417 break;
418 case 'd':
419 if (*(s - 1) != 'l') {
420 *--r = 'l'; *++r = 'd'; *++r = '\0';
422 sprintf(t, fmt, (long) x);
423 break;
424 case 'e': case 'f': case 'g':
425 sprintf(t, fmt, x);
426 break;
427 case 'o': case 'u': case 'x':
428 if (*(s - 1) == 'l')
429 sprintf(t, fmt, (long) x);
430 else
431 sprintf(t, fmt, (int) x);
432 break;
433 case 's':
434 /*r = getsval(v);*/
435 sprintf(t, fmt, r);
436 break;
437 default:
438 strcpy(t, fmt);
439 break;
441 c_free(v);
442 t += strlen(t);
444 c_free(u);
445 *t = '\0';
448 #define MAXFILE 10
449 struct {
450 char *f_name; /* file name */
451 FILE *f_fp;
452 int f_type;
453 } filetab[MAXFILE];
455 FILE *
456 getfp(file, type) char *file;
458 register int i;
459 register char *name, *mode;
460 char *awktmp();
461 FILE *fp, *efopen(), *epopen();
463 for (i = 0; i < MAXFILE; i++)
464 if (filetab[i].f_name && strcmp(filetab[i].f_name, file) == 0)
465 return filetab[i].f_fp;
466 for (i = 0; i < MAXFILE; i++)
467 if (!filetab[i].f_fp)
468 break;
469 if (i == MAXFILE)
470 error("too many files to open");
471 name = file;
472 switch (type) {
473 case R_OUT: mode = "w"; break;
474 case R_APD: mode = "a"; break;
475 case R_POUT:
476 #ifdef DOS
477 name = awktmp(i); mode = "w"; /* MS-DOS */
478 #else
479 fp = epopen(file, "w");
480 goto g1;
481 #endif
482 break;
483 case R_IN: mode = "r"; break;
484 case R_PIN:
485 #ifdef DOS
487 int savefd, fd, result;
489 name = awktmp(i);
490 if ((fd = open(name,
491 O_WRONLY|O_TEXT|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE)) == -1)
492 error("can't open %s", name);
493 savefd = dup(1); dup2(fd, 1); close(fd);
494 if ((result =
495 system(file)) == -1)
496 error("can't exec %s", file);
497 dup2(savefd, 1); close(savefd); close(fd);
498 mode = "r";
500 #else
501 fp = epopen(file,"r");
502 goto g1;
503 #endif
504 break;
506 fp = efopen(name, mode);
508 filetab[i].f_name = strsave(file);
509 filetab[i].f_type = type;
510 filetab[i].f_fp = fp;
511 return fp;
514 closeall()
516 register int i;
518 for (i = 0; i < MAXFILE; i++)
519 close1(i);
522 CELL *
523 Close(s) char *s;
525 register int i;
527 for (i = 0; i < MAXFILE; i++)
528 if (strcmp(s, filetab[i].f_name) == 0) {
529 close1(i);
530 break;
532 i = (i == MAXFILE) ? 0 : 1;
533 return mktmp(NUM, NULL, (double) i);
536 static
537 close1(i)
539 int fd, result, savefd;
540 char *awktmp();
542 if (filetab[i].f_fp == NULL)
543 return;
544 switch (filetab[i].f_type) {
545 case R_PIN:
546 #ifdef DOS
547 fclose(filetab[i].f_fp);
548 unlink(awktmp(i));
549 #else
550 pclose(filetab[i].f_fp);
551 #endif
552 break;
553 case R_IN: case R_OUT: case R_APD:
554 fclose(filetab[i].f_fp);
555 break;
556 case R_POUT:
557 #ifdef DOS
558 fclose(filetab[i].f_fp);
559 if ((fd = open(awktmp(i), O_RDONLY)) == NULL)
560 error("can't open %s", awktmp(i));
561 savefd = dup(0);
562 dup2(fd, 0);
563 close(fd);
564 if ((result =
565 system(filetab[i].f_name)) == -1)
567 spawnl(P_WAIT, "/usr/bin/sh", "sh", "-c", filetab[i].f_name, (char *) 0)) == -1)
568 fprintf(stderr, "can't spawn /bin/sh\n");
570 error("can't exec %s", filetab[i].f_name);
571 dup2(savefd, 0);
572 close(savefd);
573 unlink(awktmp(i));
574 #else
575 pclose(filetab[i].f_fp);
576 #endif
577 break;
579 sfree(filetab[i].f_name);
580 filetab[i].f_type = 0;
581 filetab[i].f_name = NULL;
582 filetab[i].f_fp = NULL;
585 #ifndef DOS
586 FILE *
587 epopen(file, mod) char *file, *mod;
589 FILE *fp, *popen();
591 if ((fp = popen(file, mod)) == NULL)
592 error("can't poen %s", file);
593 return fp;
595 #endif
597 static char *
598 awktmp(i)
600 static char str[16];
602 sprintf(str, "awk000%02d.tmp", i);
603 return str;
606 Index(s, t) char *s, *t;
608 register char *u, *v;
609 register int i;
611 for (i = 1; *s; s++, i++) {
612 for (u = s, v = t; *v; u++, v++) {
613 if (isKanji(*v)) {
614 if (*u != *v)
615 break;
616 u++; v++;
618 if (*u != *v)
619 break;
621 if (*v == '\0')
622 return i;
623 if (isKanji(*s))
624 s++;
626 return 0;