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

addfcodes.c

/*
 *                     OpenBIOS - free your system!
 *                         ( FCode tokenizer )
 *
 *  This program is part of a free implementation of the IEEE 1275-1994
 *  Standard for Boot (Initialization Configuration) Firmware.
 *
 *  Copyright (C) 2001-2005 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
 *
 */

/* **************************************************************************
 *
 *      Function(s) for entering Vendor-Specific FCodes to detokenizer.
 *
 *      (C) Copyright 2006 IBM Corporation.  All Rights Reserved.
 *      Module Author:  David L. Paktor    dlpaktor@us.ibm.com
 *
 **************************************************************************** */

/* **************************************************************************
 *
 *      Functions Exported:
 *          add_fcodes_from_list           Add Vendor-Specific FCodes from
 *                                             the file whose name is supplied.
 *
 **************************************************************************** */

/* **************************************************************************
 *
 *      Revision History:
 *          Tue, 25 Apr 2006 by David L. Paktor
 *              Identified this need when working with in-house code,
 *                  which uses some custom functions.  This solution
 *                  is (hoped to be) general enough to cover all cases.
 *          Mon, 16 Oct 2006 by David L. Paktor
 *              Add "special function" words.  So far, only one added:
 *                   double-literal   Infrastructure will support
 *                  adding others as needed.
 *
 **************************************************************************** */


/* **************************************************************************
 *
 *          Global Variables Imported
 *              indata                Buffer into which the file will be read
 *              stream_max            Size of the file buffer.
 *
 **************************************************************************** */


/* **************************************************************************
 *
 *          Global Variables Exported :
 *
 *          For "special function" identification, we will need to
 *              export Global Variables, each of which is a pointer
 *              to the address of the FCode field of the entry in
 *              the Special Functions List for that function.
 *              
 *                Variable                 Associated Name
 *              double_lit_code          double-literal
 *
 **************************************************************************** */

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

#include "detok.h"
#include "stream.h"
#include "addfcodes.h"

/* **************************************************************************
 *
 *          Internal Static Variables
 *     current_vfc_line       Line to be scanned in Vendor-FCodes buffer
 *     vfc_remainder          Remainder of Vendor-FCodes buffer to be scanned
 *     vfc_line_no            Number of current line in Vendor-FCodes buffer
 *     vfc_buf_end            Pointer to end of Vendor-FCodes buffer
 *     spcl_func_list         List of reserved Special Function names
 *     spcl_func_count        Number of reserved Special Function names
 *
 **************************************************************************** */

static char *current_vfc_line;
static char *vfc_remainder;
static int vfc_line_no = 0;
static char *vfc_buf_end;

/*  Special Functions List  */
/*  Initial fcode-field value of  -1  guarantees they won't be used  */
token_t spcl_func_list[]  =  {
      TOKEN_ENTRY( -1, "double(lit)" ),  /*  Entry  [0]  */
};

static const int spcl_func_count = (sizeof(spcl_func_list)/sizeof(token_t)) ;

/*  Global Variables for "special function" identification  */
/*  Each is a pointer to the FCode field of the entry in
 *              the Special Functions List for that function.
 */

u16 *double_lit_code = &spcl_func_list[0].fcode;


/* **************************************************************************
 *
 *      Function name:  skip_whitespace
 *      Synopsis:       Advance the given string-pointer past blanks and tabs.
 *                          (String is presumed to end before new-line)
 *
 *      Inputs:
 *         Parameters:
 *             string_line_ptr        Address of pointer to string
 *
 *      Outputs:
 *         Returned Value:            None
 *             *string_line_ptr       Advanced past blanks and tabs
 *
 **************************************************************************** */

static void skip_whitespace(char **string_line_ptr)
{
      char *cur_char_ptr = *string_line_ptr;
      for (; *cur_char_ptr != 0; cur_char_ptr++) {
            if ((*cur_char_ptr != '\t') && (*cur_char_ptr != ' ')) {
                  *string_line_ptr = cur_char_ptr;
                  break;
            }
      }
}

