diff options
Diffstat (limited to 'tools/d2c/d2c_gram.y')
-rw-r--r-- | tools/d2c/d2c_gram.y | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y new file mode 100644 index 0000000..5deb053 --- /dev/null +++ b/tools/d2c/d2c_gram.y @@ -0,0 +1,442 @@ + +%{ + +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#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 THUMB ARCH NUMBER +%token ENC_START ENC_END + +%token WORD HALF NAME SIZE BIT + +%token SYNTAX OPERAND_INTERNAL OPERAND_VISIBLE + +%token CONV EQ OP COMMA CP NOT EOR COLON + +%token RULES IF EXPR_START EQUAL BINVAL EXPR_END AND THEN SEE + + +%type <string> COPYRIGHT INS_NAME +%type <cstring> INS_DETAILS + +%type <integer> NUMBER + +%type <string> NAME +%type <integer> SIZE BIT + +%type <string> OPERAND_INTERNAL OPERAND_VISIBLE + + +%type <subst> substitution +%type <conv_list> conv_arg_list +%type <conv> conv_expr conv_arg_composed +%type <un_op> conv_expr_un_op +%type <bin_op> conv_expr_bin_op +%type <string> conv_arg_field + +%type <expr> rule_cond +%type <string> BINVAL +%type <tmpa> 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) + { + 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_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 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); } + | 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 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 <string>\t\tSpecify the main output directory.\n"); + printf("\t-a | --arch <string>\t\tDefine the archicture to handle.\n"); + printf("\t-H | --header <string>\t\tSet the base of the #ifndef / #define game.\n"); + printf("\t-e | --encoding <string>\tDefine encoding prefixes for files.\n"); + printf("\t-m | --macro <string>\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; + +} |