628 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			628 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*
 | |
|  * a small awk clone
 | |
|  *
 | |
|  * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
 | |
|  *
 | |
|  * Absolutely no warranty. Use this software with your own risk.
 | |
|  *
 | |
|  * Permission to use, copy, modify and distribute this software for any
 | |
|  * purpose and without fee is hereby granted, provided that the above
 | |
|  * copyright and disclaimer notice.
 | |
|  *
 | |
|  * This program was written to fit into 64K+64K memory of the Minix 1.2.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <ctype.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #include <fcntl.h>
 | |
| #ifdef DOS
 | |
| #include <process.h>
 | |
| #endif
 | |
| #include "awk.h"
 | |
| #include "regexp.h"
 | |
| 
 | |
| #define MAXFLD	100
 | |
| 
 | |
| extern char **FS, **RS, **OFS, **ORS, **FILENAME;
 | |
| extern double *NF, *NR;
 | |
| extern double *FNR;
 | |
| extern double *ARGC;
 | |
| extern SYMBOL *argtab[];
 | |
| extern CELL *getvar();
 | |
| 
 | |
| char *strsave(), *strcpy(), *getsval(), *jStrchr(), *strchr();
 | |
| double getfval(), atof();
 | |
| CELL *mkcell(), *mktmp(), *execute(), *patexec();
 | |
| FILE *efopen();
 | |
| 
 | |
| extern CELL truecell, falsecell;
 | |
| 
 | |
| extern int pateval;
 | |
| 
 | |
| int infileno = 1;
 | |
| FILE *ifp;
 | |
| char record[BUFSIZ];
 | |
| CELL *field[MAXFLD];
 | |
| 
 | |
| char *fs_str;
 | |
| regexp *fs_pat;
 | |
| 
 | |
| CELL *
 | |
| Getline(p) NODE *p;
 | |
| {
 | |
|   CELL *u;
 | |
|   char *fnam, *s, str[BUFSIZ];
 | |
|   int i;
 | |
|   FILE *fp, *getfp();
 | |
| 
 | |
|   if ((int) p->n_arg[0])	/* read into var */
 | |
| 	s = str;
 | |
|   else
 | |
| 	s = NULL;
 | |
|   if ((int) p->n_arg[1]) {	/* file name */
 | |
| 	u = execute(p->n_arg[1]);
 | |
| 	fnam = getsval(u);
 | |
| 	fp = getfp(fnam, (int) p->n_arg[2]);
 | |
| 	c_free(u);
 | |
| 	i = get1rec(s, fp);
 | |
|   }
 | |
|   else
 | |
| 	i = Getrec(s);
 | |
|   if (s == str) {
 | |
| 	u = execute(p->n_arg[0]);
 | |
| 	setsval(u, str);
 | |
|   }
 | |
|   return mktmp(NUM, NULL, (double) i);
 | |
| }
 | |
| 
 | |
| static
 | |
| get1rec(buf, fp) char *buf; FILE *fp;
 | |
