Logo Search packages:      
Sourcecode: fcode-utils version File versions  Download package

toke.c

/*
 *                     OpenBIOS - free your system! 
 *                         ( FCode tokenizer )
 *                          
 *  toke.c - main tokenizer loop and parameter parsing.
 *  
 *  This program is part of a free implementation of the IEEE 1275-1994 
 *  Standard for Boot (Initialization Configuration) Firmware.
 *
 *  Copyright (C) 2001-2006 by Stefan Reinauer <stepan@openbios.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
 *
 */

/* **************************************************************************
 *         Modifications made in 2005 by IBM Corporation
 *      (C) Copyright 2005 IBM Corporation.  All Rights Reserved.
 *      Modifications Author:  David L. Paktor    dlpaktor@us.ibm.com
 **************************************************************************** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#ifdef __GLIBC__
#define _GNU_SOURCE
#include <getopt.h>
#endif

#include "types.h"
#include "toke.h"
#include "stream.h"
#include "stack.h"
#include "emit.h"

#define TOKE_VERSION "1.0.2"
#define TOKE_COPYRIGHT_DATE "2001-2006"

#include "vocabfuncts.h"
#include "scanner.h"
#include "errhandler.h"
#include "usersymbols.h"
#include "clflags.h"
#include "tracesyms.h"

#define CORE_COPYR   "(C) Copyright 2001-2006 Stefan Reinauer.\n" \
                 "(C) Copyright 2006 coresystems GmbH <info@coresystems.de>"
#define IBM_COPYR    "(C) Copyright 2005 IBM Corporation.  All Rights Reserved."

/*  Temporary hack during development...  See DATE_STAMP  line below... */
#ifdef DEVEL
#include "date_stamp.h"
#endif /*  DEVEL  */

/* **************************************************************************
 *
 *     Global Variables Exported:
 *        verbose          If true, enable optional messages.
 *        noerrors         If true, create binary even if error(s) encountered.
 *        fload_list       If true, create an "FLoad-List" file
 *        dependency_list  If true, create a "Dependencies-List" file
 *
 **************************************************************************** */

bool verbose         = FALSE;
bool noerrors        = FALSE;
bool fload_list      = FALSE;
bool dependency_list = FALSE;

/* **************************************************************************
 *
 *              Internal Static Variables
 *         outputname    Name of output file supplied on command-line
 *                           with the optional  -o  switch.
 *              Internal System Variable
 *         optind        Index into argv vector of first param after options,
 *                           from which input file names will be taken.
 *
 **************************************************************************** */

static char *outputname = NULL;

/* **************************************************************************
 *
 *    Print the copyright message.
 *
 **************************************************************************** */
static void print_copyright(void)
{
      printf( "Welcome to toke - OpenBIOS tokenizer v" TOKE_VERSION "\n"
            CORE_COPYR "\n" IBM_COPYR "\n"
            "This program is free software; you may redistribute it "
            "under the terms of\nthe GNU General Public License v2. "
            "This program has absolutely no warranty.\n\n");
#ifdef DEVEL
        /*  Temporary hack during development... */
      printf( "\tTokenizer Compiled " DATE_STAMP "\n" );
#endif /*  DEVEL  */

}

/* **************************************************************************
 *
 *      Function name:    usage
 *      Synopsis:         Print convenient usage-help message
 *
 **************************************************************************** */

static void usage(char *name)
{
      printf("usage: %s [-v] [-i] [-l] [-P] [-o target] <[-d name[=value]]> "
                        "<[-f [no]flagname]> <[-I dir-path]> "
                        "<[-T symbol]> <forth-file>\n\n",name);
      printf("  -v|--verbose          print Advisory messages\n");
      printf("  -i|--ignore-errors    don't suppress output after errors\n");
      printf("  -l|--load-list        create list of FLoaded file names\n");
      printf("  -P|--dependencies     create dePendency-list file\n");
      printf("  -o|--output-name      send output to filename given\n");
      printf("  -d|--define           create user-defined symbol\n");
      printf("  -f|--flag             set (or clear) Special-Feature flag\n");
      printf("  -I|--Include          add a directory to the Include-List\n");
      printf("  -T|--Trace            add a symbol to the Trace List\n");
      printf("  -h|--help             print this help message\n\n");
      printf("  -f|--flag    help     Help for Special-Feature flags\n");
}

