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 20121220";
     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 int main(int argc, char *argv[])
     58 {
     59 	const char *fs = NULL;
     60 
     61 	setlocale(LC_CTYPE, "");
     62 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
     63 	cmdname = argv[0];
     64 	if (argc == 1) {
     65 		fprintf(stderr,
     66 		  "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
     67 		  cmdname);
     68 		exit(1);
     69 	}
     70 	signal(SIGFPE, fpecatch);
     71 
     72 	srand_seed = 1;
     73 	srand(srand_seed);
     74 
     75 	yyin = NULL;
     76 	symtab = makesymtab(NSYMTAB/NSYMTAB);
     77 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
     78 		if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
     79 			printf("awk %s\n", version);
     80 			exit(0);
     81 			break;
     82 		}
     83 		if (strncmp(argv[1], "--", 2) == 0) {	/* explicit end of args */
     84 			argc--;
     85 			argv++;
     86 			break;
     87 		}
     88 		switch (argv[1][1]) {
     89 		case 's':
     90 			if (strcmp(argv[1], "-safe") == 0)
     91 				safe = 1;
     92 			break;
     93 		case 'f':	/* next argument is program filename */
     94 			if (argv[1][2] != 0) {  /* arg is -fsomething */
     95 				if (npfile >= MAX_PFILE - 1)
     96 					FATAL("too many -f options");
     97 				pfile[npfile++] = &argv[1][2];
     98 			} else {		/* arg is -f something */
     99 				argc--; argv++;
    100 				if (argc <= 1)
    101 					FATAL("no program filename");
    102 				if (npfile >= MAX_PFILE - 1)
    103 					FATAL("too many -f options");
    104 				pfile[npfile++] = argv[1];
    105 			}
    106 			break;
    107 		case 'F':	/* set field separator */
    108 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
    109 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
    110 					fs = "\t";
    111 				else if (argv[1][2] != 0)
    112 					fs = &argv[1][2];
    113 			} else {		/* arg is -F something */
    114 				argc--; argv++;
    115 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
    116 					fs = "\t";
    117 				else if (argc > 1 && argv[1][0] != 0)
    118 					fs = &argv[1][0];
    119 			}
    120 			if (fs == NULL || *fs == '\0')
    121 				WARNING("field separator FS is empty");
    122 			break;
    123 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
    124 			if (argv[1][2] != 0) {  /* arg is -vsomething */
    125 				if (isclvar(&argv[1][2]))
    126 					setclvar(&argv[1][2]);
    127 				else
    128 					FATAL("invalid -v option argument: %s", &argv[1][2]);
    129 			} else {		/* arg is -v something */
    130 				argc--; argv++;
    131 				if (argc <= 1)
    132 					FATAL("no variable name");
    133 				if (isclvar(argv[1]))
    134 					setclvar(argv[1]);
    135 				else
    136 					FATAL("invalid -v option argument: %s", argv[1]);
    137 			}
    138 			break;
    139 		case 'd':
    140 			dbg = atoi(&argv[1][2]);
    141 			if (dbg == 0)
    142 				dbg = 1;
    143 			printf("awk %s\n", version);
    144 			break;
    145 		default:
    146 			WARNING("unknown option %s ignored", argv[1]);
    147 			break;
    148 		}
    149 		argc--;
    150 		argv++;
    151 	}
    152 	/* argv[1] is now the first argument */
    153 	if (npfile == 0) {	/* no -f; first argument is program */
    154 		if (argc <= 1) {
    155 			if (dbg)
    156 				exit(0);
    157 			FATAL("no program given");
    158 		}
    159 		   dprintf( ("program = |%s|\n", argv[1]) );
    160 		lexprog = argv[1];
    161 		argc--;
    162 		argv++;
    163 	}
    164 	recinit(recsize);
    165 	syminit();
    166 	compile_time = 1;
    167 	argv[0] = cmdname;	/* put prog name at front of arglist */
    168 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
    169 	arginit(argc, argv);
    170 	if (!safe)
    171 		envinit(environ);
    172 	yyparse();
    173 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
    174 	if (fs)
    175 		*FS = qstring(fs, '\0');
    176 	   dprintf( ("errorflag=%d\n", errorflag) );
    177 	if (errorflag == 0) {
    178 		compile_time = 0;
    179 		run(winner);
    180 	} else
    181 		bracecheck();
    182 	return(errorflag);
    183 }
    184 
    185 int pgetc(void)		/* get 1 character from awk program */
    186 {
    187 	int c;
    188 
    189 	for (;;) {
    190 		if (yyin == NULL) {
    191 			if (curpfile >= npfile)
    192 				return EOF;
    193 			if (strcmp(pfile[curpfile], "-") == 0)
    194 				yyin = stdin;
    195 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
    196 				FATAL("can't open file %s", pfile[curpfile]);
    197 			lineno = 1;
    198 		}
    199 		if ((c = getc(yyin)) != EOF)
    200 			return c;
    201 		if (yyin != stdin)
    202 			fclose(yyin);
    203 		yyin = NULL;
    204 		curpfile++;
    205 	}
    206 }
    207 
    208 char *cursource(void)	/* current source file name */
    209 {
    210 	if (npfile > 0)
    211 		return pfile[curpfile];
    212 	else
    213 		return NULL;
    214 }
    215