%{ #include #include #include #include #include #include "coder.h" extern int yylex(); extern void free_flex_memory(void); /* Affiche un message d'erreur suite à l'analyse en échec. */ static int d2c_error(rented_coder *coder, char *s); /* Affiche des indications sur l'utilisation du programme. */ static void show_usage(const char *argv0); %} %code requires { /* Pour la définition des expressions conditionnelles... */ #include "coder.h" struct action_tmp { CondActionType action; const char *details; }; } %union { char *string; /* Chaîne de caractères #1 */ const char *cstring; /* Chaîne de caractères #2 */ int integer; cond_expr *expr; /* Expression de déclenchement */ struct action_tmp tmpa; /* Transfert temporaire */ } %parse-param { rented_coder *coder } %token COPYRIGHT %token TITLE %token INS_NAME INS_DETAILS %token ENCODING %token THUMB ARCH NUMBER %token ENC_START ENC_END %token WORD HALF NAME SIZE BIT %token SYNTAX OPERAND_INTERNAL OPERAND_VISIBLE %token CONV EQ ARG %token RULES IF EXPR_START EQUAL BINVAL EXPR_END AND THEN SEE %type COPYRIGHT INS_NAME %type INS_DETAILS %type NUMBER %type NAME %type SIZE BIT %type OPERAND_INTERNAL OPERAND_VISIBLE %type ARG %type rule_cond %type BINVAL %type action %% input : name encodings { if (!dump_all_routines_using_coder(coder)) YYABORT; } name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3, NULL); } | COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); } encodings : /* empty */ | encoding encodings encoding : ENCODING THUMB NUMBER content { push_encoding_spec(coder, strdup("t"), $3); } | ENCODING ARCH NUMBER content { push_encoding_spec(coder, strdup("a"), $3); } content : /* empty */ | bitfield content | syntax content | conversions content | rules content bitfield : HALF bits { if (count_coder_bits(coder) != 16) YYABORT; } | WORD bits { if (count_coder_bits(coder) != 32) YYABORT; } bits : /* empty */ | NAME SIZE bits { register_named_field_in_coder(coder, $1, $2); } | BIT bits { register_bit_in_coder(coder, $1); } syntax : SYNTAX operands operands : /* empty */ | operands OPERAND_INTERNAL { register_syntax_item_in_coder(coder, $2, true); } | operands OPERAND_VISIBLE { register_syntax_item_in_coder(coder, $2, false); } conversions : CONV substitutions substitutions : /* empty */ | substitutions NAME EQ NAME ARG { register_conversion_in_coder(coder, $2, $4, $5); } rules : RULES rules_list rules_list : /* empty */ | rules_list rule rule : IF EXPR_START rule_cond EXPR_END THEN action { add_conditional_rule_to_coder(coder, $3, $6.action, $6.details); } rule_cond : NAME EQUAL BINVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); } | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END { $$ = build_composed_cond_expression($2, COT_AND, $6); } action : SEE INS_DETAILS { $$.action = CAT_SEE; $$.details = $2; } %% /****************************************************************************** * * * Paramètres : coder = codeur impliqué dans le processus. * * msg = message d'erreur. * * * * Description : Affiche un message d'erreur suite à l'analyse en échec. * * * * Retour : 0 * * * * Remarques : - * * * ******************************************************************************/ static int d2c_error(rented_coder *coder, char *msg) { printf("yyerror : %s\n", msg); return 0; } /****************************************************************************** * * * Paramètres : argv0 = nombre du programme exécuté. * * * * Description : Affiche des indications sur l'utilisation du programme. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void show_usage(const char *argv0) { printf("\n"); printf("Usage: %s [options] < file\n", argv0); printf("\n"); printf("Options:\n"); printf("\n"); printf("\t-h | --help\t\t\tDisplay this messsage.\n"); printf("\t-d | --dir \t\tSpecify the main output directory.\n"); printf("\t-a | --arch \t\tDefine the archicture to handle.\n"); printf("\t-H | --header \t\tSet the base of the #ifndef / #define game.\n"); printf("\t-e | --encoding \tDefine encoding prefixes for files.\n"); printf("\t-m | --macro \t\tRegister some conversion functions.\n"); printf("\n"); } /****************************************************************************** * * * Paramètres : argc = nombre d'arguments dans la ligne de commande. * * argv = arguments de la ligne de commande. * * * * Description : Point d'entrée du programme. * * * * Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. * * * * Remarques : - * * * ******************************************************************************/ int main(int argc, char **argv) { int result; /* Bilan à retourner */ rented_coder *coder; /* Codeur à briffer & employer */ int index; /* Indice de fichier à traiter */ bool need_help; /* Affichage de l'aide ? */ bool has_error; /* Erreur dans la ligne de cmd.*/ int ret; /* Bilan d'une lecture d'arg. */ char *sep; /* Caratère '=' en coupure */ static struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "dir", required_argument, NULL, 'd' }, { "arch", required_argument, NULL, 'a' }, { "header", required_argument, NULL, 'H' }, { "encoding", required_argument, NULL, 'e' }, { "macro", required_argument, NULL, 'M' }, { NULL, 0, NULL, 0 } }; result = EXIT_SUCCESS; coder = create_coder(); index = 0; need_help = false; has_error = false; while (!has_error) { ret = getopt_long(argc, argv, "hd:a:H:e:M:", long_options, &index); if (ret == -1) break; switch (ret) { case 'h': need_help = true; break; case 'd': set_coder_output_directory(coder, optarg); break; case 'a': set_coder_arch(coder, optarg); break; case 'H': set_coder_header_base(coder, optarg); break; case 'e': sep = strchr(optarg, '='); has_error = (sep == NULL); if (!has_error) { *sep = '\0'; register_encoding_in_coder(coder, optarg, sep + 1); } break; case 'M': sep = strchr(optarg, '='); has_error = (sep == NULL); if (!has_error) { *sep = '\0'; define_macro_for_coder(coder, optarg, sep + 1); } break; } } if (need_help || has_error || !do_basic_checks_with_coder(coder) || optind != argc) { show_usage(argv[0]); result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE); goto exit; } result = yyparse(coder); exit: free_flex_memory(); delete_coder(coder); return result; }