/* **************************************************************************
 *
 *      Function name:    get_args
 *      Synopsis:         Parse the Command-Line option switches
 *      
 *      Inputs:
 *         Parameters:                  NONE
 *         Global Variables:
 *                    argc      Counter of command-line arguments
 *                    argv      Vector pointing to command-line arguments
 *         Command-Line Items:  The entire command-line will be parsed
 *
 *      Outputs:
 *         Returned Value:              NONE
 *         Global Variables:
 *                verbose          set by "-v" switch
 *                noerrors           set by "-i" switch
 *                fload_list         set by "-l" switch
 *                dependency_list    set by "-P" switch
 *         Internal Static Variables
 *                outputname         set by "-o" switch
 *         Internal System Variable
 *                optind             Index into argv vector of the position
 *                                       from which to take input file names.
 *         Printout:
 *                (Copyright was already printed by the main body as a
 *                    matter of course, rather than here depending on
 *                    the Verbose flag, because  getopt()  prints its
 *                    own error messages and we want to be sure to show
 *                    the Copyright notice before any error messages.)
 *                Rules for Usage and Flags-list or Flags-help display:
 *                  Usage message on Help-Request or error.
 *                  Ask for usage help, get Usage plus list of Flag Names.
 *                  Ask for Flags-help alone, get Flags-help (names plus
 *                      explanations)
 *                  Ask for usage help and for Flags-help, get Usage plus
 *                      Flags-help, without redundant list of Flag Names.
 *                  Any help-request, exit Zero
 *                  Error in Option switches, or missing input-file name,
 *                      get error-description plus Usage
 *                  Error in Flag Names, get list of Flag Names.
 *                  Any error, exit One.
 *         Behavior:
 *                Exit (non-failure) after printing "Help" message
 *
 *      Error Detection:     Exit with failure status on:
 *          Unknown Option switches or Flag Names
 *          Missing input file name
 *
 *      Process Explanation:
 *           The following switches are recognized:
 *               v
 *               h
 *               ?
 *               i
 *               I
 *               l
 *               P
 *               o
 *               d
 *               f
 *               T
 *           The conditions they set remain in effect through
 *               the entire program run.
 *
 *      Revision History:
 *          Updated Fri, 15 Jul 2005 by David L. Paktor
 *              Don't bail on first invalid option.
 *              Flags to control special features
 *              Usage messages for "special-feature" flags
 *          Updated Mon, 18 Jul 2005 by David L. Paktor
 *              Fine-tune Usage and Flags-list or Flags-help display.
 *          Updated Sun, 27 Nov 2005 by David L. Paktor
 *              Add FLoad-List flag
 *          Updated Wed, 29 Nov 2005 by David L. Paktor
 *              Make getopt() case-insensitive
 *          Updated Fri, 17 Mar 2006 by David L. O'Paktor
 *              Make getopt() case-sensitive again,
 *                  add include-list support and dePendency-list switch
 *
 *      Extraneous Remarks:
 *          We were originally thinking about defining various classes
 *              of "Warning" Messages and (somehow) controlling their
 *              display, but now that we have "special-feature" flags
 *              that control the generation of specific messages, that
 *              step has become unnecessary...
 *
 **************************************************************************** */

