LTP GCOV extension - code coverage report
Current view: directory - fcode-utils/toke - stream.c
Test: Toke 1.0.2
Date: 2006-10-30 Instrumented lines: 290
Code covered: 97.9 % Executed lines: 284
Legend: not executed executed converted-only

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

Generated by: LTP GCOV extension version 1.5