1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 #include <stdio.h>
  31 #include <ctype.h>
  32 #include <signal.h>
  33 #include <locale.h>
  34 #include <libintl.h>
  35 #include <stdarg.h>
  36 #include <errno.h>
  37 #include <values.h>
  38 #include <langinfo.h>
  39 #include "awk.h"
  40 #include "y.tab.h"
  41 
  42 char    *version = "version Oct 11, 1989";
  43 
  44 int     dbg     = 0;
  45 uchar   *cmdname;       /* gets argv[0] for error messages */
  46 uchar   *lexprog;       /* points to program argument if it exists */
  47 int     compile_time = 2;       /* for error printing: */
  48                                 /* 2 = cmdline, 1 = compile, 0 = running */
  49 char    radixpoint = '.';
  50 
  51 static uchar    **pfile = NULL; /* program filenames from -f's */
  52 static int      npfile = 0;     /* number of filenames */
  53 static int      curpfile = 0;   /* current filename */
  54 
  55 int
  56 main(int argc, char *argv[], char *envp[])
  57 {
  58         uchar *fs = NULL;
  59         char    *nl_radix;
  60         /*
  61          * At this point, numbers are still scanned as in
  62          * the POSIX locale.
  63          * (POSIX.2, volume 2, P867, L4742-4757)
  64          */
  65         (void) setlocale(LC_ALL, "");
  66         (void) setlocale(LC_NUMERIC, "C");
  67 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
  68 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it weren't */
  69 #endif
  70         (void) textdomain(TEXT_DOMAIN);
  71         cmdname = (uchar *)argv[0];
  72         if (argc == 1) {
  73                 (void) fprintf(stderr, gettext(
  74                     "Usage: %s [-f programfile | 'program'] [-Ffieldsep] "
  75                     "[-v var=value] [files]\n"), cmdname);
  76                 exit(1);
  77         }
  78         (void) signal(SIGFPE, fpecatch);
  79         yyin = NULL;
  80         syminit();
  81         while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
  82                 if (strcmp(argv[1], "--") == 0) {
  83                         /* explicit end of args */
  84                         argc--;
  85                         argv++;
  86                         break;
  87                 }
  88                 switch (argv[1][1]) {
  89                 case 'f':       /* next argument is program filename */
  90                         argc--;
  91                         argv++;
  92                         if (argc <= 1)
  93                                 ERROR "no program filename" FATAL;
  94                         pfile = realloc(pfile, sizeof (uchar *) * (npfile + 1));
  95                         if (pfile == NULL)
  96                                 ERROR "out of space in main" FATAL;
  97                         pfile[npfile++] = (uchar *)argv[1];
  98                         break;
  99                 case 'F':       /* set field separator */
 100                         if (argv[1][2] != 0) {  /* arg is -Fsomething */
 101                                 /* wart: t=>\t */
 102                                 if (argv[1][2] == 't' && argv[1][3] == 0)
 103                                         fs = (uchar *) "\t";
 104                                 else if (argv[1][2] != 0)
 105                                         fs = (uchar *)&argv[1][2];
 106                         } else {                /* arg is -F something */
 107                                 argc--; argv++;
 108                                 if (argc > 1) {
 109                                         /* wart: t=>\t */
 110                                         if (argv[1][0] == 't' &&
 111                                             argv[1][1] == 0)
 112                                                 fs = (uchar *) "\t";
 113                                         else if (argv[1][0] != 0)
 114                                                 fs = (uchar *)&argv[1][0];
 115                                 }
 116                         }
 117                         if (fs == NULL || *fs == '\0')
 118                                 ERROR "field separator FS is empty" WARNING;
 119                         break;
 120                 case 'v':       /* -v a=1 to be done NOW.  one -v for each */
 121                         if (argv[1][2] == '\0' && --argc > 1 &&
 122                             isclvar((uchar *)(++argv)[1]))
 123                                 setclvar((uchar *)argv[1]);
 124                         break;
 125                 case 'd':
 126                         dbg = atoi(&argv[1][2]);
 127                         if (dbg == 0)
 128                                 dbg = 1;
 129                         (void) printf("awk %s\n", version);
 130                         break;
 131                 default:
 132                         ERROR "unknown option %s ignored", argv[1] WARNING;
 133                         break;
 134                 }
 135                 argc--;
 136                 argv++;
 137         }
 138         /* argv[1] is now the first argument */
 139         if (npfile == 0) {      /* no -f; first argument is program */
 140                 if (argc <= 1) {
 141                         if (dbg)
 142                                 exit(0);
 143                         ERROR "no program given" FATAL;
 144                 }
 145                 dprintf(("program = |%s|\n", argv[1]));
 146                 lexprog = (uchar *)argv[1];
 147                 argc--;
 148                 argv++;
 149         }
 150         compile_time = 1;
 151         argv[0] = (char *)cmdname;      /* put prog name at front of arglist */
 152         dprintf(("argc=%d, argv[0]=%s\n", argc, argv[0]));
 153         arginit(argc, (uchar **)argv);
 154         envinit((uchar **)envp);
 155         (void) yyparse();
 156         if (fs)
 157                 *FS = qstring(fs, '\0');
 158         dprintf(("errorflag=%d\n", errorflag));
 159         /*
 160          * done parsing, so now activate the LC_NUMERIC
 161          */
 162         (void) setlocale(LC_ALL, "");
 163         nl_radix = nl_langinfo(RADIXCHAR);
 164         if (nl_radix)
 165                 radixpoint = *nl_radix;
 166 
 167         if (errorflag == 0) {
 168                 compile_time = 0;
 169                 run(winner);
 170         } else
 171                 bracecheck();
 172         return (errorflag);
 173 }
 174 
 175 int
 176 pgetc(void)             /* get program character */
 177 {
 178         int c;
 179 
 180         for (;;) {
 181                 if (yyin == NULL) {
 182                         if (curpfile >= npfile)
 183                                 return (EOF);
 184                         yyin = (strcmp((char *)pfile[curpfile], "-") == 0) ?
 185                             stdin : fopen((char *)pfile[curpfile], "r");
 186                         if (yyin == NULL) {
 187                                 ERROR "can't open file %s",
 188                                     pfile[curpfile] FATAL;
 189                         }
 190                 }
 191                 if ((c = getc(yyin)) != EOF)
 192                         return (c);
 193                 (void) fclose(yyin);
 194                 yyin = NULL;
 195                 curpfile++;
 196         }
 197 }