/* **************************************************************************
 *
 *      Function name:  get_next_vfc_line
 *      Synopsis:       Advance to the next  vfc_line  to be processed.
 *                      Skip blanks and comments.  Indicate when end reached.
 *
 *      Inputs:
 *         Parameters:                    None
 *         Local Static Variables:
 *             vfc_remainder
 *             vfc_buf_end
 *
 *      Outputs:
 *         Returned Value:               FALSE if reached end of buffer
 *         Local Static Variables:
 *             current_vfc_line          Advanced to next line to be scanned
 *             vfc_line_no               Kept in sync with line number in file
 *
 *      Process Explanation:
 *          Comments begin with a pound-sign  ('#') or a backslash  ('\')
 *          Comment-lines or blank or empty lines will be skipped. 
 *
 **************************************************************************** */

static bool get_next_vfc_line(void)
{
      bool retval = FALSE;    /*  TRUE = not at end yet  */
      while (vfc_remainder < vfc_buf_end) {
            current_vfc_line = vfc_remainder;
            vfc_remainder = strchr(current_vfc_line, '\n');
            *vfc_remainder = 0;
            vfc_remainder++;
            vfc_line_no++;
            skip_whitespace(&current_vfc_line);
            if (*current_vfc_line == 0)
                  continue;   /*  Blank line */
            if (*current_vfc_line == '#')
                  continue;   /*  Comment  */
            if (*current_vfc_line == '\\')
                  continue;   /*  Comment  */
            retval = TRUE;
            break;            /*  Found something  */
      }
      return (retval);
}

/* **************************************************************************
 *
 *      Function name:  vfc_splash
 *      Synopsis:       Print a "splash" message to show that we
 *                          are processing Vendor-Specific FCodes,
 *                          but only once.
 *
 *      Inputs:
 *         Parameters:
 *             vf_file_name            Vendor-Specific FCodes file name
 *         Local Static Variables:
 *             did_not_splash          Control printing; once only.
 *
 *      Outputs:
 *         Returned Value:             None
 *         Local Static Variables:
 *             did_not_splash          FALSE after first call.
 *         Printout:
 *             "Splash" message...
 *
 **************************************************************************** */
static bool did_not_splash = TRUE;
static void vfc_splash(char *vf_file_name)
{
      if (did_not_splash) {
            /*  Temporary substring buffer                */
            /*  Guarantee that the malloc will be big enough.  */
            char *strbfr = malloc(strlen(vf_file_name) + 65);
            sprintf(strbfr,
                  "Reading additional FCodes from file:  %s\n",
                  vf_file_name);
            printremark(strbfr);
            free(strbfr);
            did_not_splash = FALSE;
      }
}

/* **************************************************************************
 *
 *      Function name:  add_fcodes_from_list
 *      Synopsis:       Add Vendor-Specific FCodes from the named file
 *                          to the permanent resident dictionary.
 *
 *      Inputs:
 *         Parameters:
 *             vf_file_name            Vendor-Specific FCodes file name
 *         Global Variables:
 *             verbose                 "Verbose" flag.
 *             indata                  Start of file buffer
 *             stream_max              Size of the file buffer.
 *
 *      Outputs:
 *         Returned Value:             TRUE if FCodes have actually been added
 *         Global Variables:
 *             check_tok_seq           Cleared to FALSE, then restored to TRUE
 *         Local Static Variables:
 *             vfc_remainder           Initted to start of file buffer
 *             vfc_buf_end             Initted to end of file buffer
 *         Memory Allocated
 *             Permanent copy of FCode Name
 *         When Freed?
 *             Never.  Rmeains until program termination.
 *         Printout:
 *             If verbose, "Splash" line and count of added entries.
 *
 *      Error Detection:
 *          Fail to open or read Vendor-FCodes file -- Exit program
 *          Improperly formatted input line -- print message and ignore
 *          FCode value out of valid range -- print message and ignore
 *          FCode value already in use -- print message and ignore
 *
 *      Process Explanation:
 *          Valid lines are formatted with the FCode number first
 *              and the name after, one entry per line.  Extra text
 *              after the name will be ignored, so an extra "comment"
 *              is permitted.  The FCode number must be in hex, with
 *              an optional leading  0x  or  0X   For example:  0X407
 *          The valid range for the FCode numbers is 0x010 to 0x7ff.
 *              Numbers above 0x800 infringe upon the area reserved
 *              for FCodes generated by the tokenization process.
 *          Numbers already in use will be ignored.  A Message will be
 *              printed even if the name matches the one on the line.
 *          Names may not be longer than 31 characters.
 *          Certain names will be reserved for special functions.
 *              Those names will be entered in the  detok_table 
 *              with a value of  -1  and again in the static 
 *              table associated with this function, below, to
 *              supply the variable that will be used to match
 *              the name with the special function.
 *             
 *
 **************************************************************************** */

