source: trunk/minix/commands/awk/r.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 10.3 KB
Line 
1/*
2 * a small awk clone
3 *
4 * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
5 *
6 * Absolutely no warranty. Use this software with your own risk.
7 *
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.
11 *
12 * This program was written to fit into 64K+64K memory of the Minix 1.2.
13 */
14
15
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"
26
27#define MAXFLD 100
28
29extern char **FS, **RS, **OFS, **ORS, **FILENAME;
30extern double *NF, *NR;
31extern double *FNR;
32extern double *ARGC;
33extern SYMBOL *argtab[];
34extern CELL *getvar();
35
36char *strsave(), *strcpy(), *getsval(), *jStrchr(), *strchr();
37double getfval(), atof();
38CELL *mkcell(), *mktmp(), *execute(), *patexec();
39FILE *efopen();
40
41extern CELL truecell, falsecell;
42
43extern int pateval;
44
45int infileno = 1;
46FILE *ifp;
47char record[BUFSIZ];
48CELL *field[MAXFLD];
49
50char *fs_str;
51regexp *fs_pat;
52
53CELL *
54Getline(p) NODE *p;
55{
56 CELL *u;
57 char *fnam, *s, str[BUFSIZ];
58 int i;
59 FILE *fp, *getfp();
60
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);
71 }
72 else
73 i = Getrec(s);
74 if (s == str) {
75 u = execute(p->n_arg[0]);
76 setsval(u, str);
77 }
78 return mktmp(NUM, NULL, (double) i);
79}
80
81static
82get1rec(buf, fp) char *buf; FILE *fp;
83{
84 register int c;
85 register char rs, *s;
86 int mflg;
87
88 if (buf == NULL)
89 buf = record;
90 if ((rs = **RS) == '\0') { /* multi line record */
91 mflg = 1;
92 rs = '\n';
93 }
94 else
95 mflg = 0;
96
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);
103 }
104 *s++ = c;
105 }
106 if (mflg) {
107 if ((c = getc(fp)) == '\n' || c == EOF)
108 break;
109 *s++ = '\n';
110 }
111 else
112 break;
113 }
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)++;
123 }
124 return s > buf || c != EOF ? 1 : 0;
125}
126
127Getrec(s) char *s;
128{
129 CELL *u;
130 char *file, str[8];
131
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;
144 }
145 else if (strcmp(file, "") == 0) {
146/*
147if (infileno == (int)*ARGC - 1)
148 ifp = stdin;
149*/
150 infileno++;
151 continue;
152 }
153 else {
154 if (strcmp(file, "-") == 0)
155 ifp = stdin;
156 else
157 ifp = efopen(file, "r");
158 *FILENAME = file;
159 }
160 }
161 if (get1rec(s, ifp))
162 return 1;
163 else {
164 if (ifp != stdin)
165 fclose(ifp);
166 ifp = NULL;
167 infileno++;
168 }
169 }
170 ifp = stdin; /* for further "getline" */
171 *FILENAME = "-";
172 return 0; /* EOF */
173}
174
175mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
176{
177 char *s, *t;
178 char str[BUFSIZ];
179 int i, j, n;
180 int skip = 0;
181
182 if (strlen(sep) > 1)
183 return r_mkfld(rec, sep, fld);
184
185 if (*sep == ' ' || *sep == '\0') {
186 sep = " \t\n"; skip++;
187 }
188 for (i = 1, n = (int) *NF; i <= n; i++) {
189 sfree(fld[i]->c_sval);
190 sfree(fld[i]);
191 fld[i] = NULL;
192 }
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;
200 }
201 while (*s && !jStrchr(sep, *s)) {
202 if (isKanji(*s))
203 *t++ = *s++;
204 *t++ = *s++;
205 }
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;
215 }
216 *NF = (double) i;
217 return i;
218}
219
220static
221r_mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
222{
223 char *s, *t;
224 char str[BUFSIZ];
225 int i, n;
226 regexp *mkpat();
227 extern int r_start, r_length;
228
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);
233 }
234 for (i = 1, n = (int) *NF; i <= n; i++) {
235 sfree(fld[i]->c_sval);
236 sfree(fld[i]);
237 fld[i] = NULL;
238 }
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++;
243 }
244 else {
245 while (*s)
246 *t++ = *s++;
247 }
248 *t = '\0';
249 t = str;
250 fld[++i] = mkcell(FLD|STR, str, 0.0);
251 if (*s)
252 s += r_length;
253 }
254 *NF = (double) i;
255 return i;
256}
257
258mkrec(u) CELL *u;
259{
260 register char *s, *t;
261 register int i, j;
262
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;
273 }
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++;
279 }
280 *t++ = '\0';
281}
282
283CELL *
284Field(p) NODE *p;
285{
286 CELL *u;
287 int i, j;
288
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);
297 }
298 return field[i];
299}
300
301CELL *
302P1stat(p) NODE *p;
303{
304 CELL *u;
305 double x;
306
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;
317}
318
319CELL *
320P2stat(p) NODE *p;
321{
322 static stat = 0;
323 CELL *u, *v;
324 double x;
325
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;
335 }
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;
352 }
353 return u;
354}
355
356CELL *
357Print0()
358{
359/*
360 int i, j;
361 char *s, str[BUFSIZ];
362
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);
368 }
369 strcat(str, *ORS);
370 fputs(str, stdout);
371*/
372 fprintf(stdout, "%s%s", record, *ORS);
373 return &truecell;
374}
375
376char *
377format(t, p) char *t; NODE *p;
378{
379 CELL *u, *v;
380 char *r, *s, *s0, fmt[BUFSIZ];
381 double x;
382 int i;
383
384 u = execute(p->n_arg[2]);
385 s = s0 = getsval(u);
386/*
387printf("fmt(%s)\n", s);
388*/
389 for (i = 3; *s; s++) {
390 if (isKanji(*s)) {
391 *t++ = *s++; *t++ = *s; continue;
392 }
393 if (*s != '%') {
394 *t++ = *s; continue;
395 }
396 else if (*(s + 1) == '%') {
397 *t++ = *s++; continue;
398 }
399 for (r = fmt, *r++ = *s++; *r++ = *s; s++) {
400 if (strchr("%cdefgosux", *s))
401 break;
402 }
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);
411/*
412printf("val(%d)(%s)\n", v->c_type, v->c_sval);
413*/
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';
421 }
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;
440 }
441 c_free(v);
442 t += strlen(t);
443 }
444 c_free(u);
445 *t = '\0';
446}
447
448#define MAXFILE 10
449struct {
450 char *f_name; /* file name */
451 FILE *f_fp;
452 int f_type;
453} filetab[MAXFILE];
454
455FILE *
456getfp(file, type) char *file;
457{
458 register int i;
459 register char *name, *mode;
460 char *awktmp();
461 FILE *fp, *efopen(), *epopen();
462
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
486 {
487 int savefd, fd, result;
488
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";
499 }
500#else
501 fp = epopen(file,"r");
502 goto g1;
503#endif
504 break;
505 }
506 fp = efopen(name, mode);
507g1:
508 filetab[i].f_name = strsave(file);
509 filetab[i].f_type = type;
510 filetab[i].f_fp = fp;
511 return fp;
512}
513
514closeall()
515{
516 register int i;
517
518 for (i = 0; i < MAXFILE; i++)
519 close1(i);
520}
521
522CELL *
523Close(s) char *s;
524{
525 register int i;
526
527 for (i = 0; i < MAXFILE; i++)
528 if (strcmp(s, filetab[i].f_name) == 0) {
529 close1(i);
530 break;
531 }
532 i = (i == MAXFILE) ? 0 : 1;
533 return mktmp(NUM, NULL, (double) i);
534}
535
536static
537close1(i)
538{
539 int fd, result, savefd;
540 char *awktmp();
541
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)
566/*
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");
569*/
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;
578 }
579 sfree(filetab[i].f_name);
580 filetab[i].f_type = 0;
581 filetab[i].f_name = NULL;
582 filetab[i].f_fp = NULL;
583}
584
585#ifndef DOS
586FILE *
587epopen(file, mod) char *file, *mod;
588{
589 FILE *fp, *popen();
590
591 if ((fp = popen(file, mod)) == NULL)
592 error("can't poen %s", file);
593 return fp;
594}
595#endif
596
597static char *
598awktmp(i)
599{
600 static char str[16];
601
602 sprintf(str, "awk000%02d.tmp", i);
603 return str;
604}
605
606Index(s, t) char *s, *t;
607{
608 register char *u, *v;
609 register int i;
610
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++;
617 }
618 if (*u != *v)
619 break;
620 }
621 if (*v == '\0')
622 return i;
623 if (isKanji(*s))
624 s++;
625 }
626 return 0;
627}
Note: See TracBrowser for help on using the repository browser.