| {
 | |
|   register int c;
 | |
|   register char rs, *s;
 | |
|   int mflg;
 | |
| 
 | |
|   if (buf == NULL)
 | |
| 	buf = record;
 | |
|   if ((rs = **RS) == '\0') {	/* multi line record */
 | |
| 	mflg = 1;
 | |
| 	rs = '\n';
 | |
|   }
 | |
|   else
 | |
| 	mflg = 0;
 | |
| 
 | |
|   if (feof(fp) || (c = getc(fp)) == EOF)
 | |
| 	return 0;
 | |
|   for (s = buf; ; ) {
 | |
| 	for ( ; c != rs && c != EOF; c = getc(fp)) {
 | |
| 		if (isKanji(c)) {
 | |
| 			*s++ = c; c = getc(fp);
 | |
| 		}
 | |
| 		*s++ = c;
 | |
| 	}
 | |
| 	if (mflg) {
 | |
| 		if ((c = getc(fp)) == '\n' || c == EOF)
 | |
| 			break;
 | |
| 		*s++ = '\n';
 | |
| 	}
 | |
| 	else
 | |
| 		break;
 | |
|   }
 | |
|   *s = '\0';
 | |
| #if 1
 | |
|   if (buf == record) {
 | |
| #else
 | |
|   if (buf == record && c != EOF) {
 | |
| #endif
 | |
| 	mkfld(record, *FS, field);
 | |
| 	(*NR)++;
 | |
| 	(*FNR)++;
 | |
|   }
 | |
|   return s > buf || c != EOF ? 1 : 0;
 | |
| }
 | |
| 
 | |
| Getrec(s) char *s;
 | |
| {
 | |
|   CELL *u;
 | |
|   char *file, str[8];
 | |
| 
 | |
|   while (ifp == stdin || infileno < (int)*ARGC) {
 | |
| 	if (ifp == NULL) {
 | |
| 		*FNR = 0.0;
 | |
| 		if (infileno == (int)*ARGC)
 | |
| 			break;
 | |
| 		sprintf(str, "%d", infileno);
 | |
| 		u = getvar(str, argtab);
 | |
| 		file = getsval(u);
 | |
| 		if (strchr(file, '=') != NULL) {
 | |
| 			setvar(file);
 | |
| 			infileno++;
 | |
| 			continue;
 | |
| 		}
 | |
| 		else if (strcmp(file, "") == 0) {
 | |
| /*
 | |
| if (infileno == (int)*ARGC - 1)
 | |
| 			ifp = stdin;
 | |
| */
 | |
| 			infileno++;
 | |
| 			continue;
 | |
| 		}
 | |
| 		else {
 | |
| 			if (strcmp(file, "-") == 0)
 | |
| 				ifp = stdin;
 | |
| 			else
 | |
| 				ifp = efopen(file, "r");
 | |
| 			*FILENAME = file;
 | |
| 		}
 | |
| 	}
 | |
| 	if (get1rec(s, ifp))
 | |
| 		return 1;
 | |
| 	else {
 | |
| 		if (ifp != stdin)
 | |
| 			fclose(ifp);
 | |
| 		ifp = NULL;
 | |
| 		infileno++;
 | |
| 	}
 | |
|   }
 | |
|   ifp = stdin;	/* for further "getline" */
 | |
|   *FILENAME = "-";
 | |
|   return 0;	/* EOF */
 | |
| }
 | |
| 
 | |
| mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
 | |
| {
 | |
|   char *s, *t;
 | |
|   char str[BUFSIZ];
 | |
|   int i, j, n;
 | |
|   int skip = 0;
 | |
| 
 | |
|   if (strlen(sep) > 1)
 | |
| 	return r_mkfld(rec, sep, fld);
 | |
| 
 | |
|   if (*sep == ' ' || *sep == '\0') {
 | |
| 	sep = " \t\n"; skip++;
 | |
|   }
 | |
|   for (i = 1, n = (int) *NF; i <= n; i++) {
 | |
| 	sfree(fld[i]->c_sval);
 | |
| 	sfree(fld[i]);
 | |
| 	fld[i] = NULL;
 | |
|   }
 | |
|   for (i = 0, s = rec; ; ) {
 | |
| 	t = str;
 | |
| 	if (skip) {
 | |
| 		while (*s && strchr(" \t\n", *s))
 | |
| 			s++;
 | |
| 		if (*s == '\0')
 | |
| 			break;
 | |
| 	}
 | |
| 	while (*s && !jStrchr(sep, *s)) {
 | |
| 		if (isKanji(*s))
 | |
| 			*t++ = *s++;
 | |
| 		*t++ = *s++;
 | |
| 	}
 | |
| 	*t = '\0';
 | |
| 	if (isnum(str))
 | |
| 		fld[++i] =  mkcell(FLD|STR|NUM, str, atof(str));
 | |
| 	else
 | |
| 		fld[++i] =  mkcell(FLD|STR, str, 0.0);
 | |
| 	if (*s)
 | |
| 		s++;
 | |
| 	else
 | |
| 		break;
 | |
|   }
 | |
|   *NF = (double) i;
 | |
|   return i;
 | |
| }
 | |
| 
 | |
| static
 | |
| r_mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
 | |
| {
 | |
|   char *s, *t;
 | |
|   char str[BUFSIZ];
 | |
|   int i, n;
 | |
|   regexp *mkpat();
 | |
|   extern int r_start, r_length;
 | |
| 
 | |
|   if (strcmp(*FS, fs_str) != 0) {
 | |
| 	sfree(fs_str); sfree(fs_pat);
 | |
| 	fs_str = strsave(*FS);
 | |
| 	fs_pat = mkpat(fs_str);
 | |
|   }
 | |
|   for (i = 1, n = (int) *NF; i <= n; i++) {
 | |
| 	sfree(fld[i]->c_sval);
 | |
| 	sfree(fld[i]);
 | |
| 	fld[i] = NULL;
 | |
|   }
 | |
|   for (i = 0, s = rec, t = str; *s; ) {
 | |
| 	if (match(fs_pat, s)) {
 | |
| 		for (n = r_start; --n > 0; )
 | |
| 			*t++ = *s++;
 | |
| 	}
 | |
| 	else {
 | |
| 		while (*s)
 | |
| 			*t++ = *s++;
 | |
| 	}
 | |
| 	*t = '\0';
 | |
| 	t = str;
 | |
| 	fld[++i] = mkcell(FLD|STR, str, 0.0);
 | |
| 	if (*s)
 | |
| 		s += r_length;
 | |
|   }
 | |
|   *NF = (double) i;
 | |
|   return i;
 | |
| }
 | |
| 
 | |
| mkrec(u) CELL *u;
 | |
| {
 | |
|   register char *s, *t;
 | |
|   register int i, j;
 | |
| 
 | |
|   for (j = (int)*NF, i = 1; i <= j; i++)
 | |
| 	if (field[i] == u)
 | |
| 		break;
 | |
|   if (i > j) {
 | |
| 	for ( ; i < MAXFLD; i++)
 | |
| 		if (field[i] == u)
 | |
| 			break;
 | |
| 	if (i == MAXFLD)
 | |
| 		error("too many field (%d)", i);
 | |
| 	*NF = (double)i;
 | |
|   }
 | |
|   for (t = record, i = 1, j = (int) *NF; i <= j; i++) {
 | |
| 	if (i > 1)
 | |
| 		*t++ = **OFS;
 | |
| 	for (s = getsval(field[i]); *s; )
 | |
| 		*t++ = *s++;
 | |
|   }
 | |
|   *t++ = '\0';
 | |
| }
 | |
| 
 | |
| CELL *
 | |
| Field(p) NODE *p;
 | |
| {
 | |
|   CELL *u;
 | |
|   int i, j;
 | |
| 
 | |
|   u = execute(p->n_arg[0]);
 | |
|   i = (int) getfval(u);
 | |
|   c_free(u);
 | |
|   j = (int)*NF;
 | |
|   if (i > j)
 | |
| 	for (++j; j <= i; j++) {
 | |
| 		if (field[j] == NULL)
 | |
| 			field[j] = mkcell(FLD|STR, "", 0.0);
 | |
| 	}
 | |
|   return field[i];
 | |
| }
 | |
| 
 | |
| CELL *
 | |
| P1stat(p) NODE *p;
 | |
| {
 | |
|   CELL *u;
 | |
|   double x;
 | |
| 
 | |
|   pateval++;
 | |
|   u = execute(p->n_arg[0]);
 | |
|   pateval = 0;
 | |
|   x = getfval(u);
 | |
|   c_free(u);
 | |
|   if (x != 0.0)
 | |
| 	u = execute(p->n_arg[1]);
 | |
|   else
 | |
| 	u = &truecell;
 | |
|   return u;
 | |
| }
 | |
| 
 | |
| CELL *
 | |
| P2stat(p) NODE *p;
 | |
| {
 | |
|   static stat = 0;
 | |
|   CELL *u, *v;
 | |
|   double x;
 | |
| 
 | |
|   switch (stat) {
 | |
|   case 0:
 | |
| 	pateval++;
 | |
| 	u = execute(p->n_arg[0]);
 | |
| 	pateval = 0;
 | |
| 	x = getfval(u);
 | |
| 	c_free(u);
 | |
| 	if (x == 0.0) {
 | |
| 		u = &truecell; break;
 | |
| 	}
 | |
| 	else
 | |
| 		stat++;
 | |
| 	/* fall through */
 | |
|   case 1:
 | |
| 	u = execute(p->n_arg[2]);
 | |
| 	c_free(u);
 | |
| 	pateval++;
 | |
| 	u = execute(p->n_arg[1]);
 | |
| 	pateval = 0;
 | |
| 	x = getfval(u);
 | |
| 	if (x != 0.0)
 | |
| 		stat = 0;
 | |
| 	break;
 | |
|   default:
 | |
| 	u = &truecell;
 | |
| 	break;
 | |
|   }
 | |
|   return u;
 | |
| }
 | |
| 
 | |
| CELL *
 | |
| Print0()
 | |
| {
 | |
| /*
 | |
|   int i, j;
 | |
|   char *s, str[BUFSIZ];
 | |
| 
 | |
|   for (*str = '\0', i = 1, j = (int) *NF; i <= j; i++) {
 | |
| 	if (i > 1)
 | |
| 		strcat(str, *OFS);
 | |
| 	s = getsval(field[i]);
 | |
| 	strcat(str, s);
 | |
|   }
 | |
|   strcat(str, *ORS);
 | |
|   fputs(str, stdout);
 | |
| */
 | |
|   fprintf(stdout, "%s%s", record, *ORS);
 | |
|   return &truecell;
 | |
| }
 | |
| 
 | |
| char *
 | |
| format(t, p) char *t; NODE *p;
 | |
| {
 | |
|   CELL *u, *v;
 | |
|   char *r, *s, *s0, fmt[BUFSIZ];
 | |
|   double x;
 | |
|   int i;
 | |
| 
 | |
|   u = execute(p->n_arg[2]);
 | |
|   s = s0 = getsval(u);
 | |
| /*
 | |
| printf("fmt(%s)\n", s);
 | |
| */
 | |
|   for (i = 3; *s; s++) {
 | |
| 	if (isKanji(*s)) {
 | |
| 		*t++ = *s++; *t++ = *s; continue;
 | |
| 	}
 | |
| 	if (*s != '%') {
 | |
| 		*t++ = *s; continue;
 | |
| 	}
 | |
| 	else if (*(s + 1) == '%') {
 | |
| 		*t++ = *s++; continue;
 | |
| 	}
 | |
| 	for (r = fmt, *r++ = *s++; *r++ = *s; s++) {
 | |
| 		if (strchr("%cdefgosux", *s))
 | |
| 			break;
 | |
| 	}
 | |
| 	*r = '\0';
 | |
| 	if (p->n_arg[i] == NULL)
 | |
| 		error("not enough args in printf(%s)", s0);
 | |
| 	v = execute(p->n_arg[i++]);
 | |
| 	if (*s == 's')
 | |
| 		r = getsval(v);
 | |
| 	else
 | |
| 		x = getfval(v);
 | |
| /*
 | |
| printf("val(%d)(%s)\n", v->c_type, v->c_sval);
 | |
| */
 | |
| 	switch (*s) {
 | |
| 	case 'c':
 | |
| 		sprintf(t, fmt, (int) x);
 | |
| 		break;
 | |
| 	case 'd':
 | |
| 		if (*(s - 1) != 'l') {
 | |
| 			*--r = 'l'; *++r = 'd'; *++r = '\0';
 | |
| 		}
 | |
| 		sprintf(t, fmt, (long) x);
 | |
| 		break;
 | |
| 	case 'e': case 'f': case 'g':
 | |
| 		sprintf(t, fmt, x);
 | |
| 		break;
 | |
| 	case 'o': case 'u': case 'x':
 | |
| 		if (*(s - 1) == 'l')
 | |
| 			sprintf(t, fmt, (long) x);
 | |
| 		else
 | |
| 			sprintf(t, fmt, (int) x);
 | |
| 		break;
 | |
| 	case 's':
 | |
| 		/*r = getsval(v);*/
 | |
| 		sprintf(t, fmt, r);
 | |
| 		break;
 | |
| 	default:
 | |
| 		strcpy(t, fmt);
 | |
| 		break;
 | |
| 	}
 | |
| 	c_free(v);
 | |
| 	t += strlen(t);
 | |
|   }
 | |
|   c_free(u);
 | |
|   *t = '\0';
 | |
| }
 | |
| 
 | |
| #define MAXFILE	10
 | |
| struct {
 | |
|   char *f_name;	/* file name */
 | |
|   FILE *f_fp;
 | |
|   int f_type;
 | |
| } filetab[MAXFILE];
 | |
| 
 | |
| FILE *
 | |
| getfp(file, type) char *file;
 | |
| {
 | |
|   register int i;
 | |
|   register char *name, *mode;
 | |
|   char *awktmp();
 | |
|   FILE *fp, *efopen(), *epopen();
 | |
| 
 | |
|   for (i = 0; i < MAXFILE; i++)
 | |
| 	if (filetab[i].f_name && strcmp(filetab[i].f_name, file) == 0)
 | |
| 		return filetab[i].f_fp;
 | |
|   for (i = 0; i < MAXFILE; i++)
 | |
| 	if (!filetab[i].f_fp)
 | |
| 		break;
 | |
|   if (i == MAXFILE)
 | |
| 	error("too many files to open");
 | |
|   name = file;
 | |
|   switch (type) {
 | |
|   case R_OUT:	mode = "w"; break;
 | |
|   case R_APD:	mode = "a"; break;
 | |
|   case R_POUT:
 | |
| #ifdef DOS
 | |
| 	name = awktmp(i); mode = "w";	/* MS-DOS */
 | |
| #else
 | |
| 	fp = epopen(file, "w");
 | |
| 	goto g1;
 | |
| #endif
 | |
| 	break;
 | |
|   case R_IN:	mode = "r"; break;
 | |
|   case R_PIN:
 | |
| #ifdef DOS
 | |
| 	{
 | |
| 		int savefd, fd, result;
 | |
| 
 | |
| 		name = awktmp(i);
 | |
| 		if ((fd = open(name,
 | |
| 		O_WRONLY|O_TEXT|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE)) == -1)
 | |
| 			error("can't open %s", name);
 | |
| 		savefd = dup(1); dup2(fd, 1); close(fd);
 | |
| 		if ((result =
 | |
| 			system(file)) == -1)
 | |
| 			error("can't exec %s", file);
 | |
| 		dup2(savefd, 1); close(savefd); close(fd);
 | |
| 		mode = "r";
 | |
| 	}
 | |
| #else
 | |
| 	fp = epopen(file,"r");
 | |
| 	goto g1;
 | |
| #endif
 | |
| 	break;
 | |
|   }
 | |
|   fp = efopen(name, mode);
 | |
| g1:
 | |
|   filetab[i].f_name = strsave(file);
 | |
|   filetab[i].f_type = type;
 | |
|   filetab[i].f_fp = fp;
 | |
|   return fp;
 | |
| }
 | |
| 
 | |
| closeall()
 | |
| {
 | |
|   register int i;
 | |
| 
 | |
|   for (i = 0; i < MAXFILE; i++)
 | |
| 	close1(i);
 | |
| }
 | |
| 
 | |
| CELL *
 | |
| Close(s) char *s;
 | |
| {
 | |
|   register int i;
 | |
| 
 | |
|   for (i = 0; i < MAXFILE; i++)
 | |
| 	if (strcmp(s, filetab[i].f_name) == 0) {
 | |
| 		close1(i);
 | |
| 		break;
 | |
| 	}
 | |
|   i = (i == MAXFILE) ? 0 : 1;
 | |
|   return mktmp(NUM, NULL, (double) i);
 | |
| }
 | |
| 
 | |
| static
 | |
| close1(i)
 | |
| {
 | |
|   int fd, result, savefd;
 | |
|   char *awktmp();
 | |
| 
 | |
|   if (filetab[i].f_fp == NULL)
 | |
| 	return;
 | |
|   switch (filetab[i].f_type) {
 | |
|   case R_PIN:
 | |
| #ifdef DOS
 | |
| 	fclose(filetab[i].f_fp);
 | |
| 	unlink(awktmp(i));
 | |
| #else
 | |
| 	pclose(filetab[i].f_fp);
 | |
| #endif
 | |
| 	break;
 | |
|   case R_IN: case R_OUT: case R_APD:
 | |
| 	fclose(filetab[i].f_fp);
 | |
| 	break;
 | |
|   case R_POUT:
 | |
| #ifdef DOS
 | |
| 	fclose(filetab[i].f_fp);
 | |
| 	if ((fd = open(awktmp(i), O_RDONLY)) == NULL)
 | |
| 		error("can't open %s", awktmp(i));
 | |
| 	savefd = dup(0);
 | |
| 	dup2(fd, 0);
 | |
| 	close(fd);
 | |
| 	if ((result =
 | |
| 		system(filetab[i].f_name)) == -1)
 | |
| /*
 | |
| 	spawnl(P_WAIT, "/usr/bin/sh", "sh", "-c", filetab[i].f_name, (char *) 0)) == -1)
 | |
| 		fprintf(stderr, "can't spawn /bin/sh\n");
 | |
| */
 | |
| 		error("can't exec %s", filetab[i].f_name);
 | |
| 	dup2(savefd, 0);
 | |
| 	close(savefd);
 | |
| 	unlink(awktmp(i));
 | |
| #else
 | |
| 	pclose(filetab[i].f_fp);
 | |
| #endif
 | |
| 	break;
 | |
|   }
 | |
|   sfree(filetab[i].f_name);
 | |
|   filetab[i].f_type = 0;
 | |
|   filetab[i].f_name = NULL;
 | |
|   filetab[i].f_fp = NULL;
 | |
| }
 | |
| 
 | |
| #ifndef DOS
 | |
| FILE *
 | |
| epopen(file, mod) char *file, *mod;
 | |
| {
 | |
|   FILE *fp, *popen();
 | |
| 
 | |
|   if ((fp = popen(file, mod)) == NULL)
 | |
| 	error("can't poen %s", file);
 | |
|   return fp;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static char *
 | |
| awktmp(i)
 | |
| {
 | |
|   static char str[16];
 | |
| 
 | |
|   sprintf(str, "awk000%02d.tmp", i);
 | |
|   return str;
 | |
| }
 | |
| 
 | |
| Index(s, t) char *s, *t;
 | |
| {
 | |
|   register char *u, *v;
 | |
|   register int i;
 | |
| 
 | |
|   for (i = 1; *s; s++, i++) {
 | |
| 	for (u = s, v = t; *v; u++, v++) {
 | |
| 		if (isKanji(*v)) {
 | |
| 			if (*u != *v)
 | |
| 				break;
 | |
| 			u++; v++;
 | |
| 		}
 | |
| 		if (*u != *v)
 | |
| 			break;
 | |
| 	}
 | |
| 	if (*v == '\0')
 | |
| 		return i;
 | |
| 	if (isKanji(*s))
 | |
| 		s++;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | 