static void get_args( int argc, char **argv )
{
      const char *optstring="vhilPo:d:f:I:T:?";
      int c;
      int argindx = 0;
      bool inval_opt = FALSE;
      bool help_mssg = FALSE;
      bool cl_flag_error = FALSE;

      while (1) {
#ifdef __GLIBC__
            int option_index = 0;
            static struct option long_options[] = {
                  { "verbose", 0, 0, 'v' },
                  { "help", 0, 0, 'h' },
                  { "ignore-errors", 0, 0, 'i' },
                  { "load-list",     0, 0, 'l' },
                  { "dependencies",  0, 0, 'P' },
                  { "output-name",   1, 0, 'o' },
                  { "define",        1, 0, 'd' },
                  { "flag",          1, 0, 'f' },
                  { "Include",       1, 0, 'I' },
                  { "Trace",         1, 0, 'T' },
                  { 0, 0, 0, 0 }
            };

            c = getopt_long (argc, argv, optstring,
                         long_options, &option_index);
#else
            c = getopt (argc, argv, optstring);
#endif
            if (c == -1)
                  break;

            argindx++;
            switch (c) {
            case 'v':
                  verbose=TRUE;
                  break;
            case 'o':
                  outputname = optarg;
                  break;
            case 'i':
                  noerrors = TRUE;
                  break;
            case 'l':
                  fload_list = TRUE;
                  break;
            case 'P':
                  dependency_list = TRUE;
                  break;
            case 'd':
                  {
                      char *user_symb = optarg;
                      add_user_symbol(user_symb);
                  }
                  break;
            case 'f':
                  cl_flag_error = set_cl_flag(optarg, FALSE) ;
                  break;
            case 'I':
                  {
                      char *incl_list_elem = optarg;
                      add_to_include_list(incl_list_elem);
                  }
                  break;
            case 'T':
                  add_to_trace_list(optarg);
                  break;
            case '?':
                  /*  Distinguish between a '?' from the user
                   *  and one  getopt()  returned
                   */
                  if ( argv[argindx][1] != '?' )
                  {
                      inval_opt = TRUE;
                      break;
                  }
            case 'h':
            case 'H':
                   help_mssg = TRUE;            
                  break;
            default:
                  /*  This is never executed
                   *  because  getopt()  prints the
                   *    "unknown option -- X"
                   *  message and returns a '?'
                   */
                  printf ("%s: unknown options.\n",argv[0]);
                  usage(argv[0]);
                  exit( 1 );
            }
      }

      if ( help_mssg )
      {
          usage(argv[0]);
          if ( ! clflag_help )
          {
              list_cl_flag_names();
          }
      }
      if ( clflag_help )  cl_flags_help();
      if ( help_mssg || clflag_help )
      {
          exit( 0 );
      }

      if ( inval_opt )      printf ("unknown options.\n");
      if (optind >= argc)   printf ("Input file name missing.\n");
      if ( inval_opt || (optind >= argc) )
      {
            usage(argv[0]);
      }
      if ( cl_flag_error )  list_cl_flag_names();

      if ( inval_opt || (optind >= argc) || cl_flag_error )
      {
          exit( 1);
      }

      if (verbose)
      {
          list_user_symbols();
          list_cl_flag_settings();
          display_include_list();
      }
      show_trace_list();
      save_cl_flags();
}

/* **************************************************************************
 *
 *      Main body of program.  Return 0 for success, 1 for failure.
 *
 *      Still to be done:
 *          Devise a syntax to allow the command-line to specify multiple
 *              input files together with an output file name for each.
 *          Currently, the syntax allows only one output file name to be
 *              specified; when multiple input file names are specified,
 *              the specification of an output file name is disallowed,
 *              and only the default output file names are permitted.
 *              While this works around the immediate problem, a more
 *              elegant solution could be devised...
 *
 **************************************************************************** */

int main(int argc, char **argv)
{
      int retval = 0;

      print_copyright();
      get_args( argc, argv );

      init_error_handler();

      init_stack();
      init_dictionary();

      init_scanner();
      
      if ( outputname != NULL )
      {
          if ( argc > optind + 1 )
          {
          /*  Multiple input file names w/ single output file name  */
            /*  Work-around  */
            printf( "Cannot specify single output file name "
                  "with multiple input file names.\n"
                  "Please either remove output-file-name specification,\n"
                  "or use multiple commands.\n");
              exit ( -2 );
          }
            }

      for ( ; optind < argc ; optind++ )
      {
          bool stream_ok ;

          printf("\nTokenizing  %s   ", argv[optind]);
          init_error_handler();
          stream_ok = init_stream( argv[optind]);
          if ( stream_ok )
          {
            init_output(argv[optind], outputname);

            init_scan_state();

            reset_vocabs();
            reset_cl_flags();

            tokenize();
            finish_headers();
            
            close_stream( NULL);
            if ( close_output() )  retval = 1;
          }
      }
      
      exit_scanner();
      return retval;
}


Generated by  Doxygen 1.6.0   Back to index