diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2016-01-28 23:32:25 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2016-01-28 23:32:25 (GMT) | 
| commit | 16e0fd9d89ef433848678dfc8dd20426844a2868 (patch) | |
| tree | 79075ae02c133cea21ffb555b1086aae833b3aac /tools/d2c/grammar.y | |
| parent | 66c99d59d6a6d533de0bb65488de8243213bcdea (diff) | |
Cleaned, rewritten and improved the whole code of the compiler.
Diffstat (limited to 'tools/d2c/grammar.y')
| -rw-r--r-- | tools/d2c/grammar.y | 443 | 
1 files changed, 443 insertions, 0 deletions
| diff --git a/tools/d2c/grammar.y b/tools/d2c/grammar.y new file mode 100644 index 0000000..986edd7 --- /dev/null +++ b/tools/d2c/grammar.y @@ -0,0 +1,443 @@ + +%{ + +#include <getopt.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int d2c_error(rented_coder *, char *, char *); + +/* Affiche des indications sur l'utilisation du programme. */ +static void show_usage(const char *); + +/* Prépare le traitement d'un contenu en l'affichant en mémoire. */ +static void *map_input_data(const char *, size_t *); + +%} + + +%code requires { + +#include "coder.h" +#include "helpers.h" +#include "args/decl.h" +#include "bits/decl.h" +#include "conv/decl.h" +#include "hooks/decl.h" +#include "rules/decl.h" +#include "syntax/decl.h" + + +#define handle_coder_bits(c, e, r)                          \ +    ({                                                      \ +        encoding_spec *__spec;                              \ +        coding_bits *__bits;                                \ +        bool __status;                                      \ +        __spec = get_current_encoding_spec(c);              \ +        __bits = get_bits_in_encoding_spec(__spec);         \ +        __status = load_bits_from_raw_line(__bits, e, r);   \ +        if (!__status) YYABORT;                             \ +    }) + +#define handle_coder_syntax(c, r)                           \ +    ({                                                      \ +        encoding_spec *__spec;                              \ +        asm_syntax *__syntax;                               \ +        bool __status;                                      \ +        __spec = get_current_encoding_spec(c);              \ +        __syntax = get_syntax_in_encoding_spec(__spec);     \ +        __status = load_syntax_from_raw_line(__syntax, r);  \ +        if (!__status) YYABORT;                             \ +    }) + +#define handle_coder_conversions(c, r)                      \ +    ({                                                      \ +        encoding_spec *__spec;                              \ +        conv_list *__list;                                  \ +        bool __status;                                      \ +        __spec = get_current_encoding_spec(c);              \ +        __list = get_conversions_in_encoding_spec(__spec);  \ +        __status = load_convs_from_raw_block(__list, r);    \ +        if (!__status) YYABORT;                             \ +    }) + +#define handle_coder_hooks(c, r)                            \ +    ({                                                      \ +        encoding_spec *__spec;                              \ +        instr_hooks *__hooks;;                              \ +        bool __status;                                      \ +        __spec = get_current_encoding_spec(c);              \ +        __hooks = get_hooks_in_encoding_spec(__spec);       \ +        __status = load_hooks_from_raw_line(__hooks, r);    \ +        if (!__status) YYABORT;                             \ +    }) + +#define handle_coder_rules(c, r)                            \ +    ({                                                      \ +        encoding_spec *__spec;                              \ +        decoding_rules *__rules;                            \ +        bool __status;                                      \ +        __spec = get_current_encoding_spec(c);              \ +        __rules = get_rules_in_encoding_spec(__spec);       \ +        __status = load_rules_from_raw_block(__rules, r);   \ +        if (!__status) YYABORT;                             \ +    }) + +} + +%union { + +    char *string;                           /* Chaîne de caractères #1     */ +    const char *cstring;                    /* Chaîne de caractères #2     */ + +    int integer;                            /* Valeur entière              */ + +} + + +/** + * Cf. + * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950 + */ + +%define api.pure full + +%parse-param { rented_coder *coder } { char *temp } +%lex-param { char *temp } + +%code provides { + +#define YY_DECL \ +    int d2c_lex(YYSTYPE *yylvalp, char *temp) + +YY_DECL; + +} + + +%token COPYRIGHT +%token TITLE +%token INS_NAME INS_DETAILS + +%token ENCODING +%token TYPE NUMBER +%token ENC_START ENC_END + +%token WORD HALF +%token SYNTAX +%token CONV +%token HOOKS +%token RULES + +%token RAW_LINE RAW_BLOCK + + +%type <string> COPYRIGHT INS_NAME +%type <cstring> INS_DETAILS + +%type <string> TYPE +%type <integer> NUMBER + +%type <cstring> RAW_LINE RAW_BLOCK + + +%% + + +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 +        | hooks content +        | rules content + + +bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); } +         | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); } + +syntax : SYNTAX RAW_LINE { handle_coder_syntax(coder, $2); } + +conversions : CONV RAW_BLOCK { handle_coder_conversions(coder, $2); } + +hooks : HOOKS RAW_BLOCK { handle_coder_hooks(coder, $2); } + +rules : RULES RAW_BLOCK { handle_coder_rules(coder, $2); } + + +%% + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : coder = codeur impliqué dans le processus.                   * +*                temp  = zone de travail à destination des lectures manuelles.* +*                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 *temp, 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  : filename = chemin du fichier à charger en mémoire.           * +*                length   = taille de l'espace mémoie à mettre en place. [OUT]* +*                                                                             * +*  Description : Prépare le traitement d'un contenu en l'affichant en mémoire.* +*                                                                             * +*  Retour      : Adresse valide ou MAP_FAILED en cas d'échec.                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void *map_input_data(const char *filename, size_t *length) +{ +    void *result;                           /* Espace mémoire à retourner  */ +    int fd;                                 /* Descripteur du fichier      */ +    struct stat info;                       /* Informations sur le fichier */ +    int ret;                                /* Bilan d'un appel            */ + +    result = NULL; + +    fd = open(filename, O_RDONLY); +    if (fd == -1) +    { +        perror("open"); +        goto mid_exit; +    } + +    ret = fstat(fd, &info); +    if (ret == -1) +    { +        perror("fstat"); +        goto mid_exit_with_fd; +    } + +    *length = info.st_size; + +    result = mmap(NULL, *length, PROT_READ, MAP_PRIVATE, fd, 0); +    if (result == MAP_FAILED) +    { +        perror("mmap"); +        goto mid_exit_with_fd; +    } + + mid_exit_with_fd: + +    close(fd); + + mid_exit: + +    return result; + + +} + + +/****************************************************************************** +*                                                                             * +*  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     */ +    size_t length;                          /* Nombre d'octets à traiter   */ +    char *content;                          /* Contenu brut à analyser     */ +    char *temp;                             /* Zone de travail temporaire  */ +    YY_BUFFER_STATE state;                  /* Contexte d'analyse          */ + +    static struct option long_options[] = { + +        { "help",       no_argument,        NULL,   'h' }, +        { "input",      required_argument,  NULL,   'i' }, +        { "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, "hi:d:a:H:e:M:", long_options, &index); +        if (ret == -1) break; + +        switch (ret) +        { +            case 'h': +                need_help = true; +                break; + +            case 'i': +                set_coder_input_file(coder, optarg); +                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; +    } + +    content = map_input_data(get_coder_input_file(coder), &length); +    if (content == MAP_FAILED) +    { +        result = EXIT_FAILURE; +        goto exit; +    } + +    temp = (char *)calloc(length, sizeof(char)); + +    state = d2c__scan_bytes(content, length); + +    result = yyparse(coder, temp); + +    yy_delete_buffer(state); + +    free(temp); + +    munmap(content, length); + + exit: + +    delete_coder(coder); + +    return result; + +} | 
