Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * 17-Jun-91 - Original Version 00042 * 00043 * Description: 00044 * 00045 * Utilities for processing the input command line options. 00046 * 00047 * ==================================================================== 00048 * ==================================================================== 00049 */ 00050 00051 #ifdef _KEEP_RCS_ID 00052 static const char source_file[] = __FILE__; 00053 #endif 00054 00055 #include <string.h> 00056 #include "defs.h" 00057 #include "flags.h" 00058 #include "erglob.h" 00059 #include "tracing.h" /* Is_Trace */ 00060 #include "config.h" /* Opt_Level */ 00061 00062 extern char *SBar; /* Line of dashes from tracing.h */ 00063 00064 /* ==================================================================== 00065 * 00066 * Get_Numeric_Flag 00067 * 00068 * Read a numeric flag from the flag word passed via *cp. Compare it 00069 * to the given bounds. If it is out of bounds, generate a warning and 00070 * set it to the given default. If no numeric digits are present, use 00071 * the given default. Update *cp to point past the numeric value. 00072 * 00073 * ==================================================================== 00074 */ 00075 00076 INT64 00077 Get_Numeric_Flag ( 00078 char **cp, /* Pointer to the flag pointer */ 00079 INT64 min, /* Bounds and default for flag */ 00080 INT64 max, 00081 INT64 def, 00082 char *flag /* Pointer to containing flag word */ 00083 ) 00084 { 00085 INT64 val = 0; 00086 INT64 radix = 10; 00087 char c; 00088 BOOL done = FALSE; 00089 BOOL negate = FALSE; 00090 00091 /* First check for a number: */ 00092 c = **cp; 00093 if (c == '-') { 00094 c = *++(*cp); 00095 negate = TRUE; 00096 } 00097 if ( c < '0' || c > '9' ) return def; 00098 00099 /* Next get the radix: */ 00100 if ( c == '0' ) { 00101 c = *++(*cp); 00102 if ( c == 'x' || c == 'X' ) { 00103 c = *++(*cp); 00104 radix = 16; 00105 } else radix = 8; 00106 } 00107 00108 /* Finally get the number: */ 00109 while ( ! done ) { 00110 switch ( c ) { 00111 case '8': 00112 case '9': if ( radix == 8 ) { 00113 ErrMsg ( EC_Flag_Digit, c, flag ); 00114 return def; 00115 } 00116 /* no break */ 00117 case '0': 00118 case '1': 00119 case '2': 00120 case '3': 00121 case '4': 00122 case '5': 00123 case '6': 00124 case '7': val = val*radix + (c-'0'); 00125 break; 00126 case 'a': 00127 case 'b': 00128 case 'c': 00129 case 'd': 00130 case 'e': 00131 case 'f': if ( radix != 16 ) done = TRUE; 00132 else val = val*radix + 10 + (c-'a'); 00133 break; 00134 case 'A': 00135 case 'B': 00136 case 'C': 00137 case 'D': 00138 case 'E': 00139 case 'F': if ( radix != 16 ) done = TRUE; 00140 else val = val*radix + 10 + (c-'A'); 00141 break; 00142 default: done = TRUE; 00143 break; 00144 } 00145 if ( ! done ) c = *++(*cp); 00146 } 00147 00148 if (negate) val = -val; 00149 00150 /* Check value against bounds: */ 00151 if ( val >= min && val <= max ) return val; 00152 ErrMsg ( EC_Flag_Range, val, min, max, flag ); 00153 return def; 00154 } 00155 00156 /* ==================================================================== 00157 * 00158 * Atoi_KMG 00159 * 00160 * Return TRUE if string s contains a valid numerical representation, 00161 * with suffix 'k' or 'K' meaning kilo, 'm' or 'M' meaning mega, and 00162 * 'g' or 'G' meaning giga (e.g. bytes). If suffix_required is true, 00163 * the string must end in k,K,m,M or g,G -- otherwise it's optional 00164 * (but value 0 is always legal). 00165 * 00166 * Returns the interpreted value of the string in val, and a BOOL 00167 * result indicating whether a valid value was found. 00168 * 00169 * ==================================================================== 00170 */ 00171 00172 BOOL 00173 Atoi_KMG ( const char* s, INT64* val, BOOL suffix_required ) 00174 { 00175 BOOL seen_digit = FALSE; 00176 INT64 v = 0; 00177 00178 for (;;) { 00179 char c; 00180 switch (c = *s++) { 00181 case 'k': 00182 case 'K': 00183 *val = v * 1024; 00184 return seen_digit; 00185 case 'm': 00186 case 'M': 00187 *val = v * (1024 * 1024); 00188 return seen_digit; 00189 case 'g': 00190 case 'G': 00191 *val = v * (1024 * 1024 * 1024); 00192 return seen_digit; 00193 default: 00194 if (c >= '0' && c <= '9') { 00195 v = v*10 + c - '0'; 00196 seen_digit = TRUE; 00197 } else { 00198 *val = v; 00199 return seen_digit && (!suffix_required || v == 0); 00200 } 00201 } 00202 } 00203 } 00204 00205 /* ==================================================================== 00206 * 00207 * Option descriptor and group descriptor auxiliary information 00208 * 00209 * The descriptors used in client code to identify group options are 00210 * augmented here internally to allow general-purpose printing for 00211 * trace or listing purposes. 00212 * 00213 * ==================================================================== 00214 */ 00215 00216 /* Upon initialization, we augment the option descriptor with a 00217 * collection of status information. A pointer to this structure, once 00218 * created, replaces the user's "specified" pointer in the original 00219 * structure, which moves to the auxiliary struct. 00220 */ 00221 #define ODESC_orig_specified(o) ((o)->aux) 00222 #define ODESC_aux(o) ((ODESC_AUX *)((o)->aux)) 00223 #define Set_ODESC_aux(o,a) (((o)->aux)=(ODESC_AUX *)(a)) 00224 00225 typedef union optval { 00226 UINT64 i; 00227 void *p; 00228 } OPTVAL; 00229 00230 typedef struct odesc_aux { 00231 INT16 flags; /* Various status flags */ 00232 BOOL *specified; /* The option has been specified (user's) */ 00233 OPTION_DESC *primary; /* Primary option for ODK_LIST option */ 00234 OPTVAL orig; /* Original value */ 00235 OPTVAL last; /* Last value */ 00236 } ODESC_AUX; 00237 00238 #define ODF_SET_USER 0x01 /* Set since a user print */ 00239 #define ODF_SET_INT 0x02 /* Set since a internal print */ 00240 #define ODF_SET 0x03 /* Set (for setting only) */ 00241 #define ODF_MOD_USER 0x04 /* Modified since a user print */ 00242 #define ODF_MOD_INT 0x08 /* Modified since a internal print */ 00243 #define ODF_MOD 0x0c /* Modified (for setting only) */ 00244 #define ODF_PRINT 0x10 /* Print (because set/modified) */ 00245 #define ODF_PRINTED 0x20 /* Printed (for ODK_LIST options) */ 00246 00247 #define ODA_flags(o) ((o)->flags) 00248 #define ODA_specified(o) ((o)->specified) 00249 #define ODESC_specified(o) ODA_specified(ODESC_aux(o)) 00250 #define ODA_primary(o) ((o)->primary) 00251 #define ODESC_primary(o) ODA_primary(ODESC_aux(o)) 00252 #define ODA_orig(o) ((o)->orig) 00253 #define ODA_orig_i(o) ((o)->orig.i) 00254 #define ODA_orig_p(o) ((o)->orig.p) 00255 #define ODA_last(o) ((o)->last) 00256 #define ODA_last_i(o) ((o)->last.i) 00257 #define ODA_last_p(o) ((o)->last.p) 00258 #define ODA_set_user(o) (ODA_flags(o) & ODF_SET_USER) 00259 #define Set_ODA_set_user(o) (ODA_flags(o) |= ODF_SET_USER) 00260 #define Reset_ODA_set_user(o) (ODA_flags(o) &= ~ODF_SET_USER) 00261 #define ODA_set_int(o) (ODA_flags(o) & ODF_SET_INT) 00262 #define Set_ODA_set_int(o) (ODA_flags(o) |= ODF_SET_INT) 00263 #define Reset_ODA_set_int(o) (ODA_flags(o) &= ~ODF_SET_INT) 00264 #define Set_ODA_set(o) (ODA_flags(o) |= ODF_SET) 00265 #define ODA_mod_user(o) (ODA_flags(o) & ODF_MOD_USER) 00266 #define Set_ODA_mod_user(o) (ODA_flags(o) |= ODF_MOD_USER) 00267 #define Reset_ODA_mod_user(o) (ODA_flags(o) &= ~ODF_MOD_USER) 00268 #define ODA_mod_int(o) (ODA_flags(o) & ODF_MOD_INT) 00269 #define Set_ODA_mod_int(o) (ODA_flags(o) |= ODF_MOD_INT) 00270 #define Reset_ODA_mod_int(o) (ODA_flags(o) &= ~ODF_MOD_INT) 00271 #define Set_ODA_mod(o) (ODA_flags(o) |= ODF_MOD) 00272 #define ODA_print(o) (ODA_flags(o) & ODF_PRINT) 00273 #define Set_ODA_print(o) (ODA_flags(o) |= ODF_PRINT) 00274 #define Reset_ODA_print(o) (ODA_flags(o) &= ~ODF_PRINT) 00275 #define ODA_printed(o) (ODA_flags(o) & ODF_PRINTED) 00276 #define Set_ODA_printed(o) (ODA_flags(o) |= ODF_PRINTED) 00277 #define Reset_ODA_printed(o) (ODA_flags(o) &= ~ODF_PRINTED) 00278 00279 /* Similarly, we augment the group descriptor with some auxiliary 00280 * information, including the ODESC auxiliary array: 00281 */ 00282 #define OGROUP_aux(o) ((OGROUP_AUX *)((o)->aux)) 00283 #define Set_OGROUP_aux(o,a) (((o)->aux)=(OGROUP_AUX *)(a)) 00284 00285 typedef struct ogroup_aux { 00286 mINT16 flags; /* Status flags */ 00287 mINT16 count; /* Number of options */ 00288 ODESC_AUX *odesc_aux; /* Auxiliary option descriptor array */ 00289 } OGROUP_AUX; 00290 00291 #define OGF_SET 0x01 /* Something has been set */ 00292 #define OGF_INTERNAL 0x02 /* Entire group is internal */ 00293 00294 #define OGA_flags(o) ((o)->flags) 00295 #define OGA_count(o) ((o)->count) 00296 #define OGA_odesc_aux(o) ((o)->odesc_aux) 00297 #define OGA_set(o) (OGA_flags(o) & OGF_SET) 00298 #define Set_OGA_set(o) (OGA_flags(o) |= OGF_SET) 00299 #define Reset_OGA_set(o) (OGA_flags(o) &= ~OGF_SET) 00300 #define OGA_internal(o) (OGA_flags(o) & OGF_INTERNAL) 00301 #define Set_OGA_internal(o) (OGA_flags(o) |= OGF_INTERNAL) 00302 #define Reset_OGA_internal(o) (OGA_flags(o) &= ~OGF_INTERNAL) 00303 00304 00305 /* ==================================================================== 00306 * Copy_option 00307 * underlying routine to copy odesc's to and from memory 00308 * returns number of bytes copied 00309 * ====================================================================*/ 00310 static INT 00311 Copy_option(OPTION_DESC *odesc, char *container, BOOL save) 00312 { 00313 size_t sz = 0; 00314 void *var = ODESC_variable(odesc); 00315 Is_True(ODESC_can_change_by_pragma(odesc), 00316 ("Copy_option, trying to copy option that cannot change")); 00317 00318 switch (ODESC_kind(odesc)) { 00319 case OVK_NONE: 00320 case OVK_BOOL: 00321 sz = sizeof(BOOL); break; 00322 case OVK_INT32: 00323 sz = sizeof(INT32); break; 00324 case OVK_UINT32: 00325 sz = sizeof(UINT32); break; 00326 case OVK_INT64: 00327 sz = sizeof(INT64); break; 00328 case OVK_UINT64: 00329 sz = sizeof(UINT64); break; 00330 case OVK_NAME: 00331 case OVK_SELF: 00332 sz = sizeof(char *); break; 00333 case OVK_LIST: 00334 sz = sizeof(OPTION_LIST *); break; 00335 default: /* INVALID, OBSOLETE, REPLACED, UNIMPLEMENTED */ 00336 sz = 0; break; 00337 } 00338 00339 if (save) { 00340 memcpy((void*)container, var, sz); // container <= var 00341 } else { /* restore */ 00342 memcpy(var, (void*)container, sz); // var <= container 00343 } 00344 00345 return (INT)sz; 00346 } 00347 00348 00349 /* ==================================================================== 00350 * 00351 * Duplicate_Value 00352 * 00353 * Given an option descriptor, duplicate the current value of the 00354 * associated user variable into the given container. The container 00355 * passed must be 64 bits in size. Pointers are simply replicated 00356 * (i.e. not their pointees), and are stored in the initial part of the 00357 * container. Values smaller than 64 bits are converted to 64 bits for 00358 * storage in the container. 00359 * 00360 * NOTE: this routine is different from Copy_option in that it puts 00361 * the values in the OPTVAL container and so sign extends. 00362 * ====================================================================*/ 00363 static void 00364 Duplicate_Value ( OPTION_DESC *odesc, OPTVAL *container ) 00365 { 00366 void *var = ODESC_variable(odesc); 00367 00368 switch ( ODESC_kind(odesc) ) { 00369 case OVK_NONE: 00370 case OVK_BOOL: 00371 container->i = *((BOOL *)var); 00372 break; 00373 case OVK_INT32: 00374 container->i = *((INT32 *)var); 00375 break; 00376 case OVK_UINT32: 00377 container->i = *((UINT32 *)var); 00378 break; 00379 case OVK_INT64: 00380 container->i = *((INT64 *)var); 00381 break; 00382 case OVK_UINT64: 00383 container->i = *((UINT64 *)var); 00384 break; 00385 case OVK_NAME: 00386 case OVK_SELF: 00387 container->p = *((char **)var); 00388 break; 00389 case OVK_LIST: 00390 container->p = *((OPTION_LIST **)var); 00391 break; 00392 default: 00393 break; 00394 } 00395 } 00396 00397 00398 /* ==================================================================== 00399 * 00400 * Initialize_Option_Group 00401 * 00402 * Given an option group descriptor, initialize all the auxiliary 00403 * information associated with it and its option descriptors. 00404 * 00405 * This routine should be called after any of the component options are 00406 * initialized (which is normally static and therefore not an issue), 00407 * and before we start reading options to make sure that the defaults 00408 * that we collect are valid. However, we simply call it upon any 00409 * check of the group to make sure that everything works with existing 00410 * code. 00411 * 00412 * ==================================================================== 00413 */ 00414 00415 static void 00416 Initialize_Option_Group ( OPTION_GROUP *ogroup ) 00417 { 00418 OGROUP_AUX *ogaux; 00419 INT16 count, i; 00420 OPTION_DESC *odesc; 00421 ODESC_AUX *odaux; 00422 00423 /* If we've already done it, never mind: */ 00424 if ( OGROUP_aux(ogroup) != NULL ) return; 00425 00426 /* Count the descriptors in the group, including terminator: */ 00427 count = 1; 00428 for ( odesc = OGROUP_options(ogroup); 00429 ODESC_kind(odesc) != OVK_COUNT 00430 && ODESC_kind(odesc) != OVK_OLD_COUNT; 00431 ++odesc ) 00432 { 00433 ++count; 00434 } 00435 00436 /* Allocate the auxiliary descriptors: */ 00437 ogaux = (OGROUP_AUX *) calloc ( 1, sizeof (OGROUP_AUX) ); 00438 if ( ogaux == NULL ) { 00439 ErrMsg ( EC_No_Mem, "Initialize_Option_Group: OGROUP_aux" ); 00440 } 00441 Set_OGROUP_aux ( ogroup, ogaux ); 00442 odaux = (ODESC_AUX *) calloc ( count, sizeof (ODESC_AUX) ); 00443 if ( odaux == NULL ) { 00444 ErrMsg ( EC_No_Mem, "Initialize_Option_Group: ODESC_aux" ); 00445 } 00446 OGA_odesc_aux(ogaux) = odaux; 00447 OGA_count(ogaux) = count-1; /* Not including terminator */ 00448 00449 /* Initialize the auxiliary option descriptors: */ 00450 for ( i = 0, odesc = OGROUP_options(ogroup); 00451 i < count; 00452 ++i, ++odesc, ++odaux ) 00453 { 00454 ODA_specified(odaux) = ODESC_orig_specified(odesc); 00455 Set_ODESC_aux ( odesc, odaux ); 00456 Duplicate_Value ( odesc, &ODA_orig(odaux) ); 00457 ODA_last(odaux) = ODA_orig(odaux); 00458 } 00459 00460 /* Special initialization for OVK_LIST options. Several such options 00461 * may use the same variable. So we make the ODA_primary field of 00462 * the first one's aux descriptor point to its ODESC, and then we 00463 * use the same aux descriptor for all the others. Exception: if 00464 * the secondary has a different override variable than the primary, 00465 * they can't share since that moves to the auxiliary descriptor. 00466 * 00467 * Do the same for OVK_NAME and OVK_SELF options, taking care of 00468 * situations like -TARG:isa=mips3 and -TARG:mips3 using the same 00469 * variable. 00470 */ 00471 for ( odesc = OGROUP_options(ogroup); 00472 ODESC_kind(odesc) != OVK_COUNT 00473 && ODESC_kind(odesc) != OVK_OLD_COUNT; 00474 ++odesc ) 00475 { 00476 if ( ODA_primary ( ODESC_aux(odesc) ) == NULL 00477 && ( ODESC_kind(odesc) == OVK_LIST 00478 || ODESC_kind(odesc) == OVK_NAME 00479 || ODESC_kind(odesc) == OVK_SELF ) ) 00480 { 00481 OPTION_DESC *sdesc; 00482 00483 ODA_primary ( ODESC_aux(odesc) ) = odesc; 00484 for ( sdesc = odesc+1; 00485 ODESC_kind(sdesc) != OVK_COUNT 00486 && ODESC_kind(sdesc) != OVK_OLD_COUNT; 00487 ++sdesc ) 00488 { 00489 if ( ODESC_variable(sdesc) == ODESC_variable(odesc) 00490 && ODESC_specified(sdesc) == ODESC_specified(odesc) ) 00491 { 00492 Set_ODESC_aux ( sdesc, ODESC_aux(odesc) ); 00493 } 00494 } 00495 } 00496 } 00497 } 00498 00499 /* ==================================================================== 00500 * 00501 * Set_Option_Internal 00502 * 00503 * Set the given option in the given group internal, meaning that it 00504 * won't appear on user listings. If the option name is NULL, the 00505 * entire group is set internal. 00506 * 00507 * ==================================================================== 00508 */ 00509 00510 void 00511 Set_Option_Internal ( OPTION_GROUP *ogroup, char *name ) 00512 { 00513 if ( name == NULL ) { 00514 Set_OGA_internal ( OGROUP_aux (ogroup) ); 00515 return; 00516 } else { 00517 OPTION_DESC *o; 00518 00519 for ( o = OGROUP_options(ogroup); 00520 ODESC_kind(o) != OVK_COUNT 00521 && ODESC_kind(o) != OVK_OLD_COUNT; 00522 ++o ) 00523 { 00524 if ( strcasecmp ( name, ODESC_name(o) ) == 0 ) { 00525 ODESC_visibility(o) = OV_INTERNAL; 00526 } 00527 } 00528 } 00529 } 00530 00531 /* ==================================================================== 00532 * 00533 * Initialize_Option_Groups 00534 * 00535 * Given an option group descriptor array, initialize all the auxiliary 00536 * information associated with the groups in the array. 00537 * 00538 * This routine should be called after any of the component options are 00539 * initialized (which is normally static and therefore not an issue), 00540 * and before we start reading options to make sure that the defaults 00541 * that we collect are valid. However, we simply call it upon any 00542 * check of the group to make sure that everything works with existing 00543 * code. 00544 * 00545 * ==================================================================== 00546 */ 00547 00548 void 00549 Initialize_Option_Groups ( OPTION_GROUP *ogroups ) 00550 { 00551 OPTION_GROUP *group; 00552 00553 for (group = ogroups; group && OGROUP_options(group); group++) { 00554 Initialize_Option_Group ( group ); 00555 00556 /* We may terminate with an null name list of dummy options: */ 00557 if ( OGROUP_name(group) == NULL ) break; 00558 } 00559 } 00560 00561 /* ==================================================================== 00562 * 00563 * Update_Scalar_Value 00564 * 00565 * Given an option descriptor for a scalar option type, update the 00566 * current value to that given. First identify whether this is a 00567 * modified value (relative to ODA_last) and if so mark the option 00568 * modified and reset ODA_last. Then mark the option set. Finally, 00569 * replace the option value. 00570 * 00571 * WARNING: The caller is responsible for verifying that the option 00572 * being updated is one of the scalar kinds. 00573 * 00574 * ==================================================================== 00575 */ 00576 00577 static void 00578 Update_Scalar_Value ( OPTION_DESC *odesc, UINT64 val ) 00579 { 00580 void *var = ODESC_variable(odesc); 00581 ODESC_AUX *aux = ODESC_aux(odesc); 00582 00583 if ( val != ODA_last_i(aux) ) { 00584 Set_ODA_mod(aux); 00585 ODA_last_i(aux) = val; 00586 } 00587 Set_ODA_set(aux); 00588 00589 switch ( ODESC_kind(odesc) ) { 00590 case OVK_NONE: 00591 case OVK_BOOL: 00592 *((BOOL *)var) = (BOOL)val; 00593 break; 00594 case OVK_INT32: 00595 *((INT32 *)var) = (INT32)val; 00596 break; 00597 case OVK_UINT32: 00598 *((UINT32 *)var) = (UINT32)val; 00599 break; 00600 case OVK_INT64: 00601 *((INT64 *)var) = (UINT64)val; 00602 break; 00603 case OVK_UINT64: 00604 *((UINT64 *)var) = (UINT64)val; 00605 break; 00606 default: 00607 break; 00608 } 00609 } 00610 00611 /* ==================================================================== 00612 * 00613 * Update_Pointer_Value 00614 * 00615 * Given an option descriptor for a pointer option type, update the 00616 * current value to that given. First identify whether this is a 00617 * modified value (relative to ODA_last) and if so mark the option 00618 * modified and reset ODA_last. Then mark the option set. Finally, 00619 * replace the option value. 00620 * 00621 * WARNING: The caller is responsible for verifying that the option 00622 * being updated is one of the pointer kinds. 00623 * 00624 * ==================================================================== 00625 */ 00626 00627 static void 00628 Update_Pointer_Value ( OPTION_DESC *odesc, void *val ) 00629 { 00630 void **var = (void **)ODESC_variable(odesc); 00631 ODESC_AUX *aux = ODESC_aux(odesc); 00632 00633 if ( val != ODA_last_p(aux) ) { 00634 Set_ODA_mod(aux); 00635 ODA_last_p(aux) = val; 00636 } 00637 Set_ODA_set(aux); 00638 *var = val; 00639 } 00640 00641 /* ==================================================================== 00642 * 00643 * Process_Command_Line_Group 00644 * 00645 * See header file flags.h for description. 00646 * 00647 * ==================================================================== 00648 */ 00649 00650 BOOL 00651 Process_Command_Line_Group (char *flag, OPTION_GROUP *opt_groups) 00652 { 00653 OPTION_GROUP *group; 00654 char *option, *copy, *cp, *next_cp; 00655 size_t tidx; 00656 char sep[3]; 00657 BOOL hasval; 00658 char *val = NULL; 00659 BOOL bval; 00660 INT64 ival; 00661 OPTION_DESC *odesc, *found, *first_found; 00662 OPTION_LIST *olist, *ol; 00663 00664 /* Just in case: */ 00665 Initialize_Option_Groups ( opt_groups ); 00666 00667 /* See whether flag names an option group */ 00668 option = NULL; 00669 for (group = opt_groups; group && OGROUP_name(group); group++) { 00670 register INT group_name_len; 00671 00672 if (flag[0] != *OGROUP_name(group)) 00673 continue; 00674 00675 group_name_len = strlen(OGROUP_name(group)); 00676 00677 if (strncmp(flag, OGROUP_name(group), group_name_len) == 0 && 00678 flag[group_name_len] == OGROUP_separator(group)) { 00679 /* We have a match. Point to first option char 00680 * and quit searching. 00681 */ 00682 option = flag + group_name_len + 1; 00683 break; 00684 } 00685 } 00686 00687 /* Return failure indication if flag doesn't name an option group */ 00688 if (option == NULL) 00689 return FALSE; 00690 00691 cp = copy = strdup ( option ); /* Make a permanent, modifiable copy */ 00692 next_cp = cp; 00693 00694 /* Set up a separator string: */ 00695 sep[0] = OGROUP_valmarker(group); 00696 sep[1] = OGROUP_separator(group); 00697 sep[2] = 0; 00698 00699 #ifdef Is_True_On 00700 /* Configuration check: make sure each non-NULL abbreviation is 00701 * actual prefix of option name. Otherwise, we'll never match. 00702 */ 00703 for ( odesc=OGROUP_options(group); 00704 ODESC_kind(odesc) != OVK_COUNT 00705 && ODESC_kind(odesc) != OVK_OLD_COUNT; 00706 odesc++) 00707 { 00708 char *abbrev = ODESC_abbrev(odesc); 00709 char *name = ODESC_name(odesc); 00710 Is_True ( abbrev == NULL 00711 || strncmp(abbrev, name, strlen(abbrev)) == 0, 00712 ( "Option group (%s) configuration error: " 00713 "'%s' not prefix of '%s'", 00714 OGROUP_name(group), abbrev, name ) ); 00715 } 00716 #endif 00717 00718 while ( next_cp != NULL ) { 00719 char this_flag[256]; 00720 00721 cp = next_cp; 00722 00723 /* Find end of name: */ 00724 tidx = strcspn ( cp, sep ); 00725 next_cp = ( cp[tidx] == 0 ) ? NULL : cp+tidx+1; 00726 00727 /* If it's a value, extract it: */ 00728 hasval = ( cp[tidx] == OGROUP_valmarker(group) ); 00729 cp[tidx] = 0; 00730 if ( hasval ) { 00731 val = next_cp; 00732 /* Don't consider valmarker this time: */ 00733 tidx = strcspn ( val, &sep[1] ); 00734 next_cp = ( val[tidx] == 0 ) ? NULL : val+tidx+1; 00735 val[tidx] = 0; 00736 } 00737 00738 /* Construct string containing only the current flag, 00739 * with group name for context. This lets us emit 00740 * clearer error messages. 00741 */ 00742 sprintf(this_flag, "%.50s%c%.100s", OGROUP_name(group), 00743 OGROUP_separator(group), cp); 00744 if (hasval) 00745 sprintf(this_flag+strlen(this_flag), "%c%.100s", 00746 OGROUP_valmarker(group), val); 00747 00748 /* Find the option descriptor: */ 00749 first_found = found = NULL; 00750 for ( odesc = OGROUP_options(group); 00751 !found 00752 && ODESC_kind(odesc) != OVK_COUNT 00753 && ODESC_kind(odesc) != OVK_OLD_COUNT; 00754 odesc++ ) 00755 { 00756 /* Matching rules. If abbreviation is: 00757 * (1) NULL - only whole name matches. 00758 * (2) Empty string - any non-ambiguous prefix of name matches. 00759 * (3) Any other prefix of name - anything between abbrev and whole 00760 * name matches. 00761 */ 00762 if (!ODESC_abbrev(odesc)) { 00763 /* Rule (1) */ 00764 if (strcasecmp(cp, ODESC_name(odesc)) == 0) found = odesc; 00765 } else { 00766 INT32 alen = strlen(ODESC_abbrev(odesc)); 00767 INT32 clen = strlen(cp); 00768 if (alen == 0) { 00769 /* 00770 * Rule (2). If matching, start ambiguity check 00771 * by setting first_found, unless we're already 00772 * checking for ambiguity. 00773 */ 00774 if (strncasecmp(cp, ODESC_name(odesc), clen) == 0) { 00775 if (!first_found) first_found = odesc; 00776 else found = odesc; 00777 } 00778 } else { 00779 /* Rule (3) */ 00780 if (strncasecmp(ODESC_abbrev(odesc), cp, alen) == 0 && 00781 strncasecmp(cp, ODESC_name(odesc), clen) == 0) 00782 found = odesc; 00783 } 00784 } 00785 } 00786 00787 /* Finish ambiguity check */ 00788 if (first_found) { 00789 if (found) { 00790 ErrMsg(EC_Ambig_In_Grp, cp, OGROUP_name(group), this_flag); 00791 continue; 00792 } 00793 found = first_found; 00794 } 00795 00796 if ( found == NULL ) { 00797 /* Complain: */ 00798 ErrMsg ( EC_Not_In_Grp, cp, OGROUP_name(group), this_flag ); 00799 } else { 00800 ODESC_AUX *aux = ODESC_aux(found); 00801 00802 /* Set specified flag if given */ 00803 if ( ODA_specified(aux) ) *ODA_specified(aux) = TRUE; 00804 00805 switch ( ODESC_kind(found) ) { 00806 case OVK_NONE: 00807 if ( hasval ) { 00808 ErrMsg (EC_Inv_Grp_Val, cp, OGROUP_name(group), val, 00809 this_flag); 00810 } 00811 Update_Scalar_Value ( found, (UINT64)TRUE ); 00812 break; 00813 00814 case OVK_OBSOLETE: 00815 ErrMsg ( EC_Obsolete_Opt, this_flag ); 00816 break; 00817 00818 case OVK_REPLACED: 00819 ErrMsg ( EC_Replaced_Opt, this_flag, 00820 (char *)ODESC_variable(found) ); 00821 break; 00822 00823 case OVK_UNIMPLEMENTED: 00824 ErrMsg ( EC_Unimp_Opt, this_flag ); 00825 break; 00826 00827 case OVK_BOOL: 00828 if ( hasval ) { 00829 bval = ( strcasecmp ( val, "ON" ) == 0 00830 || strcasecmp ( val, "TRUE" ) == 0 00831 || strcasecmp ( val, "YES" ) == 0 00832 || ( strcasecmp ( val, "OFF" ) != 0 00833 && strcasecmp ( val, "FALSE" ) != 0 00834 && strcasecmp ( val, "NO" ) != 0 00835 && strcmp ( val, "0" ) != 0 ) ); 00836 } else { 00837 bval = TRUE; 00838 } 00839 Update_Scalar_Value ( found, (UINT64)bval ); 00840 break; 00841 00842 case OVK_INT32: 00843 case OVK_INT64: 00844 case OVK_UINT64: 00845 case OVK_UINT32: 00846 if ( ! hasval ) { 00847 ival = ODESC_def_val(found); 00848 } else { 00849 char *tval = val; 00850 if ((*val < '0' || *val > '9') && *val != '-') 00851 ErrMsg(EC_Flag_Int_Expected, this_flag); 00852 ival = Get_Numeric_Flag ( &tval, 00853 ODESC_min_val(found), 00854 ODESC_max_val(found), 00855 ODESC_def_val(found), 00856 this_flag ); 00857 } 00858 Update_Scalar_Value ( found, (UINT64)ival ); 00859 break; 00860 00861 #if 0 00862 case OVK_INT64: 00863 case OVK_UINT64: 00864 if ( ODESC_min_val(found) < INT32_MIN || 00865 ODESC_max_val(found) > INT32_MAX ) 00866 { 00867 ErrMsg ( EC_Unimplemented, 00868 "Process_Command_Line_Group: " 00869 "> 32-bit flag values" ); 00870 } 00871 if ( ! hasval ) { 00872 ival = ODESC_def_val(found); 00873 } else { 00874 char *tval = val; 00875 if ((*val < '0' || *val > '9') && *val != '-') 00876 ErrMsg(EC_Flag_Int_Expected, this_flag); 00877 ival = Get_Numeric_Flag ( &tval, 00878 ODESC_min_val(found), 00879 ODESC_max_val(found), 00880 ODESC_def_val(found), 00881 this_flag ); 00882 } 00883 Update_Scalar_Value ( found, (UINT64)ival ); 00884 break; 00885 #endif 00886 00887 case OVK_NAME: 00888 if ( ! hasval ) { 00889 val = ""; 00890 } 00891 Update_Pointer_Value ( found, strdup (val) ); 00892 break; 00893 00894 case OVK_SELF: 00895 if ( ! hasval ) { 00896 val = cp; 00897 } 00898 Update_Pointer_Value ( found, strdup (val) ); 00899 break; 00900 00901 case OVK_LIST: 00902 olist = 00903 (OPTION_LIST *) calloc ( sizeof(OPTION_LIST), 1 ); 00904 OLIST_val(olist) = val ? strdup ( val ) : NULL; 00905 OLIST_opt(olist) = ODESC_name(found); 00906 ol = *(OPTION_LIST **)ODESC_variable(found); 00907 00908 if ( ol == NULL ) { 00909 Update_Pointer_Value ( found, olist ); 00910 00911 } else { 00912 while ( OLIST_next(ol) != NULL ) ol = OLIST_next(ol); 00913 OLIST_next(ol) = olist; 00914 00915 /* This won't actually change the apparent value of 00916 * ODA_last, since the head of the list isn't 00917 * changing. So, just mark it modified and set: 00918 */ 00919 Set_ODA_mod ( aux ); 00920 Set_ODA_set ( aux ); 00921 } 00922 break; 00923 00924 default: 00925 break; 00926 } 00927 } 00928 } 00929 00930 free(copy); 00931 /* Return success indicator */ 00932 return TRUE; 00933 } /* Process_Command_Line_Group */ 00934 00935 /* ==================================================================== 00936 * 00937 * Modified_Option 00938 * 00939 * Given an option descriptor, determine whether the option has been 00940 * modified since the ODA_last value was set, i.e. without using 00941 * Process_Command_Line_Group. 00942 * 00943 * WARNING: Because we want calls to this routine to be repeatable, we 00944 * don't update ODA_last. Therefore, multiple calls to the Print/Trace 00945 * routines may print this option even though it doesn't change between 00946 * them. 00947 * 00948 * ==================================================================== 00949 */ 00950 00951 static BOOL 00952 Modified_Option ( OPTION_DESC *odesc ) 00953 { 00954 void *var = ODESC_variable(odesc); 00955 ODESC_AUX *aux = ODESC_aux(odesc); 00956 UINT64 cur; 00957 00958 switch ( ODESC_kind(odesc) ) { 00959 case OVK_NONE: 00960 case OVK_BOOL: 00961 cur = (UINT64)*((BOOL*)var); 00962 break; 00963 case OVK_INT32: 00964 cur = (UINT64)*((INT32*)var); 00965 break; 00966 case OVK_UINT32: 00967 cur = (UINT64)*((UINT32*)var); 00968 break; 00969 case OVK_INT64: 00970 cur = (UINT64)*((INT64*)var); 00971 break; 00972 case OVK_UINT64: 00973 cur = (UINT64)*((UINT64*)var); 00974 break; 00975 case OVK_NAME: 00976 case OVK_SELF: 00977 case OVK_LIST: 00978 return ( *((void**)var) != ODA_last_p(aux) ); 00979 default: 00980 break; 00981 } 00982 00983 /* For the scalar cases, still need to check: */ 00984 return ( cur != ODA_last_i(aux) ); 00985 } 00986 00987 /* ==================================================================== 00988 * 00989 * Print_Option_Group 00990 * 00991 * Given an option group descriptor, print the options in the group 00992 * to the given file. Each line of output is prefixed by "prefix", 00993 * to allow commenting for emission in assembly sources, for instance. 00994 * The set and mod flags are updated appropriately if "update" is TRUE; 00995 * this allows them to be left unchanged if the information is to be 00996 * printed to two files (e.g. listing and assembly). 00997 * 00998 * Which options are printed depends on the "internal" and "full" 00999 * parameters, the OGA_internal flag of the group, and the 01000 * ODESC_visibility value for the option, as indicated by the 01001 * following: 01002 * internal == TRUE: 01003 * full == TRUE: print all options 01004 * full == FALSE: print only options modified since last internal 01005 * listing 01006 * internal == FALSE: (print no options if OGA_internal is set) 01007 * full == TRUE: print OV_VISIBLE and modified OV_SHY options 01008 * full == FALSE: print only OV_VISIBLE or OV_SHY options 01009 * modified since last non-internal listing 01010 * 01011 * ==================================================================== 01012 */ 01013 01014 void 01015 Print_Option_Group ( FILE *tf, OPTION_GROUP *og, char *prefix, 01016 BOOL internal, BOOL full, BOOL update ) 01017 { 01018 OPTION_DESC *desc = OGROUP_options(og); 01019 ODESC_AUX *aux; 01020 OPTION_LIST **this; 01021 OPTION_LIST *list; 01022 BOOL option_set = FALSE; 01023 BOOL visible_option = FALSE; 01024 char *bar = SBar + 12; /* shorten it a bit */ 01025 01026 /* Don't print internal groups in user mode: */ 01027 if ( !internal && OGA_internal ( OGROUP_aux(og) ) ) return; 01028 01029 /* Clear the ODA_PRINTED flags and check for set options: */ 01030 for ( desc = OGROUP_options(og); 01031 ODESC_kind(desc) != OVK_COUNT 01032 && ODESC_kind(desc) != OVK_OLD_COUNT; 01033 desc++ ) 01034 { 01035 aux = ODESC_aux(desc); 01036 Reset_ODA_printed ( aux ); 01037 if ( ( internal 01038 && ( ODA_set_int(aux) || Modified_Option(desc) ) ) 01039 || ( ! internal 01040 && ODESC_visibility(desc) != OV_INTERNAL 01041 && ( ODA_set_user(aux) || Modified_Option(desc) ) ) ) 01042 { 01043 Set_ODA_print(aux); 01044 option_set = TRUE; 01045 } else { 01046 Reset_ODA_print(aux); 01047 if ( ODESC_visibility(desc) != OV_INTERNAL ) { 01048 visible_option = TRUE; 01049 } 01050 } 01051 } 01052 01053 /* Is there anything to print? */ 01054 if ( ! ( option_set || full ) ) return; 01055 if ( ! ( option_set || internal || visible_option ) ) return; 01056 01057 /* Print a header: */ 01058 fprintf ( tf, "\n%s%s%s -%s Option Group\n", 01059 prefix, bar, prefix, OGROUP_name(og) ); 01060 if ( OGROUP_description(og) != NULL ) { 01061 fprintf ( tf, "%s\t%s\n", prefix, OGROUP_description(og) ); 01062 } 01063 fprintf ( tf, "%s%s", prefix, bar ); 01064 01065 for ( desc = OGROUP_options(og); 01066 ODESC_kind(desc) != OVK_COUNT 01067 && ODESC_kind(desc) != OVK_OLD_COUNT; 01068 desc++ ) 01069 { 01070 char mchar; 01071 01072 aux = ODESC_aux(desc); 01073 if ( ! ODA_print(aux) && ! full ) continue; 01074 if ( ! internal && ODESC_visibility(desc) == OV_INTERNAL ) continue; 01075 01076 /* Mark modified options with '#', set options with '=': */ 01077 if ( ( ! internal && (ODA_mod_user(aux) || Modified_Option(desc) ) ) 01078 || ( internal && (ODA_mod_int(aux) || Modified_Option(desc) ) ) ) 01079 { 01080 mchar = '#'; 01081 } else if ( ( ! internal && ODA_set_user(aux) ) 01082 || ( internal && ODA_set_int(aux) ) ) 01083 { 01084 mchar = '='; 01085 } else { 01086 mchar = ' '; 01087 } 01088 01089 fprintf ( tf, "%s%c %-20s= ", prefix, mchar, ODESC_name(desc)); 01090 01091 switch (ODESC_kind(desc)) { 01092 case OVK_BOOL: 01093 fprintf ( tf, "%s", *((BOOL *) ODESC_variable(desc)) ? 01094 "ON" : "OFF"); 01095 break; 01096 case OVK_INT32: 01097 fprintf ( tf, "%d", *((INT32 *) ODESC_variable(desc))); 01098 break; 01099 case OVK_INT64: 01100 fprintf ( tf, "%lld", *((INT64 *) ODESC_variable(desc))); 01101 break; 01102 case OVK_UINT32: 01103 fprintf ( tf, "%u", *((UINT32 *) ODESC_variable(desc))); 01104 break; 01105 case OVK_UINT64: 01106 fprintf ( tf, "%llu", *((UINT64 *) ODESC_variable(desc))); 01107 break; 01108 01109 case OVK_NAME: 01110 case OVK_SELF: 01111 /* These are likely to be repeasted, e.g. for 01112 * -TARG:isa=mips3 and -TARG:mips3. So check whether this 01113 * is the primary, and just refer to it from secondaries: 01114 */ 01115 if ( ODESC_primary(desc) == desc 01116 || ODESC_primary(desc) == NULL ) 01117 { 01118 fprintf ( tf, "%s", *((char **) ODESC_variable(desc))); 01119 } else { 01120 fprintf ( tf, " (See '%s' above)", 01121 ODESC_name(ODESC_primary(desc)) ); 01122 } 01123 break; 01124 01125 case OVK_LIST: 01126 /* Lists are likely to be repeated for multiple options. 01127 * If the primary isn't this option, we have that situation, 01128 * and we simply refer to the primary: 01129 */ 01130 if ( ODESC_primary(desc) == desc 01131 || ODESC_primary(desc) == NULL ) 01132 { 01133 char sep = ' '; 01134 01135 this = (OPTION_LIST **)ODESC_variable(desc); 01136 for ( list = *this; list != NULL; list = OLIST_next(list) ) { 01137 fprintf ( tf, "%c%s%c%s", sep, OLIST_opt(list), 01138 OGROUP_valmarker(og), OLIST_val(list) ); 01139 sep = OGROUP_separator(og); 01140 } 01141 } else { 01142 fprintf ( tf, " (See '%s' above)", 01143 ODESC_name(ODESC_primary(desc)) ); 01144 } 01145 break; 01146 01147 default: 01148 break; 01149 } 01150 fprintf ( tf, "\n" ); 01151 01152 if ( ODESC_description(desc) != NULL ) { 01153 fprintf ( tf, "%s (%s)\n", 01154 prefix, ODESC_description(desc) ); 01155 } 01156 } 01157 01158 fprintf ( tf, "%s%s\n", prefix, bar ); 01159 01160 if ( update ) { 01161 for ( desc = OGROUP_options(og); 01162 ODESC_kind(desc) != OVK_COUNT 01163 && ODESC_kind(desc) != OVK_OLD_COUNT; 01164 desc++ ) 01165 { 01166 aux = ODESC_aux(desc); 01167 if ( internal ) { 01168 Reset_ODA_set_int(aux); 01169 Reset_ODA_mod_int(aux); 01170 } else { 01171 Reset_ODA_set_user(aux); 01172 Reset_ODA_mod_user(aux); 01173 } 01174 } 01175 } 01176 } 01177 01178 /* ==================================================================== 01179 * 01180 * Trace_Option_Group / Trace_Command_Line_Group 01181 * 01182 * Given a command line group descriptor, trace the options in the 01183 * group to the given file, i.e. do Print_Command_Line_Group with 01184 * internal=TRUE and prefix="". Trace_Command_Line_Group is present 01185 * only for backwards compatibility. 01186 * 01187 * ==================================================================== 01188 */ 01189 01190 void 01191 Trace_Option_Group ( FILE *tf, OPTION_GROUP *og, BOOL full ) 01192 { 01193 Print_Option_Group ( tf, og, "", TRUE, full, TRUE ); 01194 } 01195 01196 /* ================================================================= */ 01197 01198 void 01199 Trace_Command_Line_Group ( FILE *tf, OPTION_GROUP *og ) 01200 { 01201 Print_Option_Group ( tf, og, "", TRUE, FALSE, TRUE ); 01202 } 01203 01204 /* ==================================================================== 01205 * 01206 * Print_Option_Groups / Trace_Option_Groups 01207 * 01208 * Same as the singular forms above, but print all groups in an array. 01209 * 01210 * ==================================================================== 01211 */ 01212 01213 void 01214 Print_Option_Groups ( FILE *tf, OPTION_GROUP *og, char *prefix, 01215 BOOL internal, BOOL full, BOOL update ) 01216 { 01217 while ( OGROUP_name(og) != NULL ) { 01218 Print_Option_Group ( tf, og, prefix, internal, full, update ); 01219 ++og; 01220 } 01221 } 01222 01223 /* ================================================================= */ 01224 01225 void 01226 Trace_Option_Groups ( FILE *tf, OPTION_GROUP *og, BOOL full ) 01227 { 01228 Print_Option_Groups ( tf, og, "", TRUE, full, TRUE ); 01229 } 01230 01231 /* ==================================================================== 01232 * 01233 * Get_Command_Line_Group 01234 * 01235 * Given an array of option groups and a group name, return a pointer 01236 * to the option group with the given name, or NULL. The array must 01237 * be terminated by a NULL name if the requested name is not present. 01238 * 01239 * ==================================================================== 01240 */ 01241 01242 OPTION_GROUP * 01243 Get_Command_Line_Group ( OPTION_GROUP *og, char *name ) 01244 { 01245 INT32 i; 01246 01247 for ( i = 0; OGROUP_name(og+i) != NULL; i++ ) { 01248 if ( strcmp ( OGROUP_name(og+i), name ) == 0 ) return og+i; 01249 } 01250 return NULL; 01251 } 01252 01253 01254 /* ==================================================================== 01255 * handle individual option inside Save_or_restore_options 01256 * ====================================================================*/ 01257 #define individual_option(opt, str) \ 01258 ODESC_kind(&odesc) = OVK_INT32; \ 01259 ODESC_variable(&odesc) = (void *)&opt; \ 01260 ODESC_can_change_by_pragma(&odesc) = TRUE; \ 01261 incr = Copy_option(&odesc, (char *)(memory+offset), save); \ 01262 offset += incr; \ 01263 Is_Trace(trace, (TFile, " %s %d: %s (%d bytes)\n", \ 01264 save ? "saving" : "restoring", offset, str, incr)); 01265 01266 01267 /* ==================================================================== 01268 * Save__or_restore_options 01269 * save or restore all options to the memory given 01270 * keep track of how much memory is used and check against size 01271 * 01272 * NOTE: this same routine to used to save and restore the options, 01273 * this way they will always be in the same order. 01274 * ====================================================================*/ 01275 void Save_or_restore_options(char *memory, INT32 size, BOOL save) 01276 { 01277 OPTION_GROUP *ogroups = Common_Option_Groups; 01278 OPTION_GROUP *group; 01279 BOOL trace = Get_Trace(TP_MISC, 0x80); /* full command line tracing */ 01280 INT32 incr, offset = 0; 01281 01282 Is_Trace(trace, (TFile, "Save_or_restore_options: %s called\n", 01283 save ? "save" : "restore")); 01284 01285 /*----------------------------------------------------------------------*/ 01286 /* go through all option groups */ 01287 for (group = ogroups; group && OGROUP_options(group) && OGROUP_name(group); 01288 group++) { 01289 OPTION_DESC *odesc; 01290 OGROUP_AUX *ogaux = OGROUP_aux(group); 01291 ODESC_AUX *odaux = OGA_odesc_aux(ogaux); 01292 INT16 i, count = OGA_count(ogaux); 01293 01294 Is_Trace(trace, (TFile, "group = %s\n", OGROUP_name(group))); 01295 01296 /* Iterate through the descriptors in the group */ 01297 for (i=0, odesc=OGROUP_options(group); i<count; i++, odesc++, odaux++) { 01298 /* only save/restore the ones that can change */ 01299 if (ODESC_can_change_by_pragma(odesc)) { 01300 incr = Copy_option(odesc, (char *)(memory+offset), save); 01301 Is_Trace(trace, (TFile, " %s %d: %s (%d bytes)\n", 01302 save ? "saving" : "restoring", 01303 offset, ODESC_name(odesc), incr)); 01304 offset += incr; 01305 #ifdef Is_True_On 01306 Is_True(offset < size, 01307 ("OPTIONS_SIZE in options_stack.h needs to be bigger\n")); 01308 #endif 01309 } 01310 } /* for (i=0, odesc=OGROUP_options(group); i<count; ... */ 01311 01312 } /* for (group = ogroups; group && OGROUP_options(group) ... */ 01313 01314 /*----------------------------------------------------------------------*/ 01315 /* now go through the options not in the groups */ 01316 { OPTION_DESC odesc; 01317 01318 Is_Trace(trace, (TFile, "group = Individual Options\n")); 01319 01320 /* Add more options here, individual_option is a macro defined above */ 01321 individual_option(Opt_Level, "Opt_Level"); 01322 } 01323 01324 /*----------------------------------------------------------------------*/ 01325 Is_Trace(trace, (TFile, "max offset = %d\n", offset)); 01326 }