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 #include <stdio.h>
00041 #include <string.h>
00042 #include <malloc.h>
00043 #include <ctype.h>
00044 #include <stdlib.h>
00045 #include <assert.h>
00046 #include "basic.h"
00047 #include "lang_defs.h"
00048 #include "string_utils.h"
00049 #include "errors.h"
00050
00051 #ifdef _WIN32
00052 #define LL_FORMAT "I64"
00053 #else
00054 #define LL_FORMAT "ll"
00055 #endif
00056
00057 #define EMPTY(x) (x[0] == NIL)
00058 #define SPACE " "
00059 #define DQUOTE "\""
00060 #define DQUOTE_SPACE "\" "
00061 #define COMMA ","
00062 #define RPAREN ")"
00063 #define FIELD_DIVIDER '|'
00064 #define OPTIONS 1
00065 #if 0
00066 #define COMBINATIONS 2
00067 #endif
00068
00069 typedef enum {
00070 normal,
00071 oneletter,
00072 oneletter_space,
00073 multiletter_space,
00074 complicated,
00075 needs_string,
00076 needs_string_or_dash,
00077 needs_directory,
00078 #ifdef KEY
00079 needs_directory_or_null,
00080
00081 #endif
00082 needs_decimal
00083 #if 0
00084 combo
00085 #endif
00086 } syntax_t;
00087
00088 #define MAX_OPTION_LENGTH 48
00089 #define MAX_NAME_LENGTH MAX_OPTION_LENGTH
00090 #define MAX_ACTION_LENGTH 256
00091
00092 typedef struct option_list_rec {
00093 int info_index;
00094 char name[MAX_OPTION_LENGTH];
00095 struct option_list_rec *next;
00096 } option_list_t;
00097
00098 typedef struct index_list_rec {
00099 int info_index;
00100 boolean negated;
00101 struct index_list_rec *next;
00102 } index_list_t;
00103
00104 typedef struct opt_info_rec {
00105 syntax_t syntax;
00106 int num_letters;
00107 boolean toggle;
00108 boolean internal;
00109 mask_t languages;
00110 mask_t phases;
00111 #if 0
00112 index_list_t *combo_list;
00113 #endif
00114 option_list_t *implies;
00115 char name[MAX_OPTION_LENGTH];
00116 char flag[MAX_OPTION_LENGTH];
00117 char action[MAX_ACTION_LENGTH];
00118 char *help;
00119 } option_info_t;
00120 #define MAX_OPTIONS 1000
00121 static option_info_t options[MAX_OPTIONS];
00122 static int num_options = 0;
00123
00124 static char implicit_vars[MAX_OPTIONS][MAX_NAME_LENGTH];
00125 static int n_ivars = 0;
00126
00127
00128
00129
00130
00131 static boolean table_for_phase = FALSE;
00132
00133 static const mask_t ALL_LANGS = -1;
00134 static const mask_t ALL_PHASES = -1;
00135 #define UNDEFINED -1
00136
00137 #define index_last_char(s) (strlen(s)-1)
00138
00139 static int
00140 find_name(char *s)
00141 {
00142 int i;
00143 size_t len;
00144 for (i = 0; i < num_options; i++) {
00145 switch(options[i].syntax) {
00146 case needs_decimal:
00147
00148 len = strlen(options[i].name);
00149 if ((strncmp(s, options[i].name, len) == 0)
00150 && (isdigit(s[len])
00151 || (s[len] == '%' && s[len+1] == 'd')
00152 || (s[len] == ' ' && s[len+1] == '%' && s[len+2] == 'd')
00153 ) )
00154 {
00155 return i;
00156 }
00157 break;
00158 case needs_string_or_dash:
00159 case needs_string:
00160 case needs_directory:
00161 #ifdef KEY
00162 case needs_directory_or_null:
00163 #endif
00164 len = strlen(options[i].name);
00165 if ((strncmp(s, options[i].name, len) == 0)
00166
00167 && (isgraph(s[len])
00168 || (s[len] == ' ' && isgraph(s[len+1])) ) )
00169 {
00170 return i;
00171 }
00172 break;
00173 default:
00174 if (strcmp(s, options[i].name) == 0)
00175 return i;
00176 break;
00177 }
00178 }
00179 internal_error("didn't find name %s", s);
00180 return UNDEFINED;
00181 }
00182
00183 static int
00184 get_line (char *line)
00185 {
00186 char c;
00187 char *p = line;
00188 while (1) {
00189 c = (char) getchar();
00190 if (c == (char) EOF) return EOF;
00191 else if (c == '\n') {
00192 *p = NIL;
00193 return 0;
00194 } else {
00195 *p = c;
00196 p++;
00197 }
00198 }
00199 }
00200
00201 static syntax_t
00202 set_option_name(char *name, char *s, int *num_letters)
00203 {
00204 syntax_t f = normal;
00205 char *pn = name;
00206 char *ps = s;
00207 *num_letters = 0;
00208 while (*ps != NIL) {
00209 if (*ps == '*') {
00210 if (*(ps+1) == NIL)
00211 f = complicated;
00212 else if (ps == s+2)
00213 f = oneletter_space;
00214 else {
00215 f = multiletter_space;
00216 *num_letters = (ps - s - 1);
00217 }
00218 } else if (*ps == '%') {
00219 switch (*(ps+1)) {
00220 case 's':
00221 f = needs_string;
00222 break;
00223 case '-':
00224 f = needs_string_or_dash;
00225 break;
00226 case 'd':
00227 case 'x':
00228 f = needs_decimal;
00229 break;
00230 case 'D':
00231 f = needs_directory;
00232 #ifdef KEY
00233 if (*(ps+2) == '?') {
00234 ps++;
00235 f = needs_directory_or_null;
00236 }
00237 #endif
00238 break;
00239 }
00240 ps++;
00241 } else {
00242 *pn = *ps;
00243 pn++;
00244 }
00245 ps++;
00246 }
00247 *pn = NIL;
00248 return f;
00249 }
00250
00251
00252 static void
00253 set_flag_name(option_info_t *opt)
00254 {
00255 char *pn = opt->name;
00256 char *pf = opt->flag;
00257 *pf++ = 'O';
00258 while (*pn != NIL) {
00259 if (*pn == ' ') pn++;
00260 if (*pn == '!') pn++;
00261 if (*pn == '-') *pf = '_';
00262 else if (*pn == '=') *pf = 'Q';
00263 else if (*pn == '#') *pf = 'P';
00264 else if (*pn == ',') *pf = 'C';
00265 else if (*pn == ':') *pf = '_';
00266 else if (*pn == '+') *pf = '_';
00267 else *pf = *pn;
00268 pf++;
00269 pn++;
00270 }
00271 switch (opt->syntax) {
00272 case needs_directory:
00273 case needs_decimal:
00274 case complicated:
00275 #ifdef KEY
00276 case needs_directory_or_null:
00277 #endif
00278
00279
00280 *pf = '_';
00281 pf++;
00282 *pf = '_';
00283 pf++;
00284 break;
00285 }
00286 *pf = NIL;
00287 }
00288
00289
00290 static void
00291 store_string(char *tgt, char *src, char *special)
00292 {
00293 char *p;
00294 if (strcmp(src, special) == 0) {
00295 *tgt = NIL;
00296 } else if (*src != '{') {
00297 strcpy(tgt, src);
00298 } else {
00299
00300 strcpy(tgt, src);
00301 strcat(tgt, " ");
00302 p = strtok(NULL, "}");
00303 strcat(tgt, p);
00304 strcat(tgt, "}");
00305 }
00306 }
00307
00308 static option_list_t *
00309 create_option_list (char **sp, int index)
00310 {
00311
00312 char *s = *sp;
00313 option_list_t *olist;
00314 option_list_t *olist_head;
00315 s = strtok(NULL, DQUOTE_SPACE);
00316 *sp = s;
00317 if (s == NULL) {
00318 return NULL;
00319 } else if (*s == FIELD_DIVIDER) {
00320 return NULL;
00321 } else {
00322 olist = (option_list_t *) malloc(sizeof(option_list_t));
00323 olist->next = NULL;
00324 olist_head = olist;
00325 if (strcmp(s, "self") == 0) {
00326 strcpy(olist->name, options[index].name);
00327 olist->info_index = index;
00328 } else {
00329 strcpy(olist->name, s);
00330 olist->info_index = UNDEFINED;
00331 }
00332 }
00333 s = strtok(NULL, DQUOTE_SPACE);
00334 while (s != NULL && *s != FIELD_DIVIDER) {
00335 if (s[0] != '-') {
00336
00337 strcat(olist->name, " ");
00338 strcat(olist->name, s);
00339 } else {
00340 olist = (option_list_t *) malloc(sizeof(option_list_t));
00341 strcpy(olist->name, s);
00342 olist->info_index = UNDEFINED;
00343
00344 olist->next = olist_head;
00345 olist_head = olist;
00346 }
00347 s = strtok(NULL, DQUOTE_SPACE);
00348 }
00349 *sp = s;
00350 return olist_head;
00351 }
00352
00353 static char *
00354 list_to_string (option_list_t *list)
00355 {
00356 option_list_t *p;
00357 char *buf;
00358 if (list == NULL) {
00359 return NULL;
00360 } else {
00361 buf = (char *) malloc(80);
00362 strcpy(buf, list->name);
00363 }
00364 for (p = list->next; p != NULL; p = p->next) {
00365 strcat(buf, " ");
00366 strcat(buf, p->name);
00367 }
00368 return buf;
00369 }
00370
00371 static mask_t
00372 create_lang_field (char *s)
00373 {
00374 char *p;
00375 mask_t bitfield = 0;
00376 for (p = s; *p != NIL; p++) {
00377 if (*p == ',') continue;
00378 bitfield |= get_language_mask(get_language(*p));
00379 }
00380 return bitfield;
00381 }
00382
00383 static mask_t
00384 create_phase_field (char *s)
00385 {
00386 char *p;
00387 mask_t bitfield = 0;
00388 for (p = s; *p != NIL; p++) {
00389 if (*p == ',') continue;
00390 bitfield |= get_phase_mask(get_phase(*p));
00391 }
00392 return bitfield;
00393 }
00394
00395 static char *
00396 create_help_msg (char *s)
00397 {
00398 if (*s != FIELD_DIVIDER)
00399 internal_error("| help msg expected: %s", s);
00400 s = strtok(NULL, DQUOTE);
00401 if (s != NULL && !isspace(*s))
00402 internal_error("| help msg expected: %s", s);
00403 s = strtok(NULL, DQUOTE);
00404 if (s == NULL) return NULL;
00405 else return string_copy(s);
00406 }
00407
00408 #define INCREMENT_INDEX(i,max)\
00409 i++;\
00410 if (i >= max) internal_error("INDEX OVERFLOWED %d", max);
00411
00412
00413
00414 static int reverse_strcmp(const void* x, const void* y) {
00415 const char * const*x1 = x;
00416 const char * const*y1 = y;
00417
00418 return strcmp(*y1, *x1);
00419 }
00420
00421
00422
00423
00424 option_info_t *find_by_flag(char *name, int last)
00425 {
00426 int i;
00427
00428 for (i = 0; i < last; i++) {
00429 if (strcmp(options[i].flag, name) == 0)
00430 return &options[i];
00431 }
00432 return NULL;
00433 }
00434
00435
00436
00437
00438 static int compare_options(option_info_t *a, option_info_t *b)
00439 {
00440 option_list_t *oa, *ob;
00441
00442 if (a->languages != b->languages)
00443 return 0;
00444 if (a->phases != b->phases)
00445 return 0;
00446 if (a->phases != b->phases)
00447 return 0;
00448 if (strcmp(a->action, b->action) != 0)
00449 return 0;
00450
00451 for (oa = a->implies, ob = b->implies;; oa = oa->next, ob = ob->next) {
00452 if ((oa != NULL) ^ (ob != NULL))
00453 return 0;
00454 if (strcmp(oa->name, ob->name) != 0)
00455 return 0;
00456 }
00457
00458 return 1;
00459 }
00460
00461
00462
00463
00464
00465 static void check_dups(void)
00466 {
00467 int i;
00468
00469 for (i = 1; i < num_options; i++) {
00470 option_info_t *opt = find_by_flag(options[i].flag, i);
00471 if (opt == NULL)
00472 continue;
00473 if (!compare_options(&options[i], opt)) {
00474 fprintf(stderr, "Error: %s and %s are not identical\n",
00475 options[i].name, opt->name);
00476 exit(1);
00477 }
00478 }
00479 }
00480
00481
00482
00483
00484 static void read_table(void)
00485 {
00486 char line[512];
00487 char line2[512];
00488 char *option_lines[MAX_OPTIONS];
00489 int option_line_count = 0;
00490 char *p;
00491 int section = 0;
00492 int i = num_options;
00493 int j;
00494
00495 strcpy(options[i].flag, "O_Unrecognized");
00496 options[i].internal = TRUE;
00497 strcpy(options[i].name, "");
00498 options[i].implies = NULL;
00499 i++;
00500
00501 #if 0
00502
00503 while (get_line(line) != EOF) {
00504 if (EMPTY(line))
00505 continue;
00506 else if (line[0] == '%' && line[1] != '%')
00507 continue;
00508 else if (strcmp(line, "%%% OPTIONS") == 0) {
00509 section = OPTIONS;
00510 break;
00511 }
00512 else {
00513 internal_error("Unexpected line: %s", line);
00514 }
00515 }
00516
00517
00518 if (section != OPTIONS) {
00519 internal_error("OPTIONS section not found");
00520 }
00521 #endif
00522 option_line_count = 0;
00523 while (get_line(line) != EOF) {
00524 char* s;
00525
00526 if (EMPTY(line))
00527 continue;
00528 else if (line[0] == '%')
00529 continue;
00530 else if (line[0] == ' ' && line[1] == NIL)
00531 continue;
00532 else if (line[0] == '\t')
00533 internal_error("unexpected line (help msg?): %s", line);
00534 else if (line[0] != '-' && line[0] != 'I')
00535 internal_error("unexpected line: [%s]", line);
00536
00537 if (get_line(line2) == EOF)
00538 internal_error("unexpected EOF for line2");
00539
00540 s = malloc(strlen(line) + strlen(line2) + 4);
00541 if (s == NULL)
00542 internal_error("memory allocation failed");
00543 sprintf(s, "%s %c %s", line, FIELD_DIVIDER, line2);
00544
00545 option_lines[option_line_count] = s;
00546 INCREMENT_INDEX(option_line_count, MAX_OPTIONS);
00547 }
00548
00549 qsort(option_lines, option_line_count, sizeof(char*),
00550 reverse_strcmp);
00551
00552
00553 for (j = 0; j < option_line_count; ++j) {
00554
00555 p = strtok(option_lines[j], SPACE);
00556 if (*p == 'I') {
00557 options[i].internal = TRUE;
00558 p++;
00559 } else
00560 options[i].internal = FALSE;
00561 if (*p != '-')
00562 internal_error("MISSING - : %s", p);
00563 options[i].syntax =
00564 set_option_name(options[i].name, p, &options[i].num_letters);
00565 if (options[i].syntax == normal
00566 && strlen(options[i].name) == 2)
00567 options[i].syntax = oneletter;
00568 set_flag_name(&options[i]);
00569 p = strtok(NULL, SPACE);
00570 store_string(options[i].action, p, ";");
00571 if (strncmp(p, "toggle", 6) == 0)
00572 options[i].toggle = TRUE;
00573 else
00574 options[i].toggle = FALSE;
00575 if (!table_for_phase) {
00576 p = strtok(NULL, SPACE);
00577 options[i].languages = create_lang_field(p);
00578 if ( options[i].internal ) {
00579 options[i].languages |=
00580 get_language_mask ( L_internal );
00581 }
00582 p = strtok(NULL, SPACE);
00583 options[i].phases = create_phase_field(p);
00584 }
00585 options[i].implies = create_option_list(&p,i);
00586 options[i].help = create_help_msg(p);
00587 INCREMENT_INDEX(i, MAX_OPTIONS);
00588 }
00589
00590 check_dups();
00591
00592 #if 0
00593
00594 if (section != COMBINATIONS) {
00595 internal_error("COMBINATIONS section not found");
00596 }
00597
00598 while (get_line(line) != EOF) {
00599 if (EMPTY(line))
00600 continue;
00601 else if (line[0] == '%' && line[1] != '%')
00602 continue;
00603 else if (strncmp(line, "%%% ", 4) == 0) {
00604 internal_error("Unexpected sections line: %s", line);
00605 }
00606 else {
00607
00608 if (line[0] != '\"')
00609 internal_error("MISSING \" : %s", line);
00610 p = strtok(line+1, DQUOTE);
00611 set_option_name(options[i].name, p, &options[i].num_letters);
00612 options[i].syntax = combo;
00613 set_flag_name(&options[i]);
00614 p = strtok(NULL, SPACE);
00615 store_string(options[i].action, p, "OKAY");
00616 options[i].implies = create_option_list(&p,i);
00617 options[i].languages = ALL_LANGS;
00618 options[i].phases = ALL_PHASES;
00619 options[i].help = NULL;
00620 INCREMENT_INDEX(i, MAX_OPTIONS);
00621 }
00622 }
00623 #endif
00624
00625 num_options = i;
00626 }
00627
00628 static void
00629 fill_option_info (void)
00630 {
00631 int i;
00632 option_list_t *p;
00633 index_list_t *pc;
00634 char *s;
00635 char buffer[MAX_OPTION_LENGTH];
00636 for (i = 0; i < num_options; i++) {
00637 p = options[i].implies;
00638 while (p != NULL) {
00639 if (p->info_index == UNDEFINED) {
00640 p->info_index = find_name(p->name);
00641 }
00642 p = p->next;
00643 }
00644 #if 0
00645 if (options[i].syntax == combo) {
00646 options[i].combo_list = NULL;
00647 strcpy(buffer, options[i].name);
00648 s = strtok(buffer, SPACE);
00649 while (s != NULL) {
00650 pc = (index_list_t*) malloc(sizeof(index_list_t));
00651 if (*s == '!') {
00652 pc->negated = TRUE;
00653 s++;
00654 } else {
00655 pc->negated = FALSE;
00656 }
00657 pc->info_index = find_name(s);
00658 pc->next = options[i].combo_list;
00659 options[i].combo_list = pc;
00660 s = strtok(NULL, SPACE);
00661 }
00662 }
00663 #endif
00664 }
00665 }
00666
00667 static void
00668 dump_option_info (void)
00669 {
00670 int i;
00671 for (i = 0; i < num_options; i++) {
00672 if (!EMPTY(options[i].action))
00673 printf("%s: action: %s\n", options[i].name,
00674 options[i].action);
00675 }
00676 }
00677
00678 static void
00679 add_implicit_var (char *s)
00680 {
00681 int i;
00682 for (i = 0; i < n_ivars; i++) {
00683 if (strcmp(s, implicit_vars[i]) == 0) {
00684
00685 return;
00686 }
00687 }
00688 strcpy(implicit_vars[n_ivars], s);
00689 n_ivars++;
00690 }
00691
00692 static FILE *
00693 begin_file (char *name)
00694 {
00695 FILE *f;
00696 f = fopen(name, "w");
00697 fprintf(f, "/* THIS FILE IS AUTOMATICALLY GENERATED BY table */\n\n");
00698 return f;
00699 }
00700
00701 static void
00702 write_option_names (void)
00703 {
00704 int i;
00705 char *ivar;
00706 buffer_t buffer;
00707 FILE *f;
00708 f = begin_file("option_names.h");
00709 for (i = 0; i < num_options; i++) {
00710 if (!find_by_flag(options[i].flag, i))
00711 fprintf(f, "#define %s %d\n", options[i].flag, i);
00712 if (options[i].toggle) {
00713
00714 #ifdef KEY
00715
00716
00717 char *p = options[i].action;
00718 while ((p = strstr(p, "toggle(&")) != NULL) {
00719 p = p + 8;
00720 strcpy(buffer, p);
00721 ivar = strtok(buffer,COMMA);
00722 add_implicit_var(ivar);
00723 }
00724 #else
00725 strcpy(buffer, ((char*)options[i].action)+8);
00726 ivar = strtok(buffer,COMMA);
00727 add_implicit_var(ivar);
00728 #endif
00729 }
00730 }
00731 fprintf(f, "#define LAST_PREDEFINED_OPTION %d\n", num_options);
00732 fprintf(f, "extern int max_options;\n\n");
00733 for (i = 0; i < n_ivars; i++) {
00734 fprintf(f, "extern int %s;\n", implicit_vars[i]);
00735 }
00736 fclose(f);
00737 }
00738
00739 static void
00740 write_init_options (void)
00741 {
00742 int i;
00743 option_list_t *q;
00744 FILE *f;
00745 f = begin_file("init_options.i");
00746 fprintf(f, "#include \"option_names.h\"\n");
00747 fprintf(f, "#include \"opt_actions.h\"\n\n");
00748 for (i = 0; i < n_ivars; i++) {
00749 fprintf(f, "int %s = UNDEFINED;\n", implicit_vars[i]);
00750 }
00751 fprintf(f, "\n");
00752 fprintf(f, "static void\n");
00753 if (table_for_phase) {
00754 fprintf(f, "create_option_info (int flag, char *name, char *help_msg)\n");
00755 fprintf(f, "{\n");
00756 } else {
00757 fprintf(f, "create_option_info (int flag, mask_t lang_mask, mask_t phase_mask, char *name, char *help_msg)\n");
00758 fprintf(f, "{\n");
00759 fprintf(f, "\toptions[flag].valid_langs = lang_mask;\n");
00760 fprintf(f, "\toptions[flag].valid_phases = phase_mask;\n");
00761 #if 0
00762 fprintf(f, "\toptions[flag].combo_list = NULL;\n");
00763 #endif
00764 }
00765 fprintf(f, "\toptions[flag].implies = NULL;\n");
00766 fprintf(f, "\toptions[flag].name = string_copy(name);\n");
00767 fprintf(f, "\toptions[flag].help_msg = string_copy(help_msg);\n");
00768 fprintf(f, "}\n\n");
00769 fprintf(f, "static void\n");
00770 fprintf(f, "create_implies_item (int key, int index, char *name)\n");
00771 fprintf(f, "{\n");
00772 fprintf(f, "\toption_list_t *p;\n");
00773 fprintf(f, "\tp = (option_list_t *) malloc(sizeof(option_list_t));\n");
00774 fprintf(f, "\tp->info_index = index;\n");
00775 fprintf(f, "\tp->name = string_copy(name);\n");
00776 fprintf(f, "\tp->next = options[key].implies;\n");
00777 fprintf(f, "\toptions[key].implies = p;\n");
00778 fprintf(f, "}\n\n");
00779 #if 0
00780 if (!table_for_phase) {
00781 fprintf(f, "static void\n");
00782 fprintf(f, "create_combo_item (int key, int index)\n");
00783 fprintf(f, "{\n");
00784 fprintf(f, "\tindex_list_t *p;\n");
00785 fprintf(f, "\tp = (index_list_t *) malloc(sizeof(index_list_t));\n");
00786 fprintf(f, "\tp->info_index = index;\n");
00787 fprintf(f, "\tp->next = options[key].combo_list;\n");
00788 fprintf(f, "\toptions[key].combo_list = p;\n");
00789 fprintf(f, "}\n\n");
00790 }
00791 #endif
00792 fprintf(f, "\nextern void\n");
00793 fprintf(f, "init_options (void)\n");
00794 fprintf(f, "{\n");
00795 fprintf(f, "\toptions = (option_info_t *) malloc(max_options*sizeof(option_info_t));\n");
00796
00797 for (i = 0; i < num_options; i++) {
00798 if (find_by_flag(options[i].flag, i))
00799 continue;
00800 if (table_for_phase) {
00801 fprintf(f, "\tcreate_option_info(%d,\"%s\",",
00802 i, options[i].name);
00803 } else {
00804 if (sizeof(mask_t)>4)
00805 {
00806 fprintf(f, "\tcreate_option_info("
00807 "%d,%#" LL_FORMAT "xLL,%#" LL_FORMAT "xLL,\"%s\",",
00808 i, options[i].languages, options[i].phases, options[i].name);
00809 }
00810 else
00811 {
00812 fprintf(f, "\tcreate_option_info("
00813 "%d,%#" LL_FORMAT "x,%#" LL_FORMAT "x,\"%s\",",
00814 i, options[i].languages, options[i].phases, options[i].name);
00815 }
00816 }
00817 if (options[i].help == NULL)
00818 fprintf(f, "NULL);\n");
00819 else
00820 fprintf(f, "\"%s\");\n", options[i].help);
00821 q = options[i].implies;
00822 while (q != NULL) {
00823
00824
00825 fprintf(f, "\tcreate_implies_item(%s, %d, \"%s\");\n",
00826 options[i].flag, q->info_index, q->name);
00827 q = q->next;
00828 }
00829 #if 0
00830 if (!table_for_phase) {
00831 if (options[i].syntax == combo) {
00832 index_list_t *index_lst = options[i].combo_list;
00833 while (index_lst != NULL) {
00834 fprintf(f, "\tcreate_combo_item(%s, %d);\n",
00835 options[i].flag, index_lst->info_index);
00836 index_lst = index_lst->next;
00837 }
00838 }
00839 }
00840 #endif
00841 }
00842 fprintf(f, "}\n\n");
00843 fclose(f);
00844 }
00845
00846 static void
00847 write_get_option (void)
00848 {
00849 int i, j;
00850 FILE *f;
00851 f = begin_file("get_option.i");
00852 fprintf(f, "/* return option index */\n");
00853 fprintf(f, "extern int\n");
00854 fprintf(f, "get_option(int *argi, char *argv[])\n");
00855 fprintf(f, "{\n");
00856 fprintf(f, "/* don't reset optargs, as may contain needed info */\n");
00857 fprintf(f, "optargd = 0;\n");
00858 fprintf(f, "switch (argv[*argi][optindex]) {\n");
00859 i = 0;
00860 while (i < num_options) {
00861 #if 0
00862 if (options[i].internal || options[i].syntax == combo) {
00863 #endif
00864 if (options[i].internal) {
00865
00866 i++;
00867 continue;
00868 }
00869 if (find_by_flag(options[i].flag, i))
00870 continue;
00871 if (options[i].name[1] == '\0')
00872 fprintf(f, "case '\\0':\n");
00873 else
00874 fprintf(f, "case '%c':\n", options[i].name[1]);
00875 while (1) {
00876 switch (options[i].syntax) {
00877 case normal:
00878 fprintf(f, "\tif (strcmp(argv[*argi],\"%s\") == 0) {\n",
00879 options[i].name);
00880 fprintf(f, "\t\tget_next_arg(argi);\n");
00881 fprintf(f, "\t\treturn %s;\n", options[i].flag);
00882 fprintf(f, "\t\t/* NOTREACHED */\n");
00883 fprintf(f, "\t}\n");
00884 break;
00885 case oneletter:
00886 fprintf(f, "\tget_next_char(argv, argi);\n");
00887 fprintf(f, "\treturn %s;\n", options[i].flag);
00888 fprintf(f, "\t/* NOTREACHED */\n");
00889 break;
00890 case oneletter_space:
00891 case multiletter_space:
00892 if (options[i].syntax == multiletter_space) {
00893 char *temp = string_copy(options[i].name);
00894 int nil_index = options[i].num_letters+1;
00895 temp[nil_index] = NIL;
00896 fprintf(f, "\tif ((strncmp(argv[*argi],\"%s\",%d) == 0)\n",
00897 temp, nil_index);
00898 fprintf(f, "\t&& strcmp(next_string_after(\"%s\",argv,argi),\"%s\") == 0) {\n",
00899 temp, options[i].name+nil_index);
00900 fprintf(f, "\t\tend_option(argv, argi, %d);\n", nil_index);
00901 } else {
00902 fprintf(f, "\tif (strcmp(next_string(argv,argi), \"%s\") == 0) {\n",
00903 options[i].name+2);
00904 }
00905 fprintf(f, "\t\toptargs = get_optarg(argv,argi);\n");
00906 fprintf(f, "\t\tget_next_arg(argi);\n");
00907 fprintf(f, "\t\treturn %s;\n", options[i].flag);
00908 fprintf(f, "\t\t/* NOTREACHED */\n");
00909 fprintf(f, "\t}\n");
00910 break;
00911 case needs_string_or_dash:
00912 case needs_string:
00913 case needs_directory:
00914 case needs_decimal:
00915 #ifdef KEY
00916 case needs_directory_or_null:
00917 #endif
00918
00919 fprintf(f, "\tif (!is_new_arg) break;\n");
00920
00921
00922 if (strlen(options[i].name) > 2) {
00923 fprintf(f, "\tif (strncmp(argv[*argi],\"%s\",%ld) == 0) {\n",
00924 options[i].name, (long)strlen(options[i].name));
00925 fprintf(f, "\t\tend_option(argv, argi, %ld);\n",
00926 (long)strlen(options[i].name));
00927 }
00928 if (options[i].syntax == needs_decimal) {
00929 fprintf(f, "\tif (is_decimal(next_string(argv,argi))) {\n");
00930 } else if (options[i].syntax == needs_directory
00931 #ifdef KEY
00932 || options[i].syntax == needs_directory_or_null
00933 #endif
00934 ) {
00935 fprintf(f, "\tif (want_directory(next_string(argv,argi))) {\n");
00936 }
00937 fprintf(f, "\t\toptargs = get_optarg(argv, argi);\n");
00938 if (options[i].syntax == needs_decimal) {
00939 fprintf(f, "\t\toptargd = atoi(optargs);\n");
00940 }
00941 fprintf(f, "\t\tget_next_arg(argi);\n");
00942 if (options[i].syntax == needs_string_or_dash)
00943 fprintf(f, "\t\treturn add_string_option_or_dash(%s,optargs);\n",
00944 options[i].flag);
00945 #ifdef KEY
00946 else if (options[i].syntax == needs_directory)
00947 fprintf(f, "\t\treturn add_any_string_option(%s,optargs);\n",
00948 options[i].flag);
00949 #endif
00950 else
00951 fprintf(f, "\t\treturn add_string_option(%s,optargs);\n",
00952 options[i].flag);
00953 fprintf(f, "\t\t/* NOTREACHED */\n");
00954 if (options[i].syntax == needs_directory
00955 #ifdef KEY
00956 || options[i].syntax == needs_directory_or_null
00957 #endif
00958 ) {
00959 fprintf(f, "\t} else if (!is_last_char(argv,argi)) {\n");
00960 fprintf(f, "\t\tif (fullwarn) {\n");
00961 fprintf(f, "\t\t\twarning(\"%%s does not refer to a valid directory\", option_name);\n");
00962 fprintf(f, "\t\t}\n");
00963 fprintf(f, "\t\toptargs = get_optarg(argv,argi);\n");
00964 fprintf(f, "\t\tget_next_arg(argi);\n");
00965 #ifdef KEY
00966 fprintf(f, "\t\treturn add_any_string_option(%s,optargs);\n",
00967 options[i].flag);
00968 #else
00969 fprintf(f, "\t\treturn add_string_option(%s,optargs);\n",
00970 options[i].flag);
00971 #endif
00972 fprintf(f, "\t\t/* NOTREACHED */\n");
00973 }
00974 #ifdef KEY
00975
00976
00977 if (options[i].syntax == needs_directory_or_null) {
00978 fprintf(f, "\t} else {\n");
00979 fprintf(f, "\t optargs = current_string(argv,argi);\n");
00980 fprintf(f, "\t get_next_arg(argi);\n");
00981 fprintf(f, "\t return O_dummy;\n");
00982 }
00983 #endif
00984 if (options[i].syntax != needs_string
00985 && options[i].syntax != needs_string_or_dash
00986 ) {
00987 fprintf(f, "\t}\n");
00988 }
00989 if (strlen(options[i].name) > 2) {
00990 fprintf(f, "\t}\n");
00991 }
00992 break;
00993 case complicated:
00994
00995
00996 if (strlen(options[i].name) > 2) {
00997 fprintf(f, "\tif (strncmp(argv[*argi],\"%s\",%ld) == 0) {\n",
00998 options[i].name, (long)strlen(options[i].name));
00999 }
01000 fprintf(f, "\t\treturn parse_%s_option(argv, argi);\n",
01001 options[i].name+1);
01002 fprintf(f, "\t\t/* NOTREACHED */\n");
01003 if (strlen(options[i].name) > 2) {
01004 fprintf(f, "\t}\n");
01005 }
01006 break;
01007 }
01008 if (i+1 < num_options
01009 && options[i+1].name[1] == options[i].name[1])
01010 {
01011
01012 i++;
01013 } else {
01014 break;
01015 }
01016 }
01017 fprintf(f, "\tbreak;\n");
01018 i++;
01019 }
01020 fprintf(f, "}\n");
01021 fprintf(f, "optargs = current_string(argv,argi);\n");
01022 fprintf(f, "get_next_arg(argi);\n");
01023 fprintf(f, "return O_Unrecognized;\n");
01024 fprintf(f, "}\n");
01025
01026
01027 fprintf(f, "/* if alias, return real option index */\n");
01028 fprintf(f, "extern int\n");
01029 fprintf(f, "get_real_option_if_aliased(int flag)\n");
01030 fprintf(f, "{\n");
01031 fprintf(f, " switch (flag) {\n");
01032 for (i = 0; i < num_options; i++) {
01033
01034
01035
01036 if (options[i].languages == get_language_mask(L_ALL)
01037 && options[i].phases == 0
01038 && EMPTY(options[i].action)
01039 && options[i].implies != NULL
01040 && options[i].implies->next == NULL)
01041 {
01042 j = options[i].implies->info_index;
01043 if (options[i].syntax == normal
01044 || options[i].syntax == oneletter)
01045 {
01046 if (options[j].syntax == normal) {
01047 fprintf(f, "\tcase %s: return %s;\n",
01048 options[i].flag,
01049 options[j].flag);
01050 }
01051 else if (options[j].syntax == needs_string ||
01052 options[j].syntax == needs_string_or_dash) {
01053 fprintf(f, "\tcase %s: {\n", options[i].flag);
01054 fprintf(f, "\t\toptargs = \"%s\";\n",
01055 options[i].implies->name
01056 + strlen(options[j].name));
01057 fprintf(f, "\t\treturn add_string_option(%s,optargs);\n",
01058 options[j].flag);
01059 fprintf(f, "\t\t}\n");
01060 }
01061 else continue;
01062 }
01063 else if (options[i].syntax == options[j].syntax) {
01064
01065 fprintf(f, "\tcase %s: return %s;\n",
01066 options[i].flag,
01067 options[j].flag);
01068 }
01069 else continue;
01070 }
01071 }
01072 fprintf(f, "\tdefault: return flag;\n");
01073 fprintf(f, " }\n");
01074 fprintf(f, "}\n");
01075 fclose(f);
01076 }
01077
01078 static void
01079 write_opt_action (void)
01080 {
01081 int i;
01082 buffer_t buf;
01083 char *tvar;
01084 char *tval;
01085 FILE *f;
01086 f = begin_file("opt_action.i");
01087 fprintf(f, "#include \"string_utils.h\"\n\n");
01088 fprintf(f, "#include \"get_options.h\"\n\n");
01089 fprintf(f, "#include \"lib_phase_dir.h\"\n\n");
01090 fprintf(f, "/* do action associated with option */\n");
01091 fprintf(f, "extern void\n");
01092 fprintf(f, "opt_action (int optflag)\n");
01093 fprintf(f, "{\n");
01094 fprintf(f, "switch (optflag) {\n");
01095
01096 for (i = 0; i < num_options; i++) {
01097 if (!options[i].internal &&
01098
01099 !EMPTY(options[i].action) &&
01100 find_by_flag(options[i].flag, i) == NULL) {
01101 fprintf(f, "case %s:\n", options[i].flag);
01102 fprintf(f, "\t%s\n", options[i].action);
01103 fprintf(f, "\tbreak;\n");
01104 }
01105 }
01106 fprintf(f, "}\n");
01107 fprintf(f, "}\n\n");
01108 fprintf(f, "/* return whether to mark this flag as unseen */\n");
01109 fprintf(f, "extern boolean\n");
01110 fprintf(f, "flag_is_superceded (int optflag)\n");
01111 fprintf(f, "{\n");
01112 fprintf(f, "switch (optflag) {\n");
01113 for (i = 0; i < num_options; i++) {
01114 if (options[i].toggle) {
01115 if (find_by_flag(options[i].flag, i))
01116 continue;
01117
01118 fprintf(f, "case %s:\n", options[i].flag);
01119
01120 strcpy(buf, options[i].action+8);
01121 tvar = strtok(buf,COMMA);
01122
01123 tval = strtok(NULL,RPAREN);
01124 fprintf(f, "\tif (%s != %s) return TRUE;\n", tvar, tval);
01125 fprintf(f, "\tbreak;\n");
01126 }
01127 }
01128 fprintf(f, "}\n");
01129 fprintf(f, "return FALSE;\n");
01130 fprintf(f, "}\n\n");
01131 fclose(f);
01132 }
01133
01134 #if 0
01135 static void
01136 write_check_combos (void)
01137 {
01138 int i, n;
01139 index_list_t *q;
01140 FILE *f;
01141 f = fopen("check_combos.c", "w");
01142 fprintf(f, "/* THIS FILE IS AUTOMATICALLY GENERATED BY table */\n\n");
01143 fprintf(f, "#include <stddef.h>\n");
01144 fprintf(f, "#include \"options.h\"\n");
01145 fprintf(f, "#include \"option_seen.h\"\n");
01146 fprintf(f, "#include \"option_names.h\"\n");
01147 fprintf(f, "#include \"opt_actions.h\"\n");
01148 fprintf(f, "#include \"errors.h\"\n");
01149 fprintf(f, "\n");
01150 fprintf(f, "/* replace individual options with combo */\n");
01151 fprintf(f, "static void\n");
01152 fprintf(f, "replace_with_combo (int combo_index)\n");
01153 fprintf(f, "{\n");
01154 fprintf(f, "\tint flag;\n");
01155 fprintf(f, "\tint count = 1;\n");
01156 fprintf(f, "\tFOREACH_OPTION_IN_COMBO(flag,combo_index) {\n");
01157 fprintf(f, "\t\tif (count == 1) {\n");
01158 fprintf(f, "\t\t\treplace_option_seen(flag, combo_index);\n");
01159 fprintf(f, "\t\t} else {\n");
01160 fprintf(f, "\t\t\tset_option_unseen(flag);\n");
01161 fprintf(f, "\t\t}\n");
01162 fprintf(f, "\t\tcount++;\n");
01163 fprintf(f, "\t}\n");
01164 fprintf(f, "}\n\n");
01165 fprintf(f, "static void\n");
01166 fprintf(f, "report_combo_errors (void)\n");
01167 fprintf(f, "{\n");
01168 for (i = 0; i < num_options; i++) {
01169 if (options[i].syntax == combo && !EMPTY(options[i].action)) {
01170 if (find_by_flag(options[i].flag, i))
01171 continue;
01172 fprintf(f, "\tif (option_was_seen(%s)) {\n",
01173 options[i].flag);
01174 if (strcmp(options[i].action, "WARNING") == 0) {
01175 fprintf(f, "\t\twarning(\"%s combination not allowed, replaced with %s\");\n",
01176 options[i].name, list_to_string(options[i].implies));
01177 } else {
01178 fprintf(f, "\t\tparse_error(\"%s\", \"illegal combination\");\n",
01179 options[i].name);
01180 }
01181 fprintf(f, "\t}\n");
01182 }
01183 }
01184 fprintf(f, "}\n\n");
01185 fprintf(f, "extern boolean\n");
01186 fprintf(f, "is_replacement_combo (int combo_index)\n");
01187 fprintf(f, "{\n");
01188 fprintf(f, "\tswitch (combo_index) {\n");
01189 for (i = n = 0; i < num_options; i++) {
01190 if (options[i].syntax == combo && !EMPTY(options[i].action)
01191 && strcmp(options[i].action, "WARNING") == 0 )
01192 {
01193 if (find_by_flag(options[i].flag, i))
01194 continue;
01195 fprintf(f, "\tcase %s:\n", options[i].flag);
01196 n++;
01197 }
01198 }
01199 if (n)
01200 fprintf(f, "\t\treturn TRUE;\n");
01201 fprintf(f, "\tdefault:\n");
01202 fprintf(f, "\t\treturn FALSE;\n");
01203 fprintf(f, "\t}\n");
01204 fprintf(f, "}\n\n");
01205 fprintf(f, "extern void\n");
01206 fprintf(f, "check_for_combos (void)\n");
01207 fprintf(f, "{\n");
01208 for (i = 0; i < num_options; i++) {
01209 if (options[i].syntax == combo) {
01210 if (find_by_flag(options[i].flag, i))
01211 continue;
01212 q = options[i].combo_list;
01213 if (q == NULL) internal_error("empty combo_list?");
01214 fprintf(f, "\tif (");
01215 if (q->negated) fprintf(f, "!");
01216 fprintf(f, "option_was_seen(%s)",
01217 options[q->info_index].flag);
01218 q = q->next;
01219 while (q != NULL) {
01220 fprintf(f, " && ");
01221 if (q->negated) fprintf(f, "!");
01222 fprintf(f, "option_was_seen(%s)",
01223 options[q->info_index].flag);
01224 q = q->next;
01225 }
01226 fprintf(f, ") {\n");
01227
01228 fprintf(f, "\t\treplace_with_combo(%s);\n",
01229 options[i].flag);
01230
01231 for (q = options[i].combo_list; q != NULL; q = q->next) {
01232 if (options[q->info_index].toggle) {
01233 fprintf(f, "\t\tun%s\n",
01234 options[q->info_index].action);
01235 }
01236 }
01237 fprintf(f, "\t}\n");
01238 }
01239 }
01240 fprintf(f, "\treport_combo_errors();\n");
01241 fprintf(f, "}\n\n");
01242 fclose(f);
01243 }
01244 #endif
01245
01246 static void
01247 write_implicits (void)
01248 {
01249 int i;
01250 FILE *f;
01251 f = fopen("implicits.c", "w");
01252 fprintf(f, "/* THIS FILE IS AUTOMATICALLY GENERATED BY table */\n\n");
01253 fprintf(f, "#include \"string_utils.h\"\n\n");
01254 fprintf(f, "#include \"options.h\"\n");
01255 fprintf(f, "#include \"option_seen.h\"\n");
01256 fprintf(f, "#include \"option_names.h\"\n");
01257 fprintf(f, "#include \"opt_actions.h\"\n");
01258 fprintf(f, "#include \"get_options.h\"\n\n");
01259 fprintf(f, "#include \"errors.h\"\n");
01260 fprintf(f, "extern void\n");
01261 fprintf(f, "toggle_implicits (void)\n");
01262 fprintf(f, "{\n");
01263 for (i = 0; i < num_options; i++) {
01264 if (options[i].toggle) {
01265 if (strstr(options[i].action, "optarg") != NULL) {
01266
01267
01268 continue;
01269 }
01270 fprintf(f, "\tif (option_was_implicitly_seen(%s)) {\n",
01271 options[i].flag);
01272 fprintf(f, "\t\toption_name = get_option_name(%s);\n",
01273 options[i].flag);
01274 fprintf(f, "\t\t%s\n", options[i].action);
01275 fprintf(f, "\t}\n");
01276 }
01277 }
01278 fprintf(f, "}\n\n");
01279 fclose(f);
01280 }
01281
01282 int
01283 main (int argc, char *argv[])
01284 {
01285 boolean debug = FALSE;
01286 program_name = argv[0];
01287 if (argc == 2 && strcmp(argv[1], "-phase") == 0) {
01288 table_for_phase = TRUE;
01289 }
01290 read_table();
01291 fill_option_info();
01292 if (debug) dump_option_info();
01293
01294 write_option_names();
01295 write_init_options();
01296 write_get_option();
01297 write_opt_action();
01298 #if 0
01299 if (!table_for_phase) {
01300 write_check_combos();
01301 }
01302 #endif
01303 write_implicits();
01304 return(error_status);
01305 }