00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
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"
00060 #include "config.h"
00061
00062 extern char *SBar;
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 INT64
00077 Get_Numeric_Flag (
00078 char **cp,
00079 INT64 min,
00080 INT64 max,
00081 INT64 def,
00082 char *flag
00083 )
00084 {
00085 INT64 val = 0;
00086 INT64 radix = 10;
00087 char c;
00088 BOOL done = FALSE;
00089 BOOL negate = FALSE;
00090
00091
00092 c = **cp;
00093 if (c == '-') {
00094 c = *++(*cp);
00095 negate = TRUE;
00096 }
00097 if ( c < '0' || c > '9' ) return def;
00098
00099
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
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
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
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
00159
00160
00161
00162
00163
00164
00165
00166
00167
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
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
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;
00232 BOOL *specified;
00233 OPTION_DESC *primary;
00234 OPTVAL orig;
00235 OPTVAL last;
00236 } ODESC_AUX;
00237
00238 #define ODF_SET_USER 0x01
00239 #define ODF_SET_INT 0x02
00240 #define ODF_SET 0x03
00241 #define ODF_MOD_USER 0x04
00242 #define ODF_MOD_INT 0x08
00243 #define ODF_MOD 0x0c
00244 #define ODF_PRINT 0x10
00245 #define ODF_PRINTED 0x20
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
00280
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;
00287 mINT16 count;
00288 ODESC_AUX *odesc_aux;
00289 } OGROUP_AUX;
00290
00291 #define OGF_SET 0x01
00292 #define OGF_INTERNAL 0x02
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
00307
00308
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:
00336 sz = 0; break;
00337 }
00338
00339 if (save) {
00340 memcpy((void*)container, var, sz);
00341 } else {
00342 memcpy(var, (void*)container, sz);
00343 }
00344
00345 return (INT)sz;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
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
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
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
00424 if ( OGROUP_aux(ogroup) != NULL ) return;
00425
00426
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
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;
00448
00449
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
00461
00462
00463
00464
00465
00466
00467
00468
00469
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
00502
00503
00504
00505
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
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
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
00557 if ( OGROUP_name(group) == NULL ) break;
00558 }
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
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
00614
00615
00616
00617
00618
00619
00620
00621
00622
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
00644
00645
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
00665 Initialize_Option_Groups ( opt_groups );
00666
00667
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
00680
00681
00682 option = flag + group_name_len + 1;
00683 break;
00684 }
00685 }
00686
00687
00688 if (option == NULL)
00689 return FALSE;
00690
00691 cp = copy = strdup ( option );
00692 next_cp = cp;
00693
00694
00695 sep[0] = OGROUP_valmarker(group);
00696 sep[1] = OGROUP_separator(group);
00697 sep[2] = 0;
00698
00699 #ifdef Is_True_On
00700
00701
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
00724 tidx = strcspn ( cp, sep );
00725 next_cp = ( cp[tidx] == 0 ) ? NULL : cp+tidx+1;
00726
00727
00728 hasval = ( cp[tidx] == OGROUP_valmarker(group) );
00729 cp[tidx] = 0;
00730 if ( hasval ) {
00731 val = next_cp;
00732
00733 tidx = strcspn ( val, &sep[1] );
00734 next_cp = ( val[tidx] == 0 ) ? NULL : val+tidx+1;
00735 val[tidx] = 0;
00736 }
00737
00738
00739
00740
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
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
00757
00758
00759
00760
00761
00762 if (!ODESC_abbrev(odesc)) {
00763
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
00771
00772
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
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
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
00798 ErrMsg ( EC_Not_In_Grp, cp, OGROUP_name(group), this_flag );
00799 } else {
00800 ODESC_AUX *aux = ODESC_aux(found);
00801
00802
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
00916
00917
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
00932 return TRUE;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
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
00984 return ( cur != ODA_last_i(aux) );
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
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;
01025
01026
01027 if ( !internal && OGA_internal ( OGROUP_aux(og) ) ) return;
01028
01029
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
01054 if ( ! ( option_set || full ) ) return;
01055 if ( ! ( option_set || internal || visible_option ) ) return;
01056
01057
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
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
01112
01113
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
01127
01128
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
01181
01182
01183
01184
01185
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
01207
01208
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
01234
01235
01236
01237
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
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
01269
01270
01271
01272
01273
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);
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
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
01297 for (i=0, odesc=OGROUP_options(group); i<count; i++, odesc++, odaux++) {
01298
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 }
01311
01312 }
01313
01314
01315
01316 { OPTION_DESC odesc;
01317
01318 Is_Trace(trace, (TFile, "group = Individual Options\n"));
01319
01320
01321 individual_option(Opt_Level, "Opt_Level");
01322 }
01323
01324
01325 Is_Trace(trace, (TFile, "max offset = %d\n", offset));
01326 }