LTP GCOV extension - code coverage report
Current view: directory - fcode-utils/toke - parselocals.c
Test: Toke 1.0.2
Date: 2006-10-30 Instrumented lines: 135
Code covered: 100.0 % Executed lines: 135
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                 :  *      Parsing functions for IBM-style Local Values
      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                 :  *          declare_locals      Pick up the Locals' names after the {
      38                 :  *          handle_local        Insert the code to access a Local
      39                 :  *          exists_as_local     Confirm whether a name is in the Locals vocab
      40                 :  *          assign_local        Process the "Assign to a Local" operator ( -> )
      41                 :  *          finish_locals       Insert the code for exiting a routine
      42                 :  *                                  that uses locals
      43                 :  *          forget_locals       Remove the locals' names from the search   
      44                 :  *
      45                 :  **************************************************************************** */
      46                 : 
      47                 : /* **************************************************************************
      48                 :  *
      49                 :  *          These are the names of the three routines that will be invoked
      50                 :  *          when Locals are used.  Their definitions exist in a separate
      51                 :  *          Local Values Support FCode source-file that must be FLOADed
      52                 :  *          into the user's tokenization source.
      53                 :  *
      54                 :  **************************************************************************** */
      55                 : 
      56                 : /*  Note that the enclosing curly-braces are part of the name  */
      57                 : static const char* push_locals = "{push-locals}"; /* ( #ilocals #ulocals -- ) */
      58                 : static const char* pop_locals = "{pop-locals}";   /* ( #locals -- )           */
      59                 : static const char* local_addr = "_{local}";       /* ( local# -- addr )       */
      60                 : 
      61                 : /*  Switchable Fetch or Store operator to apply to  local_addr.   */
      62                 : static const char* local_op = "@";   /*  Initially Fetch  */
      63                 : 
      64                 : 
      65                 : /* **************************************************************************
      66                 :  *
      67                 :  *      Revision History:
      68                 :  *          Updated Wed, 13 Jul 2005 by David L. Paktor
      69                 :  *              Command-line control for:
      70                 :  *                  Support for Locals in general
      71                 :  *                  Whether to accept the "legacy" separator (semicolon)
      72                 :  *                  Whether to issue a message for the "legacy" separator
      73                 :  *          Updated Tue, 10 Jan 2006 by David L. Paktor
      74                 :  *              Convert to  tic_hdr_t  type vocabulary.
      75                 :  *
      76                 :  **************************************************************************** */
      77                 : 
      78                 : #include <stdio.h>
      79                 : #include <stdlib.h>
      80                 : #include <string.h>
      81                 : 
      82                 : #include "parselocals.h"
      83                 : #include "ticvocab.h"
      84                 : #include "dictionary.h"
      85                 : #include "scanner.h"
      86                 : #include "errhandler.h"
      87                 : #include "clflags.h"
      88                 : #include "stream.h"
      89                 : #include "emit.h"
      90                 : #include "devnode.h"
      91                 : #include "flowcontrol.h"
      92                 : #include "tracesyms.h"
      93                 : 
      94                 : /* **************************************************************************
      95                 :  *
      96                 :  *      Global Variables Imported
      97                 :  *          statbuf
      98                 :  *          pc    
      99                 :  *          opc
     100                 :  *          incolon
     101                 :  *          lastcolon
     102                 :  *          ibm_locals_legacy_separator      Accept ; as the "legacy" separator
     103                 :  *          ibm_legacy_separator_message     Issue a message for "legacy" sep'r
     104                 :  *
     105                 :  **************************************************************************** */
     106                 : 
     107                 : /* **************************************************************************
     108                 :  *
     109                 :  *          Internal Static Variables
     110                 :  *              local_names        Vocabulary for new local-names
     111                 :  *              num_ilocals        Number of initialized local variables
     112                 :  *              num_ulocals        Number of uninitialized local variables
     113                 :  *              localno            Running Local-Number to be assigned
     114                 :  *              eval_buf           Internally-generated string to be parsed
     115                 :  *              l_d_lineno         Locals Declaration Line Number
     116                 :  *
     117                 :  **************************************************************************** */
     118                 : 
     119                 : static tic_hdr_t *local_names = NULL;
     120                 : static int num_ilocals = 0;
     121                 : static int num_ulocals = 0;
     122                 : static int localno = 0;
     123                 : static char eval_buf[64];
     124                 : static unsigned int l_d_lineno;         /*  For Error Messages   */
     125                 : 
     126                 : /* **************************************************************************
     127                 :  *
     128                 :  *     The  local_names  vocabulary follows the same  tic_hdr_t   structure
     129                 :  *         as the dictionaries of tokens, special-functions, etcetera.   Its
     130                 :  *         "parameter field" is an integer, used to store the Local's number,
     131                 :  *         an its "function" is invoke_local(), defined further below.
     132                 :  *
     133                 :  *     The vocabulary is initially empty, so there's no need for an "init"
     134                 :  *         or a "reset" routine.
     135                 :  *
     136                 :  **************************************************************************** */
     137                 : 
     138                 : /* **************************************************************************
     139                 :  *
     140                 :  *      Function name:  int_to_str
     141                 :  *      Synopsis:       Convert an integer into a compilable string.
     142                 :  *                      Suport routine for invoke_local().
     143                 :  *
     144                 :  *      Inputs:
     145                 :  *         Parameters:
     146                 :  *             num             The number to convert
     147                 :  *             bufr            The buffer into which to place it.
     148                 :  *                                 Needn't be very long:
     149                 :  *                                 five at least, ten is enough
     150                 :  *
     151                 :  *      Outputs:
     152                 :  *         Returned Value:     Pointer to  bufr
     153                 :  *             bufr            Contents are changed.
     154                 :  *
     155                 :  *      Process Explanation:
     156                 :  *          Convert into decimal.  If the number is greater than 8,
     157                 :  *              prepend a  d#  in front of it.  If less, don't.
     158                 :  *              We specifically want to avoid a  d#  in front of
     159                 :  *              the numbers 0 1 2 and 3, which are also named constants;
     160                 :  *              there's no need to treat 'em as literals.
     161                 :  *          The calling routine will be responsible for allocating
     162                 :  *              and freeing the buffer.
     163                 :  *
     164                 :  *      Extraneous Remarks:
     165                 :  *          Too bad  atoi()  isn't a Standard C function; I could convert
     166                 :  *             using the current base, and be guaranteed that it would be
     167                 :  *             interpreted in the same base.
     168                 :  *          Instead, I have to fiddle-faddle around with  d#  ...
     169                 :  *
     170                 :  **************************************************************************** */
     171                 : 
     172                 : static char *int_to_str( int num, char *bufr)
     173             862 : {
     174             862 :      char* prefix = "d# ";
     175             862 :      if ( num < 8 ) prefix = "";
     176             862 :      sprintf(bufr,"%s%d",prefix, num);
     177             862 :      return (bufr);
     178                 : }
     179                 : 
     180                 : 
     181                 : 
     182                 : /* **************************************************************************
     183                 :  *
     184                 :  *      Function name:  invoke_local
     185                 :  *      Synopsis:       Compile-in the code to access the Local whose
     186                 :  *                      assigned Number is given.  This function is
     187                 :  *                      entered into the Local-Names Vocabulary entry.
     188                 :  *      
     189                 :  *      Inputs:
     190                 :  *         Parameters:
     191                 :  *             pfield              The Vocabulary entry's Param field, taken
     192                 :  *                                     from the Assigned Number of the Local.
     193                 :  *         Local Static Variables:
     194                 :  *             local_addr          Name of  _{local}  routine, invoked
     195                 :  *                                     when a Local is used 
     196                 :  *             local_op            Fetch or Store operator to apply.
     197                 :  *
     198                 :  *      Outputs:
     199                 :  *         Returned Value:         None
     200                 :  *         Local Static Variables:
     201                 :  *             eval_buf            Phrase constructed here; will become new
     202                 :  *                                     Source Input Buffer, temporarily
     203                 :  *
     204                 :  *      Error Detection:
     205                 :  *          If the Local Values Support FCode source-file was not
     206                 :  *              FLOADed into the user's tokenization source, then
     207                 :  *              the function  _{local}  will be an "unknown name".
     208                 :  *
     209                 :  *      Process Explanation:
     210                 :  *          We are going to generate a string of the form:
     211                 :  *                  " #local _{local} OP"
     212                 :  *              and pass it to the Parser for evaluation.
     213                 :  *          The call to  _{local}  is preceded by its parameter, which is
     214                 :  *               its Assigned Local-Number, and followed by the appropriate
     215                 :  *               OPerator, which will be "Fetch" if the Local's name was
     216                 :  *               invoked by itself, or "Store" if its invocation was made
     217                 :  *               in conjuction with the  ->  operator.
     218                 :  *          The string-buffer may be local, but it must be stable.
     219                 :  *
     220                 :  *      Revision History:
     221                 :  *      Updated Thu, 24 Mar 2005 by David L. Paktor
     222                 :  *          Factored-out to permit  lookup_local()  to be a "pure"
     223                 :  *          function that can be used for duplicate-name detection.
     224                 :  *      Updated Tue, 10 Jan 2006 by David L. Paktor
     225                 :  *          Accommodate conversion to  tic_hdr_t  type vocabulary.
     226                 :  *
     227                 :  **************************************************************************** */
     228                 : 
     229                 : static void invoke_local( tic_param_t pfield )
     230             618 : {
     231                 :     char local_num_buf[10];
     232             618 :     int loc_num = (int)pfield.deflt_elem;
     233                 : 
     234             618 :     int_to_str(loc_num, local_num_buf);
     235             618 :     sprintf( eval_buf, "%s %s %s", local_num_buf, local_addr, local_op );
     236             618 :     eval_string( eval_buf);
     237                 : 
     238             618 : }
     239                 : 
     240                 : 
     241                 : /* **************************************************************************
     242                 :  *
     243                 :  *      Function name:  locals_separator
     244                 :  *      Synopsis:       Test whether the given character is the separator
     245                 :  *                          between initted and uninitted Local Names.
     246                 :  *                      Optionally, allow Semi-Colon as a separator and issue
     247                 :  *                          an optional Advisory.
     248                 :  *
     249                 :  *      Inputs:
     250                 :  *         Parameters:
     251                 :  *             subj     One-character "subject" of the test
     252                 :  *         Global Variables:    
     253                 :  *             ibm_locals_legacy_separator     Allow Semi-Colon as a separator?
     254                 :  *             ibm_legacy_separator_message    Issue an Advisory message?
     255                 :  *
     256                 :  *      Outputs:
     257                 :  *         Returned Value:   TRUE if the character is the separator
     258                 :  *
     259                 :  *      Error Detection:
     260                 :  *          If the separator is Semi-Colon, and  ibm_locals_legacy_separator 
     261                 :  *              is TRUE, then if  ibm_legacy_separator_message  is TRUE,
     262                 :  *              issue an Advisory message.
     263                 :  *          If the flag to allow Semi-Colon is FALSE, then simply do not
     264                 :  *              acknowledge a valid separator.  Other routines will report
     265                 :  *              an erroneous attempt to use an already-defined symbol.
     266                 :  *
     267                 :  *      Revision History:
     268                 :  *          Updated Wed, 13 Jul 2005 by David L. Paktor
     269                 :  *          Bring the questions of whether to accept semicolon as a separator
     270                 :  *              -- and whether to issue a message for it -- under the control 
     271                 :  *              of external flags (eventually set by command-line switches),
     272                 :  *              rather than being hard-compiled.
     273                 :  *
     274                 :  *      Extraneous Remarks:
     275                 :  *          In the interest of avoiding too deeply nested "IF"s, I will
     276                 :  *              not be adhering strictly to the rules of structure.
     277                 :  *
     278                 :  **************************************************************************** */
     279                 : 
     280                 : static bool locals_separator( char subj )
     281             166 : {
     282             166 :     bool retval = FALSE;
     283                 :     /*  Is it the preferred (i.e., non-legacy) separator?   */
     284             166 :     if ( subj == '|' )
     285                 :     {  
     286              49 :         retval = TRUE;
     287              49 :         return ( retval );
     288                 :     }
     289                 :         
     290             117 :     if ( ibm_locals_legacy_separator )
     291                 :     {
     292             108 :         if ( subj == ';' )
     293                 :         {
     294              17 :             retval = TRUE;
     295              17 :             if ( ibm_legacy_separator_message )
     296                 :             {
     297              14 :                 tokenization_error ( WARNING , "Semicolon as separator in "
     298                 :                     "Locals declaration is deprecated in favor of '|'\n");
     299                 :             }
     300                 :         }
     301                 :     }
     302             117 :     return ( retval );
     303                 : }
     304                 : 
     305                 : /* **************************************************************************
     306                 :  *
     307                 :  *      Function name:  add_local
     308                 :  *      Synopsis:       Given a pointer to a name and a number, enter
     309                 :  *                      them into the vocabulary for new Local names.
     310                 :  *      
     311                 :  *      Inputs:
     312                 :  *         Parameters:
     313                 :  *             lnum              The assigned number
     314                 :  *             lname             Pointer to the name
     315                 :  *         Local Static Variables:
     316                 :  *             local_names       The vocabulary for new Local names
     317                 :  *
     318                 :  *      Outputs:
     319                 :  *         Returned Value:       NONE
     320                 :  *         Local Static Variables:
     321                 :  *             local_names       Enter the new Local's name and number.
     322                 :  *         Memory Allocated:
     323                 :  *             A place into which the name will be copied
     324                 :  *         When Freed?
     325                 :  *             When  forget_locals()  routine frees up all memory
     326                 :  *                 allocations in the "Local Names" Vocabulary.
     327                 :  *
     328                 :  *      Process Explanation:
     329                 :  *          Allocate a stable place in memory for the name, via  strdup().
     330                 :  *          The entry's "action" will be the  invoke_local()  function,
     331                 :  *              defined above.  The "parameter field" size is zero.
     332                 :  *
     333                 :  **************************************************************************** */
     334                 : 
     335                 : static void add_local( TIC_P_DEFLT_TYPE lnum, char *lname)
     336             336 : {
     337                 :     char *lnamecopy ;
     338                 : 
     339             336 :     lnamecopy = strdup( lname);
     340             336 :     add_tic_entry( lnamecopy, invoke_local, lnum,
     341                 :                        LOCAL_VAL, 0, FALSE,  NULL,
     342                 :                                &local_names );
     343             336 : }
     344                 : 
     345                 : 
     346                 : /* **************************************************************************
     347                 :  *
     348                 :  *      Function name:  gather_locals
     349                 :  *      Synopsis:       Collect Local names, for both initted and uninitted
     350                 :  *                      Return an indication as to whether to continue
     351                 :  *                      gathering Locals' names
     352                 :  *      
     353                 :  *      Inputs:
     354                 :  *         Parameters:
     355                 :  *             initted        TRUE if we are gathering initted Local names.
     356                 :  *             counter        Pointer to variable that's counting names.
     357                 :  *         Global Variables:
     358                 :  *             statbuf        The symbol just retrieved from the input stream.
     359                 :  *         Local Static Variables:
     360                 :  *             localno        Running Local-Number to be assigned
     361                 :  *             l_d_lineno     Line # of Locals Declar'n start (for err mssg)
     362                 :  *
     363                 :  *      Outputs:
     364                 :  *         Returned Value:    TRUE = Ended with initted/uninitted separator
     365                 :  *         Local Static Variables:
     366                 :  *             localno        Incremented for each Local name declared
     367                 :  *             local_names    Enter the new locals' names into the Vocabulary.
     368                 :  *                            Numeric field is assigned local number.
     369                 :  *
     370                 :  *      Error Detection:
     371                 :  *          A Local-name that duplicates an existing name is an ERROR.
     372                 :  *              Especially if that name is <Semicolon> and the flag
     373                 :  *              called  ibm_locals_legacy_separator  was not set.
     374                 :  *          Issue an Error if close-curly-brace terminator is not found,
     375                 :  *              or if imbedded comment is not terminated, before end of file.
     376                 :  *          If the Separator is found a second-or-more time, issue an Error
     377                 :  *              and continue collecting uninitted Local names.
     378                 :  *
     379                 :  *      Revision History:
     380                 :  *      Updated Thu, 24 Mar 2005 by David L. Paktor
     381                 :  *          Allow comments to be interspersed among the declarations.
     382                 :  *          Error-check duplicate Local-name.
     383                 :  *      Updated Wed, 30 Mar 2005 by David L. Paktor
     384                 :  *          Warning when name length exceeds ANSI-specified max (31 chars). 
     385                 :  *      Updated Thu, 07 Jul 2005 by David L. Paktor
     386                 :  *          Protect against PC pointer-overrun due to unterminated
     387                 :  *              comment or declaration.
     388                 :  *          Error-check for numbers.
     389                 :  *          No name-length check; doesn't go into FCode anyway.
     390                 :  *
     391                 :  **************************************************************************** */
     392                 : 
     393                 : static bool gather_locals( bool initted, int *counter )
     394             137 : {
     395                 :     signed long wlen;
     396             137 :     bool retval = FALSE;
     397                 : 
     398                 :     while ( TRUE )
     399                 :     {
     400             683 :         wlen = get_word();
     401                 : 
     402             683 :         if ( wlen <= 0 )
     403                 :         {
     404               6 :             warn_unterm( TKERROR, "Local-Values Declaration", l_d_lineno);
     405               6 :             break;
     406                 :         }
     407                 : 
     408                 :         /*  Allow comments to be interspersed among the declarations.  */
     409             677 :         if ( filter_comments( statbuf) )
     410                 :         {
     411                 :             /*  Unterminated and Multi-line checking already handled   */
     412             115 :             continue;
     413                 :         }
     414                 :         /*  Is this the terminator or the separator? */
     415             562 :         if ( wlen == 1 )    /*  Maybe   */
     416                 :         {
     417                 :             /*  Check for separator   */
     418             166 :             if (locals_separator( statbuf[0] ) )
     419                 :             {
     420                 :                 /*  If gathering initted Local names, separator is legit  */
     421              66 :                 if ( initted )
     422                 :                 {
     423              61 :                     retval = TRUE;
     424              61 :                     break;
     425                 :                 }else{
     426               5 :                     tokenization_error ( TKERROR,
     427                 :                         "Excess separator -- %s -- found "
     428                 :                             "in Local-Values declaration", statbuf);
     429               5 :                     in_last_colon( TRUE);
     430               5 :                     continue;
     431                 :                 }
     432                 :             }
     433                 :             /*  Haven't found the separator.  Check for the terminator  */
     434             100 :             if ( statbuf[0] == '}' )
     435                 :             {
     436              70 :                 break;
     437                 :             }
     438                 :         }
     439                 :         /*  It was not the terminator or the separator  */
     440                 :         {
     441                 :             long tmp;
     442                 :             char *where_pt1;  char *where_pt2;
     443                 :             /*  Error-check for duplicated names  */
     444             426 :             if ( word_exists ( statbuf, &where_pt1, &where_pt2 ) )
     445                 :             {
     446              87 :                 tokenization_error ( TKERROR, "Cannot declare %s "
     447                 :                     "as a Local-Name; it's already defined %s%s",
     448                 :                         statbuf, where_pt1, where_pt2 );
     449              87 :                 show_node_start();
     450              87 :                 continue;
     451                 :             }
     452                 :             /*  Error-check for numbers.  */
     453             339 :             if ( get_number(&tmp) )
     454                 :             {
     455               3 :                 tokenization_error ( TKERROR, "Cannot declare %s "
     456                 :                     "as a Local-Name; it's a number.\n", statbuf );
     457               3 :                 continue;
     458                 :             }
     459                 : 
     460                 :             /*  We've got a valid new local-name    */
     461                 :             /*  Don't need to check name length; it won't go into the FCode  */
     462                 : 
     463                 :             /*  Increment our counting-v'ble  */
     464             336 :             *counter += 1;
     465                 : 
     466                 :             /*  Define our new local-name in the Locals' vocabulary  */
     467             336 :             add_local( localno, statbuf );
     468                 : 
     469                 :             /*  Bump the running Local-Number  */
     470             336 :             localno++;
     471                 : 
     472                 :         }
     473                 :     }
     474             137 :     return ( retval );
     475                 : }
     476                 : 
     477                 : 
     478                 : /* **************************************************************************
     479                 :  *
     480                 :  *      Function name:  activate_locals
     481                 :  *      Synopsis:       Compile-in the call to  {push-locals}  that
     482                 :  *                      the new definition under construction will need,
     483                 :  *                      now that the Locals have been declared.
     484                 :  *      
     485                 :  *      Inputs:
     486                 :  *         Parameters:                NONE
     487                 :  *         Global Variables:
     488                 :  *             num_ilocals              First argument to  {push-locals}
     489                 :  *             num_ulocals              Second argument to  {push-locals}
     490                 :  *             push_locals              Name of  {push-locals}  routine.
     491                 :  *
     492                 :  *      Outputs:
     493                 :  *         Returned Value:            NONE
     494                 :  *         Local Static Variables:
     495                 :  *             eval_buf               Phrase constructed here; will become
     496                 :  *                                        new Source Input Buffer, temporarily
     497                 :  *
     498                 :  *      Error Detection:
     499                 :  *          If the Local Values Support FCode source-file was not
     500                 :  *              FLOADed into the user's tokenization source, then
     501                 :  *              the function  {push-locals}  will be an "unknown name".
     502                 :  *
     503                 :  *      Process Explanation:
     504                 :  *          We are going to generate a string of the form:
     505                 :  *                  " #ilocals #ulocals {push-locals}"
     506                 :  *              and pass it to the Parser for evaluation.
     507                 :  *          The string-buffer may be local, but it must be stable.
     508                 :  *
     509                 :  *      Question under consideration.:
     510                 :  *          Do we want to check if  {push-locals}  is an unknown name,
     511                 :  *              and give the user a hint of what's needed?  And, if so,
     512                 :  *              do we do it only once, or every time?
     513                 :  *
     514                 :  **************************************************************************** */
     515                 : 
     516                 : static void activate_locals( void )
     517              76 : {
     518                 :     char ilocals_buf[10];
     519                 :     char ulocals_buf[10];
     520                 :      
     521              76 :     int_to_str(num_ilocals, ilocals_buf ); 
     522              76 :     int_to_str(num_ulocals, ulocals_buf );
     523              76 :     sprintf( eval_buf,"%s %s %s",ilocals_buf, ulocals_buf, push_locals);
     524              76 :     eval_string( eval_buf);
     525              76 : }
     526                 : 
     527                 : /* **************************************************************************
     528                 :  *
     529                 :  *      Function name:  error_check_locals
     530                 :  *      Synopsis:       Indicate whether Locals declaration is erronious
     531                 :  *      
     532                 :  *      Inputs:
     533                 :  *         Parameters:     NONE
     534                 :  *         Global Variables:
     535                 :  *             incolon             TRUE if colon def'n is in effect.
     536                 :  *             opc                 FCode Output buffer Position Counter
     537                 :  *             lastcolon           Value of opc when Colon def'n was started
     538                 :  *
     539                 :  *      Outputs:
     540                 :  *         Returned Value:         TRUE if found errors severe enough to
     541                 :  *                                     preclude further processing of Decl'n
     542                 :  *
     543                 :  *      Errors Detected:
     544                 :  *           Colon definition not in effect.  ERROR and return TRUE.
     545                 :  *           Locals declaration inside body of colon-definition (i.e., after
     546                 :  *                something has been compiled-in to it) is potentially risky,
     547                 :  *                but may be valid, and is a part of legacy practice.  It
     548                 :  *                will not be treated as an outright ERROR, but it will
     549                 :  *                generate a WARNING...
     550                 :  *           Multiple locals declarations inside a single colon-definition
     551                 :  *                are completely disallowed.  ERROR and return TRUE.
     552                 :  *           Locals declaration inside a control-structure is prohibited.
     553                 :  *                Generate an ERROR, but return FALSE to allow processing
     554                 :  *                of the declaration to continue.
     555                 :  *
     556                 :  **************************************************************************** */
     557                 : 
     558                 : /*  The value of  lastcolon  when Locals Declaration is made.
     559                 :  *      If it's the same, that detects multiple locals declaration attempt.
     560                 :  */
     561                 : static int last_local_colon = 0;
     562                 : 
     563                 : static bool error_check_locals ( void )
     564              81 : {
     565              81 :     bool retval = FALSE;
     566                 :     
     567              81 :     if ( ! incolon )
     568                 :     {
     569               4 :         tokenization_error ( TKERROR,
     570                 :             "Can only declare Locals inside of a Colon-definition.\n");
     571               4 :         retval = TRUE;
     572                 :     } else {
     573              77 :         if ( last_local_colon == lastcolon )
     574                 :         {
     575               1 :             tokenization_error ( TKERROR, "Excess Locals Declaration");
     576               1 :             in_last_colon( TRUE);
     577               1 :             retval = TRUE;
     578                 :         }else{
     579              76 :             last_local_colon = lastcolon;
     580              76 :             if ( opc > lastcolon )
     581                 :             {
     582               5 :                 tokenization_error ( WARNING,
     583                 :                     "Declaring Locals after the body of a Colon-definition "
     584                 :                     "has begun is not recommended.\n");
     585                 :             }
     586              76 :             announce_control_structs( TKERROR,
     587                 :                 "Local-Values Declaration encountered",
     588                 :                     last_colon_abs_token_no);
     589                 :         }
     590                 :     }
     591              81 :     return ( retval );
     592                 : }
     593                 : 
     594                 : /* **************************************************************************
     595                 :  *
     596                 :  *      Function name:  declare_locals
     597                 :  *      Synopsis:       Process (or Ignore) the Declaration of Locals,
     598                 :  *                          upon encountering Curly-brace ( {  )
     599                 :  *      
     600                 :  *      Inputs:
     601                 :  *         Parameters:
     602                 :  *             ignoring            TRUE if "Ignoring"
     603                 :  *         Global Variables:
     604                 :  *             statbuf             Next symbol to process.
     605                 :  *             lineno              Current Line Number in Input File
     606                 :  *             report_multiline    FALSE to suspend multiline warning
     607                 :  *
     608                 :  *      Outputs:
     609                 :  *         Returned Value:         NONE
     610                 :  *         Global Variables:
     611                 :  *             statbuf             Advanced to end of Locals Declaration.
     612                 :  *             pc                  Bumped past the close-curly-brace
     613                 :  *         Local Static Variables:
     614                 :  *             localno             Init'd, then updated by gather_locals()
     615                 :  *             l_d_lineno          Line Number of start of Locals Declaration
     616                 :  *
     617                 :  *      Error Detection:
     618                 :  *          See  error_check_locals()
     619                 :  *              After Error messages, will bypass further processing until the
     620                 :  *                  terminating close-curly-brace of a Locals Declaration.
     621                 :  *                  If the terminating close-curly-brace missing under those
     622                 :  *                  circumstances, issue an Error
     623                 :  *              If terminating close-curly-brace is missing when the Locals
     624                 :  *                  Declaration is otherwise valid, gather_locals() will
     625                 :  *                  detect and report the Error.
     626                 :  *              Warning if multiline declaration.  Because embedded comments
     627                 :  *                  may also supppress the multiline warning, we need to save
     628                 :  *                  and restore the state of the report_multiline switch...
     629                 :  *
     630                 :  **************************************************************************** */
     631                 : 
     632                 : void declare_locals ( bool ignoring)
     633              91 : {
     634              91 :     num_ilocals = 0;
     635              91 :     num_ulocals = 0;
     636              91 :     localno = 0;
     637                 :     
     638              91 :     l_d_lineno = lineno;
     639              91 :     bool sav_rep_mul_lin = report_multiline;
     640              91 :     report_multiline = TRUE;
     641                 : 
     642              91 :     if ( ignoring || error_check_locals() )
     643                 :     {
     644              15 :        if ( skip_until ( '}' ) )
     645                 :        {
     646               2 :            warn_unterm(TKERROR,
     647                 :                "misplaced Local-Values Declaration", l_d_lineno);
     648                 :        }else{
     649              13 :            pc++ ;  /*  Get past the close-curly-brace  */
     650                 :        }
     651                 :     }else{
     652              76 :        if (gather_locals( TRUE,  &num_ilocals ) )
     653                 :        {
     654              61 :            gather_locals( FALSE, &num_ulocals );
     655                 :        }
     656                 :     }
     657                 : 
     658                 :     /*  If PC has reached the END,  gather_locals()  will
     659                 :      *      have already issued an "unterminated" Error;
     660                 :      *      a "multiline" warning would be redundant
     661                 :      *      repetitive, unnecessary, excessive, unaesthetic
     662                 :      *      and -- did I already mention? -- redundant.
     663                 :      */
     664              91 :     if ( pc < end )
     665                 :     {
     666              83 :         report_multiline = sav_rep_mul_lin;
     667              83 :         warn_if_multiline( "Local-Values declaration", l_d_lineno);
     668                 :     }
     669                 : 
     670                 :     /*  Don't do anything if no Locals were declared    */
     671                 :     /*  This could happen if the  {  }  field is empty  */
     672              91 :     if ( localno != 0 )
     673                 :     {
     674              76 :         activate_locals();
     675                 :     }
     676              91 : }
     677                 : 
     678                 : /* **************************************************************************
     679                 :  *
     680                 :  *      Function name:  handle_local
     681                 :  *      Synopsis:       Process the given name as a Local Name;
     682                 :  *                      indicate if it was a valid Local Name.
     683                 :  *
     684                 :  *      Inputs:
     685                 :  *         Parameters:
     686                 :  *             lname                The "Local" name for which to look
     687                 :  *         Local Static Variables:  
     688                 :  *             local_names          The vocabulary for Local names
     689                 :  *
     690                 :  *      Outputs:
     691                 :  *         Returned Value:          TRUE if the name is a valid "Local Name"
     692                 :  *
     693                 :  **************************************************************************** */
     694                 : 
     695                 : static bool handle_local( char *lname)
     696             103 : {
     697             103 :     bool retval = handle_tic_vocab( lname, local_names );
     698             103 :     return ( retval ) ;
     699                 : }
     700                 : 
     701                 : /* **************************************************************************
     702                 :  *
     703                 :  *      Function name:  lookup_local
     704                 :  *      Synopsis:       Return a pointer to the data-structure of the named
     705                 :  *                      word, only if it was a valid Local Name.
     706                 :  *
     707                 :  *      Inputs:
     708                 :  *         Parameters:
     709                 :  *             lname                The "Local" name for which to look
     710                 :  *         Local Static Variables:  
     711                 :  *             local_names          The vocabulary for Local names
     712                 :  *
     713                 :  *      Outputs:
     714                 :  *         Returned Value:          Pointer to the data-structure, or
     715                 :  *                                      NULL if not found.
     716                 :  *
     717                 :  **************************************************************************** */
     718                 : 
     719                 : tic_hdr_t *lookup_local( char *lname)
     720           16576 : {
     721           16576 :     tic_hdr_t *retval = lookup_tic_entry( lname, local_names );
     722           16576 :     return ( retval ) ;
     723                 : }
     724                 : 
     725                 : 
     726                 : /* **************************************************************************
     727                 :  *
     728                 :  *      Function name:  create_local_alias
     729                 :  *      Synopsis:       Create an alias in the "Local Names" Vocabulary
     730                 :  *
     731                 :  *      Associated FORTH word:              ALIAS
     732                 :  *
     733                 :  *      Inputs:
     734                 :  *         Parameters:
     735                 :  *             old_name             Name of existing entry
     736                 :  *             new_name             New name for which to create an entry
     737                 :  *
     738                 :  *      Outputs:
     739                 :  *         Returned Value:          TRUE if  old_name  found in "Locals" vocab
     740                 :  *         Global Variables:    
     741                 :  *             local_names          Will point to the new entry
     742                 :  *         Memory Allocated:
     743                 :  *             Memory for the new entry, by the support routine
     744                 :  *         When Freed?
     745                 :  *             When  forget_locals()  routine frees up all memory
     746                 :  *                 allocations in the "Local Names" Vocabulary.
     747                 :  *
     748                 :  **************************************************************************** */
     749                 : 
     750                 : bool create_local_alias(char *new_name, char *old_name)
     751             163 : {
     752             163 :     bool retval = create_tic_alias( new_name, old_name, &local_names );
     753             163 :     return ( retval );
     754                 : }
     755                 : 
     756                 : /* **************************************************************************
     757                 :  *
     758                 :  *      Function name:  exists_as_local
     759                 :  *      Synopsis:       Simply confirm whether a given name exists
     760                 :  *                      within the Locals vocabulary.
     761                 :  *      
     762                 :  *      Inputs:
     763                 :  *         Parameters:
     764                 :  *             stat_name          Name to look up
     765                 :  *
     766                 :  *      Outputs:
     767                 :  *         Returned Value:        TRUE if stat_name was a Local
     768                 :  *
     769                 :  **************************************************************************** */
     770                 : 
     771                 : bool exists_as_local( char *stat_name )
     772              50 : {
     773              50 :     bool retval = exists_in_tic_vocab(stat_name, local_names );
     774              50 :     return ( retval );
     775                 : }
     776                 : 
     777                 : 
     778                 : /* **************************************************************************
     779                 :  *
     780                 :  *      Function name:  assign_local
     781                 :  *      Synopsis:       Process the "Assign to a Local" operator ( -> )
     782                 :  *      
     783                 :  *      Inputs:
     784                 :  *         Parameters:             NONE
     785                 :  *         Global Variables:
     786                 :  *             statbuf          Next symbol to process
     787                 :  *             pc               Input-source Scanning pointer
     788                 :  *             lineno           Input-source Line Number. Used for Err Mssg.
     789                 :  *
     790                 :  *      Outputs:
     791                 :  *         Returned Value:         NONE
     792                 :  *         Global Variables:
     793                 :  *             statbuf          Advanced to next symbol
     794                 :  *             pc               Advanced; may be unchanged if error.
     795                 :  *             lineno           Advanced; may be unchanged if error
     796                 :  *             local_op         Will be set to Store and then reset to Fetch.
     797                 :  *         Global Behavior:
     798                 :  *             Construct a phrase and pass it to the Tokenizer.
     799                 :  *
     800                 :  *      Error Detection:
     801                 :  *          If next symbol is not a Local name, print ERROR message    
     802                 :  *              and restore  pc  so that the next symbol will be    
     803                 :  *              processed by ordinary means.
     804                 :  *          In the extremely unlikely case that -> is last symbol in  
     805                 :  *              the source-file, report an ERROR.
     806                 :  *
     807                 :  *      Process Explanation:
     808                 :  *          Save the PC.
     809                 :  *          Get the next symbol; check for end-of-file.
     810                 :  *          Set Local Operator ( local_op ) to "Store", to prepare to apply it.
     811                 :  *          Pass the next symbol to  handle_local() .
     812                 :  *          If  handle_local()  failed to find the name, you have
     813                 :  *              detected an error; restore  pc .
     814                 :  *          Otherwise, you have invoked the local and applied "Store" to it.
     815                 :  *          At the end, reset  local_op  to "Fetch".
     816                 :  *
     817                 :  **************************************************************************** */
     818                 : 
     819                 : void assign_local ( void )
     820             107 : {
     821                 :     signed long wlen;
     822                 :     bool is_okay;
     823             107 :     u8 *savd_pc = pc;
     824             107 :     unsigned int savd_lineno = lineno;
     825                 : 
     826             107 :     wlen = get_word();
     827                 : 
     828             107 :         if ( wlen <= 0 )
     829                 :         {
     830               4 :             warn_unterm(TKERROR, "Locals Assignment", lineno);
     831               4 :             return;
     832                 :         }
     833                 : 
     834             103 :     local_op = "!";   /*  Set to Store  */
     835                 : 
     836             103 :     is_okay = handle_local( statbuf);
     837             103 :     if( INVERSE(is_okay)  )
     838                 :     {
     839               6 :         tokenization_error ( TKERROR,
     840                 :             "Cannot apply -> to %s, only to a declared Local.\n", statbuf );
     841               6 :         pc = savd_pc;
     842               6 :         lineno = savd_lineno;
     843                 :     }
     844             103 :     local_op = "@";   /*  Reset to Fetch  */
     845                 : }
     846                 : 
     847                 : /* **************************************************************************
     848                 :  *
     849                 :  *      Function name:  finish_locals
     850                 :  *      Synopsis:       Compile-in the call to  {pop-locals}  that the
     851                 :  *                      new definition under construction will need
     852                 :  *                      when it's about to complete execution, i.e.,
     853                 :  *                      before an EXIT or a SemiColon.  But only if the
     854                 :  *                      current definition under construction is using Locals.
     855                 :  *      
     856                 :  *      Inputs:
     857                 :  *         Parameters:       NONE
     858                 :  *             
     859                 :  *         Local Static Variables:
     860                 :  *             localno            Total # of Locals.
     861                 :  *                                    Both a param to  {pop-locals} 
     862                 :  *                                    and an indicator that Locals are in use.
     863                 :  *             pop_locals         Name of  {pop-locals}  routine.
     864                 :  *
     865                 :  *      Outputs:
     866                 :  *         Returned Value:        NONE
     867                 :  *         Local Static Variables:
     868                 :  *             eval_buf            Phrase constructed here; will become new
     869                 :  *                                     Source Input Buffer, temporarily
     870                 :  *
     871                 :  *      Error Detection:
     872                 :  *          If the Local Values Support FCode source-file was not
     873                 :  *              FLOADed into the user's tokenization source, then
     874                 :  *              the function  {pop-locals}  will be an "unknown name".
     875                 :  *
     876                 :  *      Revision History:
     877                 :  *          Updated Fri, 24 Feb 2006 by David L. Paktor
     878                 :  *              The eval_string() routine no longer calls its own
     879                 :  *                  instance of  tokenize() .  In order to make a
     880                 :  *                  smooth transition between the processing the
     881                 :  *                  internally-generated string and the resumption
     882                 :  *                  of processing the source file, it simply sets
     883                 :  *                  up the string to be processed next.
     884                 :  *              In this case, however, we need to have the string
     885                 :  *                  processed right away, as the calling routine
     886                 :  *                  emits a token that must follow those generated
     887                 :  *                  by this.
     888                 :  *              Fortunately, we know the exact contents of the string.
     889                 :  *                  Two calls to tokenize_one_word() will satisfy the
     890                 :  *                  requirement.
     891                 :  *
     892                 :  **************************************************************************** */
     893                 : 
     894                 : void finish_locals ( void )
     895             585 : {
     896                 :      /*    Don't do anything if Locals are not in use    */
     897             585 :     if ( localno > 0 )
     898                 :     {
     899                 :         char nlocals_buf[10];
     900                 :      
     901              92 :         int_to_str(localno, nlocals_buf ); 
     902              92 :         sprintf( eval_buf,"%s %s",nlocals_buf, pop_locals);
     903              92 :         eval_string( eval_buf);
     904              92 :         tokenize_one_word( get_word() );
     905              92 :         tokenize_one_word( get_word() );
     906                 :     }
     907             585 : }
     908                 : 
     909                 : /* **************************************************************************
     910                 :  *
     911                 :  *      Function name:  forget_locals
     912                 :  *      Synopsis:       Remove the Locals' names from the special Vocabulary
     913                 :  *                      free-up their allocated memory, and reset the Locals'
     914                 :  *                      counters (which are also the indication that Locals
     915                 :  *                      are in use).  This is done at the time a SemiColon
     916                 :  *                      is processed.  But only if the current definition
     917                 :  *                      under construction is using Locals.
     918                 :  *      
     919                 :  *      Inputs:
     920                 :  *         Parameters:              NONE
     921                 :  *         Local Static Variables:
     922                 :  *             local_names          The vocabulary for new Local names
     923                 :  *
     924                 :  *      Outputs:
     925                 :  *         Returned Value:          NONE
     926                 :  *         Local Static Variables:
     927                 :  *             local_names          Emptied and pointing at NULL.
     928                 :  *             num_ilocals          Reset to zero
     929                 :  *             num_ulocals              ditto
     930                 :  *             localno                  ditto
     931                 :  *         Memory Freed
     932                 :  *             All memory allocations in the "Local Names" Vocabulary.
     933                 :  *
     934                 :  **************************************************************************** */
     935                 : 
     936                 : void forget_locals ( void )
     937             567 : {
     938                 :      /*    Don't do anything if Locals are not in use    */
     939             567 :     if ( localno != 0 )
     940                 :     {
     941              74 :         reset_tic_vocab( &local_names, NULL ) ;
     942                 : 
     943              74 :         num_ilocals = 0;
     944              74 :         num_ulocals = 0;
     945              74 :         localno = 0;
     946                 :     }
     947             567 : }

Generated by: LTP GCOV extension version 1.5