bool add_fcodes_from_list(char *vf_file_name)
{
      bool retval = FALSE;
      int added_fc_count = 0;
      check_tok_seq = FALSE;

      if (verbose)
            vfc_splash(vf_file_name);

      if (init_stream(vf_file_name) != 0) {
            char *strbfr = malloc(strlen(vf_file_name) + 65);
            sprintf(strbfr,
                  "Could not open Additional FCodes file:  %s\n",
                  vf_file_name);
            printremark(strbfr);
            free(strbfr);
            exit(1);
      }
      vfc_remainder = indata;
      vfc_buf_end = indata + stream_max - 1;

      while (get_next_vfc_line()) {
            char vs_fc_name[36];
            int vs_fc_number;
            int scan_result;
            char *lookup_result;
            char *fc_name_cpy;

            /*  For each line of input, we need to check that we have
             *      two strings, one of which is the number and the
             *      second of which is the name.  We will check for
             *      the various formats allowed for the number
             */

            /*    Start with a lower-case  0x    */
            scan_result = sscanf(current_vfc_line, "0x%x %32s",
                             &vs_fc_number, vs_fc_name);

            if (scan_result != 2) { /*  Allow a capital  0X   */
                  scan_result = sscanf(current_vfc_line, "0X%x %32s",
                                   &vs_fc_number, vs_fc_name);
            }
            if (scan_result != 2) { /*  Try it without the  0x   */
                  scan_result = sscanf(current_vfc_line, "%x %32s",
                                   &vs_fc_number, vs_fc_name);
            }

            if (scan_result != 2) { /*  That's it... */
                  char *strbfr =
                      malloc(strlen(current_vfc_line) + 65);
                  vfc_splash(vf_file_name);
                  sprintf(strbfr,
                        "Line #%d, invalid format.  Ignoring:  %s\n",
                        vfc_line_no, current_vfc_line);
                  printremark(strbfr);
                  free(strbfr);
                  continue;
            }

            if ((vs_fc_number < 0x10) || (vs_fc_number > 0x7ff)) {
                  char *strbfr = malloc(85);
                  vfc_splash(vf_file_name);
                  sprintf(strbfr,
                        "Line #%d, FCode number out of range:  0x%x  Ignoring.\n",
                        vfc_line_no, vs_fc_number);
                  printremark(strbfr);
                  free(strbfr);
                  continue;
            }

            lookup_result = lookup_token((u16) vs_fc_number);
            if (strcmp(lookup_result, "ferror") != 0) {
                  char *strbfr = malloc(strlen(lookup_result) + 85);
                  vfc_splash(vf_file_name);
                  sprintf(strbfr,
                        "Line #%d.  FCode number 0x%x is already "
                        "defined as %s  Ignoring.\n",
                        vfc_line_no, vs_fc_number, lookup_result);
                  printremark(strbfr);
                  free(strbfr);
                  continue;
            }

            /*    Check if the name is on the "Special Functions List"  */
            {
                  bool found_spf = FALSE;
                  int indx;
                  for (indx = 0; indx < spcl_func_count; indx++) {
                        if ( strcmp( vs_fc_name, spcl_func_list[indx].name) == 0 ) {
                              char strbuf[64];
                              found_spf = TRUE;
                              spcl_func_list[indx].fcode = vs_fc_number;
                              link_token( &spcl_func_list[indx]);
                              added_fc_count++;
                              sprintf( strbuf,  "Added Special Function FCode "
                                     "number 0x%03x, name %s\n", vs_fc_number, vs_fc_name);
                              printremark( strbuf);
                              break;
                        }
                  }

                  if (found_spf) 
                        continue;
            }

            /*  We've passed all the tests!  */
            fc_name_cpy = strdup(vs_fc_name);
            add_token((u16) vs_fc_number, fc_name_cpy);
            added_fc_count++;
            retval = TRUE;
      }

      if (verbose) {
            char strbfr[32]; 
            sprintf(strbfr,
                  "Added %d FCode numbers\n", added_fc_count);
            printremark(strbfr);
      }

      close_stream();
      check_tok_seq = TRUE;
      return (retval);
}

Generated by  Doxygen 1.6.0   Back to index