"Fossies" - the Fresh Open Source Software Archive

Member "bc-1.06.95/bc/main.c" (5 Sep 2006, 8241 Bytes) of package /linux/misc/old/bc-1.06.95.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "main.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.06.95_vs_1.07.

    1 /*  This file is part of GNU bc.
    2 
    3     Copyright (C) 1991-1994, 1997, 2006 Free Software Foundation, Inc.
    4 
    5     This program is free software; you can redistribute it and/or modify
    6     it under the terms of the GNU General Public License as published by
    7     the Free Software Foundation; either version 2 of the License , or
    8     (at your option) any later version.
    9 
   10     This program is distributed in the hope that it will be useful,
   11     but WITHOUT ANY WARRANTY; without even the implied warranty of
   12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13     GNU General Public License for more details.
   14 
   15     You should have received a copy of the GNU General Public License
   16     along with this program; see the file COPYING.  If not, write to:
   17       The Free Software Foundation, Inc.
   18       Foundation, Inc.  51 Franklin Street, Fifth Floor,
   19       Boston, MA 02110-1301  USA
   20 
   21     You may contact the author by:
   22        e-mail:  philnelson@acm.org
   23       us-mail:  Philip A. Nelson
   24                 Computer Science Department, 9062
   25                 Western Washington University
   26                 Bellingham, WA 98226-9062
   27        
   28 *************************************************************************/
   29 
   30 /* main.c: The main program for bc.  */
   31 
   32 #include "bcdefs.h"
   33 #include <signal.h>
   34 #include <errno.h>
   35 #include "proto.h"
   36 #include "getopt.h"
   37 
   38 
   39 /* Variables for processing multiple files. */
   40 static char first_file;
   41 
   42 /* Points to the last node in the file name list for easy adding. */
   43 static file_node *last = NULL;
   44 
   45 /* long option support */
   46 static struct option long_options[] =
   47 {
   48   {"compile",     0, &compile_only, TRUE},
   49   {"help",        0, 0,             'h'},
   50   {"interactive", 0, 0,             'i'},
   51   {"mathlib",     0, &use_math,     TRUE},
   52   {"quiet",       0, &quiet,        TRUE},
   53   {"standard",    0, &std_only,     TRUE},
   54   {"version",     0, 0,             'v'},
   55   {"warn",        0, &warn_not_std, TRUE},
   56 
   57   {0, 0, 0, 0}
   58 };
   59 
   60 
   61 static void
   62 usage (const char *progname)
   63 {
   64   printf ("usage: %s [options] [file ...]\n%s%s%s%s%s%s%s", progname,
   65           "  -h  --help         print this usage and exit\n",
   66       "  -i  --interactive  force interactive mode\n",
   67       "  -l  --mathlib      use the predefined math routines\n",
   68       "  -q  --quiet        don't print initial banner\n",
   69       "  -s  --standard     non-standard bc constructs are errors\n",
   70       "  -w  --warn         warn about non-standard bc constructs\n",
   71       "  -v  --version      print version information and exit\n");
   72 }
   73 
   74 
   75 static void
   76 parse_args (argc, argv)
   77      int argc;
   78      char **argv;
   79 {
   80   int optch;
   81   int long_index;
   82   file_node *temp;
   83 
   84   /* Force getopt to initialize.  Depends on GNU getopt. */
   85   optind = 0;
   86 
   87   /* Parse the command line */
   88   while (1)
   89     {
   90       optch = getopt_long (argc, argv, "chilqswv", long_options, &long_index);
   91 
   92       if (optch == EOF)  /* End of arguments. */
   93     break;
   94 
   95       switch (optch)
   96     {
   97     case 0: /* Long option setting a var. */
   98       break;
   99 
  100     case 'c':  /* compile only */
  101       compile_only = TRUE;
  102       break;
  103 
  104     case 'h':  /* help */
  105       usage(argv[0]);
  106       exit (0);
  107       break;
  108 
  109     case 'i':  /* force interactive */
  110       interactive = TRUE;
  111       break;
  112 
  113     case 'l':  /* math lib */
  114       use_math = TRUE;
  115       break;
  116 
  117     case 'q':  /* quiet mode */
  118       quiet = TRUE;
  119       break;
  120 
  121     case 's':  /* Non standard features give errors. */
  122       std_only = TRUE;
  123       break;
  124 
  125     case 'v':  /* Print the version. */
  126       show_bc_version ();
  127       exit (0);
  128       break;
  129 
  130     case 'w':  /* Non standard features give warnings. */
  131       warn_not_std = TRUE;
  132       break;
  133 
  134     default:
  135       usage(argv[0]);
  136       exit (1);
  137     }
  138     }
  139 
  140 #ifdef QUIET
  141   quiet = TRUE;
  142 #endif
  143 
  144   /* Add file names to a list of files to process. */
  145   while (optind < argc)
  146     {
  147       temp = (file_node *) bc_malloc(sizeof(file_node));
  148       temp->name = argv[optind];
  149       temp->next = NULL;
  150       if (last == NULL)
  151     file_names = temp;
  152       else
  153     last->next = temp;
  154       last = temp;
  155       optind++;
  156     }
  157 }
  158 
  159 /* The main program for bc. */
  160 int
  161 main (argc, argv)
  162      int argc;
  163      char *argv[];
  164 {
  165   char *env_value;
  166   const char *env_argv[30];
  167   int   env_argc;
  168   
  169   /* Interactive? */
  170   if (isatty(0) && isatty(1)) 
  171     interactive = TRUE;
  172 
  173 #ifdef HAVE_SETVBUF
  174   /* attempt to simplify interaction with applications such as emacs */
  175   (void) setvbuf(stdout, NULL, _IOLBF, 0);
  176 #endif
  177 
  178   /* Environment arguments. */
  179   env_value = getenv ("BC_ENV_ARGS");
  180   if (env_value != NULL)
  181     {
  182       env_argc = 1;
  183       env_argv[0] = "BC_ENV_ARGS";
  184       while (*env_value != 0)
  185     {
  186       if (*env_value != ' ')
  187         {
  188           env_argv[env_argc++] = env_value;
  189           while (*env_value != ' ' && *env_value != 0)
  190         env_value++;
  191           if (*env_value != 0)
  192         {
  193           *env_value = 0;
  194           env_value++;
  195         }
  196         }
  197       else
  198         env_value++;
  199     }
  200       parse_args (env_argc, env_argv);
  201     }
  202 
  203   /* Command line arguments. */
  204   parse_args (argc, argv);
  205 
  206   /* Other environment processing. */
  207   if (getenv ("POSIXLY_CORRECT") != NULL)
  208     std_only = TRUE;
  209 
  210   env_value = getenv ("BC_LINE_LENGTH");
  211   if (env_value != NULL)
  212     {
  213       line_size = atoi (env_value);
  214       if (line_size < 3 && line_size != 0)
  215     line_size = 70;
  216     }
  217   else
  218     line_size = 70;
  219 
  220   /* Initialize the machine.  */
  221   init_storage();
  222   init_load();
  223 
  224   /* Set up interrupts to print a message. */
  225   if (interactive)
  226     signal (SIGINT, use_quit);
  227 
  228   /* Initialize the front end. */
  229   init_tree();
  230   init_gen ();
  231   is_std_in = FALSE;
  232   first_file = TRUE;
  233   if (!open_new_file ())
  234     exit (1);
  235 
  236 #if defined(LIBEDIT)
  237   if (interactive) {
  238     /* Enable libedit support. */
  239     edit = el_init ("bc", stdin, stdout, stderr);
  240     hist = history_init();
  241     el_set (edit, EL_EDITOR, "emacs");
  242     el_set (edit, EL_HIST, history, hist);
  243     el_set (edit, EL_PROMPT, null_prompt);
  244     el_source (edit, NULL);
  245     history (hist, &histev, H_SETSIZE, INT_MAX);
  246   }
  247 #endif
  248 
  249 #if defined(READLINE)
  250   if (interactive) {
  251     /* Readline support.  Set both application name and input file. */
  252     rl_readline_name = "bc";
  253     rl_instream = stdin;
  254     using_history ();
  255   }
  256 #endif
  257 
  258   /* Do the parse. */
  259   yyparse ();
  260 
  261   /* End the compile only output with a newline. */
  262   if (compile_only)
  263     printf ("\n");
  264 
  265 #if defined(LIBEDIT)
  266   if (edit != NULL)
  267     el_end(edit);
  268 #endif
  269   exit (0);
  270 }
  271 
  272 
  273 /* This is the function that opens all the files. 
  274    It returns TRUE if the file was opened, otherwise
  275    it returns FALSE. */
  276 
  277 int
  278 open_new_file ()
  279 {
  280   FILE *new_file;
  281   file_node *temp;
  282 
  283   /* Set the line number. */
  284   line_no = 1;
  285 
  286   /* Check to see if we are done. */
  287   if (is_std_in) return (FALSE);
  288 
  289   /* Open the other files. */
  290   if (use_math && first_file)
  291     {
  292       /* Load the code from a precompiled version of the math libarary. */
  293       extern char *libmath[];
  294       char **mstr;
  295       char tmp;
  296       /* These MUST be in the order of first mention of each function.
  297      That is why "a" comes before "c" even though "a" is defined after
  298      after "c".  "a" is used in "s"! */
  299       tmp = lookup ("e", FUNCT);
  300       tmp = lookup ("l", FUNCT);
  301       tmp = lookup ("s", FUNCT);
  302       tmp = lookup ("a", FUNCT);
  303       tmp = lookup ("c", FUNCT);
  304       tmp = lookup ("j", FUNCT);
  305       mstr = libmath;
  306       while (*mstr) {
  307            load_code (*mstr);
  308        mstr++;
  309       }
  310     }
  311   
  312   /* One of the argv values. */
  313   if (file_names != NULL)
  314     {
  315       new_file = fopen (file_names->name, "r");
  316       if (new_file != NULL)
  317     {
  318       new_yy_file (new_file);
  319       temp = file_names;
  320       file_name  = temp->name;
  321       file_names = temp->next;
  322       free (temp);
  323       return TRUE;
  324     }
  325       fprintf (stderr, "File %s is unavailable.\n", file_names->name);
  326       exit (1);
  327     }
  328   
  329   /* If we fall through to here, we should return stdin. */
  330   new_yy_file (stdin);
  331   is_std_in = TRUE;
  332   return TRUE;
  333 }
  334 
  335 
  336 /* Set yyin to the new file. */
  337 
  338 void
  339 new_yy_file (file)
  340      FILE *file;
  341 {
  342   if (!first_file) fclose (yyin);
  343   yyin = file;
  344   first_file = FALSE;
  345 }
  346 
  347 
  348 /* Message to use quit.  */
  349 
  350 void
  351 use_quit (sig)
  352      int sig;
  353 {
  354 #ifdef DONTEXIT
  355   int save = errno;
  356   write (1, "\n(interrupt) use quit to exit.\n", 31);
  357   signal (SIGINT, use_quit);
  358   errno = save;
  359 #else
  360   write (1, "\n(interrupt) Exiting bc.\n", 26);
  361 #if defined(LIBEDIT)
  362   if (edit != NULL)
  363     el_end(edit);
  364 #endif
  365   exit(0);
  366 #endif
  367 }