%{ #include #include #include #include #include #include "coder.h" #include "d2c_tok.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 *, char *); /* Affiche des indications sur l'utilisation du programme. */ static void show_usage(const char *); %} %code requires { /* Pour la définition des expressions conditionnelles... */ #include "coder.h" #include "conv.h" struct action_tmp { CondActionType action; const char *details; }; #define register_named_field_in_coder(c, n, l) \ ({ \ encoding_spec *__spec; \ coding_bits *__bits; \ __spec = get_current_encoding_spec(c); \ __bits = get_bits_in_encoding_spec(__spec); \ register_named_field_in_bits(__bits, n, l); \ }) #define register_bit_in_coder(c, v) \ ({ \ encoding_spec *__spec; \ coding_bits *__bits; \ __spec = get_current_encoding_spec(c); \ __bits = get_bits_in_encoding_spec(__spec); \ register_bit_in_bits(__bits, v); \ }) #define count_coder_bits(c) \ ({ \ encoding_spec *__spec; \ coding_bits *__bits; \ __spec = get_current_encoding_spec(c); \ __bits = get_bits_in_encoding_spec(__spec); \ count_coded_bits(__bits); \ }) #define register_syntax_item_in_coder(c, n, i) \ ({ \ encoding_spec *__spec; \ asm_syntax *__syntax; \ __spec = get_current_encoding_spec(c); \ __syntax = get_syntax_in_encoding_spec(__spec); \ register_syntax_item(__syntax, n, i); \ }) #define register_conversion_in_coder(c, f) \ ({ \ encoding_spec *__spec; \ conv_list *__list; \ __spec = get_current_encoding_spec(c); \ __list = get_conversions_in_encoding_spec(__spec); \ register_conversion(__list, f); \ }) #define add_conditional_rule_to_coder(c, e, a, d) \ ({ \ encoding_spec *__spec; \ decoding_rules *__rules; \ __spec = get_current_encoding_spec(c); \ __rules = get_rules_in_encoding_spec(__spec); \ register_conditional_rule(__rules, e, a, d); \ }) } %union { char *string; /* Chaîne de caractères #1 */ const char *cstring; /* Chaîne de caractères #2 */ int integer; conv_func *subst; /* Fonction de conversion */ conv_arg_list_t *conv_list; /* Liste d'arguments de conv. */ conv_expr_t *conv; /* Expression de conversion */ ConvUnaryOperation un_op; /* Opération unaire */ ConvBinaryOperation bin_op; /* Opération bianire */ 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 TYPE NUMBER %token ENC_START ENC_END %token WORD HALF NAME SIZE BIT %token SYNTAX OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE %token CONV EQ OP COMMA CP NOT EOR COLON %token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE UNPREDICTABLE %type COPYRIGHT INS_NAME %type INS_DETAILS %type TYPE %type NUMBER %type NAME %type SIZE BIT %type OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE %type substitution %type conv_arg_list %type conv_expr conv_arg_composed %type conv_expr_un_op %type conv_expr_bin_op %type conv_arg_field %type rule_cond %type BINVAL IMMVAL %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 TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } content : /* empty */ | bitfield content | syntax content | conversions content | rules content bitfield : HALF bits { if (count_coder_bits(coder) != 16) { fprintf(stderr, "Unexpected word size: %u vs 16\n", count_coder_bits(coder)); YYABORT; } } | WORD bits { if (count_coder_bits(coder) != 32) { fprintf(stderr, "Unexpected word size: %u vs 32\n", count_coder_bits(coder)); 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_NAME { register_syntax_item_in_coder(coder, $2, SIT_KEYWORD); } | operands OPERAND_INTERNAL { register_syntax_item_in_coder(coder, $2, SIT_INT_OPERAND); } | operands OPERAND_VISIBLE { register_syntax_item_in_coder(coder, $2, SIT_EXT_OPERAND); } conversions : CONV substitutions substitutions : /* empty */ | substitutions substitution { register_conversion_in_coder(coder, $2); } substitution : NAME EQ conv_expr { $$ = make_conv_from_expr($1, $3); } | NAME EQ NAME OP conv_arg_list CP { $$ = make_conv_from_func($1, $3, $5); } conv_arg_list : conv_expr { $$ = build_conv_arg_list($1); } | conv_arg_list COMMA conv_expr { $$ = extend_conv_arg_list($1, $3); printf("extend\n"); } conv_expr : NAME { $$ = build_conv_expr_from_name($1); } | NUMBER { $$ = build_conv_expr_from_number($1); } | conv_arg_composed { $$ = $1; } | OP conv_expr CP { $$ = $2; } | conv_expr_un_op conv_expr { $$ = build_unary_conv_expr($2, $1); } | OP conv_expr conv_expr_bin_op conv_expr CP { $$ = build_binary_conv_expr($2, $4, $3); } conv_expr_un_op : NOT { $$ = CUO_NOT; } conv_expr_bin_op : EOR { $$ = CBO_EOR; } conv_arg_composed : conv_arg_field COLON conv_arg_field { $$ = build_composed_conv_expr($1, $3); } | conv_arg_composed COLON conv_arg_field { $$ = extend_composed_conv_expr($1, $3); } conv_arg_field : NAME { $$ = $1; printf(" composed::name '%s'\n", $1); } | BINVAL { $$ = $1; printf(" composed::bin '%s'\n", $1); } 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); } | NAME EQUAL IMMVAL { $$ = 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; } | UNPREDICTABLE { $$.action = CAT_UNPREDICTABLE; $$.details = NULL; } %% /****************************************************************************** * * * 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 line %d: %s\n", d2c_get_lineno(), 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(get_coder_pre_proc(coder), optarg, sep + 1); } break; case 'M': sep = strchr(optarg, '='); has_error = (sep == NULL); if (!has_error) { *sep = '\0'; define_macro(get_coder_pre_proc(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; }