Home | History | Annotate | Download | only in one-true-awk
      1 /****************************************************************
      2 Copyright (C) Lucent Technologies 1997
      3 All Rights Reserved
      4 
      5 Permission to use, copy, modify, and distribute this software and
      6 its documentation for any purpose and without fee is hereby
      7 granted, provided that the above copyright notice appear in all
      8 copies and that both that the copyright notice and this
      9 permission notice and warranty disclaimer appear in supporting
     10 documentation, and that the name Lucent Technologies or any of
     11 its entities not be used in advertising or publicity pertaining
     12 to distribution of the software without specific, written prior
     13 permission.
     14 
     15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
     17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
     18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
     22 THIS SOFTWARE.
     23 ****************************************************************/
     24 
     25 const char	*version = "version 20190125";
     26 
     27 #define DEBUG
     28 #include <stdio.h>
     29 #include <ctype.h>
     30 #include <locale.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <signal.h>
     34 #include "awk.h"
     35 #include "ytab.h"
     36 
     37 extern	char	**environ;
     38 extern	int	nfields;
     39 
     40 int	dbg	= 0;
     41 Awkfloat	srand_seed = 1;
     42 char	*cmdname;	/* gets argv[0] for error messages */
     43 extern	FILE	*yyin;	/* lex input file */
     44 char	*lexprog;	/* points to program argument if it exists */
     45 extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
     46 int	compile_time = 2;	/* for error printing: */
     47 				/* 2 = cmdline, 1 = compile, 0 = running */
     48 
     49 #define	MAX_PFILE	20	/* max number of -f's */
     50 
     51 char	*pfile[MAX_PFILE];	/* program filenames from -f's */
     52 int	npfile = 0;	/* number of filenames */
     53 int	curpfile = 0;	/* current filename */
     54 
     55 int	safe	= 0;	/* 1 => "safe" mode */
     56 
     57 /* Can this work with recursive calls?  I don't think so.
     58 void segvcatch(int n)
     59 {
     60 	FATAL("segfault.  Do you have an unbounded recursive call?", n);
     61 }
     62 */
     63 
     64 int main(int argc, char *argv[])
     65 {
     66 	const char *fs = NULL;
     67 
     68 	setlocale(LC_CTYPE, "");
     69 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
     70 	cmdname = argv[0];
     71 	if (argc == 1) {
     72 		fprintf(stderr,
     73 		  "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
     74 		  cmdname);
     75 		exit(1);
     76 	}
     77 	signal(SIGFPE, fpecatch);
     78 	/*signal(SIGSEGV, segvcatch); experiment */
     79 
     80 	srand_seed = 1;
     81 	srand(srand_seed);
     82 
     83 	yyin = NULL;
     84 	symtab = makesymtab(NSYMTAB/NSYMTAB);
     85 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
     86 		if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
     87 			printf("awk %s\n", version);
     88 			exit(0);
     89 			break;
     90 		}
     91 		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
     92 			argc--;
     93 			argv++;
     94 			break;
     95 		}
     96 		switch (argv[1][1]) {
     97 		case 's':
     98 			if (strcmp(argv[1], "-safe") == 0)
     99 				safe = 1;
    100 			break;
    101 		case 'f':	/* next argument is program filename */
    102 			if (argv[1][2] != 0) {  /* arg is -fsomething */
    103 				if (npfile >= MAX_PFILE - 1)
    104 					FATAL("too many -f options");
    105 				pfile[npfile++] = &argv[1][2];
    106 			} else {		/* arg is -f something */
    107 				argc--; argv++;
    108 				if (argc <= 1)
    109 					FATAL("no program filename");
    110 				if (npfile >= MAX_PFILE - 1)
    111 					FATAL("too many -f options");
    112 				pfile[npfile++] = argv[1];
    113 			}
    114 			break;
    115 		case 'F':	/* set field separator */
    116 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
    117 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
    118 					fs = "\t";
    119 				else if (argv[1][2] != 0)
    120 					fs = &argv[1][2];
    121 			} else {		/* arg is -F something */
    122 				argc--; argv++;
    123 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
    124 					fs = "\t";
    125 				else if (argc > 1 && argv[1][0] != 0)
    126 					fs = &argv[1][0];
    127 			}
    128 			if (fs == NULL || *fs == '\0')
    129 				WARNING("field separator FS is empty");
    130 			break;
    131 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
    132 			if (argv[1][2] != 0) {  /* arg is -vsomething */
    133 				if (isclvar(&argv[1][2]))
    134 					setclvar(&argv[1][2]);
    135 				else
    136 					FATAL("invalid -v option argument: %s", &argv[1][2]);
    137 			} else {		/* arg is -v something */
    138 				argc--; argv++;
    139 				if (argc <= 1)
    140 					FATAL("no variable name");
    141 				if (isclvar(argv[1]))
    142 					setclvar(argv[1]);
    143 				else
    144 					FATAL("invalid -v option argument: %s", argv[1]);
    145 			}
    146 			break;
    147 		case 'd':
    148 			dbg = atoi(&argv[1][2]);
    149 			if (dbg == 0)
    150 				dbg = 1;
    151 			printf("awk %s\n", version);
    152 			break;
    153 		default:
    154 			WARNING("unknown option %s ignored", argv[1]);
    155 			break;
    156 		}
    157 		argc--;
    158 		argv++;
    159 	}
    160 	/* argv[1] is now the first argument */
    161 	if (npfile == 0) {	/* no -f; first argument is program */
    162 		if (argc <= 1) {
    163 			if (dbg)
    164 				exit(0);
    165 			FATAL("no program given");
    166 		}
    167 		   dprintf( ("program = |%s|\n", argv[1]) );
    168 		lexprog = argv[1];
    169 		argc--;
    170 		argv++;
    171 	}
    172 	recinit(recsize);
    173 	syminit();
    174 	compile_time = 1;
    175 	argv[0] = cmdname;	/* put prog name at front of arglist */
    176 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
    177 	arginit(argc, argv);
    178 	if (!safe)
    179 		envinit(environ);
    180 	yyparse();
    181 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
    182 	if (fs)
    183 		*FS = qstring(fs, '\0');
    184 	   dprintf( ("errorflag=%d\n", errorflag) );
    185 	if (errorflag == 0) {
    186 		compile_time = 0;
    187 		run(winner);
    188 	} else
    189 		bracecheck();
    190 	return(errorflag);
    191 }
    192 
    193 int pgetc(void)		/* get 1 character from awk program */
    194 {
    195 	int c;
    196 
    197 	for (;;) {
    198 		if (yyin == NULL) {
    199 			if (curpfile >= npfile)
    200 				return EOF;
    201 			if (strcmp(pfile[curpfile], "-") == 0)
    202 				yyin = stdin;
    203 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
    204 				FATAL("can't open file %s", pfile[curpfile]);
    205 			lineno = 1;
    206 		}
    207 		if ((c = getc(yyin)) != EOF)
    208 			return c;
    209 		if (yyin != stdin)
    210 			fclose(yyin);
    211 		yyin = NULL;
    212 		curpfile++;
    213 	}
    214 }
    215 
    216 char *cursource(void)	/* current source file name */
    217 {
    218 	if (npfile > 0)
    219 		return pfile[curpfile];
    220 	else
    221 		return NULL;
    222 }
    223