Main Page | Data Structures | File List | Data Fields | Globals

toke.c

Go to the documentation of this file.
00001 /*
00002  *                     OpenBIOS - free your system! 
00003  *                         ( FCode tokenizer )
00004  *                          
00005  *  toke.c - main tokenizer loop and parameter parsing.
00006  *  
00007  *  This program is part of a free implementation of the IEEE 1275-1994 
00008  *  Standard for Boot (Initialization Configuration) Firmware.
00009  *
00010  *  Copyright (C) 2001-2006 by Stefan Reinauer <stepan@openbios.org>
00011  *
00012  *  This program is free software; you can redistribute it and/or modify
00013  *  it under the terms of the GNU General Public License as published by
00014  *  the Free Software Foundation; version 2 of the License.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
00024  *
00025  */
00026 
00027 /* **************************************************************************
00028  *         Modifications made in 2005 by IBM Corporation
00029  *      (C) Copyright 2005 IBM Corporation.  All Rights Reserved.
00030  *      Modifications Author:  David L. Paktor    dlpaktor@us.ibm.com
00031  **************************************************************************** */
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <unistd.h>
00037 
00038 #ifdef __GLIBC__
00039 #define _GNU_SOURCE
00040 #include <getopt.h>
00041 #endif
00042 
00043 #include "types.h"
00044 #include "toke.h"
00045 #include "stream.h"
00046 #include "stack.h"
00047 #include "emit.h"
00048 
00049 #define TOKE_VERSION "1.0.0"
00050 
00051 #include "vocabfuncts.h"
00052 #include "scanner.h"
00053 #include "errhandler.h"
00054 #include "usersymbols.h"
00055 #include "clflags.h"
00056 #include "tracesyms.h"
00057 
00058 #define CORE_COPYR   "(C) Copyright 2001-2006 Stefan Reinauer.\n" \
00059                      "(C) Copyright 2006 coresystems GmbH <info@coresystems.de>"
00060 #define IBM_COPYR    "(C) Copyright 2005 IBM Corporation.  All Rights Reserved."
00061 
00062 /*  Temporary hack during development...  See DATE_STAMP  line below... */
00063 #ifdef DEVEL
00064 #include "date_stamp.h"
00065 #endif /*  DEVEL  */
00066 
00067 /* **************************************************************************
00068  *
00069  *     Global Variables Exported:
00070  *        verbose          If true, enable optional messages.
00071  *        noerrors         If true, create binary even if error(s) encountered.
00072  *        fload_list       If true, create an "FLoad-List" file
00073  *        dependency_list  If true, create a "Dependencies-List" file
00074  *
00075  **************************************************************************** */
00076 
00077 bool verbose         = FALSE;
00078 bool noerrors        = FALSE;
00079 bool fload_list      = FALSE;
00080 bool dependency_list = FALSE;
00081 
00082 /* **************************************************************************
00083  *
00084  *              Internal Static Variables
00085  *         outputname    Name of output file supplied on command-line
00086  *                           with the optional  -o  switch.
00087  *              Internal System Variable
00088  *         optind        Index into argv vector of first param after options,
00089  *                           from which input file names will be taken.
00090  *
00091  **************************************************************************** */
00092 
00093 static char *outputname = NULL;
00094 
00095 /* **************************************************************************
00096  *
00097  *    Print the copyright message.
00098  *
00099  **************************************************************************** */
00100 static void print_copyright(void)
00101 {
00102         printf( "Welcome to toke - OpenBIOS tokenizer v" TOKE_VERSION "\n"
00103                 CORE_COPYR "\n" IBM_COPYR "\n"
00104                 "This program is free software; you may redistribute it "
00105                 "under the terms of\nthe GNU General Public License. This "
00106                 "program has absolutely no warranty.\n\n");
00107 #ifdef DEVEL
00108         /*  Temporary hack during development... */
00109         printf( "\tTokenizer Compiled " DATE_STAMP "\n" );
00110 #endif /*  DEVEL  */
00111 
00112 }
00113 
00114 /* **************************************************************************
00115  *
00116  *      Function name:    usage
00117  *      Synopsis:         Print convenient usage-help message
00118  *
00119  **************************************************************************** */
00120 
00121 static void usage(char *name)
00122 {
00123         printf("usage: %s [-v] [-i] [-l] [-P] [-o target] <[-d name[=value]]> "
00124                                 "<[-f [no]flagname]> <[-I dir-path]> "
00125                                 "<[-T symbol]> <forth-file>\n\n",name);
00126         printf("  -v|--verbose          print Advisory messages\n");
00127         printf("  -i|--ignore-errors    don't suppress output after errors\n");
00128         printf("  -l|--load-list        create list of FLoaded file names\n");
00129         printf("  -P|--dependencies     create dePendency-list file\n");
00130         printf("  -o|--output-name      send output to filename given\n");
00131         printf("  -d|--define           create user-defined symbol\n");
00132         printf("  -f|--flag             set (or clear) Special-Feature flag\n");
00133         printf("  -I|--Include          add a directory to the Include-List\n");
00134         printf("  -T|--Trace            add a symbol to the Trace List\n");
00135         printf("  -h|--help             print this help message\n\n");
00136         printf("  -f|--flag    help     Help for Special-Feature flags\n");
00137 }
00138 
00139 /* **************************************************************************
00140  *
00141  *      Function name:    get_args
00142  *      Synopsis:         Parse the Command-Line option switches
00143  *      
00144  *      Inputs:
00145  *         Parameters:                  NONE
00146  *         Global Variables:
00147  *                    argc      Counter of command-line arguments
00148  *                    argv      Vector pointing to command-line arguments
00149  *         Command-Line Items:  The entire command-line will be parsed
00150  *
00151  *      Outputs:
00152  *         Returned Value:              NONE
00153  *         Global Variables:
00154  *                verbose            set by "-v" switch
00155  *                noerrors           set by "-i" switch
00156  *                fload_list         set by "-l" switch
00157  *                dependency_list    set by "-P" switch
00158  *         Internal Static Variables
00159  *                outputname         set by "-o" switch
00160  *         Internal System Variable
00161  *                optind             Index into argv vector of the position
00162  *                                       from which to take input file names.
00163  *         Printout:
00164  *                (Copyright was already printed by the main body as a
00165  *                    matter of course, rather than here depending on
00166  *                    the Verbose flag, because  getopt()  prints its
00167  *                    own error messages and we want to be sure to show
00168  *                    the Copyright notice before any error messages.)
00169  *                Rules for Usage and Flags-list or Flags-help display:
00170  *                  Usage message on Help-Request or error.
00171  *                  Ask for usage help, get Usage plus list of Flag Names.
00172  *                  Ask for Flags-help alone, get Flags-help (names plus
00173  *                      explanations)
00174  *                  Ask for usage help and for Flags-help, get Usage plus
00175  *                      Flags-help, without redundant list of Flag Names.
00176  *                  Any help-request, exit Zero
00177  *                  Error in Option switches, or missing input-file name,
00178  *                      get error-description plus Usage
00179  *                  Error in Flag Names, get list of Flag Names.
00180  *                  Any error, exit One.
00181  *         Behavior:
00182  *                Exit (non-failure) after printing "Help" message
00183  *
00184  *      Error Detection:     Exit with failure status on:
00185  *          Unknown Option switches or Flag Names
00186  *          Missing input file name
00187  *
00188  *      Process Explanation:
00189  *           The following switches are recognized:
00190  *               v
00191  *               h
00192  *               ?
00193  *               i
00194  *               I
00195  *               l
00196  *               P
00197  *               o
00198  *               d
00199  *               f
00200  *               T
00201  *           The conditions they set remain in effect through
00202  *               the entire program run.
00203  *
00204  *      Revision History:
00205  *          Updated Fri, 15 Jul 2005 by David L. Paktor
00206  *              Don't bail on first invalid option.
00207  *              Flags to control special features
00208  *              Usage messages for "special-feature" flags
00209  *          Updated Mon, 18 Jul 2005 by David L. Paktor
00210  *              Fine-tune Usage and Flags-list or Flags-help display.
00211  *          Updated Sun, 27 Nov 2005 by David L. Paktor
00212  *              Add FLoad-List flag
00213  *          Updated Wed, 29 Nov 2005 by David L. Paktor
00214  *              Make getopt() case-insensitive
00215  *          Updated Fri, 17 Mar 2006 by David L. O'Paktor
00216  *              Make getopt() case-sensitive again,
00217  *                  add include-list support and dePendency-list switch
00218  *
00219  *      Extraneous Remarks:
00220  *          We were originally thinking about defining various classes
00221  *              of "Warning" Messages and (somehow) controlling their
00222  *              display, but now that we have "special-feature" flags
00223  *              that control the generation of specific messages, that
00224  *              step has become unnecessary...
00225  *
00226  **************************************************************************** */
00227 
00228 static void get_args( int argc, char **argv )
00229 {
00230         const char *optstring="vhilPo:d:f:I:T:?";
00231         int c;
00232         int argindx = 0;
00233         bool inval_opt = FALSE;
00234         bool help_mssg = FALSE;
00235         bool cl_flag_error = FALSE;
00236 
00237         while (1) {
00238 #ifdef __GLIBC__
00239                 int option_index = 0;
00240                 static struct option long_options[] = {
00241                         { "verbose", 0, 0, 'v' },
00242                         { "help", 0, 0, 'h' },
00243                         { "ignore-errors", 0, 0, 'i' },
00244                         { "load-list",     0, 0, 'l' },
00245                         { "dependencies",  0, 0, 'P' },
00246                         { "output-name",   1, 0, 'o' },
00247                         { "define",        1, 0, 'd' },
00248                         { "flag",          1, 0, 'f' },
00249                         { "Include",       1, 0, 'I' },
00250                         { "Trace",         1, 0, 'T' },
00251                         { 0, 0, 0, 0 }
00252                 };
00253 
00254                 c = getopt_long (argc, argv, optstring,
00255                                  long_options, &option_index);
00256 #else
00257                 c = getopt (argc, argv, optstring);
00258 #endif
00259                 if (c == -1)
00260                         break;
00261 
00262                 argindx++;
00263                 switch (c) {
00264                 case 'v':
00265                         verbose=TRUE;
00266                         break;
00267                 case 'o':
00268                         outputname = optarg;
00269                         break;
00270                 case 'i':
00271                         noerrors = TRUE;
00272                         break;
00273                 case 'l':
00274                         fload_list = TRUE;
00275                         break;
00276                 case 'P':
00277                         dependency_list = TRUE;
00278                         break;
00279                 case 'd':
00280                         {
00281                             char *user_symb = optarg;
00282                             add_user_symbol(user_symb);
00283                         }
00284                         break;
00285                 case 'f':
00286                         cl_flag_error = set_cl_flag(optarg, FALSE) ;
00287                         break;
00288                 case 'I':
00289                         {
00290                             char *incl_list_elem = optarg;
00291                             add_to_include_list(incl_list_elem);
00292                         }
00293                         break;
00294                 case 'T':
00295                         add_to_trace_list(optarg);
00296                         break;
00297                 case '?':
00298                         /*  Distinguish between a '?' from the user
00299                          *  and one  getopt()  returned
00300                          */
00301                         if ( argv[argindx][1] != '?' )
00302                         {
00303                             inval_opt = TRUE;
00304                             break;
00305                         }
00306                 case 'h':
00307                 case 'H':
00308                          help_mssg = TRUE;              
00309                         break;
00310                 default:
00311                         /*  This is never executed
00312                          *  because  getopt()  prints the
00313                          *    "unknown option -- X"
00314                          *  message and returns a '?'
00315                          */
00316                         printf ("%s: unknown options.\n",argv[0]);
00317                         usage(argv[0]);
00318                         exit( 1 );
00319                 }
00320         }
00321 
00322         if ( help_mssg )
00323         {
00324             usage(argv[0]);
00325             if ( ! clflag_help )
00326             {
00327                 list_cl_flag_names();
00328             }
00329         }
00330         if ( clflag_help )  cl_flags_help();
00331         if ( help_mssg || clflag_help )
00332         {
00333             exit( 0 );
00334         }
00335 
00336         if ( inval_opt )      printf ("unknown options.\n");
00337         if (optind >= argc)   printf ("Input file name missing.\n");
00338         if ( inval_opt || (optind >= argc) )
00339         {
00340                 usage(argv[0]);
00341         }
00342         if ( cl_flag_error )  list_cl_flag_names();
00343 
00344         if ( inval_opt || (optind >= argc) || cl_flag_error )
00345         {
00346             exit( 1);
00347         }
00348 
00349         if (verbose)
00350         {
00351             list_user_symbols();
00352             list_cl_flag_settings();
00353             display_include_list();
00354         }
00355         save_cl_flags();
00356 }
00357 
00358 /* **************************************************************************
00359  *
00360  *      Main body of program.  Return 0 for success, 1 for failure.
00361  *
00362  *      Still to be done:
00363  *          Devise a syntax to allow the command-line to specify multiple
00364  *              input files together with an output file name for each.
00365  *          Currently, the syntax allows only one output file name to be
00366  *              specified; when multiple input file names are specified,
00367  *              the specification of an output file name is disallowed,
00368  *              and only the default output file names are permitted.
00369  *              While this works around the immediate problem, a more
00370  *              elegant solution could be devised...
00371  *
00372  **************************************************************************** */
00373 
00374 int main(int argc, char **argv)
00375 {
00376         int retval = 0;
00377 
00378         print_copyright();
00379         get_args( argc, argv );
00380 
00381         init_stack();
00382         init_dictionary();
00383 
00384         init_scanner();
00385         
00386         if ( outputname != NULL )
00387         {
00388             if ( argc > optind + 1 )
00389             {
00390             /*  Multiple input file names w/ single output file name  */
00391                 /*  Work-around  */
00392                 printf( "Cannot specify single output file name "
00393                         "with multiple input file names.\n"
00394                         "Please either remove output-file-name specification,\n"
00395                         "or use multiple commands.\n");
00396                 exit ( -2 );
00397             }
00398                 }
00399 
00400         for ( ; optind < argc ; optind++ )
00401         {
00402             bool stream_ok ;
00403 
00404             printf("\nTokenizing  %s   ", argv[optind]);
00405             init_error_handler();
00406             stream_ok = init_stream( argv[optind]);
00407             if ( stream_ok )
00408             {
00409                 init_output(argv[optind], outputname);
00410 
00411                 init_scan_state();
00412 
00413                 reset_vocabs();
00414                 reset_cl_flags();
00415 
00416                 tokenize();
00417                 finish_headers();
00418                 
00419                 close_stream( NULL);
00420                 if ( close_output() )  retval = 1;
00421             }
00422         }
00423         
00424         exit_scanner();
00425         return retval;
00426 }
00427 

Generated on Fri Aug 18 14:03:39 2006 for Toke1.0 by  doxygen 1.4.4