LTP GCOV extension - code coverage report
Current view: directory - fcode-utils/toke - conditl.c
Test: FCode suite 1.0.2
Date: 2006-10-30 Instrumented lines: 116
Code covered: 100.0 % Executed lines: 116
Legend: not executed executed converted-only

       1                 : /*
       2                 :  *                     OpenBIOS - free your system!
       3                 :  *                         ( FCode tokenizer )
       4                 :  *
       5                 :  *  This program is part of a free implementation of the IEEE 1275-1994
       6                 :  *  Standard for Boot (Initialization Configuration) Firmware.
       7                 :  *
       8                 :  *  Copyright (C) 2001-2005 Stefan Reinauer, <stepan@openbios.org>
       9                 :  *
      10                 :  *  This program is free software; you can redistribute it and/or modify
      11                 :  *  it under the terms of the GNU General Public License as published by
      12                 :  *  the Free Software Foundation; version 2 of the License.
      13                 :  *
      14                 :  *  This program is distributed in the hope that it will be useful,
      15                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17                 :  *  GNU General Public License for more details.
      18                 :  *
      19                 :  *  You should have received a copy of the GNU General Public License
      20                 :  *  along with this program; if not, write to the Free Software
      21                 :  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
      22                 :  *
      23                 :  */
      24                 : 
      25                 : /* **************************************************************************
      26                 :  *
      27                 :  *      Conditional-Compilation support for Tokenizer
      28                 :  *
      29                 :  *      (C) Copyright 2005 IBM Corporation.  All Rights Reserved.
      30                 :  *      Module Author:  David L. Paktor    dlpaktor@us.ibm.com
      31                 :  *
      32                 :  **************************************************************************** */
      33                 : 
      34                 : /* **************************************************************************
      35                 :  *
      36                 :  *      Functions Exported:
      37                 :  *          init_conditionals_vocab    Initialize the "Conditionals" Vocabulary.
      38                 :  *          handle_conditional         Confirm whether a given name is a valid
      39                 :  *                                         Conditional, and, if so, perform its
      40                 :  *                                         function and return an indication.
      41                 :  *          create_conditional_alias   Add an alias to "Conditionals" vocab
      42                 :  *          reset_conditionals         Reset the "Conditionals" Vocabulary
      43                 :  *                                         to its "Built-In" position.
      44                 :  *
      45                 :  **************************************************************************** */
      46                 : 
      47                 : #include <stdio.h>
      48                 : #include <stdlib.h>
      49                 : 
      50                 : #include <string.h>
      51                 : #include <errno.h>
      52                 : 
      53                 : #include "scanner.h"
      54                 : #include "errhandler.h"
      55                 : #include "ticvocab.h"
      56                 : #include "conditl.h"
      57                 : #include "stack.h"
      58                 : #include "dictionary.h"
      59                 : #include "vocabfuncts.h"
      60                 : #include "usersymbols.h"
      61                 : #include "stream.h"
      62                 : #include "clflags.h"
      63                 : 
      64                 : /* **************************************************************************
      65                 :  *
      66                 :  *          Global Variables Imported
      67                 :  *              statbuf               Start of input-source buffer
      68                 :  *              pc                    Input-source Scanning pointer
      69                 :  *              iname                 Current Input File name
      70                 :  *              lineno                Current Line Number in Input File
      71                 :  *
      72                 :  **************************************************************************** */
      73                 : 
      74                 : /* **************************************************************************
      75                 :  *
      76                 :  *              Local Static Variables
      77                 :  *      already_ignoring      Location from which to pass a parameter,
      78                 :  *                            called "alr_ign" to the main routine.  Each
      79                 :  *                            "Conditional" will have an associated routine
      80                 :  *                            that takes the pointer to this as its argument.
      81                 :  *                            The pointer to this will satisfy the "param-field"
      82                 :  *                            requirement of a TIC_HDR-style "Vocabulary"-list.
      83                 :  *      conditionals_tbl      TIC_HDR-style "Vocabulary"-list table, initialized
      84                 :  *                            as an array.
      85                 :  *      conditionals          Pointer to "tail" of Conditionals Vocabulary-list
      86                 :  *
      87                 :  **************************************************************************** */
      88                 : 
      89                 : /* **************************************************************************
      90                 :  *
      91                 :  *      The lists of synonymous forms of the #ELSE and #THEN operators
      92                 :  *          are incorporated into the "Shared Words" Vocabulary.
      93                 :  *
      94                 :  **************************************************************************** */
      95                 : 
      96                 : /* **************************************************************************
      97                 :  *
      98                 :  *      Function name:  is_a_then  /  is_an_else
      99                 :  *      Synopsis:       Indicate whether the given name is one of the
     100                 :  *                      [then] / [else]  synonyms
     101                 :  *      
     102                 :  *      Inputs:
     103                 :  *         Parameters:
     104                 :  *             a_word                        Word to test
     105                 :  *
     106                 :  *      Outputs:
     107                 :  *         Returned Value:       TRUE if the given name is one of the synonyms
     108                 :  *
     109                 :  *      Process Explanation:
     110                 :  *          The functions are twins, hence bundling them like this...
     111                 :  *
     112                 :  **************************************************************************** */
     113                 : 
     114                 : 
     115                 : /* **************************************************************************
     116                 :  *
     117                 :  *      Support function:  is_a_type
     118                 :  *      Synopsis:          Indicate whether the given name is a "shared word"
     119                 :  *                         whose FWord Token matches the one given
     120                 :  *
     121                 :  *      Inputs:
     122                 :  *         Parameters:
     123                 :  *             tname                        Target name to look for
     124                 :  *             fw_type                      The FWord Token type to match
     125                 :  *
     126                 :  *      Outputs:
     127                 :  *         Returned Value:                  TRUE if it matches
     128                 :  *
     129                 :  **************************************************************************** */
     130                 : 
     131                 : 
     132                 : static bool is_a_type( char *tname, fwtoken fw_type)
     133           61758 : {
     134           61758 :     bool retval = FALSE;
     135           61758 :     tic_fwt_hdr_t *found = (tic_fwt_hdr_t *)lookup_shared_f_exec_word( tname );
     136           61758 :     if ( found != NULL )
     137                 :     {
     138            2344 :         if ( found->pfield.fw_token == fw_type )  retval = TRUE;
     139                 :     }
     140           61758 :     return ( retval );
     141                 : }
     142                 : 
     143                 : static bool is_a_then( char *a_word)
     144           31196 : {
     145           31196 :     bool retval = is_a_type( a_word, CONDL_ENDER);
     146           31196 :     return ( retval );
     147                 : }
     148                 : 
     149                 : static bool is_an_else( char *a_word)
     150           30562 : {
     151           30562 :     bool retval = is_a_type( a_word, CONDL_ELSE);
     152           30562 :     return ( retval );
     153                 : }
     154                 : 
     155                 : /* **************************************************************************
     156                 :  *
     157                 :  *     This is a somewhat roundabout way of passing an "already ignoring"
     158                 :  *         parameter to the various Conditional Operators.  Each operator's
     159                 :  *         Parameter-Field Pointer points to this.  The calling routine
     160                 :  *         must set it (or rely on the default); the routine that handles
     161                 :  *         nesting of Conditionals must save and restore a local copy.
     162                 :  *
     163                 :  **************************************************************************** */
     164                 : 
     165                 : static bool already_ignoring = FALSE;
     166                 : 
     167                 : /* **************************************************************************
     168                 :  *
     169                 :  *      Further down, will define and initialize a word-list table with
     170                 :  *          all the functions that implement the Conditional Operators,
     171                 :  *          and we'll link it in with the "Global Vocabulary" pointer.
     172                 :  *
     173                 :  *      We'll call the word-list the "Conditionals Vocabulary Table",
     174                 :  *          and refer to its entries as the "Conditionals Vocabulary",
     175                 :  *          even though it isn't really a separate vocabulary...
     176                 :  * 
     177                 :  **************************************************************************** */
     178                 : 
     179                 : 
     180                 : /* **************************************************************************
     181                 :  *
     182                 :  *      We also need a few common routines to pass as "Ignoring" functions
     183                 :  *          for a few occasional words that take another word or two from
     184                 :  *          the input stream as their arguments.  For example, if the user
     185                 :  *          were to write:   alias [otherwise] [else]   and that were to
     186                 :  *          occur within a segment already being ignored, we need to make
     187                 :  *          sure that this doesn't get processed as an occurrence of  [else]
     188                 :  *          Similarly with macro-definitions.
     189                 :  *
     190                 :  *      Since we are using the term "ignore a word" to mean "look it up and
     191                 :  *          process it in Ignoring-state", we need a different term to name
     192                 :  *          this class of routine; let's use the term "skip a word" where
     193                 :  *          the "word" is strictly an input token, delimited by whitespace.
     194                 :  *
     195                 :  **************************************************************************** */
     196                 :  
     197                 : /* **************************************************************************
     198                 :  *
     199                 :  *      Function name:  skip_a_word
     200                 :  *      Synopsis:       Consume one input-token ("word") from the
     201                 :  *                          Input Stream, with no processing
     202                 :  *
     203                 :  *      Inputs:
     204                 :  *         Parameters:
     205                 :  *             pfield             "Parameter field" pointer, to satisfy
     206                 :  *                                    the calling convention, but not used
     207                 :  *
     208                 :  *      Outputs:
     209                 :  *         Returned Value:        NONE
     210                 :  *
     211                 :  **************************************************************************** */
     212                 : 
     213                 : void skip_a_word( tic_bool_param_t pfield )
     214              97 : {
     215              97 :     /* signed long wlen = */ get_word();
     216              97 : }
     217                 : 
     218                 : /* **************************************************************************
     219                 :  *
     220                 :  *      Function name:  skip_a_word_in_line
     221                 :  *      Synopsis:       Consume one input-token ("word") on the same line
     222                 :  *                          as the current line of input, from the Input
     223                 :  *                          Stream, with no processing.
     224                 :  *
     225                 :  *      Inputs:
     226                 :  *         Parameters:
     227                 :  *             pfield             "Parameter field" pointer, to satisfy
     228                 :  *                                    the calling convention, but not used
     229                 :  *         Global Variables:
     230                 :  *             statbuf            The word being processed, which expects
     231                 :  *                                    another word on the same line; used
     232                 :  *                                    for the Error message.
     233                 :  *
     234                 :  *      Outputs:
     235                 :  *         Returned Value:        NONE
     236                 :  *
     237                 :  *      Error Detection:
     238                 :  *          get_word_in_line() will check and report if no word on same line.
     239                 :  *
     240                 :  **************************************************************************** */
     241                 : void skip_a_word_in_line( tic_bool_param_t pfield )
     242              85 : {
     243              85 :     /* bool isokay = */ get_word_in_line( statbuf);
     244              85 : }
     245                 : 
     246                 : /* **************************************************************************
     247                 :  *
     248                 :  *      Function name:  skip_two_words_in_line
     249                 :  *      Synopsis:       Consume two input-tokens ("words") on the same line
     250                 :  *                          as the current line of input, from the Input
     251                 :  *                          Stream, with no processing.
     252                 :  *
     253                 :  *      Inputs:
     254                 :  *         Parameters:
     255                 :  *             pfield             "Parameter field" pointer, to satisfy
     256                 :  *                                    the calling convention, but not used
     257                 :  *         Global Variables:
     258                 :  *             statbuf            The word being processed, which expects
     259                 :  *                                    two words on the same line; used for
     260                 :  *                                    the Error message.
     261                 :  *
     262                 :  *      Outputs:
     263                 :  *         Returned Value:         NONE
     264                 :  *         Memory Allocated
     265                 :  *             Copy of  statbuf  for Error message.
     266                 :  *         When Freed?
     267                 :  *             End of this routine
     268                 :  *
     269                 :  *      Error Detection:
     270                 :  *          get_word_in_line() will check and report
     271                 :  *
     272                 :  **************************************************************************** */
     273                 : 
     274                 : void skip_two_words_in_line( tic_bool_param_t pfield )
     275              16 : {
     276              16 :     char *func_cpy = strupr( strdup( statbuf));
     277              16 :     if ( get_word_in_line( func_cpy) )
     278                 :     {
     279              16 :         /* bool isokay = */ get_word_in_line( func_cpy);
     280                 :     }
     281              16 :     free( func_cpy);
     282              16 : }
     283                 : 
     284                 : 
     285                 : /* **************************************************************************
     286                 :  *
     287                 :  *      Function name:  ignore_one_word
     288                 :  *      Synopsis:       Handle a word that needs processing while "ignoring"
     289                 :  *                          Ignore the rest.
     290                 :  *
     291                 :  *      Inputs:
     292                 :  *         Parameters:
     293                 :  *             tname                  Target name to test
     294                 :  *         Local Static Variables:
     295                 :  *             already_ignoring       The "Already Ignoring" flag
     296                 :  *
     297                 :  *      Outputs:
     298                 :  *         Returned Value:            NONE
     299                 :  *         Global Variables:
     300                 :  *             tic_found              Set to the TIC-entry that has just been
     301                 :  *                                        found, in case it's a Macro.
     302                 :  *         Local Static Variables:
     303                 :  *             already_ignoring       Intermediately set to TRUE, then
     304                 :  *                                        returned to former state.
     305                 :  *
     306                 :  *      Process Explanation:
     307                 :  *          When we are ignoring source input, we still need to be
     308                 :  *              sensitive to the nesting of Conditional Operators, to
     309                 :  *              consume comments and user -message text-bodies, and to
     310                 :  *              expand Macros, among other things.
     311                 :  *         Rather than create special cases here for each one, we have
     312                 :  *              added an "ign_funct" pointer to those words where this
     313                 :  *              is relevant, including Conditional Operators. 
     314                 :  *          Save the state of  already_ignoring  and set it to TRUE
     315                 :  *              Execute the "Ignoring" Function associated with the entry
     316                 :  *              Restore  already_ignoring  to its previous state.
     317                 :  *          This is necessary if the word is a Conditional Operator and
     318                 :  *              is harmless otherwise.
     319                 :  *
     320                 :  **************************************************************************** */
     321                 : 
     322                 : static void ignore_one_word( char *tname)
     323            2038 : {
     324            2038 :     tic_bool_hdr_t *found = (tic_bool_hdr_t *)lookup_word( tname, NULL, NULL);
     325            2038 :     if ( found != NULL )
     326                 :     {
     327            1941 :         if ( found->ign_func != NULL )
     328                 :         {
     329            1541 :             bool save_already_ignoring = already_ignoring;
     330            1541 :             already_ignoring = TRUE ;
     331            1541 :             tic_found = (tic_hdr_t *)found;
     332                 : 
     333            1541 :             found->ign_func( found->pfield);
     334                 : 
     335            1541 :             already_ignoring = save_already_ignoring;
     336                 :         }
     337                 :     }
     338            2038 : }
     339                 : 
     340                 : /* **************************************************************************
     341                 :  *
     342                 :  *      Function name:  conditionally_tokenize
     343                 :  *      Synopsis:       Conduct tokenization while a Conditional-Tokenization
     344                 :  *                          operator is in effect.  This is the core of the
     345                 :  *                          implementation of Conditional-Tokenization.
     346                 :  *      
     347                 :  *      Inputs:
     348                 :  *         Parameters:
     349                 :  *             cond             The state of the Condition-Flag that the
     350                 :  *                                  immediate Conditional Operator acquired.
     351                 :  *                                  TRUE means "do not ignore".  Its sense
     352                 :  *                                  is reversed when [ELSE] is encountered.
     353                 :  *             alr_ign          TRUE means we are Already Ignoring source input,
     354                 :  *                                  except for Conditional Operators...
     355                 :  *         Global Variables:
     356                 :  *             statbuf       The symbol (word) just retrieved from input stream.
     357                 :  *             iname         Current Input File name (for Error Messages)
     358                 :  *             lineno        Current Line Number in Input File (ditto)
     359                 :  *             trace_conditionals   Whether to issue ADVISORY messages about
     360                 :  *                                      the state of Conditional Tokenization.
     361                 :  *
     362                 :  *      Outputs:
     363                 :  *         Returned Value:       NONE
     364                 :  *         Global Variables:
     365                 :  *             statbuf           Will be advanced to the balancing [THEN] op'r.
     366                 :  *             already_ignoring  Set to TRUE if nested Conditional encountered;
     367                 :  *                                  restored to previous state when done.
     368                 :  *         Memory Allocated
     369                 :  *             Duplicate of Input File name, for Error Messages
     370                 :  *         When Freed?
     371                 :  *             Just prior to exit from routine.
     372                 :  *         Printout:
     373                 :  *             ADVISORY messages, if "Trace-Conditionals" flag was selected.
     374                 :  *             
     375                 :  *         Global Behavior:
     376                 :  *            Tokenization happens, or inputs are ignored, as necessary.
     377                 :  *
     378                 :  *      Error Detection:
     379                 :  *          End-of-file encountered on reading a word    
     380                 :  *              ERROR.  Conditional Operators must be balanced within a file
     381                 :  *          More than one [ELSE] encountered:  ERROR if processing segment;
     382                 :  *              if ignoring, WARNING.
     383                 :  *
     384                 :  *      Process Explanation:
     385                 :  *          Read a word at a time.   Allow Macros to "pop" transparently,
     386                 :  *              but not source files.
     387                 :  *          If the word is a [THEN], we are done.
     388                 :  *          If the word is an [ELSE], then, if we are not Already Ignoring,
     389                 :  *                  invert the sense of whether we are ignoring source input. 
     390                 :  *              If this is not the only [ELSE] in the block, report an Error
     391                 :  *                  and disregard it.
     392                 :  *          If we are ignoring source input, for whatever reason, we still
     393                 :  *              need to be sensitive to the nesting of Conditional Operators:
     394                 :  *              If the word is a Conditional Operator, activate it with the
     395                 :  *                  "Already Ignoring" parameter set to TRUE; doing so will
     396                 :  *                  result in a nested call to this routine.
     397                 :  *              Otherwise, i.e., if the word is not a Conditional Operator,
     398                 :  *                  we may still need to process it in "ignoring" mode:
     399                 :  *                  we need, for instance, to consume strings, comments
     400                 :  *                  and the text-bodies of user-messages in their entirety,
     401                 :  *                  in case there is a reference to an [ELSE] or suchlike.
     402                 :  *                  The words that need processing while "ignoring" will
     403                 :  *                  have a valid function-pointer in their ign_func field.
     404                 :  *          If we are not ignoring source input, pass the word along to the
     405                 :  *              tokenize_one_word routine and process it.  If the word is
     406                 :  *              a Conditional Operator, it will be handled in the context
     407                 :  *              of normal (i.e., non-ignored) tokenization, and, again, a
     408                 :  *              nested call to this routine will result...
     409                 :  *
     410                 :  *      Revision History:
     411                 :  *          Updated Thu, 23 Feb 2006 by David L. Paktor
     412                 :  *              Conditional Blocks may begin with a Conditional Operator in
     413                 :  *                  a Macro definition and do not need to be concluded in
     414                 :  *                  the body of the Macro.
     415                 :  *          Updated Fri, 10 Mar 2006 by David L. Paktor
     416                 :  *              Recognize aliased string, comment and user-message delimiters
     417                 :  *                  in a segment that is being ignored; Conditional Operators
     418                 :  *                  within the text body of any of these are always consumed
     419                 :  *                  and never unintentionally processed.  Macros are always
     420                 :  *                  processed; Conditional Operators inside a Macro body are
     421                 :  *                  recognized, so the Macro continues to function as intended.
     422                 :  *
     423                 :  **************************************************************************** */
     424                 : 
     425                 : static void conditionally_tokenize( bool cond, bool alr_ign )
     426             642 : {
     427                 :     
     428                 :     signed long wlen;
     429                 : 
     430                 :     /*  Note:  The following variables *must* remain within
     431                 :      *      the scope of this routine; a distinct instance
     432                 :      *      is needed each time this routine is re-entered
     433                 :      *     (aka "a nested call").
     434                 :      */
     435                 :     bool ignoring;
     436             642 :     bool first_else = TRUE;  /*  The "else" we see is the first.  */
     437             642 :     bool not_done = TRUE;
     438             642 :     unsigned int cond_strt_lineno = lineno;
     439             642 :     char *cond_strt_ifile_nam = strdup( iname);
     440                 : 
     441             642 :     ignoring = BOOLVAL( ( cond == FALSE ) || ( alr_ign != FALSE ) );
     442                 : 
     443             642 :     if ( trace_conditionals )
     444                 :     {
     445              87 :         char *cond_val = cond ? "True" : "False" ;
     446              87 :         char *cond_junct = alr_ign ? ", but Already " : "; ";
     447              87 :         char *processg = ignoring ? "Ignoring" : "Processing" ;
     448              87 :         tokenization_error( INFO,
     449                 :             "Tokenization-Condition is %s%s%s.\n",
     450                 :                 cond_val, cond_junct, processg);
     451                 :     }
     452                 : 
     453           31903 :     while ( not_done )
     454                 :     {
     455           31263 :         wlen = get_word();
     456           31263 :         if ( wlen == 0 )
     457                 :         {
     458              61 :             continue;
     459                 :         }
     460                 : 
     461           31202 :         if ( wlen < 0 )
     462                 :         {
     463               6 :             tokenization_error( TKERROR,
     464                 :                 "Conditional without conclusion; started");
     465               6 :             just_where_started( cond_strt_ifile_nam, cond_strt_lineno);
     466               6 :             not_done = FALSE ;
     467               6 :             continue;
     468                 :         }
     469                 : 
     470           31196 :         if ( is_a_then ( statbuf ) )
     471                 :         {
     472             634 :             if ( trace_conditionals )
     473                 :             {
     474              86 :                 tokenization_error( INFO,
     475                 :                     "Concluding Conditional");
     476              86 :                 just_started_at( cond_strt_ifile_nam, cond_strt_lineno);
     477                 :             }
     478             634 :             not_done = FALSE ;
     479             634 :             continue;
     480                 :         }
     481                 : 
     482           30562 :         if ( is_an_else( statbuf ) )
     483                 :         {
     484             379 :             if ( ! alr_ign )
     485                 :             {
     486             287 :                 if ( first_else )
     487                 :                 {
     488             285 :                     ignoring = INVERSE( ignoring);
     489                 :                 }
     490                 :             }
     491                 : 
     492             379 :             if ( ! first_else )
     493                 :             {
     494               4 :                 int severity = ignoring ? WARNING : TKERROR ;
     495               4 :                 char *the_scop = ignoring ? "(ignored)" : "the" ;
     496               4 :                 tokenization_error( severity, "Multiple %s directives "
     497                 :                     "within %s scope of the Conditional",
     498                 :                          strupr(statbuf), the_scop);
     499               4 :                 just_started_at( cond_strt_ifile_nam, cond_strt_lineno);
     500                 :             }else{
     501             375 :                 first_else = FALSE;
     502             375 :                 if ( trace_conditionals )
     503                 :                 {
     504              70 :                     char *when_enc = alr_ign ? "While already" : "Now" ;
     505                 :                     char *processg = alr_ign ? "ignoring" :
     506              70 :                                     ignoring ? "Ignoring" : "Processing" ;
     507              70 :                     char *enc       = alr_ign ? ", e" : ".  E" ;
     508                 : 
     509              70 :                     tokenization_error( INFO,
     510                 :                         "%s %s%sncountered %s belonging to Conditional",
     511                 :                             when_enc, processg, enc, strupr(statbuf) );
     512              70 :                     just_started_at( cond_strt_ifile_nam, cond_strt_lineno);
     513                 :                 }
     514                 :             }
     515                 : 
     516                 :             continue;
     517                 :         }
     518                 : 
     519                 :         /*  If we are ignoring source input, for whatever reason, we still
     520                 :          *      need to be sensitive to the nesting of Conditional Operators
     521                 :          *      and some other commands and directives, as indicated...
     522                 :          */
     523           30183 :         if ( ignoring )
     524                 :         {
     525            2038 :             ignore_one_word( statbuf );
     526                 :         }else{
     527                 :             /*  And if we're not ignoring source input, process it! */
     528           28145 :             tokenize_one_word ( wlen );
     529                 :         }
     530                 :     }
     531             640 : }
     532                 : 
     533                 : /* **************************************************************************
     534                 :  *
     535                 :  *      We will now define a series of fairly simple functions that
     536                 :  *          will be performed by the various Conditional Operators in
     537                 :  *          the "Conditionals Vocabulary".
     538                 :  *
     539                 :  *      Each one takes, as an argument, the "parameter field" pointer,
     540                 :  *          which, in all cases, points to the local  already_ignoring 
     541                 :  *          flag, passed as an int to satisfy C's strong-typing.  The
     542                 :  *          routine will internally recast it as a  bool .
     543                 :  *
     544                 :  *      If it is TRUE, the routine will bypass the test for its particular
     545                 :  *          type of condition, and go directly to  conditionally_tokenize
     546                 :  *          In most cases, testing for the condition would be harmless,
     547                 :  *          but in the case where the test is for an item on the stack,
     548                 :  *          it would be harmful because the sequence that put the item
     549                 :  *          on the stack was also being ignored...
     550                 :  *
     551                 :  *      We'll give these functions short prologs.  Synonyms will simply
     552                 :  *          have separate entries in the Vocabulary Table, associated
     553                 :  *          with the same function.
     554                 :  *
     555                 :  **************************************************************************** */
     556                 : 
     557                 : /* **************************************************************************
     558                 :  *
     559                 :  *      But first, a support routine...
     560                 :  *
     561                 :  **************************************************************************** */
     562                 : 
     563                 : /* **************************************************************************
     564                 :  *
     565                 :  *      Function name:  conditional_word_in_line
     566                 :  *      Synopsis:       Common code for the types of conditionals that
     567                 :  *                          require a word on the same line.
     568                 :  *
     569                 :  *      Inputs:
     570                 :  *         Parameters:
     571                 :  *             alr_ign         TRUE if we are already ignoring
     572                 :  *             exist_test      TRUE if the test is for "existence" of the word
     573                 :  *             exist_funct     Name of the function to call for the test
     574                 :  *         Global Variables:
     575                 :  *             stat_word       Word for which to test
     576                 :  *
     577                 :  *      Outputs:
     578                 :  *         Returned Value:     NONE
     579                 :  *
     580                 :  *      Error Detection:
     581                 :  *          The word in question must appear on the same line as the directive;
     582                 :  *              the call to  get_word_in_line()  checks for that and reports.
     583                 :  *          If the word did not appear on the same line, then the directive
     584                 :  *              will be disregarded and processing will proceed as though it
     585                 :  *              were absent.  This may lead to a cascade of errors...
     586                 :  *
     587                 :  *      Process Explanation:
     588                 :  *          The supplied  exist_funct()  will test for the existence of
     589                 :  *              the word, now read into  statbuf , in the appropriate 
     590                 :  *              venue.
     591                 :  *          We only call the  exist_funct()  if we are not already ignoring.
     592                 :  *
     593                 :  **************************************************************************** */
     594                 : 
     595                 : static void conditional_word_in_line( bool alr_ign,
     596                 :                                           bool exist_test,
     597                 :                                               bool (*exist_funct)() )
     598             274 : {
     599             274 :     if ( get_word_in_line( statbuf) )
     600                 :     {
     601             263 :         bool cond = FALSE;
     602             263 :         if ( INVERSE( alr_ign) )
     603                 :         {
     604             234 :             bool exists = exist_funct( statbuf);
     605             234 :             cond = BOOLVAL( exists == exist_test);
     606                 :         }
     607             263 :         conditionally_tokenize( cond, alr_ign );
     608                 :     }
     609             272 : }
     610                 : 
     611                 : 
     612                 : /* **************************************************************************
     613                 :  *
     614                 :  *      Function name:  if_exists
     615                 :  *      Synopsis:       Test for existence of a given word, in the dictionary.
     616                 :  *
     617                 :  *      Associated Tokenizer directives:        [ifexist]
     618                 :  *                                              #ifexist
     619                 :  *                                              [#ifexist]
     620                 :  *                                              [ifexists]
     621                 :  *                                              #ifexists
     622                 :  *                                              [#ifexists]
     623                 :  *        (Note variants with and without final 's'
     624                 :  *
     625                 :  **************************************************************************** */
     626                 : 
     627                 : static void if_exists( tic_param_t pfield )
     628              69 : {
     629              69 :     bool alr_ign = *pfield.bool_ptr;
     630              69 :     conditional_word_in_line( alr_ign, TRUE, exists_in_current );
     631              69 : }
     632                 : 
     633                 : /* **************************************************************************
     634                 :  *
     635                 :  *      Function name:  if_not_exist
     636                 :  *      Synopsis:       Test for Non-existence, in the appropriate dictionary,)
     637                 :  *                          of the given word.
     638                 :  *
     639                 :  *      Associated Tokenizer directives:        [ifnexist]
     640                 :  *                                              #ifnexist
     641                 :  *                                              [#ifnexist]
     642                 :  *        (Note:  Variants with final 's' didn't make sense here.)
     643                 :  *
     644                 :  *      Explanatory Notes:
     645                 :  *          This is the exact inverse of  if_exists
     646                 :  *
     647                 :  **************************************************************************** */
     648                 : 
     649                 : static void if_not_exist( tic_bool_param_t pfield )
     650              73 : {
     651              73 :     bool alr_ign = *pfield.bool_ptr;
     652              73 :     conditional_word_in_line( alr_ign, FALSE, exists_in_current );
     653              73 : }
     654                 : 
     655                 : /* **************************************************************************
     656                 :  *
     657                 :  *      Function name:  if_defined
     658                 :  *      Synopsis:       Test for existence of a user-defined symbol
     659                 :  *
     660                 :  *      Associated Tokenizer directives:        [ifdef]
     661                 :  *                                              #ifdef
     662                 :  *                                              [#ifdef]
     663                 :  *
     664                 :  **************************************************************************** */
     665                 : 
     666                 : static void if_defined( tic_bool_param_t pfield )
     667              63 : {
     668              63 :     bool alr_ign = *pfield.bool_ptr;
     669              63 :     conditional_word_in_line( alr_ign, TRUE, exists_as_user_symbol );
     670              63 : }
     671                 : 
     672                 : /* **************************************************************************
     673                 :  *
     674                 :  *      Function name:  if_not_defined
     675                 :  *      Synopsis:       Test for NON-existence of a user-defined symbol
     676                 :  *
     677                 :  *      Associated Tokenizer directives:        [ifndef]
     678                 :  *                                              #ifndef
     679                 :  *                                              [#ifndef]
     680                 :  *
     681                 :  **************************************************************************** */
     682                 : 
     683                 : static void if_not_defined( tic_bool_param_t pfield )
     684              69 : {
     685              69 :     bool alr_ign = *pfield.bool_ptr;
     686              69 :     conditional_word_in_line( alr_ign, FALSE, exists_as_user_symbol );
     687              67 : }
     688                 : 
     689                 : 
     690                 : /* **************************************************************************
     691                 :  *
     692                 :  *      Function name:  if_from_stack
     693                 :  *      Synopsis:       Test the number on top of the run-time stack
     694                 :  *
     695                 :  *      Associated Tokenizer directive:         [if]
     696                 :  *
     697                 :  *      Process Explanation:
     698                 :  *          When we are ignoring source input, and we still need to be
     699                 :  *              sensitive to the nesting of Conditional Operators, we
     700                 :  *              will not consume the number on the stack; this function
     701                 :  *              is after all, being ignored and should not perform any
     702                 :  *              action other than making sure the [else]s and [then]s
     703                 :  *              get properly counted.
     704                 :  *
     705                 :  **************************************************************************** */
     706                 : 
     707                 : static void if_from_stack( tic_bool_param_t pfield )
     708             379 : {
     709             379 :     bool alr_ign = *pfield.bool_ptr;
     710             379 :     bool cond = FALSE;
     711                 : 
     712             379 :     if ( ! alr_ign )
     713                 :     {
     714             291 :         long num = dpop();
     715             291 :         if (num != 0)
     716                 :         {
     717             213 :             cond = TRUE;
     718                 :         }
     719                 :     }
     720             379 :     conditionally_tokenize( cond, alr_ign );
     721             379 : }
     722                 : 
     723                 : /*  For future functions, use  conditl.BlankTemplate.c  */
     724                 : 
     725                 : /* **************************************************************************
     726                 :  *
     727                 :  *      Here, at long last, we define and initialize the structure containing
     728                 :  *          all the functions we support for Conditional Operators.
     729                 :  *
     730                 :  **************************************************************************** */
     731                 : 
     732                 : #define ADD_CONDL(str, func )   BUILTIN_BOOL_TIC(str, func, already_ignoring )
     733                 : 
     734                 : static tic_bool_hdr_t conditionals_vocab_tbl[] = {
     735                 :     ADD_CONDL ("[ifexist]"   , if_exists      ) ,
     736                 :     ADD_CONDL ("[ifexists]"  , if_exists      ) ,
     737                 :     ADD_CONDL ("#ifexist"    , if_exists      ) ,
     738                 :     ADD_CONDL ("#ifexists"   , if_exists      ) ,
     739                 :     ADD_CONDL ("[#ifexist]"  , if_exists      ) ,
     740                 :     ADD_CONDL ("[#ifexists]" , if_exists      ) ,
     741                 :     ADD_CONDL ("[ifnexist]"  , if_not_exist   ) ,
     742                 :     ADD_CONDL ("#ifnexist"   , if_not_exist   ) ,
     743                 :     ADD_CONDL ("[#ifnexist]" , if_not_exist   ) ,
     744                 :     ADD_CONDL ("[ifdef]"     , if_defined     ) ,
     745                 :     ADD_CONDL ("#ifdef"      , if_defined     ) ,
     746                 :     ADD_CONDL ("[#ifdef]"    , if_defined     ) ,
     747                 :     ADD_CONDL ("[ifndef]"    , if_not_defined ) ,
     748                 :     ADD_CONDL ("#ifndef"     , if_not_defined ) ,
     749                 :     ADD_CONDL ("[#ifndef]"   , if_not_defined ) ,
     750                 :     ADD_CONDL ("[if]"        , if_from_stack  )
     751                 : };
     752                 : 
     753                 : 
     754                 : /* **************************************************************************
     755                 :  *
     756                 :  *      Function name:  init_conditionals_vocab
     757                 :  *      Synopsis:       Initialize the "Conditionals Vocabulary Table"
     758                 :  *                          link-pointers dynamically, and link it in
     759                 :  *                          with the given ("Global") Vocabulary pointer.
     760                 :  *
     761                 :  **************************************************************************** */
     762                 : 
     763                 : void init_conditionals_vocab( tic_hdr_t **tic_vocab_ptr )
     764             170 : {
     765                 :     static const int conditionals_vocab_max_indx =
     766                 :          sizeof(conditionals_vocab_tbl)/sizeof(tic_bool_hdr_t);
     767                 : 
     768             170 :     init_tic_vocab( (tic_hdr_t *)conditionals_vocab_tbl,
     769                 :                         conditionals_vocab_max_indx,
     770                 :                             tic_vocab_ptr );
     771             170 : }
     772                 : 

Generated by: LTP GCOV extension version 1.5