00001 /* 00002 * OpenBIOS - free your system! 00003 * ( FCode tokenizer ) 00004 * 00005 * This program is part of a free implementation of the IEEE 1275-1994 00006 * Standard for Boot (Initialization Configuration) Firmware. 00007 * 00008 * Copyright (C) 2001-2005 Stefan Reinauer, <stepan@openbios.org> 00009 * 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; version 2 of the License. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA 00022 * 00023 */ 00024 00025 /* ************************************************************************** 00026 * 00027 * General-purpose support functions for 00028 * Threaded Interpretive Code (T. I. C.)-type vocabularies 00029 * 00030 * (C) Copyright 2005 IBM Corporation. All Rights Reserved. 00031 * Module Author: David L. Paktor dlpaktor@us.ibm.com 00032 * 00033 **************************************************************************** */ 00034 00035 /* ************************************************************************** 00036 * 00037 * We are going to implement a strategy that takes better advantage 00038 * of the concept of Threaded Interpretive Code (well, okay, 00039 * it won't really be interpretive ... ) We will use it to 00040 * implement a small (but expandable) subset of FORTH-like 00041 * commands in Tokenizer-Escape mode, as well as a few other 00042 * things, such as conditional-tokenization. 00043 * 00044 * The Threaded Interpretive Code Header data structure is described 00045 * in detail in the accompanying ticvocab.h header-file. 00046 * 00047 * In most cases, the contents of a beginning portion of the vocabulary 00048 * are known at compile-time, and later parts are added by the 00049 * user at run-time. (The linked-list structure is needed to allow 00050 * for that.) We can initialize the known start of the vocabulary 00051 * easily, except for the link-pointers, as an array. 00052 * We can either explicitly state an index for each entry's link-pointer 00053 * to the previous entry (which can become a problem to maintain) or 00054 * have a function to initialize the links dynamically, at run-time. 00055 * I think I will (regretfully, resignedly) choose the latter. 00056 * 00057 * We will define a few general-purpose functions for dealing with 00058 * T. I. C. -type vocabularies. Eventually, it might be a good 00059 * idea to convert all the vocabularies to this structure... 00060 * 00061 **************************************************************************** */ 00062 00063 /* ************************************************************************** 00064 * 00065 * 00066 * Revision History: 00067 * Mon, 19 Dec 2005 by David L. Paktor 00068 * Begin converting most, if not all, of the vocabularies to 00069 * T. I. C. -type structure. 00070 * 00071 **************************************************************************** */ 00072 00073 00074 /* ************************************************************************** 00075 * 00076 * Functions Exported: 00077 * init_tic_vocab Initialize a TIC_HDR -type vocabulary 00078 * add_tic_entry Add an entry to a TIC_HDR -type vocabulary 00079 * lookup_tic_entry Look for a name in a TIC_HDR -type vocabulary 00080 * handle_tic_vocab Perform a function in a TIC_HDR -type vocab 00081 * exists_in_tic_vocab Confirm whether a given name exists in a 00082 * TIC_HDR -type vocabulary 00083 * create_tic_alias Duplicate the behavior of one name with 00084 * another name. Return a "success" flag. 00085 * reset_tic_vocab Reset a given TIC_HDR -type vocabulary to 00086 * its "Built-In" position. 00087 * 00088 **************************************************************************** */ 00089 00090 00091 /* ************************************************************************** 00092 * 00093 * Global Variables Exported 00094 * tic_found The entry, in a TIC_HDR -type vocabulary, 00095 * that has just been found and is being 00096 * "handled". Needed for protection against 00097 * recursion in a User-defined Macro (which 00098 * should occur only rarely). 00099 * 00100 **************************************************************************** */ 00101 00102 00103 #include <stdlib.h> 00104 #include <string.h> 00105 #include "ticvocab.h" 00106 #include "errhandler.h" 00107 00108 tic_hdr_t *tic_found; 00109 00110 /* ************************************************************************** 00111 * 00112 * Function name: init_tic_vocab 00113 * Synopsis: Dynamically initialize the link-pointers 00114 * of the.given TIC_HDR -type vocabulary 00115 * 00116 * Inputs: 00117 * Parameters: 00118 * tic_vocab_tbl Pointer to the initial TIC_HDR vocab array 00119 * max_indx Maximum Index of the initial array. 00120 * tic_vocab_ptr Pointer to the vocab "tail" 00121 * 00122 * Outputs: 00123 * Returned Value: None 00124 * Global Variables: 00125 * The link-fields of the initial TIC_HDR vocab array entries 00126 * will be filled in. 00127 * Supplied Pointers: 00128 * *tic_vocab_ptr Points to the last element in the array 00129 * 00130 * Process Explanation: 00131 * The value that tic_vocab_ptr has upon entry to the routine 00132 * (which may point to the end of another array which is to 00133 * precede this one in the voacbulary) gets entered into 00134 * the link-pointer field of the first element of the array. 00135 * For this reason, it is important that all TIC_HDR vocabulary 00136 * pointers that will be pased to this routine have their 00137 * initial values explicitly declared NULL. 00138 * 00139 **************************************************************************** */ 00140 00141 void init_tic_vocab( tic_hdr_t *tic_vocab_tbl, 00142 int max_indx, 00143 tic_hdr_t **tic_vocab_ptr) 00144 { 00145 int indx; 00146 for ( indx = 0 ; indx < max_indx ; indx++ ) 00147 { 00148 tic_vocab_tbl[indx].next = *tic_vocab_ptr; 00149 *tic_vocab_ptr = &tic_vocab_tbl[indx]; 00150 } 00151 } 00152 00153 00154 /* ************************************************************************** 00155 * 00156 * Function name: add_tic_entry 00157 * Synopsis: Add an entry to the given TIC_HDR -type vocabulary 00158 * 00159 * Inputs: 00160 * Parameters: 00161 * tname Pointer to space containing the name of the entry 00162 * tfunct Pointer to the routine the new entry will call 00163 * tparam The "parameter field" value (may be a pointer) 00164 * fw_defr FWord Token of the entry's Definer 00165 * pfldsiz Size of "param field" (if a pointer to alloc'd mem) 00166 * ign_fnc Pointer to "ignoring" routine for new entry 00167 * tic_vocab Pointer to ptr to "tail" of T.I.C.-type vocab-list 00168 * 00169 * Outputs: 00170 * Returned Value: NONE 00171 * Supplied Pointers: 00172 * *tic_vocab Will point to new entry 00173 * Memory Allocated: 00174 * For the new entry. 00175 * When Freed? 00176 * When reset_tic_vocab() is applied to the same vocab-list. 00177 * 00178 * Error Detection: 00179 * Failure to allocate memory is a Fatal Error. 00180 * 00181 * Process Explanation: 00182 * The name pointer is presumed to already point to a stable, 00183 * newly-allocated memory-space. If the parameter field is 00184 * actually a pointer, it, too, is presumed to already have 00185 * been allocated. 00186 * Memory will be allocated for the entry itself; its pointers 00187 * will be entered and the given pointer-to-the-tail-of-the- 00188 * -vocabulary will be updated to point to the new entry. 00189 * 00190 **************************************************************************** */ 00191 00192 void add_tic_entry( char *tname, 00193 void (*tfunct)(), 00194 TIC_P_DEFLT_TYPE tparam, 00195 fwtoken fw_defr, 00196 int pfldsiz, 00197 void (*ign_fnc)(), 00198 tic_hdr_t **tic_vocab ) 00199 { 00200 tic_hdr_t *new_entry; 00201 00202 new_entry = safe_malloc(sizeof(tic_hdr_t), "adding tic_entry"); 00203 new_entry->name = tname; 00204 new_entry->next = *tic_vocab; 00205 new_entry->funct = tfunct; 00206 new_entry->pfield.deflt_elem = tparam; 00207 new_entry->fword_defr = fw_defr; 00208 new_entry->ign_func = ign_fnc; 00209 new_entry->pfld_size = pfldsiz; 00210 00211 *tic_vocab = new_entry; 00212 00213 } 00214 00215 /* ************************************************************************** 00216 * 00217 * Function name: lookup_tic_entry 00218 * Synopsis: Look for a name in the given TIC_HDR -type vocabulary 00219 * 00220 * Inputs: 00221 * Parameters: 00222 * tname The "target" name for which to look 00223 * tic_vocab Pointer to the T. I. C. -type vocabulary 00224 * 00225 * Outputs: 00226 * Returned Value: Pointer to the relevant entry, or 00227 * NULL if name not found. 00228 * 00229 * Extraneous Remarks: 00230 * We don't set the global tic_found here because this routine 00231 * is not always called when the found function is going to 00232 * be executed; sometimes it is called for error-detection, 00233 * for instance... 00234 * 00235 **************************************************************************** */ 00236 00237 tic_hdr_t *lookup_tic_entry( char *tname, tic_hdr_t *tic_vocab ) 00238 { 00239 tic_hdr_t *curr ; 00240 00241 for (curr = tic_vocab ; curr != NULL ; curr=curr->next) 00242 { 00243 if ( strcasecmp(tname, curr->name) == 0 ) 00244 { 00245 break; 00246 } 00247 } 00248 00249 return ( curr ) ; 00250 } 00251 00252 /* ************************************************************************** 00253 * 00254 * Function name: exists_in_tic_vocab 00255 * Synopsis: Confirm whether the given name exists in the 00256 * given TIC_HDR -type vocabulary 00257 * 00258 * Inputs: 00259 * Parameters: 00260 * tname The name for which to look 00261 * tic_vocab Pointer to the T. I. C. -type vocabulary 00262 * 00263 * Outputs: 00264 * Returned Value: TRUE if name is found, 00265 * 00266 **************************************************************************** */ 00267 00268 bool exists_in_tic_vocab( char *tname, tic_hdr_t *tic_vocab ) 00269 { 00270 tic_hdr_t *found ; 00271 bool retval = FALSE; 00272 00273 found = lookup_tic_entry( tname, tic_vocab ); 00274 if ( found != NULL ) 00275 { 00276 retval = TRUE; 00277 } 00278 00279 return ( retval ); 00280 } 00281 00282 00283 /* ************************************************************************** 00284 * 00285 * Function name: create_tic_alias 00286 * Synopsis: Create an Alias in a TIC_HDR -type vocabulary 00287 * Return a "success" flag. 00288 * 00289 * Associated FORTH word: ALIAS 00290 * 00291 * Inputs: 00292 * Parameters: 00293 * old_name Name of existing entry 00294 * new_name New name for which to create an entry 00295 * *tic_vocab Pointer to the "tail" of the 00296 * T. I. C. -type vocab-list 00297 * 00298 * Outputs: 00299 * Returned Value: TRUE if old_name found in given vocab 00300 * Supplied Pointers: 00301 * *tic_vocab Will be updated to point to the new entry 00302 * Memory Allocated: 00303 * For the new entry, by the support routine. 00304 * When Freed? 00305 * When reset_tic_vocab() is applied to the same vocab-list. 00306 * 00307 * Process Explanation: 00308 * Both the "old" and "new" names are presumed to already point to 00309 * stable, freshly allocated memory-spaces. 00310 * Even if the "old" entry's pfld_size is not zero, meaning its 00311 * param-field is a pointer to allocated memory, we still do 00312 * not need to copy it into a freshly allocated memory-space, 00313 * as long as we make the new alias-entry's pfld_size zero: 00314 * the reference to the old space will work, and the old 00315 * entry's param-field memory space will not be freed with 00316 * the alias-entry but only with the "old" entry. 00317 * 00318 **************************************************************************** */ 00319 00320 bool create_tic_alias( char *new_name, char *old_name, tic_hdr_t **tic_vocab ) 00321 { 00322 tic_hdr_t *found ; 00323 bool retval = FALSE; 00324 00325 found = lookup_tic_entry( old_name, *tic_vocab ); 00326 if ( found != NULL ) 00327 { 00328 add_tic_entry( new_name, found->funct, 00329 found->pfield.deflt_elem, 00330 found->fword_defr, 00331 0, found->ign_func, tic_vocab ); 00332 retval = TRUE; 00333 } 00334 00335 return ( retval ); 00336 } 00337 00338 00339 /* ************************************************************************** 00340 * 00341 * Function name: handle_tic_vocab 00342 * Synopsis: Perform the function associated with the given name 00343 * in the given TIC_HDR -type vocabulary 00344 * 00345 * Inputs: 00346 * Parameters: 00347 * tname The "target" name for which to look 00348 * tic_vocab Pointer to the T. I. C. -type vocabulary 00349 * 00350 * Outputs: 00351 * Returned Value: TRUE if the given name is valid in the given vocab 00352 * Global Variables: 00353 * tic_found Points to the TIC entry of the "target" 00354 * name, if it was found; else, NULL. 00355 * Global Behavior: 00356 * Whatever the associated function does... 00357 * 00358 * Process Explanation: 00359 * Find the name and execute its associated function. 00360 * If the name is not in the given vocabulary, return 00361 * an indication; leave it to the calling routine 00362 * to decide how to proceed. 00363 * 00364 **************************************************************************** */ 00365 00366 bool handle_tic_vocab( char *tname, tic_hdr_t *tic_vocab ) 00367 { 00368 bool retval = FALSE; 00369 00370 tic_found = lookup_tic_entry( tname, tic_vocab ); 00371 if ( tic_found != NULL ) 00372 { 00373 tic_found->funct( tic_found->pfield); 00374 retval = TRUE; 00375 } 00376 00377 return ( retval ) ; 00378 } 00379 00380 /* ************************************************************************** 00381 * 00382 * Function name: reset_tic_vocab 00383 * Synopsis: Reset a given TIC_HDR -type vocabulary to 00384 * its given "Built-In" position. 00385 * 00386 * Inputs: 00387 * Parameters: 00388 * *tic_vocab Pointer to the T. I. C.-type vocab-list 00389 * reset_position Position to which to reset the list 00390 * 00391 * Outputs: 00392 * Returned Value: NONE 00393 * Supplied Pointers: 00394 * *tic_vocab Reset to given "Built-In" position. 00395 * Memory Freed 00396 * All memory allocated by user-definitions will be freed 00397 * 00398 * Process Explanation: 00399 * The "stable memory-spaces" to which the name and parameter 00400 * field pointers point are presumed to have been acquired 00401 * by allocation of memory, which is reasonable for entries 00402 * created by the user as opposed to the built-in entries, 00403 * which we are, in any case, not releasing. 00404 * The parameter-field size field tells us whether we need to 00405 * free() the parameter-field pointer. 00406 * 00407 **************************************************************************** */ 00408 00409 void reset_tic_vocab( tic_hdr_t **tic_vocab, tic_hdr_t *reset_position ) 00410 { 00411 tic_hdr_t *next_t; 00412 00413 next_t = *tic_vocab; 00414 while ( next_t != reset_position ) 00415 { 00416 next_t = (*tic_vocab)->next ; 00417 00418 free( (*tic_vocab)->name ); 00419 if ( (*tic_vocab)->pfld_size != 0 ) 00420 { 00421 free( (*tic_vocab)->pfield.chr_ptr ); 00422 } 00423 free( *tic_vocab ); 00424 *tic_vocab = next_t ; 00425 } 00426 }