Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
flags.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines