LTP GCOV extension - code coverage report
Current view: directory - fcode-utils/toke - stream.c
Test: toke.info
Date: 2006-08-18 Instrumented lines: 290
Code covered: 97.2 % Executed lines: 282

       1                 : /*
       2                 :  *                     OpenBIOS - free your system! 
       3                 :  *                         ( FCode tokenizer )
       4                 :  *                          
       5                 :  *  stream.c - source program streaming from file.
       6                 :  *  
       7                 :  *  This program is part of a free implementation of the IEEE 1275-1994 
       8                 :  *  Standard for Boot (Initialization Configuration) Firmware.
       9                 :  *
      10                 :  *  Copyright (C) 2001-2005 by Stefan Reinauer <stepan@openbios.org>
      11                 :  *
      12                 :  *  This program is free software; you can redistribute it and/or modify
      13                 :  *  it under the terms of the GNU General Public License as published by
      14                 :  *  the Free Software Foundation; version 2 of the License.
      15                 :  *
      16                 :  *  This program is distributed in the hope that it will be useful,
      17                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :  *  GNU General Public License for more details.
      20                 :  *
      21                 :  *  You should have received a copy of the GNU General Public License
      22                 :  *  along with this program; if not, write to the Free Software
      23                 :  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
      24                 :  *
      25                 :  */
      26                 : 
      27                 : /* **************************************************************************
      28                 :  *         Modifications made in 2005 by IBM Corporation
      29                 :  *      (C) Copyright 2005 IBM Corporation.  All Rights Reserved.
      30                 :  *      Modifications Author:  David L. Paktor    dlpaktor@us.ibm.com
      31                 :  **************************************************************************** */
      32                 : 
      33                 : #include <stdio.h>
      34                 : #include <stdlib.h>
      35                 : #ifdef __GLIBC__
      36                 : #define __USE_XOPEN_EXTENDED
      37                 : #endif
      38                 : #include <string.h>
      39                 : #include <sys/stat.h>
      40                 : 
      41                 : #include "emit.h"
      42                 : #include "stream.h"
      43                 : #include "errhandler.h"
      44                 : #include "toke.h"
      45                 : 
      46                 : /* **************************************************************************
      47                 :  *
      48                 :  *      Revision History:
      49                 :  *      Updated Tue, 31 Jan 2006 by David L. Paktor
      50                 :  *          Add support for embedded Environment-Variables in path name
      51                 :  *      Updated Thu, 16 Feb 2006 David L. Paktor
      52                 :  *          Collect missing (inaccessible) filenames
      53                 :  *      Updated Thu, 16 Mar 2006 David L. Paktor
      54                 :  *          Add support for Include-Lists
      55                 :  *
      56                 :  **************************************************************************** */
      57                 : 
      58                 : /* **************************************************************************
      59                 :  *
      60                 :  *          Global Variables Exported
      61                 :  *              start                 Start of input-source buffer
      62                 :  *              end                   End of input-source buffer
      63                 :  *              pc                    Input-source Scanning pointer
      64                 :  *              iname                 Current Input File name
      65                 :  *              lineno                Current Line Number in Input File
      66                 :  *              ostart                Start of Output Buffer
      67                 :  *              opc                   FCode Output Buffer Position Counter
      68                 :  *              oname                 Output File name
      69                 :  *
      70                 :  **************************************************************************** */
      71                 : 
      72                 : 
      73                 : /* Input pointers, Position Counters and Length counters */
      74                 : u8 *start = NULL;
      75                 : u8 *pc;
      76                 : u8 *end;
      77                 : char *iname = NULL;
      78                 : unsigned int lineno = 0;
      79                 : unsigned int abs_token_no = 0;  /*  Absolute Token Number in all Source Input
      80                 :                                  *      Will be used to identify position
      81                 :                                  *      where colon-definition begins and
      82                 :                                  *      to limit clearing of control-structs.
      83                 :                                  */
      84                 : static unsigned int ilen;   /*  Length of Input Buffer   */
      85                 : 
      86                 : /* output pointers */
      87                 : u8 *ostart;
      88                 : char *oname = NULL;
      89                 : unsigned int opc;           /*  Output Position Counter  */
      90                 : 
      91                 : /* We want to limit exposure of this v'ble, so don't put it in  .h  file  */
      92                 : unsigned int olen;          /*  Length of Output Buffer  */
      93                 : /* We want to limit exposure of this Imported Function, likewise.  */
      94                 : void init_emit( void);
      95                 : 
      96                 : /* **************************************************************************
      97                 :  *
      98                 :  *          Internal Static Variables
      99                 :  *     load_list_name       Name of the Load List File
     100                 :  *     load_list_file       (Pointer to) File-Structure for the Load List File
     101                 :  *     depncy_list_name     Name of the Dependency List File
     102                 :  *     depncy_file     (Pointer to) File-Structure for the Dependency List File
     103                 :  *     missing_list_name    Name of the Missing-Files-List File
     104                 :  *     missing_list_file    (Pointer to) File-Structure for Missing-List File
     105                 :  *     no_files_missing     TRUE if able to load all files
     106                 :  *
     107                 :  **************************************************************************** */
     108                 : 
     109                 : static char *load_list_name;
     110                 : static FILE *load_list_file;
     111                 : static char *depncy_list_name;
     112                 : static FILE *depncy_file;
     113                 : static char *missing_list_name;
     114                 : static FILE *missing_list_file;
     115                 : static bool no_files_missing = TRUE;
     116                 : 
     117                 : /* **************************************************************************
     118                 :  *
     119                 :  *         Private data-structure for Include-List support
     120                 :  *
     121                 :  *     Components are simply a string-pointer and a link pointer
     122                 :  *
     123                 :  **************************************************************************** */
     124                 : 
     125                 : typedef struct incl_list
     126                 : {
     127                 :         char             *dir_path;
     128                 :         struct incl_list *next;
     129                 :     } incl_list_t;
     130                 : 
     131                 : /* **************************************************************************
     132                 :  *
     133                 :  *          Internal Static Variables associated with Include-List support
     134                 :  *     include_list_start        Start of the Include-List
     135                 :  *     include_list_next         Next entry in Include-List to add or read
     136                 :  *     max_dir_path_len          Size of longest entry in the Include-List
     137                 :  *     include_list_full_path    Full-Path (i.e., expanded File-name with
     138                 :  *                                   Include-List Entry) that was last opened.
     139                 :  *
     140                 :  **************************************************************************** */
     141                 : static incl_list_t *include_list_start = NULL;
     142                 : static incl_list_t *include_list_next = NULL;
     143                 : static unsigned int max_dir_path_len = 0;
     144                 : static char *include_list_full_path = NULL;
     145                 : 
     146                 : 
     147                 : /* **************************************************************************
     148                 :  *
     149                 :  *      Function name:  add_to_include_list
     150                 :  *      Synopsis:       Add an entry to the Include-List
     151                 :  *
     152                 :  *      Inputs:
     153                 :  *         Parameters:
     154                 :  *             dir_compt               Directory Component to add to Inc-List
     155                 :  *         Local Static Variables:
     156                 :  *             include_list_start      First entry in the Include-List
     157                 :  *             include_list_next       Next entry in Include-List to add
     158                 :  *             max_dir_path_len        Previous max Dir-Component Length 
     159                 :  *
     160                 :  *      Outputs:
     161                 :  *         Returned Value:             NONE
     162                 :  *         Local Static Variables:
     163                 :  *             include_list_start      Assigned a value, first time through
     164                 :  *             include_list_next       "Next" field updated with new entry,
     165                 :  *                                         then pointer updated to new entry.
     166                 :  *             max_dir_path_len        Maximum Length 
     167                 :  *         Memory Allocated
     168                 :  *             For the list-entry, and for the directory/path name to be added
     169                 :  *         When Freed?
     170                 :  *             Remains in effect through the life of the program.
     171                 :  *
     172                 :  *      Process Explanation:
     173                 :  *          Unlike most of our linked-lists, this one will be linked forward,
     174                 :  *              i.e., in the order elements are added, and will be searched
     175                 :  *              in a forward order.
     176                 :  *          This means extra code to handle the first entry.
     177                 :  *          Allocate and initialize the New Include-List Entry.
     178                 :  *          If this is the first entry, point the List-Starter at it.
     179                 :  *          Otherwise, the Last-Entry-on-the-List pointer is already valid;
     180                 :  *              point its "next" field at the New Entry.
     181                 :  *          Point the Last-Entry-on-the-List pointer at the New Entry.
     182                 :  *
     183                 :  **************************************************************************** */
     184                 : 
     185                 : void add_to_include_list( char *dir_compt)
     186              75 : {
     187              75 :     unsigned int new_path_len = strlen( dir_compt);
     188                 :     incl_list_t *new_i_l_e = safe_malloc( sizeof( incl_list_t),
     189              75 :         "adding to include-list" );
     190                 : 
     191              75 :     new_i_l_e->dir_path = strdup( dir_compt);
     192              75 :     new_i_l_e->next = NULL;
     193                 : 
     194              75 :     if ( include_list_start == NULL )
     195                 :     {
     196              31 :         include_list_start = new_i_l_e;
     197                 :     }else{
     198              44 :        include_list_next->next = new_i_l_e;
     199                 :     }
     200                 :     
     201              75 :     include_list_next = new_i_l_e;
     202              75 :     if ( new_path_len > max_dir_path_len  ) max_dir_path_len = new_path_len;
     203              75 : }
     204                 : 
     205                 : #define   DISPLAY_WIDTH  80
     206                 : /* **************************************************************************
     207                 :  *
     208                 :  *      Function name:  display_include_list
     209                 :  *      Synopsis:       Display the Include-List, once it's completed,
     210                 :  *                          if "verbose" mode is in effect.
     211                 :  *
     212                 :  *      Inputs:
     213                 :  *         Parameters:                    NONE
     214                 :  *         Local Static Variables:
     215                 :  *             include_list_start         First entry in the Include-List
     216                 :  *             include_list_next          Next entry, as we step through.
     217                 :  *         Macro:
     218                 :  *             DISPLAY_WIDTH              Width limit of the display
     219                 :  *
     220                 :  *      Outputs:
     221                 :  *         Returned Value:                NONE
     222                 :  *         Local Static Variables:
     223                 :  *             include_list_next          NULL, when reaches end of Incl-List
     224                 :  *         Printout:
     225                 :  *             The elements of the Include-List, separated by a space, on
     226                 :  *                 a line up to the DISPLAY_WIDTH, or on a line by itself
     227                 :  *                 if the element is wider.
     228                 :  *
     229                 :  *      Process Explanation:
     230                 :  *          The calling routine will check for the  verbose  flag.
     231                 :  *          Nothing to be done here if Include-List is NULL.
     232                 :  *          Print a header, then the list.
     233                 :  *
     234                 :  **************************************************************************** */
     235                 : 
     236                 : void display_include_list( void)
     237             153 : {
     238             153 :     if ( include_list_start != NULL )
     239                 :     {
     240              29 :         int curr_wid = DISPLAY_WIDTH;     /*  Current width; force new line  */
     241              29 :         printf("\nInclude-List:");
     242              29 :         include_list_next = include_list_start ;
     243             129 :         while ( include_list_next != NULL )
     244                 :         {
     245              71 :             int this_wid = strlen( include_list_next->dir_path) + 1;
     246              71 :             char *separator = " ";
     247              71 :             if ( curr_wid + this_wid > DISPLAY_WIDTH )
     248                 :             {
     249              33 :                 separator = "\n\t";
     250              33 :                 curr_wid = 7;  /*  Allow 1 for the theoretical space  */
     251                 :             }
     252              71 :             printf("%s%s", separator, include_list_next->dir_path);
     253              71 :             curr_wid += this_wid;
     254              71 :             include_list_next = include_list_next->next ;
     255                 :         }
     256              29 :         printf("\n");
     257                 :     }
     258             153 : }
     259                 : 
     260                 : 
     261                 : 
     262                 : /* **************************************************************************
     263                 :  *
     264                 :  *          We cannot accommodate the structures of the different
     265                 :  *              routines that open files with a single function, so
     266                 :  *              we will have to divide the action up into pieces:
     267                 :  *              one routine to initialize the include-list search, a
     268                 :  *              second to return successive candidates.  The calling
     269                 :  *              routine will do the operation (stat or fopen) until
     270                 :  *              it succeeds or the list is exhausted.  Then it will
     271                 :  *              call a final routine to clean up and display messages.
     272                 :  *
     273                 :  *          I'm sure I don't need to mention that, when no include-list
     274                 :  *              is defined, these functions will still support correct
     275                 :  *              operation...
     276                 :  *
     277                 :  **************************************************************************** */
     278                 : 
     279                 : /* **************************************************************************
     280                 :  *
     281                 :  *      Function name:  init_incl_list_scan
     282                 :  *      Synopsis:       Initialize the search through the Include-List
     283                 :  *
     284                 :  *      Inputs:
     285                 :  *         Parameters:
     286                 :  *             base_name               Expanded user-supplied file-name
     287                 :  *         Local Static Variables:
     288                 :  *             include_list_start      First entry in the Include-List
     289                 :  *             max_dir_path_len        Maximum Directory Component Length 
     290                 :  *
     291                 :  *      Outputs:
     292                 :  *         Returned Value:             NONE
     293                 :  *         Local Static Variables:
     294                 :  *             include_list_next       Next entry in Include-List to read
     295                 :  *             include_list_full_path  Full-Path Buffer pointer
     296                 :  *         Memory Allocated
     297                 :  *             Full-Path Buffer        (If Include-List was defined)
     298                 :  *         When Freed?
     299                 :  *             In  finish_incl_list_scan()
     300                 :  *
     301                 :  *      Process Explanation:
     302                 :  *          The  base_name  passed to the routine is expected to have
     303                 :  *              any embedded Environment-Variables already expanded.
     304                 :  *          The Full-Path Buffer is presumed to be unallocated, and
     305                 :  *              its pointer to be NULL.
     306                 :  *          The Next-Entry-to-read pointer is also presumed to be NULL.
     307                 :  *          If an Include-List has been defined, we will allocate memory
     308                 :  *              for the Full-Path Buffer and point the Next-Entry pointer
     309                 :  *              at the Start of the List.  If not, no need to do anything.
     310                 :  *
     311                 :  **************************************************************************** */
     312                 : 
     313                 : static void init_incl_list_scan( char *base_name)
     314             438 : {
     315             438 :     if ( include_list_start != NULL )
     316                 :     {
     317                 :         /*  Allocate memory for the file-name buffer.
     318                 :          *      maximum path-element length plus base-name length
     319                 :          *      plus one for the slash plus one for the ending NULL
     320                 :          */
     321              90 :         unsigned int new_path_len = max_dir_path_len + strlen( base_name) + 2;
     322              90 :         include_list_full_path = safe_malloc( new_path_len,
     323                 :             "scanning include-list" );
     324              90 :         include_list_next = include_list_start;
     325                 :     }
     326             438 : }
     327                 : 
     328                 : /* **************************************************************************
     329                 :  *
     330                 :  *      Function name:  scan_incl_list
     331                 :  *      Synopsis:       Prepare the next candidate in the include-list search
     332                 :  *                          Indicate when the end has been reached.
     333                 :  *
     334                 :  *      Inputs:
     335                 :  *         Parameters:
     336                 :  *             base_name               Expanded user-supplied file-name
     337                 :  *         Local Static Variables:
     338                 :  *             include_list_full_path  Full-Path Buffer pointer
     339                 :  *             include_list_next       Next entry in Include-List to read
     340                 :  *
     341                 :  *      Outputs:
     342                 :  *         Returned Value:             TRUE if valid candidate; FALSE when done
     343                 :  *         Local Static Variables:
     344                 :  *             include_list_full_path  Next Full file-name Path to use
     345                 :  *             include_list_next       Updated to next entry in the List
     346                 :  *
     347                 :  *      Process Explanation:
     348                 :  *          Include-List Components are presumed not to require any expansion;
     349                 :  *              the Shell is expected to resolve any Environment-Variables
     350                 :  *              supplied in command-line arguments before they are passed
     351                 :  *              to the (this) application-program.
     352                 :  *          We will, therefore, not attempt to expand any Components of
     353                 :  *              the Include-List.  
     354                 :  *          If the Full-Path Buffer pointer is NULL, it indicates that no
     355                 :  *              entries have been made to the Include-List and this is our
     356                 :  *              first time through this routine in this search; we will
     357                 :  *              use the base-name as supplied, presumably relative to the
     358                 :  *              current directory.  Point the buffer-pointer at the base-
     359                 :  *              -name and return "Not Done".
     360                 :  *          Otherwise, we will look at the Next-Entry pointer:
     361                 :  *              If it is NULL, we have come to the end of the Include-List;
     362                 :  *                  whether because no Include-List was defined or because
     363                 :  *                  we have reached the end, we will return "Done".
     364                 :  *              Otherwise, we will load the Full-Path Buffer with the entry
     365                 :  *                  currently indicated by the Next-Entry pointer, advance
     366                 :  *                  it to the next entry in the List and return "Not Done".
     367                 :  *          We will supply a slash as the directory-element separator in
     368                 :  *              between the Include-List entry and the  base_name 
     369                 :  *
     370                 :  *      Extraneous Remarks:
     371                 :  *          The slash as directory-element separator works in UNIX-related
     372                 :  *              environments, but is not guaranteed in others.  I would
     373                 :  *              have preferred to specify that Include-List Components are
     374                 :  *              required to end with the appropriate separator, but that
     375                 :  *              was neither acceptable nor compatible with existing practice
     376                 :  *              in other utilities, and the effort to programmatically
     377                 :  *              determine the separator used by the Host O/S was too much
     378                 :  *              for such a small return.  And besides, we already have so
     379                 :  *              many other UNIX-centric assumptions hard-coded into the
     380                 :  *              routines in this file (dollar-sign to signify Environment
     381                 :  *              Variables, period for file-name-extension separator, etc.)
     382                 :  *              that it's just too much of an uphill battle anymore...
     383                 :  *
     384                 :  **************************************************************************** */
     385                 : 
     386                 : static bool scan_incl_list( char *base_name)
     387             545 : {
     388             545 :     bool retval = FALSE;   /*  default to "Done"  */
     389                 :         
     390             545 :     if ( include_list_full_path == NULL )
     391                 :     {
     392             348 :         include_list_full_path = base_name;
     393             348 :         retval = TRUE;
     394                 :     }else{
     395             197 :         if ( include_list_next != NULL )
     396                 :         {
     397                 : 
     398                 :             /*  Special case:  If the next Directory Component is
     399                 :              *      an empty string, do not prepend a slash; that
     400                 :              *      would either become a root-based absolute path,
     401                 :              *      or, if the base-name is itself an absolute path,
     402                 :              *      it would be a path that begins with two slashes,
     403                 :              *      and *some* Host Operating Systems ***REALLY***
     404                 :              *      DO NOT LIKE that!
     405                 :              */
     406             181 :             if ( strlen( include_list_next->dir_path) == 0 )
     407                 :             {
     408               8 :                 sprintf( include_list_full_path, "%s", base_name);
     409                 :             }else{
     410             173 :                 sprintf( include_list_full_path, "%s/%s",
     411                 :                     include_list_next->dir_path, base_name);
     412                 :             }
     413             181 :             include_list_next = include_list_next->next;
     414             181 :             retval = TRUE;
     415                 :         }
     416                 :     }
     417                 : 
     418             545 :     return( retval);
     419                 : }
     420                 : 
     421                 : /* **************************************************************************
     422                 :  *
     423                 :  *      Function name:  finish_incl_list_scan
     424                 :  *      Synopsis:       Clean up after a search through the Include-List
     425                 :  *                          Display appropriate messages.
     426                 :  *
     427                 :  *      Inputs:
     428                 :  *         Parameters:
     429                 :  *             op_succeeded            TRUE if intended operation was ok.
     430                 :  *             
     431                 :  *         Local Static Variables:
     432                 :  *             include_list_start      Non-NULL if Include-List was defined
     433                 :  *
     434                 :  *      Outputs:
     435                 :  *         Returned Value:             NONE
     436                 :  *         Local Static Variables:
     437                 :  *             include_list_full_path  Reset to NULL
     438                 :  *             include_list_next       Reset to NULL
     439                 :  *         Memory Freed
     440                 :  *             Full-Path Buffer        (If Include-List was defined)
     441                 :  *         Printout:
     442                 :  *             If file was found in Include-List, Advisory showing where.
     443                 :  *
     444                 :  **************************************************************************** */
     445                 : 
     446                 : static void finish_incl_list_scan( bool op_succeeded)
     447             441 : {
     448             441 :     if ( include_list_start != NULL )
     449                 :     {
     450              91 :         if ( op_succeeded )
     451                 :         {
     452              86 :             tokenization_error( INFO,
     453                 :                 "File was found in %s\n" ,include_list_full_path );
     454                 :         }
     455              91 :         free( include_list_full_path);
     456                 :     }
     457             441 :     include_list_full_path = NULL;
     458             441 :     include_list_next = NULL;
     459             441 : }
     460                 : 
     461                 : /* **************************************************************************
     462                 :  *
     463                 :  *      Function name:  open_incl_list_file
     464                 :  *      Synopsis:       Look in the Include-List, if one is defined, for
     465                 :  *                          the file whose name is given and open it.
     466                 :  *
     467                 :  *      Inputs:
     468                 :  *         Parameters:
     469                 :  *             base_name               Expanded user-supplied file-name
     470                 :  *             mode                    Mode-string to use; usually "r" or "rb"
     471                 :  *         Local Static Variables:
     472                 :  *             include_list_full_path  Full Path to use in fopen atttempt
     473                 :  *
     474                 :  *      Outputs:
     475                 :  *         Returned Value:             File structure pointer; NULL if failed
     476                 :  *         Local Static Variables:
     477                 :  *             include_list_full_path  Full Path used, if succeeded
     478                 :  *
     479                 :  *      Error Detection:
     480                 :  *          Calling routine will detect and report Errors.
     481                 :  *
     482                 :  *      Process Explanation:
     483                 :  *          This routine will initialize and step through Include-List.
     484                 :  *              Calling routine will be responsible for "finishing" the
     485                 :  *              Include-List search, as well as any Advisory messages.
     486                 :  *
     487                 :  **************************************************************************** */
     488                 : 
     489                 : static FILE *open_incl_list_file( char *base_name, char *mode)
     490              15 : {
     491              15 :     FILE *retval = NULL;
     492                 : 
     493              15 :     init_incl_list_scan( base_name);
     494              66 :     while ( scan_incl_list( base_name) )
     495                 :     {
     496              43 :         retval = fopen( include_list_full_path, mode);
     497              43 :         if ( retval != NULL )
     498                 :         {
     499               7 :             break; 
     500                 :         }
     501                 :     }
     502                 : 
     503              15 :     return (retval);
     504                 : }
     505                 : 
     506                 : /* **************************************************************************
     507                 :  *
     508                 :  *      Function name:  stat_incl_list_file
     509                 :  *      Synopsis:       Look in the Include-List, if defined, for given file,
     510                 :  *                          and collect its statistics.
     511                 :  *                      
     512                 :  *
     513                 :  *      Inputs:
     514                 :  *         Parameters:
     515                 :  *             base_name               Expanded user-supplied file-name
     516                 :  *             file_info               Pointer to STAT structure
     517                 :  *         Local Static Variables:
     518                 :  *             include_list_full_path  Full Path to use in file-status atttempt
     519                 :  *
     520                 :  *      Outputs:
     521                 :  *         Returned Value:             TRUE if succeeded.
     522                 :  *         Local Static Variables:
     523                 :  *             include_list_full_path  Full Path used, if succeeded
     524                 :  *         Supplied Pointers:
     525                 :  *             *file_info              File-statistics structure from STAT call
     526                 :  *
     527                 :  *      Error Detection:
     528                 :  *          Calling routine will detect and report Errors.
     529                 :  *          
     530                 :  *      Process Explanation:
     531                 :  *          This routine will initialize and step through Include-List.
     532                 :  *              Calling routine will be responsible for "finishing" the
     533                 :  *              Include-List search, as well as any Advisory messages.
     534                 :  *
     535                 :  **************************************************************************** */
     536                 : 
     537                 : static bool stat_incl_list_file( char *base_name, struct stat *file_info)
     538             423 : {
     539             423 :     bool retval = FALSE;
     540             423 :     int stat_reslt = -1;    /*  Success = 0   */
     541                 : 
     542             423 :     init_incl_list_scan( base_name);
     543             423 :     while ( scan_incl_list( base_name) )
     544                 :     {
     545             972 :         stat_reslt = stat( include_list_full_path, file_info);
     546             486 :         if ( stat_reslt == 0 )
     547                 :         {
     548             415 :             retval = TRUE;
     549             415 :             break; 
     550                 :         }
     551                 :     }
     552                 : 
     553             423 :     return (retval);
     554                 : }
     555                 : 
     556                 : /* **************************************************************************
     557                 :  *
     558                 :  *      Function name:  init_inbuf
     559                 :  *      Synopsis:       Set the given buffer as the current input source
     560                 :  *      
     561                 :  *      Inputs:
     562                 :  *         Parameters:
     563                 :  *             inbuf         Pointer to start of new input buffer
     564                 :  *             buflen        Length of new input buffer
     565                 :  *
     566                 :  *      Outputs:
     567                 :  *         Returned Value:    NONE
     568                 :  *         Global Variables:
     569                 :  *             start             Points to given buffer
     570                 :  *             end               Points to end of new input buffer
     571                 :  *             pc                Re-initialized      
     572                 :  *
     573                 :  **************************************************************************** */
     574                 : 
     575                 : void init_inbuf(char *inbuf, unsigned int buflen)
     576            1609 : {
     577            1609 :     start = inbuf;
     578            1609 :     pc = start;
     579            1609 :     end = pc + buflen;
     580            1609 : }
     581                 : 
     582                 : /* **************************************************************************
     583                 :  *
     584                 :  *      Function name:  could_not_open
     585                 :  *      Synopsis:       Report the "Could not open" Message for various Files.
     586                 :  *
     587                 :  *      Inputs:
     588                 :  *         Parameters:
     589                 :  *             severity                  Severity of message, WARNING or ERROR
     590                 :  *             fle_nam                   Name of file
     591                 :  *             for_what                  Phrase after "... for "
     592                 :  *
     593                 :  *      Outputs:
     594                 :  *         Returned Value:               NONE
     595                 :  *         Printout:
     596                 :  *             Message of indicated severity.
     597                 :  *
     598                 :  *      Error Detection:
     599                 :  *          Error already detected; reported here.
     600                 :  *
     601                 :  **************************************************************************** */
     602                 : 
     603                 : static void could_not_open(int severity, char *fle_nam, char *for_what)
     604               6 : {
     605               6 :     tokenization_error( severity, "Could not open file %s for %s.\n",
     606                 :         fle_nam, for_what);
     607                 : 
     608               6 : }
     609                 : 
     610                 : /* **************************************************************************
     611                 :  *
     612                 :  *      Function name:  file_is_missing
     613                 :  *      Synopsis:       Add the given File to the Missing-Files-List.
     614                 :  *
     615                 :  *      Inputs:
     616                 :  *         Parameters:
     617                 :  *             fle_nam                   Name of file
     618                 :  *         Local Static Variables:
     619                 :  *             missing_list_file         Missing-Files-List File Structure
     620                 :  *                                           May be NULL if none was opened
     621                 :  *
     622                 :  *      Outputs:
     623                 :  *         Returned Value:               NONE
     624                 :  *         Local Static Variables:
     625                 :  *             no_files_missing         Set FALSE
     626                 :  *         File Output:
     627                 :  *             Write File name to Missing-Files-List (if one was opened)
     628                 :  *
     629                 :  *      Error Detection:
     630                 :  *          Error already detected; reported here.
     631                 :  *
     632                 :  **************************************************************************** */
     633                 : 
     634                 : static void file_is_missing( char *fle_nam)
     635              20 : {
     636              20 :     if ( missing_list_file != NULL )
     637                 :     {
     638               8 :         fprintf( missing_list_file, "%s\n", fle_nam);
     639               8 :         no_files_missing = FALSE;
     640                 :     }
     641              20 : }
     642                 : 
     643                 : /* **************************************************************************
     644                 :  *
     645                 :  *      Function name:  add_to_load_lists
     646                 :  *      Synopsis:       Add the given input file-name to the Load-List File,
     647                 :  *                      and the Full File path to the Dependency-List File.
     648                 :  *
     649                 :  *      Inputs:
     650                 :  *         Parameters:
     651                 :  *             in_name                  Name of given input Source File
     652                 :  *         Local Static Variables:
     653                 :  *             load_list_file           Load List File Structure pointer
     654                 :  *             depncy_file              Dependency-List File Structure ptr
     655                 :  *                            Either may be NULL if the file was not opened.
     656                 :  *             include_list_full_path   Full Path to where the file was found.
     657                 :  *
     658                 :  *      Outputs:
     659                 :  *         Returned Value:               NONE
     660                 :  *         File Output:
     661                 :  *             Write given file-name to Load-List file (if one was opened)
     662                 :  *             Write File Path to Dependency-List file (if one was opened)
     663                 :  *
     664                 :  *      Process Explanation:
     665                 :  *          Write into the Load-List file the input Source Filename in the
     666                 :  *              same form -- i.e., unexpanded -- as was supplied by the User.
     667                 :  *          Write into the Dependency-List file the full expanded path, as
     668                 :  *              supplied by the program to the Host Operating System.
     669                 :  *
     670                 :  **************************************************************************** */
     671                 : 
     672                 : static void add_to_load_lists( const char *in_name)
     673             570 : {
     674             570 :     if ( load_list_file != NULL )
     675                 :     {
     676             184 :         fprintf( load_list_file, "%s\n", in_name);
     677                 :     }
     678             570 :     if ( depncy_file != NULL )
     679                 :     {
     680               7 :         fprintf( depncy_file, "%s\n", include_list_full_path);
     681                 :     }
     682             570 : }
     683                 : 
     684                 : 
     685                 : /* **************************************************************************
     686                 :  *
     687                 :  *      In the functions that support accessing files whose path-names
     688                 :  *          contain embedded Environment-Variables, the commentaries
     689                 :  *          will refer to this process, or to inputs that require it,
     690                 :  *          using variants of the term "expand".
     691                 :  *
     692                 :  *      We will also keep some of the relevant information as Local
     693                 :  *          Static Variables.
     694                 :  *
     695                 :  **************************************************************************** */
     696                 : 
     697                 : static char expansion_buffer[ 2*GET_BUF_MAX];
     698                 : static bool was_expanded;
     699                 : static int expansion_msg_severity = INFO;
     700                 : 
     701                 : /* **************************************************************************
     702                 :  *
     703                 :  *      Function name:  expanded_name
     704                 :  *      Synopsis:       Advisory message to display filename expansion.
     705                 :  *
     706                 :  *      Inputs:
     707                 :  *         Parameters:
     708                 :  *         Local Static Variables:
     709                 :  *             was_expanded              TRUE if expansion happened
     710                 :  *             expansion_buffer          Buffer with result of expansion
     711                 :  *             expansion_msg_severity    Whether it's an ordinary Advisory
     712                 :  *                                           or we force a message.
     713                 :  *
     714                 :  *      Outputs:
     715                 :  *         Returned Value:               NONE
     716                 :  *             
     717                 :  *         Printout:
     718                 :  *             Advisory message showing expansion, if expansion happened
     719                 :  *             Otherwise, nothing.
     720                 :  *
     721                 :  **************************************************************************** */
     722                 : 
     723                 : static void expanded_name( void )
     724              29 : {
     725              29 :     if ( was_expanded )
     726                 :     {
     727              27 :         tokenization_error( expansion_msg_severity,
     728                 :             "File name expanded to:  %s\n", expansion_buffer);
     729                 :     }
     730              29 : }
     731                 : 
     732                 : 
     733                 : /* **************************************************************************
     734                 :  *
     735                 :  *      Function name:  expansion_error
     736                 :  *      Synopsis:       Supplemental message to display filename expansion.
     737                 :  *                      Called after an expanded-filename failure was reported.
     738                 :  *
     739                 :  *      Inputs:
     740                 :  *         Parameters:
     741                 :  *         Global Variables:
     742                 :  *             verbose                   Set by "-v" switch
     743                 :  *
     744                 :  *      Outputs:
     745                 :  *         Returned Value:               NONE
     746                 :  *         Printout:
     747                 :  *             Advisory message showing expansion, if applicable
     748                 :  *                 and if wasn't already shown.
     749                 :  *
     750                 :  *      Error Detection:
     751                 :  *          Called after Error was reported.
     752                 :  *
     753                 :  *      Process Explanation:
     754                 :  *          Presumptions are that:
     755                 :  *              An Error message, showing the user-supplied form of the
     756                 :  *                  pathname is also being displayed
     757                 :  *              An advisory message showing the pathname expansion may
     758                 :  *                  have been displayed during the expansion process,
     759                 :  *                  if  verbose  was TRUE.
     760                 :  *          The purpose of this routine is to display the expansion if
     761                 :  *              it had not already just been displayed, i.e., if  verbose
     762                 :  *              is not set to TRUE:  Temporarily force the display of an
     763                 :  *              Advisory message.
     764                 :  *
     765                 :  *      Extraneous Remarks:
     766                 :  *          If this routine is called before the Error message is displayed,
     767                 :  *              the verbose and non-verbose versions of the Log-File will
     768                 :  *              match up nicely...
     769                 :  *
     770                 :  **************************************************************************** */
     771                 : 
     772                 : static void expansion_error( void )
     773              31 : {
     774              31 :     if ( INVERSE( verbose) )
     775                 :     {
     776               9 :         expansion_msg_severity |= FORCE_MSG;
     777               9 :         expanded_name();
     778               9 :         expansion_msg_severity ^= FORCE_MSG;
     779                 :     }
     780              31 : }
     781                 : 
     782                 : 
     783                 : /* **************************************************************************
     784                 :  *
     785                 :  *      Function name:  expand_pathname
     786                 :  *      Synopsis:       Perform the expansion of a path-name that may contain
     787                 :  *                          embedded Environment-Variables
     788                 :  *
     789                 :  *      Inputs:
     790                 :  *         Parameters:
     791                 :  *             input_pathname           The user-supplied filename
     792                 :  *         Global/Static MACRO:
     793                 :  *             GET_BUF_MAX              Size of expansion buffer is twice this.
     794                 :  *
     795                 :  *      Outputs:
     796                 :  *         Returned Value:              Pointer to expanded name, or to
     797                 :  *                                          input if no expansion needed.
     798                 :  *                                      NULL if error.
     799                 :  *         Local Static Variables:
     800                 :  *             was_expanded             TRUE if expansion needed and succeeded
     801                 :  *             expansion_buffer         Result of expansion
     802                 :  *         Printout:
     803                 :  *             Advisory message showing expansion
     804                 :  *             Presumption is that an Advisory giving the user-supplied
     805                 :  *                 pathname was already printed.
     806                 :  *
     807                 :  *      Error Detection:
     808                 :  *          Syntax error.  System might print something; it might not be
     809                 :  *              captured, even to a log-file.  System failure return might
     810                 :  *              be the only program-detectable indication.  Display ERROR
     811                 :  *              message and return NULL pointer.  Calling routine will
     812                 :  *              display the user-supplied pathname in its Error message
     813                 :  *              indicating failure to open the file.
     814                 :  *
     815                 :  *      Process Explanation:
     816                 :  *          Generally speaking, we will let the Shell expand the Environment
     817                 :  *              Variables embedded in the user-supplied pathname.
     818                 :  *          First, though, we will see if the expansion is necessary:  Look
     819                 :  *              for the telltale character, '$', in the input string.  If
     820                 :  *              it's not there, there are no Env't-V'bles, and no expansion
     821                 :  *              is necessary.  Return the pointer to the input string and
     822                 :  *              we're done.  Otherwise.....
     823                 :  *          Acquire a temporary file-name.  Construct a string of the form:
     824                 :  *                      echo input_string > temp_file_name
     825                 :  *              and then issue that string as a command to the Shell.
     826                 :  *          If that string generates a system-call failure, report an ERROR.
     827                 :  *          Open the temporary file and read its contents.  That will be
     828                 :  *              the expansion of the input string.  If its length exceeds
     829                 :  *              the capacity of the expansion buffer, it's another ERROR.
     830                 :  *          (Of course, don't forget to delete the temporary file.)
     831                 :  *          Place the null-byte marker at the end of the expanded name,
     832                 :  *              trimming off the terminating new-line.
     833                 :  *          Success.  Display the expanded name (as an Advisory message)
     834                 :  *              Return the pointer to the expansion buffer and set the flag.
     835                 :  *              (Did I mention don't forget to delete the temporary file?)
     836                 :  *
     837                 :  *      Extraneous Remarks:
     838                 :  *          This implementation approach turned out to be the simplest and
     839                 :  *              cleanest way to accomplish our purpose.  It also boasts the
     840                 :  *              HUGE advantage of not requiring re-invention of a well-used
     841                 :  *              (proverbial) wheel.  Plus, any variations allowed by the
     842                 :  *              shell (e.g.,: $PWD:h ) are automatically converted, too,
     843                 :  *              depending on the System shell (e.g., not for Bourne shell).
     844                 :  *          In order to spare you, the maintenance programmer, unnecessary
     845                 :  *              agony, I will list a few other approaches I tested, with a
     846                 :  *              brief note about the results of each:
     847                 :  *          (1)
     848                 :  *          I actually tried parsing the input line and passing each component
     849                 :  *              V'ble to the getenv() function, accumulating the results into
     850                 :  *              a conversion buffer.  I needed to check for every possible
     851                 :  *              delimiter, and handle curly-brace enclosures.  The resultant
     852                 :  *              code was *UGLY* ... you'd be appalled!  The only good spot was
     853                 :  *              that I was able to compensate for an open-curly-brace without
     854                 :  *              a corresponding close-curly-brace (if close-c-b wasn't found,
     855                 :  *              resume the search for other delimiters...) which, apparently,
     856                 :  *              the System does not or will not do.  It was, however, too
     857                 :  *              small a compensation for all the awfulness entailed overall.
     858                 :  *
     859                 :  *          I tried various approaches to using the Environment-Variables to
     860                 :  *              convert and retrieve the input string:
     861                 :  *          (2)
     862                 :  *          Create a command-string that would set an Env't V'ble to the
     863                 :  *              input-string, and pass the command-string to the system() call,
     864                 :  *              then retrieve the Env't V'ble thus set via getenv().  No dice;
     865                 :  *              the system() call operated in a separate sub-shell and could
     866                 :  *              not export its Env't upwards.
     867                 :  *          (3)
     868                 :  *          Use the setenv() command to set an Env't V'ble to the input-string
     869                 :  *              and retrieve it via getenv().  The returned string matched the
     870                 :  *              input-string without converting it.
     871                 :  *          (4)
     872                 :  *          Use the setenv() command to set an Env't V'ble to a string like:
     873                 :  *                      `echo input_string`
     874                 :  *              Again, the string retrieved via getenv() exactly matched the
     875                 :  *              unconverted command-string, back-quotes and all.
     876                 :  *
     877                 :  *          Of course, the equivalents of (2), (3) and (4) worked as desired
     878                 :  *              when tested as direct commands to the Shell.  UNIX can be
     879                 :  *              funny that way...
     880                 :  *
     881                 :  *          Oh!  Also:  we will slightly stretch the rules of well-structured
     882                 :  *              code.
     883                 :  *
     884                 :  **************************************************************************** */
     885                 : 
     886                 : static char *expand_pathname( const char *input_pathname)
     887             443 : {
     888                 :     static const int buffer_max = GET_BUF_MAX * 2;
     889                 : 
     890             443 :     char *retval = (char *)input_pathname;
     891             443 :     was_expanded = FALSE;
     892                 : 
     893                 :     /*  If no '$' is found, expansion is unnecessary.  */
     894             443 :     if ( strchr( input_pathname, '$') != NULL )
     895                 :     {
     896                 :         FILE *temp_file;
     897                 :         int syst_stat;
     898              25 :         const char *temp_file_name = tmpnam( NULL);
     899                 : 
     900                 :         /*  Use the expansion buffer for our temporary command string  */
     901              25 :         sprintf( expansion_buffer,
     902                 :             "echo %s>%s\n", input_pathname, temp_file_name);
     903              25 :         syst_stat = system( expansion_buffer);
     904              25 :         if ( syst_stat != 0 )
     905                 :         {
     906               5 :             tokenization_error( TKERROR,
     907                 :                 "Expansion Syntax.\n");
     908                 :             /*  The "File-Opening" error message will show the input string */
     909               5 :             return( NULL);
     910                 :         }
     911                 : 
     912              20 :         temp_file = fopen( temp_file_name, "r");  /*  Cannot fail.   */
     913              20 :         syst_stat = fread( expansion_buffer, 1, buffer_max, temp_file);
     914                 :         /*  Error test.  Length of what we read is not a good indicator;
     915                 :          *      it's limited anyway by buffer_max.
     916                 :          *  Valid test is if last character read was the new-line.
     917                 :          */
     918              20 :         if ( expansion_buffer[syst_stat-1] != '\n' )
     919                 :         {
     920               0 :             tokenization_error( TKERROR,
     921                 :                 "Expansion buffer overflow.  Max length is %d.\n",
     922                 :                     buffer_max);
     923               0 :             retval = NULL;
     924                 :         }else{
     925              20 :             expansion_buffer[syst_stat-1] =0;
     926              20 :             was_expanded = TRUE;
     927              20 :             retval = expansion_buffer;
     928              20 :             expanded_name();
     929                 :         }
     930                 : 
     931              20 :         fclose( temp_file);
     932              20 :         remove( temp_file_name);
     933                 :     }
     934                 : 
     935             438 :     return( retval);
     936                 : }
     937                 : 
     938                 : /* **************************************************************************
     939                 :  *
     940                 :  *      Function name:  open_expanded_file
     941                 :  *      Synopsis:       Open a file, expanding Environment-Variables that
     942                 :  *                          may be embedded in the given path-name.
     943                 :  *
     944                 :  *      Inputs:
     945                 :  *         Parameters:
     946                 :  *             path_name              The user-supplied path-name
     947                 :  *             mode                   Mode-string to use; usually "r" or "rb"
     948                 :  *             for_what               Phrase to use in Messages
     949                 :  *
     950                 :  *      Outputs:
     951                 :  *         Returned Value:            Pointer to FILE structure; NULL if failed
     952                 :  *         Local Static Variables:
     953                 :  *             was_expanded          TRUE if expansion happened
     954                 :  *             expansion_buffer      Result of expansion
     955                 :  *         Printout:
     956                 :  *             Advisory message showing expansion
     957                 :  *
     958                 :  *      Error Detection:
     959                 :  *          If expansion or system-call for file-open failed,
     960                 :  *              report Error and return NULL.
     961                 :  *
     962                 :  **************************************************************************** */
     963                 : 
     964                 : FILE *open_expanded_file( const char *path_name, char *mode, char *for_what)
     965              18 : {
     966                 : 
     967              18 :     FILE *retval = NULL;
     968                 : 
     969              18 :     char *infile_name = expand_pathname( path_name);
     970              18 :     if ( infile_name != NULL )
     971                 :     {
     972              15 :         retval = open_incl_list_file( infile_name, mode);
     973                 :     }
     974                 : 
     975              18 :     if ( retval == NULL )
     976                 :     {
     977              11 :         expansion_error();
     978              11 :         tokenization_error ( TKERROR,
     979                 :             "Failed to open file %s for %s\n", path_name, for_what );
     980                 :     }
     981                 : 
     982              18 :     finish_incl_list_scan( BOOLVAL( retval != NULL) );
     983                 : 
     984              18 :     return( retval);
     985                 : }
     986                 : 
     987                 : /* **************************************************************************
     988                 :  *
     989                 :  *      Function name:  init_stream
     990                 :  *      Synopsis:       Open a file and make it the current source.
     991                 :  *                      This is called, not only at the start of tokenization,
     992                 :  *                      but also when a subsidiary file is FLOADed.
     993                 :  *      
     994                 :  *      Inputs:
     995                 :  *         Parameters:
     996                 :  *             name                     Name of the new Input File to open
     997                 :  *                                          May be path-name containing
     998                 :  *                                          embedded Environment-Variables.
     999                 :  *         Global Variables:
    1000                 :  *             oname                    NULL if opening Primary Input File
    1001                 :  *         Local Static Variables:
    1002                 :  *             include_list_full_path   Full Path to where the file was found
    1003                 :  *
    1004                 :  *      Outputs:
    1005                 :  *         Returned Value:    TRUE = opened and read file successfully
    1006                 :  *         Global Variables     (Only changed if successful):
    1007                 :  *             iname                    Set to new Input File name
    1008                 :  *             lineno                   Re-initialized to 1
    1009                 :  *         Local Static Variables:
    1010                 :  *             no_files_missing         Set FALSE if couldn't read input file
    1011                 :  *             include_list_full_path   Retains full-path if file opened was
    1012                 :  *                      the Primary Input File (as contrasted with an FLoaded
    1013                 :  *                      Source file), in which case a call to  init_output()
    1014                 :  *                      is expected; the Full-Path Buffer will be freed there.
    1015                 :  *         Memory Allocated
    1016                 :  *             Duplicate of Input File name (becomes  iname  )
    1017                 :  *             A fresh input buffer; input file is copied to it.
    1018                 :  *                 Becomes  start  by action of call to  init_inbuf().
    1019                 :  *         When Freed?
    1020                 :  *             By  close_stream()
    1021                 :  *         File Output:
    1022                 :  *             Write new Input File name to Load-List file.
    1023                 :  *             Writing to Missing-Files-List File if failure,
    1024                 :  *                 or Full File path to Dependency-List File,
    1025                 :  *                 is handled by called routine.
    1026                 :  *         Other Exotic Effects:
    1027                 :  *             Force a flush of  stdout  before printing ERROR messages
    1028                 :  *             
    1029                 :  *      Error Detection:
    1030                 :  *          Failure to open or read Input file:  ERROR; suppress output;
    1031                 :  *              write Input File name to Missing-Files-List File.
    1032                 :  *
    1033                 :  *      Process Explanation:
    1034                 :  *          Free local buffer on failure.
    1035                 :  *          Caller should only invoke  close_stream()  if this call succeeded.
    1036                 :  *          Some filesystems use zeros for new-line; we need to convert
    1037                 :  *              those zeros to line-feeds.
    1038                 :  *          Similarly for files that have carr-ret/line-feed; the carr-ret
    1039                 :  *              will cause havoc; replace it w/ a space.
    1040                 :  *      
    1041                 :  *      Revision History:
    1042                 :  *      Updated Thu, 07 Apr 2005 by David L. Paktor
    1043                 :  *          Restructured.  If opened file, close it, even if can't read it.
    1044                 :  *          Return TRUE on success.
    1045                 :  *          Caller examines return value.    
    1046                 :  *      Updated Wed, 13 Jul 2005 by David L. Paktor
    1047                 :  *          Replace carr-rets with spaces.   
    1048                 :  *      Updated Sun, 27 Nov 2005 by David L. Paktor
    1049                 :  *          Write new Input File name to Load-List file. 
    1050                 :  *      Updated Tue, 31 Jan 2006 by David L. Paktor
    1051                 :  *          Add support for embedded Environment-Variables in path name
    1052                 :  *      Updated Thu, 16 Feb 2006 David L. Paktor
    1053                 :  *          Collect missing (inaccessible) filenames
    1054                 :  *      Updated Fri, 17 Mar 2006 David L. O'Paktor
    1055                 :  *          Add support for Include-List search
    1056                 :  *
    1057                 :  *      Still to be done:
    1058                 :  *          Set a flag when carr-ret has been replaced by space;
    1059                 :  *              when a string crosses a line, if this flag is set,
    1060                 :  *              issue a warning that an extra space has been inserted.
    1061                 :  *
    1062                 :  **************************************************************************** */
    1063                 : 
    1064                 : bool init_stream( const char *name)
    1065             425 : {
    1066                 :     FILE *infile;
    1067                 :     u8 *newbuf;
    1068                 :         struct stat finfo;
    1069             425 :     bool stat_succ = FALSE;
    1070             425 :     bool tried_stat = FALSE;
    1071             425 :     bool retval = FALSE;
    1072             425 :     bool inp_fil_acc_err = FALSE;
    1073             425 :     bool inp_fil_open_err = FALSE;
    1074             425 :     bool inp_fil_read_err = FALSE;
    1075                 : 
    1076             425 :     char *infile_name = expand_pathname( name);
    1077                 : 
    1078             425 :     if ( (infile_name != NULL) )
    1079                 :     {
    1080             423 :         tried_stat = TRUE;
    1081             423 :         stat_succ = stat_incl_list_file( infile_name, &finfo);
    1082                 :     }
    1083                 : 
    1084             425 :     if ( INVERSE( stat_succ) )
    1085                 :     {
    1086              10 :         inp_fil_acc_err = TRUE;
    1087                 :     }else{
    1088                 :         
    1089             415 :         infile = fopen( include_list_full_path, "r");
    1090             415 :         if ( infile == NULL )
    1091                 :         {
    1092               3 :             inp_fil_open_err = TRUE;
    1093                 :         }else{
    1094                 :         
    1095             412 :         ilen=finfo.st_size;
    1096             412 :             newbuf = safe_malloc(ilen+1, "initting stream");
    1097                 : 
    1098             412 :             if ( fread( newbuf, ilen, 1, infile) != 1 )
    1099                 :             {
    1100               7 :                 inp_fil_read_err = TRUE;
    1101               7 :                 free( newbuf );
    1102                 :             } else {
    1103                 :                 unsigned int i;
    1104                 : 
    1105             405 :                 retval = TRUE ;
    1106                 :                 /*  Replace zeroes in the file with LineFeeds. */
    1107                 :                 /*  Replace carr-rets with spaces.  */
    1108         2387462 :                 for (i=0; i<ilen; i++)
    1109                 :                 {
    1110         2387057 :                     char test_c = newbuf[i];
    1111         2387057 :                     if ( test_c == 0    ) newbuf[i] = 0x0a;
    1112         2387057 :                     if ( test_c == 0x0d ) newbuf[i] = ' ';
    1113                 :         }
    1114             405 :                 newbuf[ilen]=0;
    1115                 : 
    1116             405 :                 init_inbuf(newbuf, ilen);
    1117                 : 
    1118                 :                 /*   If the -l option was specified, write the name of the
    1119                 :                  *       new input-file to the Load-List file...  UNLESS
    1120                 :                  *       this is the first time through and we haven't yet
    1121                 :                  *       opened the Load-List file, in which case we'll
    1122                 :                  *       just open it here and wait until we create the
    1123                 :                  *       output-file name (since the Load-List file name
    1124                 :                  *       depends on the output-file name anyway) before
    1125                 :                  *       we write the initial input-file name to it.
    1126                 :                  */
    1127                 :                 /*   Looking for the option-flag _and_ for a non-NULL value
    1128                 :                  *       of the file-structure pointer is redundandundant:
    1129                 :                  *       The non-NULL pointer is sufficient, once the List
    1130                 :                  *       File has been created...
    1131                 :                  */
    1132                 :                 /*   Same thing applies if the -P option was specified,
    1133                 :                  *       for the Dependency-List file, except there we'll
    1134                 :                  *       write the full path to where the file was found.
    1135                 :                  */
    1136                 :                 /*   We have a routine to do both of those.   */
    1137             405 :                 add_to_load_lists( name);
    1138                 :                 /*
    1139                 :                  *   And... there's one slight complication:  If this is
    1140                 :                  *       the first time through, (i.e., we're opening the
    1141                 :                  *       Primary Input File) then we haven't yet opened the
    1142                 :                  *       Dependency-List file, and we need to preserve the
    1143                 :                  *       Full file-name Buffer until the call to  init_output()
    1144                 :                  *       where the include-list scan will be "finish"ed.
    1145                 :                  *   Actually, we want to postpone "finish"ing the inc-l scan
    1146                 :                  *       for several reasons beyond the Dependency-List file, 
    1147                 :                  *       such as completing the File Name Announcement first.
    1148                 :                  *   A NULL output-name buffer is our indicator.
    1149                 :                  */
    1150             405 :                 if ( oname == NULL )
    1151                 :                 {
    1152                 :                     /*  Quick way to suppress "finish"ing the i-l scan */
    1153             165 :                     tried_stat = FALSE; 
    1154                 :                 }
    1155                 :             }
    1156             412 :         fclose(infile);
    1157                 :         }
    1158                 :     }
    1159                 :         
    1160             425 :     FFLUSH_STDOUT       /*   Do this first  */
    1161                 :     /*  Now we can deliver our postponed error and advisory messages  */
    1162             425 :     if ( INVERSE( retval) )
    1163                 :     {
    1164              20 :         file_is_missing( (char *)name);
    1165              20 :         if ( inp_fil_acc_err )
    1166                 :         {
    1167              10 :             expansion_error();
    1168              10 :             tokenization_error( TKERROR, 
    1169                 :                 "Could not access input file %s\n", name);
    1170                 :         }else{
    1171              10 :             if ( inp_fil_open_err )
    1172                 :             {
    1173               3 :                 expansion_error();
    1174               3 :                 could_not_open( TKERROR, (char *)name, "input");
    1175                 :             }else{
    1176               7 :                 if ( inp_fil_read_err )
    1177                 :                 {
    1178               7 :                     expansion_error();
    1179               7 :                     tokenization_error( TKERROR, 
    1180                 :                         "Could not read input file %s\n", name);
    1181                 :                 }
    1182                 :             }
    1183                 :         }
    1184                 :         }
    1185                 :         
    1186             425 :     if ( tried_stat )
    1187                 :     {
    1188             258 :         finish_incl_list_scan( stat_succ);
    1189                 :     }
    1190                 : 
    1191                 :     /*  Don't change the input file name and line-number until after
    1192                 :      *      the Advisory showing where the file was found.
    1193                 :      */
    1194             425 :     if ( retval )
    1195                 :     {
    1196             405 :         iname=strdup(name);
    1197             405 :         lineno=1;
    1198                 :     }
    1199                 :         
    1200             425 :     return ( retval );
    1201                 :         
    1202                 : }
    1203                 : 
    1204                 : /* **************************************************************************
    1205                 :  *
    1206                 :  *      Function name:  extend_filename 
    1207                 :  *      Synopsis:       Change the filename to the given extension
    1208                 :  *
    1209                 :  *      Inputs:
    1210                 :  *         Parameters:
    1211                 :  *             base_name                  Name of the Input Base File
    1212                 :  *             new_ext                    New ext'n (with leading period)
    1213                 :  *
    1214                 :  *      Outputs:
    1215                 :  *         Returned Value:                Result filename
    1216                 :  *         Memory Allocated
    1217                 :  *             Buffer for result filename
    1218                 :  *         When Freed?
    1219                 :  *             At end of Tokenization, by  close_output().
    1220                 :  *
    1221                 :  *      Process Explanation:
    1222                 :  *          If the Input Base File Name has an extension, it will be replaced
    1223                 :  *              with the given new extension.  If not, the new extension will
    1224                 :  *              simply be appended.
    1225                 :  *          If the Input Base File Name has an extension that matches the
    1226                 :  *              new extension, a duplicate of the extension will be appended.
    1227                 :  *
    1228                 :  *      Extraneous Remarks:
    1229                 :  *          I only recently added protection against the situation where the
    1230                 :  *              Input Base File Name has no extension, but the Directory Path
    1231                 :  *              leading to it has a period in one of the directory names.
    1232                 :  *              Granted, this is a rare case, but not altogether impossible;
    1233                 :  *              I would have done it earlier except for the fact that the
    1234                 :  *              separator between directories may vary with different Host
    1235                 :  *              Operating Systems.
    1236                 :  *          However, at this point we have UNIX-centric assumptions hard-
    1237                 :  *              -coded in to so many other places that we might as well
    1238                 :  *              go with the slash here too.
    1239                 :  *
    1240                 :  **************************************************************************** */
    1241                 : 
    1242                 : static char *extend_filename( const char *base_name, const char *new_ext)
    1243             247 : {
    1244                 :     char *retval;
    1245                 :     char *ext;
    1246                 :         unsigned int len; /* should this be size_t? */
    1247                 :     const char *root;
    1248                 : 
    1249             247 :     root = strrchr(base_name, '/');
    1250             247 :     if ( root == NULL )  root = base_name;
    1251                 : 
    1252             247 :     ext = strrchr(root, '.');
    1253             247 :     if ( ext != NULL )
    1254                 :     {
    1255             245 :         if ( strcasecmp(ext, new_ext) == 0 )
    1256                 :         {
    1257               0 :             ext = NULL;
    1258                 :         }
    1259                 :     }
    1260                 : 
    1261             247 :     len = ext ? (ext - base_name) : (unsigned int)strlen(base_name) ;
    1262             247 :     retval = safe_malloc(len+strlen(new_ext)+1, "extending file-name");
    1263             247 :     memcpy( retval, base_name, len);
    1264             247 :     retval[len] = 0;
    1265             247 :     strcat(retval, new_ext);
    1266                 : 
    1267             247 :     return( retval);
    1268                 : }
    1269                 : 
    1270                 : /* **************************************************************************
    1271                 :  *
    1272                 :  *      Function name:  init_output
    1273                 :  *      Synopsis:       After the Input Source File has been opened, assign 
    1274                 :  *                          the name for the Binary Output File; initialize
    1275                 :  *                          the FCode Output Buffer; assign names for the
    1276                 :  *                          FLoad List, Dependency-List, and Missing-Files
    1277                 :  *                          List files; open them and write their first
    1278                 :  *                          entries to them.
    1279                 :  *                     Announce the Input and various output file names.
    1280                 :  *
    1281                 :  *      Inputs:
    1282                 :  *         Parameters:
    1283                 :  *             in_name                  Name of the Input Source File
    1284                 :  *             out_name                 Name of the Binary Output File, if
    1285                 :  *                                          specified on the Command Line,
    1286                 :  *                                          or NULL if not.
    1287                 :  *         Global Variables:
    1288                 :  *             fload_list               Whether to create an FLoad-List file
    1289                 :  *             dependency_list          Whether to create a Dependency-List file
    1290                 :  *         Local Static Variables:
    1291                 :  *             include_list_full_path   Full Path to the Input Source File;
    1292                 :  *                                          should still be valid from opening
    1293                 :  *                                          of Primary Source Input file, for
    1294                 :  *                                          first entry to Dependency-List file.
    1295                 :  *
    1296                 :  *      Outputs:
    1297                 :  *         Returned Value:              NONE
    1298                 :  *         Global Variables:
    1299                 :  *             oname                    Binary Output File Name
    1300                 :  *             ostart                   Start of FCode Output Buffer
    1301                 :  *             opc                      FCode Output Buffer Position Counter
    1302                 :  *             abs_token_no             Initialized to 1
    1303                 :  *         Local Static Variables:
    1304                 :  *             load_list_name           Name of the Load List File
    1305                 :  *             load_list_file           FLoad List File Structure pointer
    1306                 :  *             depncy_list_name         Name of the Dependency List File ptr
    1307                 :  *             depncy_file              Dependency List File Structure
    1308                 :  *             missing_list_name        Name of the Missing-Files-List File
    1309                 :  *             missing_list_file        Missing-Files-List File Structure
    1310                 :  *             no_files_missing         Initialized to TRUE
    1311                 :  *         Memory Allocated
    1312                 :  *             Binary Output File Name Buffer
    1313                 :  *             FCode Output Buffer
    1314                 :  *             FLoad List File Name Buffer
    1315                 :  *             Dependency List File Name Buffer
    1316                 :  *             
    1317                 :  *         When Freed?
    1318                 :  *             In  close_output()
    1319                 :  *         File Output:
    1320                 :  *             FLoad List or Dependency List files are opened (if specified).
    1321                 :  *                 Primary Source Input file name and path, respectively,
    1322                 :  *                 are written as the first entry to each.
    1323                 :  *         Printout:
    1324                 :  *             (Announcement of input file name has already been made)
    1325                 :  *             Announce binary output, fload- and dependency- -list file names
    1326                 :  *
    1327                 :  *      Error Detection:
    1328                 :  *          Failure to open FLoad List or Dependency List file:  ERROR;
    1329                 :  *              suppress binary output.  Further attempts to write to
    1330                 :  *              FLoad List or Dependency List files are prevented by
    1331                 :  *              the respective FILE_structure pointers being NULL.
    1332                 :  *          Failure to open Missing-Files-List file:  WARNING
    1333                 :  *
    1334                 :  *      Process Explanation:
    1335                 :  *          If no Output File Name was specified on the Command Line, the
    1336                 :  *              name of the Binary (FCode) Output File will be derived
    1337                 :  *              from the name of the Input File by replacing its extension
    1338                 :  *              with  .fc , or, if  the Input File had no extension, by
    1339                 :  *              merely appending the extension  .fc 
    1340                 :  *          In the odd case where the Input File name has an extension
    1341                 :  *              of  .fc, we will merely append another  .fc  extension.
    1342                 :  *          If  fload_list  is TRUE (i.e., the "-l" option was specified on
    1343                 :  *              the command-line, the FLoad List File name will be derived
    1344                 :  *              from the name of the Output File by the same rules, only with
    1345                 :  *              an extension of  .fl   Open the FLoad List File.  Write the
    1346                 :  *              name of the initial input file to the FLoad List File.
    1347                 :  *          Similarly if the "-P" command-line option was specified, the name
    1348                 :  *              of the Dependency List File will be derived with an extension
    1349                 :  *              of  .P  Open it and write the Full Path for the initial input
    1350                 :  *              file to it.  NOTE:  To do that, we need to have preserved the
    1351                 :  *              Full Path-name Buffer from the call to  init_stream()   We
    1352                 :  *              will "finish" it here, after we've used it.
    1353                 :  *          The Missing-Files-List File will be created if either option was
    1354                 :  *              specified.  Its name will be derived similarly, with an
    1355                 :  *              extension of  .fl.missing
    1356                 :  *
    1357                 :  **************************************************************************** */
    1358                 : 
    1359                 : void init_output( const char *in_name, const char *out_name )
    1360             165 : {
    1361                 :         /* preparing output */
    1362                 : 
    1363             165 :         if( out_name != NULL )
    1364                 :         {
    1365              54 :                 oname = strdup( out_name );
    1366                 :         }else{
    1367             111 :                 oname = extend_filename( in_name, ".fc"); 
    1368                 :         }
    1369                 :         
    1370                 :         /* output buffer size. this is 128k per default now, but we
    1371                 :          * could reallocate if we run out. KISS for now.
    1372                 :          */
    1373             165 :         olen = OUTPUT_SIZE;
    1374             165 :         ostart=safe_malloc(olen, "initting output buffer");
    1375                 : 
    1376             165 :         opc = 0;
    1377             165 :         init_emit();  /* Init'l'zns needed by our companion file, emit.c  */
    1378                 : 
    1379             165 :         printf("Binary output to %s ", oname);
    1380             165 :         if ( fload_list )
    1381                 :         {
    1382              65 :             load_list_name = extend_filename( oname, ".fl");
    1383              65 :             load_list_file = fopen( load_list_name,"w");
    1384              65 :             printf("  FLoad-list to %s ", load_list_name);
    1385                 :         }
    1386             165 :         if ( dependency_list )
    1387                 :         {
    1388               6 :             depncy_list_name = extend_filename( oname, ".P");
    1389               6 :             depncy_file = fopen( depncy_list_name,"w");
    1390               6 :             printf("  Dependency-list to %s ", depncy_list_name);
    1391                 :         }
    1392             165 :         printf("\n");
    1393                 : 
    1394             165 :         add_to_load_lists( in_name);
    1395                 :         
    1396                 :         /*  Let's avoid collisions between stdout and stderr  */
    1397             165 :         FFLUSH_STDOUT
    1398                 : 
    1399                 :         /*  Now we can deliver our advisory and error messages  */
    1400                 :         
    1401                 :         {
    1402                 :             /* Suspend showing filename in advisory and error messages. */
    1403             165 :             char *temp_iname = iname;
    1404             165 :             iname = NULL; 
    1405                 :         
    1406             165 :             finish_incl_list_scan( TRUE);
    1407                 : 
    1408             165 :             if ( fload_list && (load_list_file == NULL) )
    1409                 :             {
    1410               2 :                 could_not_open( TKERROR, load_list_name, "Load-List");
    1411               2 :                 free( load_list_name);
    1412                 :             }
    1413             165 :             if ( dependency_list && (depncy_file == NULL) )
    1414                 :             {
    1415               0 :                 could_not_open( TKERROR, depncy_list_name,
    1416                 :                     "Dependency-List");
    1417               0 :                 free( depncy_list_name);
    1418                 : }
    1419                 : 
    1420             165 :             if ( fload_list || dependency_list )
    1421                 :             {
    1422              65 :                 missing_list_name = extend_filename( oname, ".fl.missing");
    1423              65 :                 missing_list_file = fopen( missing_list_name,"w");
    1424              65 :                 no_files_missing = TRUE;
    1425                 : 
    1426              65 :                 if ( missing_list_file == NULL )
    1427                 :                 {
    1428               1 :                     could_not_open( WARNING, missing_list_name,
    1429                 :                         "Missing-Files List" );
    1430               1 :                     free( missing_list_name);
    1431                 :                 }
    1432                 :             }
    1433             165 :             iname = temp_iname;
    1434                 :         }
    1435             165 :         abs_token_no = 1;
    1436             165 : }
    1437                 : 
    1438                 : /* **************************************************************************
    1439                 :  *
    1440                 :  *      Function name:  increase_output_buffer
    1441                 :  *      Synopsis:       Reallocate the Output Buffer to double its prior size 
    1442                 :  *
    1443                 :  *      Inputs:
    1444                 :  *         Parameters:                  NONE
    1445                 :  *         Global Variables:
    1446                 :  *             ostart                   Start-address of current Output Buffer
    1447                 :  *             olen                     Current size of the Output Buffer
    1448                 :  *         Local Static Variables:
    1449                 :  *
    1450                 :  *      Outputs:
    1451                 :  *         Returned Value:                 NONE
    1452                 :  *         Local Static Variables:
    1453                 :  *             olen                     Doubled from value at input
    1454                 :  *             ostart                   Start-address of new Output Buffer
    1455                 :  *         Memory Allocated
    1456                 :  *             A new FCode Output Buffer, using the  realloc()  facility.
    1457                 :  *         When Freed?
    1458                 :  *             In  close_output()
    1459                 :  *         Memory Freed
    1460                 :  *             Former FCode Output Buffer, also by means of  realloc() 
    1461                 :  *
    1462                 :  *         Printout:
    1463                 :  *             Advisory message that this is taking place.
    1464                 :  *
    1465                 :  *      Error Detection:
    1466                 :  *          FATAL if  realloc()  fails.
    1467                 :  *          FATAL if output buffer has been expanded to a size beyond
    1468                 :  *              what an INT can express.  Unlikely? maybe; impossible? no...
    1469                 :  *
    1470                 :  *      Process Explanation:
    1471                 :  *          Because we are allowing the Output Buffer to be relocated, we
    1472                 :  *              must take care to limit the exposure to external routines
    1473                 :  *              of its actual address.  All references to locations within
    1474                 :  *              the Output Buffer should be made in terms of an _offset_.
    1475                 :  *
    1476                 :  *      Extraneous Remarks:
    1477                 :  *          Unfortunately, it is not feasible to completely isolate the
    1478                 :  *              actual address of the Output Buffer, but we will keep the
    1479                 :  *              exposure limited to the routines in  emit.c
    1480                 :  *          Similarly, it wasn't feasible to keep this routine isolated,
    1481                 :  *              nor the variable  olen  , but we will limit their exposure.
    1482                 :  *
    1483                 :  **************************************************************************** */
    1484                 : void increase_output_buffer( void );  /*  Keep the prototype local  */
    1485                 : void increase_output_buffer( void )
    1486               6 : {
    1487                 :     u8 *newout;
    1488                 : 
    1489               6 :     if ( olen == 0 )
    1490                 :     {
    1491               0 :         tokenization_error( FATAL,
    1492                 :                 "Output Buffer reallocation overflow.");
    1493                 :     }else{
    1494                 :         unsigned int rea_len;
    1495               6 :         olen = olen * 2;
    1496               6 :         rea_len = olen;
    1497               6 :         if ( rea_len == 0 )   rea_len = (unsigned int)-1;
    1498               6 :         tokenization_error( INFO,
    1499                 :             "Output Buffer overflow.  "
    1500                 :                 "Relocating and increasing to %d bytes.\n", rea_len);
    1501                 : 
    1502               6 :         newout = realloc(ostart, rea_len);
    1503               6 :         if ( newout == NULL)
    1504                 :         {
    1505               0 :             tokenization_error( FATAL,
    1506                 :                 "Could not reallocate %d bytes for Output Buffer", rea_len);
    1507                 :         }
    1508                 : 
    1509               6 :         ostart = newout;
    1510                 :     }
    1511               6 : }
    1512                 : 
    1513                 : 
    1514                 : /* **************************************************************************
    1515                 :  *
    1516                 :  *      Function name:  close_stream
    1517                 :  *      Synopsis:       Free-up the memory used for the current input file
    1518                 :  *                          whenever it is closed.  Reset pointers and
    1519                 :  *                          line-counter.  Close files as necessary.
    1520                 :  *
    1521                 :  *      The dummy parameter is there to accommodate Macro-recursion protection. 
    1522                 :  *          It's a long story; don't get me started...
    1523                 :  *
    1524                 :  **************************************************************************** */
    1525                 : 
    1526                 : void close_stream( _PTR dummy)
    1527             404 : {
    1528             404 :         free(start);
    1529             404 :         free(iname);
    1530             404 :         start = NULL;
    1531             404 :         iname = NULL;
    1532             404 :         lineno = 0;
    1533             404 : }
    1534                 : 
    1535                 : /* **************************************************************************
    1536                 :  *
    1537                 :  *      Function name:  close_output
    1538                 :  *      Synopsis:       Write the Binary Output file, if appropriate.
    1539                 :  *                          Return a "Failure" flag.
    1540                 :  *
    1541                 :  **************************************************************************** */
    1542                 : 
    1543                 : 
    1544                 : bool close_output(void)
    1545             164 : {
    1546             164 :     bool retval = TRUE;  /*  "Failure"  */
    1547             164 :     if ( error_summary() )
    1548                 :     { 
    1549             147 :         if ( opc == 0 )
    1550                 : {
    1551              18 :             retval = FALSE;  /*  "Not a problem"  */
    1552                 :         }else{
    1553                 :         FILE *outfile;
    1554                 : 
    1555             129 :             outfile=fopen( oname,"w");
    1556             129 :             if (!outfile)
    1557                 :             {
    1558                 :                 /*  Don't do this as a  tokenization_error( TKERROR
    1559                 :                  *      because those are all counted, among other reasons...
    1560                 :                  */ 
    1561               2 :                 printf( "Could not open file %s for output.\n", oname);
    1562                 :             }else{
    1563                 :         
    1564             127 :                 if ( fwrite(ostart, opc, 1, outfile) != 1 )
    1565                 :                 {
    1566               0 :                     tokenization_error( FATAL, "While writing output.");
    1567                 :         }
    1568                 :         
    1569             127 :         fclose(outfile);
    1570                 : 
    1571             127 :                 printf("toke: wrote %d bytes to bytecode file '%s'\n",
    1572                 :                     opc, oname);
    1573             127 :                 retval = FALSE;  /*  "No problem"  */
    1574                 :             }
    1575                 :         }
    1576                 :     }
    1577                 :         
    1578             164 :         free(oname);
    1579             164 :     free(ostart);
    1580             164 :     oname = NULL;
    1581             164 :     ostart = NULL;
    1582             164 :     opc = 0;
    1583             164 :     olen = OUTPUT_SIZE;
    1584                 : 
    1585             164 :     if ( load_list_file != NULL )
    1586                 :     {
    1587              63 :         fclose(load_list_file);
    1588              63 :         free(load_list_name);
    1589                 :     }
    1590             164 :     if ( depncy_file != NULL )
    1591                 :     {
    1592               6 :         fclose(depncy_file);
    1593               6 :         free(depncy_list_name);
    1594                 :     }
    1595             164 :     if ( missing_list_file != NULL )
    1596                 :     {
    1597              64 :         fclose( missing_list_file);
    1598              64 :         if ( no_files_missing )
    1599                 :         {
    1600              62 :             remove( missing_list_name);
    1601                 :         }
    1602              64 :         free( missing_list_name);
    1603                 :     }
    1604                 : 
    1605             164 :     load_list_file = NULL;
    1606             164 :     load_list_name = NULL;
    1607             164 :     missing_list_file = NULL;
    1608             164 :     missing_list_name = NULL;
    1609             164 :     depncy_file = NULL;
    1610             164 :     depncy_list_name = NULL;
    1611                 : 
    1612             164 :     return ( retval );
    1613                 : }
    1614                 : 

Generated by: LTP GCOV extension version 1.5