diff options
Diffstat (limited to 'tools/d2c')
| -rw-r--r-- | tools/d2c/Makefile.am | 3 | ||||
| -rw-r--r-- | tools/d2c/bits/manager.c | 14 | ||||
| -rw-r--r-- | tools/d2c/coder.c | 248 | ||||
| -rw-r--r-- | tools/d2c/coder.h | 18 | ||||
| -rw-r--r-- | tools/d2c/d2c.mk | 37 | ||||
| -rwxr-xr-x | tools/d2c/d2c_genmakefile.sh | 60 | ||||
| -rw-r--r-- | tools/d2c/format/Makefile.am | 31 | ||||
| -rw-r--r-- | tools/d2c/format/decl.h | 37 | ||||
| -rw-r--r-- | tools/d2c/format/grammar.y | 107 | ||||
| -rw-r--r-- | tools/d2c/format/manager.c | 145 | ||||
| -rw-r--r-- | tools/d2c/format/manager.h | 50 | ||||
| -rw-r--r-- | tools/d2c/format/tokens.l | 26 | ||||
| -rw-r--r-- | tools/d2c/grammar.y | 79 | ||||
| -rw-r--r-- | tools/d2c/pproc.c | 26 | ||||
| -rw-r--r-- | tools/d2c/pproc.h | 3 | ||||
| -rw-r--r-- | tools/d2c/spec.c | 134 | ||||
| -rw-r--r-- | tools/d2c/spec.h | 7 | ||||
| -rw-r--r-- | tools/d2c/tokens.l | 110 | 
18 files changed, 997 insertions, 138 deletions
diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am index e89384f..dc4fdf8 100644 --- a/tools/d2c/Makefile.am +++ b/tools/d2c/Makefile.am @@ -33,6 +33,7 @@ d2c_SOURCES =							\  d2c_LDADD =								\  	bits/libd2cbits.la					\  	conv/libd2cconv.la					\ +	format/libd2cformat.la				\  	hooks/libd2chooks.la				\  	rules/libd2crules.la				\  	syntax/libd2csyntax.la				\ @@ -43,4 +44,4 @@ d2c_LDADD =								\  CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h -SUBDIRS = args bits conv hooks rules syntax +SUBDIRS = args bits conv format hooks rules syntax diff --git a/tools/d2c/bits/manager.c b/tools/d2c/bits/manager.c index db6392d..cc2783b 100644 --- a/tools/d2c/bits/manager.c +++ b/tools/d2c/bits/manager.c @@ -282,9 +282,9 @@ raw_bitfield *find_named_field_in_bits(const coding_bits *bits, const char *name  /******************************************************************************  *                                                                             * -*  Paramètres  : spec    = spécification servant de base à l'opération.       * -*                fd      = descripteur d'un flux ouvert en écriture.          * -*                wide    = taille des mots manipulés (en bits).               * +*  Paramètres  : spec = spécification servant de base à l'opération.          * +*                fd   = descripteur d'un flux ouvert en écriture.             * +*                wide = taille des mots manipulés (en bits).                  *  *                                                                             *  *  Description : Déclare les variables C associées aux champs de bits.        *  *                                                                             * @@ -309,8 +309,8 @@ bool declare_used_bits_fields(const coding_bits *bits, int fd, unsigned int wide  /******************************************************************************  *                                                                             * -*  Paramètres  : spec    = spécification servant de base à l'opération.       * -*                fd      = descripteur d'un flux ouvert en écriture.          * +*  Paramètres  : spec = spécification servant de base à l'opération.          * +*                fd   = descripteur d'un flux ouvert en écriture.             *  *                                                                             *  *  Description : Vérifie que les bits fixes correspondent au masque attendu.  *  *                                                                             * @@ -353,8 +353,8 @@ bool check_bits_correctness(const coding_bits *bits, int fd)  /******************************************************************************  *                                                                             * -*  Paramètres  : spec    = spécification servant de base à l'opération.       * -*                fd      = descripteur d'un flux ouvert en écriture.          * +*  Paramètres  : spec = spécification servant de base à l'opération.          * +*                fd   = descripteur d'un flux ouvert en écriture.             *  *                                                                             *  *  Description : Définit les variables C associées aux champs de bits.        *  *                                                                             * diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c index 83910aa..869461f 100644 --- a/tools/d2c/coder.c +++ b/tools/d2c/coder.c @@ -47,14 +47,18 @@  struct _rented_coder  {      const char *input;                      /* Fichier de définitions      */ +    InputOutputType type;                   /* Type des définitions (E/S)  */      const char *outdir;                     /* Lieu d'enregistrement       */      const char *arch;                       /* Architecture à traiter      */      const char *header;                     /* En-tête pour les en-têtes   */ +    const char *const_prefix;               /* Préfixe pour les opérandes  */      pre_processor *pp;                      /* Pré-processeur avec macros  */      char *copyright;                        /* Récupération des droits     */      char *ins;                              /* Désignation humaine         */ +    char separator;                         /* Caractère de séparation     */ +    char *raw_details;                      /* Eventuels compléments bruts */      char *details;                          /* Eventuels compléments       */      encoding_spec **specs;                  /* Définitions déjà en place   */ @@ -89,6 +93,9 @@ static int create_code_file(const rented_coder *, const char *, const char *, co  /* Ecrit une partie des fonctions issues des spécifications. */  static bool dump_all_matching_specs_in_coder(const rented_coder *, const string_exch *, int, int); +/* Ecrit une partie des fonctions issues des spécifications. */ +static bool dump_all_matching_specs_from_format(const rented_coder *, const string_exch *, int, int); +  /* ---------------------------------------------------------------------------------- */ @@ -144,8 +151,11 @@ void delete_coder(rented_coder *coder)      if (coder->ins != NULL)          free(coder->ins); -    if (coder->details != NULL) +    if (coder->raw_details != NULL) +    { +        free(coder->raw_details);          free(coder->details); +    }      for (i = 0; i < coder->specs_count; i++)          delete_encoding_spec(coder->specs[i]); @@ -174,7 +184,15 @@ void delete_coder(rented_coder *coder)  bool do_basic_checks_with_coder(const rented_coder *coder)  { -    return (coder->outdir != NULL && coder->arch != NULL && coder->header != NULL); +    bool result;                            /* Validité à retourner        */ + +    result = coder->type != IOT_UNDEFINED && coder->outdir != NULL; +    result &= coder->arch != NULL && coder->header != NULL; + +    if (coder->type == IOT_FORMAT) +        result &= (coder->const_prefix != NULL); + +    return result;  } @@ -220,6 +238,26 @@ void set_coder_input_file(rented_coder *coder, const char *input)  /******************************************************************************  *                                                                             * +*  Paramètres  : coder = gestion par la machine en remplacement de l'humain.  * +*                type  = type de définition à attendre.                       * +*                                                                             * +*  Description : Spécifie le type de format à prendre en compte (E/S).        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void set_coder_input_type(rented_coder *coder, InputOutputType type) +{ +    coder->type = type; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : coder  = gestion par la machine en remplacement de l'humain. *  *                outdir = répertoire de génération des fichiers.              *  *                                                                             * @@ -280,6 +318,26 @@ void set_coder_header_base(rented_coder *coder, const char *header)  /******************************************************************************  *                                                                             * +*  Paramètres  : coder  = gestion par la machine en remplacement de l'humain. * +*                prefix = préfixe pour les types d'opérandes.                 * +*                                                                             * +*  Description : Définit le préfixe pour les opérandes chargées par format.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void set_coder_const_prefix(rented_coder *coder, const char *prefix) +{ +    coder->const_prefix = prefix; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : coder = gestion par la machine en remplacement de l'humain.  *  *                                                                             *  *  Description : Fournit le pré-processeur du compilateur.                    * @@ -302,6 +360,7 @@ pre_processor *get_coder_pre_proc(const rented_coder *coder)  *  Paramètres  : coder   = gestion par la machine en remplacement de l'humain.*  *                copy    = droits de copie en anglais.                        *  *                ins     = désignation humaine de l'instruction.              * +*                sep     = caractère de séparation avant les détails.         *  *                details = compléments d'informations éventuels ou NULL.      *  *                                                                             *  *  Description : Enregistre les contours d'une instruction d'assemblage.      * @@ -312,11 +371,23 @@ pre_processor *get_coder_pre_proc(const rented_coder *coder)  *                                                                             *  ******************************************************************************/ -void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, const char *details) +void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, char sep, const char *details)  {      coder->copyright = copy;      coder->ins = make_string_lower(ins); -    coder->details = (details != NULL ? make_callable(details, true) : strdup("")); + +    coder->separator = sep; + +    if (details != NULL) +    { +        coder->raw_details = strdup(details); +        coder->details = make_callable(details, true); +    } +    else +    { +        coder->raw_details = strdup(""); +        coder->details = strdup(""); +    }  } @@ -366,7 +437,8 @@ void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index)      spec = coder->cur_spec; -    define_encoding_spec_code_name(spec, prefix, index); +    if (prefix != NULL) +        define_encoding_spec_code_name(spec, prefix, index);      coder->specs = (encoding_spec **)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec *));      coder->specs[coder->specs_count - 1] = spec; @@ -494,9 +566,18 @@ static char *build_template_filename(const rented_coder *coder, const char *pref      char *result;                           /* Chaîne construite à renvoyer*/      size_t length;                          /* Taille du nom de fichier    */ -    length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(prefix) + 1 + strlen(name) + 3; -    result = (char *)calloc(length, sizeof(char)); -    snprintf(result, length, ".gen/%s.%s.tmpl.%c", prefix, name, ext); +    if (prefix == NULL) +    { +        length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(name) + 3; +        result = (char *)calloc(length, sizeof(char)); +        snprintf(result, length, ".gen/%s.tmpl.%c", name, ext); +    } +    else +    { +        length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(prefix) + 1 + strlen(name) + 3; +        result = (char *)calloc(length, sizeof(char)); +        snprintf(result, length, ".gen/%s.%s.tmpl.%c", prefix, name, ext); +    }      return result; @@ -523,6 +604,7 @@ static bool create_template_file(const rented_coder *coder, const char *prefix,      char *pathname;                         /* Chemin d'accès à constituer */      bool exist;                             /* Note une présence établie   */      int fd;                                 /* Flux ouvert pour création   */ +    const char *valid_prefix;               /* Prefix vide au besoin       */      char *uprefix;                          /* Préfixe en majuscule        */      char *uname;                            /* Nom en majuscule            */ @@ -545,11 +627,13 @@ static bool create_template_file(const rented_coder *coder, const char *prefix,      if (fd != -1)      { -        write_owner_comments(coder, fd, prefix, name, ext); +        valid_prefix = prefix != NULL ? prefix : ""; + +        write_owner_comments(coder, fd, valid_prefix, name, ext);          if (ext == 'h')          { -            uprefix = make_string_upper(strdup(prefix)); +            uprefix = make_string_upper(strdup(valid_prefix));              uname = make_string_upper(strdup(name));              dprintf(fd, "#ifndef %s_%s%s_H\n", coder->header, uprefix, uname); @@ -568,7 +652,7 @@ static bool create_template_file(const rented_coder *coder, const char *prefix,          }          else          { -            dprintf(fd, "#include \"%sopcodes.h\"\n", prefix); +            dprintf(fd, "#include \"%sopcodes.h\"\n", valid_prefix);              dprintf(fd, "\n");              dprintf(fd, "##INCLUDES##\n"); @@ -611,9 +695,18 @@ static char *build_code_filename(const rented_coder *coder, const char *input, c      point = strstr(orig, ".");      if (point != NULL) *point = '\0'; -    length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(prefix) + 1 + strlen(name) + 3; -    result = (char *)calloc(length, sizeof(char)); -    snprintf(result, length, ".gen/%s.%s.%s.%c", orig, prefix, name, ext); +    if (prefix == NULL) +    { +        length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(name) + 3; +        result = (char *)calloc(length, sizeof(char)); +        snprintf(result, length, ".gen/%s.%s.%c", orig, name, ext); +    } +    else +    { +        length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(prefix) + 1 + strlen(name) + 3; +        result = (char *)calloc(length, sizeof(char)); +        snprintf(result, length, ".gen/%s.%s.%s.%c", orig, prefix, name, ext); +    }      free(orig); @@ -807,7 +900,22 @@ bool dump_all_routines_using_coder(const rented_coder *coder)              /* Production de code... */ -            result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd); +            switch (coder->type) +            { +                case IOT_UNDEFINED: +                    assert(false); +                    result = false; +                    break; + +                case IOT_RAW: +                    result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd); +                    break; + +                case IOT_FORMAT: +                    result = dump_all_matching_specs_from_format(coder, encoding, header_fd, code_fd); +                    break; + +            }              close(header_fd);              close(code_fd); @@ -899,7 +1007,7 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st          dprintf(cfd, "*\n");      dprintf(cfd, "                                                                              *\n"); -    dprintf(cfd, "*  Retour      : Bilan de l'opération.                                        *\n"); +    dprintf(cfd, "*  Retour      : Instruction mise en place ou NULL en cas d'échec.            *\n");      dprintf(cfd, "*                                                                             *\n");      dprintf(cfd, "*  Remarques   : -                                                            *\n");      dprintf(cfd, "*                                                                             *\n"); @@ -942,3 +1050,111 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : coder    = gestion par la machine en remplacement d'humain.  * +*                encoding = sélection de l'encodage à traiter.                * +*                hfd      = flux ouvert en écriture pour les déclarations.    * +*                cfd      = flux ouvert en écriture pour les définitions.     * +*                                                                             * +*  Description : Ecrit une partie des fonctions issues des spécifications.    * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool dump_all_matching_specs_from_format(const rented_coder *coder, const string_exch *encoding, int hfd, int cfd) +{ +    bool result;                            /* Bilan à retourner           */ +    char *keyword;                          /* Mot clef appelable en code  */ +    size_t maxlen;                          /* Taille à compléter          */ +    encoding_spec *spec;                    /* Définition à traiter        */ + +    keyword = make_callable(coder->ins, false); + +    /* Désassemblage : déclaration */ + +    dprintf(hfd, "/* Décode une instruction de type '%s'. */\n", coder->ins); + +    if (encoding->dest == NULL) +        dprintf(hfd, "GArchInstruction *%s_read_instr_%s%s", +                coder->arch, keyword, coder->details); +    else +        dprintf(hfd, "GArchInstruction *%s_read_%sinstr_%s%s", +                coder->arch, encoding->dest, keyword, coder->details); + +    dprintf(hfd, "("); +    dprintf(hfd, "const GArchProcessor *, GProcContext *, const GBinContent *, "); +    dprintf(hfd, "vmpa2t *, GExeFormat *"); +    dprintf(hfd, ");\n"); + +    dprintf(hfd, "\n"); + +    /* Désassemblage : définitions */ + +    dprintf(cfd, "\n"); + +    dprintf(cfd, "/******************************************************************************\n"); +    dprintf(cfd, "*                                                                             *\n"); +    dprintf(cfd, "*  Paramètres  : proc    = processeur de l'architecture d'exécution.          *\n"); +    dprintf(cfd, "*                ctx     = contexte associé à la phase de désassemblage.      *\n"); +    dprintf(cfd, "*                content = flux de données à analyser.                        *\n"); +    dprintf(cfd, "*                pos     = position courante dans ce flux. [OUT]              *\n"); +    dprintf(cfd, "*                format  = format du fichier contenant le code.               *\n"); +    dprintf(cfd, "*                                                                             *\n"); +    dprintf(cfd, "*  Description : Décode une instruction de type '%s'.", coder->ins); + +    maxlen = 28 - strlen(coder->ins); + +    if (maxlen < 28) +        dprintf(cfd, "%*s\n", (int)maxlen, "*"); +    else +        dprintf(cfd, "*\n"); + +    dprintf(cfd, "                                                                              *\n"); +    dprintf(cfd, "*  Retour      : Instruction mise en place ou NULL en cas d'échec.            *\n"); +    dprintf(cfd, "*                                                                             *\n"); +    dprintf(cfd, "*  Remarques   : -                                                            *\n"); +    dprintf(cfd, "*                                                                             *\n"); +    dprintf(cfd, "******************************************************************************/\n"); + +    dprintf(cfd, "\n"); + +    if (encoding->dest == NULL) +        dprintf(cfd, "GArchInstruction *%s_read_instr_%s%s", +                coder->arch, keyword, coder->details); +    else +        dprintf(cfd, "GArchInstruction *%s_read_%sinstr_%s%s", +                coder->arch, encoding->dest, keyword, coder->details); + +    dprintf(cfd, "("); +    dprintf(cfd, "const GArchProcessor *proc, GProcContext *ctx, const GBinContent *content, "); +    dprintf(cfd, "vmpa2t *pos, GExeFormat *format"); +    dprintf(cfd, ")"); + +    dprintf(cfd, "\n"); +    dprintf(cfd, "{"); +    dprintf(cfd, "\n"); + +    assert(coder->specs_count == 1); + +    spec = coder->specs[0]; + +    assert(has_encoding_spec_prefix(spec, encoding->src)); + +    result = write_encoding_spec_format_disass(spec, cfd, coder->arch, encoding->dest, +                                               coder->ins, coder->separator, coder->raw_details, +                                               coder->pp, coder->const_prefix); + +    dprintf(cfd, "}\n"); +    dprintf(cfd, "\n"); + +    free(keyword); + +    return result; + +} diff --git a/tools/d2c/coder.h b/tools/d2c/coder.h index d9f0f0e..7ba88bc 100644 --- a/tools/d2c/coder.h +++ b/tools/d2c/coder.h @@ -41,6 +41,16 @@ typedef struct _rented_coder rented_coder;  /* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */ +/* Type d'entrée/sortie attendues */ +typedef enum _InputOutputType +{ +    IOT_UNDEFINED,                          /* Type non défini             */ +    IOT_RAW,                                /* Lecture de contenu brut     */ +    IOT_FORMAT                              /* Définition d'opérandes      */ + +} InputOutputType; + +  /* Débute la définition d'une fonction de désassemblage. */  rented_coder *create_coder(void); @@ -56,6 +66,9 @@ const char *get_coder_input_file(const rented_coder *);  /* Spécifie le fichier de définition à prendre en entrée. */  void set_coder_input_file(rented_coder *, const char *); +/* Spécifie le type de format à prendre en compte (E/S). */ +void set_coder_input_type(rented_coder *, InputOutputType); +  /* Spécifie le répertoire de base pour les sorties de code. */  void set_coder_output_directory(rented_coder *, const char *); @@ -65,11 +78,14 @@ void set_coder_arch(rented_coder *, const char *);  /* Définit la base des protections des fichiers d'en-tête. */  void set_coder_header_base(rented_coder *, const char *); +/* Définit le préfixe pour les opérandes chargées par format. */ +void set_coder_const_prefix(rented_coder *, const char *); +  /* Fournit le pré-processeur du compilateur. */  pre_processor *get_coder_pre_proc(const rented_coder *);  /* Enregistre les contours d'une instruction d'assemblage. */ -void save_notes_for_coder(rented_coder *, char *, char *, const char *); +void save_notes_for_coder(rented_coder *, char *, char *, char, const char *); diff --git a/tools/d2c/d2c.mk b/tools/d2c/d2c.mk index b0b7b92..72269b7 100644 --- a/tools/d2c/d2c.mk +++ b/tools/d2c/d2c.mk @@ -9,19 +9,42 @@ fix_verbose = $(fix_verbose_@AM_V@)  fix_verbose_ = $(fix_verbose_@AM_DEFAULT_V@)  fix_verbose_0 = echo "  FIX     " `basename $$f`; -# D2C_BIN =  -# D2C_OUTDIR =  -# D2C_ARCH =  -# D2C_HEADER =  -# D2C_ENCODINGS =  -# D2C_MACROS =  + +# D2C_BIN = +# D2C_TYPE = +# D2C_OUTDIR = +# D2C_ARCH = +# D2C_HEADER = +# D2C_ENCODINGS = +# D2C_MACROS = +# D2C_PREFIX = + +# FIXED_C_INCLUDES = +# FIXED_H_INCLUDES = +  SUFFIXES = .g  .d.g: -	$(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) +	$(d2c_verbose)$(D2C_BIN) -i $< -t $(D2C_TYPE) -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) -p $(D2C_PREFIX)  	@touch $@ +d2c_final_rules: fix_includes_in_c_templates fix_includes_in_h_templates untabify_disass + +fix_includes_in_c_templates: +	for f in `find .gen/ -name '*tmpl.c'`; do			\ +		if grep -q '##INCLUDES##' $$f; then				\ +			$(fix_verbose)sed -i 's/##INCLUDES##/$(FIXED_C_INCLUDES)/' $$f;	\ +		fi;												\ +	done + +fix_includes_in_h_templates: +	@for f in `find .gen/ -name '*tmpl.h'`; do			\ +		if grep -q '##INCLUDES##' $$f; then				\ +			$(fix_verbose)sed -i 's/##INCLUDES##/$(FIXED_H_INCLUDES)/' $$f ;	\ +		fi;												\ +	done +  # Merci http://www.commandlinefu.com/commands/view/10276/grep-tab-t  untabify_disass:  	@find .gen/ -name '*[ch]' -exec grep -q $$'\t' {} \; -exec sed -i 's/\t/    /g' {} \; diff --git a/tools/d2c/d2c_genmakefile.sh b/tools/d2c/d2c_genmakefile.sh index 2338b6d..7911d04 100755 --- a/tools/d2c/d2c_genmakefile.sh +++ b/tools/d2c/d2c_genmakefile.sh @@ -29,19 +29,31 @@ $echo >> ${MAKEFILE_TMP}  $echo "include ${globalmk}" >> ${MAKEFILE_TMP}  $echo >> ${MAKEFILE_TMP} -OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d . -f 3 | sort | uniq` +if [ "$1" = "-" ]; then +    OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d. -f2 | sort | uniq` +else +    OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d. -f3 | sort | uniq` +fi  # Génération des en-têtes de décodage  for arch in $*;  do -    $echo -n "${arch}_HEADER_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} +    if [ ${arch} = "-" ]; then +        arch_name="" +        arch_name_dotted="" +    else +        arch_name="${arch}_" +        arch_name_dotted="${arch}_." +    fi + +    $echo -n "${arch_name}HEADER_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}      has_header=""      for op in $OPCODES;      do -        template="${input}/*${arch}_.${op}.c" +        template="${input}/*.${arch_name_dotted}${op}.c"          sources=`ls $template 2> /dev/null` @@ -62,8 +74,8 @@ do      $echo >> ${MAKEFILE_TMP}      $echo >> ${MAKEFILE_TMP} -    $echo -n "${arch}_opcodes.h: " >> ${MAKEFILE_TMP} -    $echo "\$(${arch}_HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} +    $echo -n "${arch_name}opcodes.h: " >> ${MAKEFILE_TMP} +    $echo "\$(${arch_name}HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}      if [ -z "${has_header}" ]; then @@ -71,7 +83,7 @@ do      else -        $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.opcodes.tmpl.h > \$@" >> ${MAKEFILE_TMP} +        $echo -e "\t\$(cini_verbose)cat ${input}/${arch_name_dotted}opcodes.tmpl.h > \$@" >> ${MAKEFILE_TMP}          $echo -e "\t\$(cgen_verbose)cat \$^ >> \$@" >> ${MAKEFILE_TMP}          $echo -e "\t\$(cfini_verbose)echo >> \$@" >> ${MAKEFILE_TMP}          $echo -en "\t\$(cfini_verbose)echo \"#endif\t /* " >> ${MAKEFILE_TMP} @@ -93,7 +105,15 @@ for op in $OPCODES;  do      for arch in $*;      do -        template="${input}/*${arch}_.${op}.c" +        if [ ${arch} = "-" ]; then +            arch_name="" +            arch_name_dotted="" +        else +            arch_name="${arch}_" +            arch_name_dotted="${arch}_." +        fi + +        template="${input}/*.${arch_name_dotted}${op}.c"          sources=`ls $template 2> /dev/null` @@ -101,7 +121,7 @@ do              continue          fi -        $echo -n "${op}_${arch}_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} +        $echo -n "${op}_${arch_name}FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}          for src in ${sources};          do @@ -112,13 +132,13 @@ do          $echo >> ${MAKEFILE_TMP}          $echo >> ${MAKEFILE_TMP} -        $echo -n "${arch}_${op}.c: " >> ${MAKEFILE_TMP} -        $echo -n "\$(${op}_${arch}_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} -        $echo " ${arch}_opcodes.h" >> ${MAKEFILE_TMP} +        $echo -n "${arch_name}${op}.c: " >> ${MAKEFILE_TMP} +        $echo -n "\$(${op}_${arch_name}FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} +        $echo " ${arch_name}opcodes.h" >> ${MAKEFILE_TMP} -        $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP} +        $echo -e "\t\$(cini_verbose)cat ${input}/${arch_name_dotted}${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP}          $echo -ne "\t\$(cgen_verbose)cat \$(" >> ${MAKEFILE_TMP} -        $echo -ne "${op}_${arch}_FILES" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} +        $echo -ne "${op}_${arch_name}FILES" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}          $echo -e ") >> \$@" >> ${MAKEFILE_TMP}          $echo >> ${MAKEFILE_TMP} @@ -135,18 +155,26 @@ $echo -n "GENERATED_FILES =" >> ${MAKEFILE_TMP}  for arch in $*;  do +    if [ ${arch} = "-" ]; then +        arch_name="" +        arch_name_dotted="" +    else +        arch_name="${arch}_" +        arch_name_dotted="${arch}_." +    fi +      $echo -ne " \\" >> ${MAKEFILE_TMP} -    $echo -ne "\n\t${arch}_opcodes.h" >> ${MAKEFILE_TMP} +    $echo -ne "\n\t${arch_name}opcodes.h" >> ${MAKEFILE_TMP}      for op in $OPCODES;      do -        template="${input}/*${arch}_.${op}.c" +        template="${input}/*.${arch_name_dotted}${op}.c"          sources=`ls $template 2> /dev/null`          if [ ! -z "${sources}" ]; then              $echo -ne " \\" >> ${MAKEFILE_TMP} -            $echo -ne "\n\t${arch}_${op}.c" >> ${MAKEFILE_TMP} +            $echo -ne "\n\t${arch_name}${op}.c" >> ${MAKEFILE_TMP}              continue          fi diff --git a/tools/d2c/format/Makefile.am b/tools/d2c/format/Makefile.am new file mode 100644 index 0000000..7afd98d --- /dev/null +++ b/tools/d2c/format/Makefile.am @@ -0,0 +1,31 @@ + +BUILT_SOURCES = grammar.h + + +# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS +# afin de conserver des noms de fichiers simples, ie sans le nom de la +# bibliothèque de sortie en préfixe. + +AM_YFLAGS = -v -d -p format_ + +AM_LFLAGS = -P format_ -o lex.yy.c --header-file=tokens.h			\ +			-Dyylval=format_lval -Dyyget_lineno=format_get_lineno 	\ +			-Dyy_scan_string=format__scan_string					\ +			-Dyy_delete_buffer=format__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES  = libd2cformat.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cformat_la_SOURCES =				\ +	decl.h								\ +	manager.h manager.c					\ +	tokens.l							\ +	grammar.y + + +# Automake fait les choses à moitié +CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h diff --git a/tools/d2c/format/decl.h b/tools/d2c/format/decl.h new file mode 100644 index 0000000..0b7775a --- /dev/null +++ b/tools/d2c/format/decl.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * decl.h - déclarations de prototypes utiles + * + * Copyright (C) 2016 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _TOOLS_D2C_FORMAT_DECL_H +#define _TOOLS_D2C_FORMAT_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à une définition de format. */ +bool load_format_from_raw_line(operands_format *, const char *); + + + +#endif  /* _TOOLS_D2C_BITS_DECL_H */ diff --git a/tools/d2c/format/grammar.y b/tools/d2c/format/grammar.y new file mode 100644 index 0000000..062d616 --- /dev/null +++ b/tools/d2c/format/grammar.y @@ -0,0 +1,107 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(operands_format *, char *); + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + +    char *string;                           /* Chaîne de caractères        */ + +} + + +%define api.pure full + +%parse-param { operands_format *format } + +%code provides { + +#define YY_DECL \ +    int format_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token OPS_TYPE + +%type <string> OPS_TYPE + + + +%% + + +type : OPS_TYPE { set_operands_format_type(format, $1); } + + +%% + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = structure impliquée dans le processus.              * +*                msg    = message d'erreur.                                   * +*                                                                             * +*  Description : Affiche un message d'erreur suite à l'analyse en échec.      * +*                                                                             * +*  Retour      : 0                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int yyerror(operands_format *format, char *msg) +{ +	printf("bits yyerror line %d: %s\n", yyget_lineno(), msg); + +	return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = structure à constituer à partir de données lues.    * +*                raw    = données brutes à analyser.                          * +*                                                                             * +*  Description : Interprête des données relatives à une définition de format. * +*                                                                             * +*  Retour      : true si l'opération s'est bien déroulée, false sinon.        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool load_format_from_raw_line(operands_format *format, const char *raw) +{ +    bool result;                            /* Bilan à faire remonter      */ +    YY_BUFFER_STATE state;                  /* Support d'analyse           */ +    int status;                             /* Bilan de l'analyse          */ + +    state = yy_scan_string(raw); + +    status = yyparse(format); + +    result = (status == 0); + +    yy_delete_buffer(state); + +    return result; + +} diff --git a/tools/d2c/format/manager.c b/tools/d2c/format/manager.c new file mode 100644 index 0000000..070b70c --- /dev/null +++ b/tools/d2c/format/manager.c @@ -0,0 +1,145 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - enregistrement de la définition des opérandes attendus + * + * Copyright (C) 2014 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "manager.h" + + +#include <malloc.h> + + +#include "../helpers.h" + + + +/* Mémorisation de la définition d'opérandes */ +struct _operands_format +{ +    char *type;                             /* Définitions des opérandes   */ + +}; + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée un nouveau gestionnaire de définitions d'opérandes.     * +*                                                                             * +*  Retour      : Nouvelle structure prête à emploi.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +operands_format *create_operands_format(void) +{ +    operands_format *result;                /* Définition vierge à renvoyer*/ + +    result = (operands_format *)calloc(1, sizeof(operands_format)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = gestionnaire de définition d'opérandes à libérer.   * +*                                                                             * +*  Description : Supprime de la mémoire un gestionnaire de définitions.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void delete_operands_format(operands_format *format) +{ +    if (format->type != NULL) +        free(format->type); + +    free(format); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = gestionnaire de définition d'opérandes à traiter.   * +*                type   = définitions des opérandes à charger.                * +*                                                                             * +*  Description : Précise le type d'opérandes dont la définition est à charger.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void set_operands_format_type(operands_format *format, char *type) +{ +    if (format->type != NULL) +        free(format->type); + +    format->type = make_string_upper(type); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : spec   = spécification servant de base à l'opération.        * +*                fd     = descripteur d'un flux ouvert en écriture.           * +*                arch   = architecture visée par l'opération.                 * +*                prefix = préfixe pour le type de définitions d'opérandes.    * +*                exit   = exprime le besoin d'une voie de sortie. [OUT]       * +*                                                                             * +*  Description : Définit le chargement des opérandes prévus par la définition.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool define_operands_loading(const operands_format *format, int fd, const char *arch, const char *prefix, bool *exit) +{ +    if (format->type == NULL) +    { +        fprintf(stderr, "Error: no type defined for operands.\n"); +        return false; +    } + +    *exit = true; + +    dprintf(fd, "\tif (!%s_read_operands(result, format, content, pos, endian, %s%s))\n", +            arch, prefix, format->type); + +    dprintf(fd, "\t\tgoto bad_exit;\n"); +    dprintf(fd, "\n"); + +    return true; + +} diff --git a/tools/d2c/format/manager.h b/tools/d2c/format/manager.h new file mode 100644 index 0000000..4555710 --- /dev/null +++ b/tools/d2c/format/manager.h @@ -0,0 +1,50 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour l'enregistrement de la définition des opérandes attendus + * + * Copyright (C) 2014 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _TOOLS_D2C_FORMAT_MANAGER_H +#define _TOOLS_D2C_FORMAT_MANAGER_H + + +#include <stdbool.h> + + + +/* Mémorisation de la définition d'opérandes */ +typedef struct _operands_format operands_format; + + +/* Crée un nouveau gestionnaire de définitions d'opérandes. */ +operands_format *create_operands_format(void); + +/* Supprime de la mémoire un gestionnaire de définitions. */ +void delete_operands_format(operands_format *); + +/* Précise le type d'opérandes dont la définition est à charger. */ +void set_operands_format_type(operands_format *, char *); + +/* Définit le chargement des opérandes prévus par la définition. */ +bool define_operands_loading(const operands_format *, int, const char *, const char *, bool *); + + + +#endif  /* _TOOLS_D2C_FORMAT_MANAGER_H */ diff --git a/tools/d2c/format/tokens.l b/tools/d2c/format/tokens.l new file mode 100644 index 0000000..12ca7f0 --- /dev/null +++ b/tools/d2c/format/tokens.l @@ -0,0 +1,26 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option noyy_top_state + +%x bsize + + +%% + + +" "                     { } + +[A-Za-z0-9_]*   { yylvalp->string = strdup(yytext); return OPS_TYPE; } + + +%% diff --git a/tools/d2c/grammar.y b/tools/d2c/grammar.y index 986edd7..02b2671 100644 --- a/tools/d2c/grammar.y +++ b/tools/d2c/grammar.y @@ -30,11 +30,23 @@ static void *map_input_data(const char *, size_t *);  #include "args/decl.h"  #include "bits/decl.h"  #include "conv/decl.h" +#include "format/decl.h"  #include "hooks/decl.h"  #include "rules/decl.h"  #include "syntax/decl.h" +#define handle_coder_format(c, r)                           \ +    ({                                                      \ +        encoding_spec *__spec;                              \ +        operands_format *__format;                          \ +        bool __status;                                      \ +        __spec = get_current_encoding_spec(c);              \ +        __format = get_format_in_encoding_spec(__spec);     \ +        __status = load_format_from_raw_line(__format, r);  \ +        if (!__status) YYABORT;                             \ +    }) +  #define handle_coder_bits(c, e, r)                          \      ({                                                      \          encoding_spec *__spec;                              \ @@ -94,6 +106,7 @@ static void *map_input_data(const char *, size_t *);  %union { +    char character;                         /* Simple caractère isolé      */      char *string;                           /* Chaîne de caractères #1     */      const char *cstring;                    /* Chaîne de caractères #2     */ @@ -124,12 +137,13 @@ YY_DECL;  %token COPYRIGHT  %token TITLE -%token INS_NAME INS_DETAILS +%token INS_NAME INS_SEP INS_DETAILS  %token ENCODING  %token TYPE NUMBER  %token ENC_START ENC_END +%token FORMAT  %token WORD HALF  %token SYNTAX  %token CONV @@ -140,6 +154,7 @@ YY_DECL;  %type <string> COPYRIGHT INS_NAME +%type <character> INS_SEP  %type <cstring> INS_DETAILS  %type <string> TYPE @@ -153,14 +168,27 @@ YY_DECL;  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); } +name : COPYRIGHT TITLE INS_NAME                     { save_notes_for_coder(coder, $1, $3, '\0', NULL); } +     | COPYRIGHT TITLE INS_NAME INS_SEP INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4, $5); }  encodings : /* empty */            | encoding encodings -encoding : ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } +encoding : ENCODING TYPE NUMBER format_content { push_encoding_spec(coder, $2, $3); } +         | ENCODING format_content { push_encoding_spec(coder, NULL, -1); } +         | ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } + + +/* Définitions à l'aide d'un format défini */ + +format_content : /* empty */ +               | format format_content + +format : FORMAT RAW_LINE { handle_coder_format(coder, $2); } + + +/* Définitions à l'aide de données brutes */  content : /* empty */ @@ -170,7 +198,6 @@ content : /* empty */          | hooks content          | rules content -  bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); }           | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); } @@ -225,7 +252,7 @@ static void show_usage(const char *argv0)  {      printf("\n"); -    printf("Usage: %s [options] < file\n", argv0); +    printf("Usage: %s [options]\n", argv0);      printf("\n"); @@ -234,11 +261,14 @@ static void show_usage(const char *argv0)      printf("\n");      printf("\t-h | --help\t\t\tDisplay this messsage.\n"); +    printf("\t-i | --input <file>\t\tProvide the input file containing the description.\n"); +    printf("\t-t | --type <raw|format>\tSet the type of the input file.\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-e | --encoding <none|string>\tDefine encoding prefixes for files.\n");      printf("\t-m | --macro <string>\t\tRegister some conversion functions.\n"); +    printf("\t-p | --prefix <string>\t\tDefine a prefix to format operand type constants (see -t).\n");      printf("\n"); @@ -333,11 +363,13 @@ int main(int argc, char **argv)          { "help",       no_argument,        NULL,   'h' },          { "input",      required_argument,  NULL,   'i' }, +        { "type",       required_argument,  NULL,   't' },          { "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' }, +        { "prefix",     required_argument,  NULL,   'p' },          { NULL,         0,                  NULL,   0   }      }; @@ -353,7 +385,7 @@ int main(int argc, char **argv)      while (!has_error)      { -        ret = getopt_long(argc, argv, "hi:d:a:H:e:M:", long_options, &index); +        ret = getopt_long(argc, argv, "hi:t:d:a:H:e:M:p:", long_options, &index);             if (ret == -1) break;          switch (ret) @@ -366,6 +398,13 @@ int main(int argc, char **argv)                  set_coder_input_file(coder, optarg);                  break; +            case 't': +                if (strcmp(optarg, "raw") == 0) +                    set_coder_input_type(coder, IOT_RAW); +                else if (strcmp(optarg, "format") == 0) +                    set_coder_input_type(coder, IOT_FORMAT); +                break; +              case 'd':                  set_coder_output_directory(coder, optarg);                  break; @@ -380,13 +419,20 @@ int main(int argc, char **argv)              case 'e': -                sep = strchr(optarg, '='); -                has_error = (sep == NULL); - -                if (!has_error) +                if (strcmp(optarg, "none") == 0) +                    register_empty_encoding(get_coder_pre_proc(coder)); +  +                else                  { -                    *sep = '\0'; -                    register_encoding(get_coder_pre_proc(coder), optarg, sep + 1); +                    sep = strchr(optarg, '='); +                    has_error = (sep == NULL); + +                    if (!has_error) +                    { +                        *sep = '\0'; +                        register_encoding(get_coder_pre_proc(coder), optarg, sep + 1); +                    } +                  }                  break; @@ -404,6 +450,10 @@ int main(int argc, char **argv)                  break; +            case 'p': +                set_coder_const_prefix(coder, optarg); +                break; +          }      } @@ -412,6 +462,7 @@ int main(int argc, char **argv)      {          show_usage(argv[0]);          result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE); +        printf("need help ? %d  -  result = %d vs %d\n", need_help, result, EXIT_SUCCESS);          goto exit;      } diff --git a/tools/d2c/pproc.c b/tools/d2c/pproc.c index 8644af5..fb72774 100644 --- a/tools/d2c/pproc.c +++ b/tools/d2c/pproc.c @@ -92,6 +92,32 @@ void delete_pre_processor(pre_processor *pp)  /******************************************************************************  *                                                                             * +*  Paramètres  : pp = pré-processeur dont le contenu est à compléter.         * +*                                                                             * +*  Description : Enregistre une correspondance nule en matière d'encodage.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void register_empty_encoding(pre_processor *pp) +{ +    string_exch *encoding;                  /* Traduction à conserver      */ + +    pp->encodings = (string_exch *)realloc(pp->encodings, ++pp->encodings_count * sizeof(string_exch)); + +    encoding = &pp->encodings[pp->encodings_count - 1]; + +    encoding->src = NULL; +    encoding->dest = NULL; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : pp   = pré-processeur dont le contenu est à compléter.       *  *                src  = chaîne à remplacer dans les définitions.              *  *                dest = chaîne de remplacement.                               * diff --git a/tools/d2c/pproc.h b/tools/d2c/pproc.h index 2a7b6c8..a2812f8 100644 --- a/tools/d2c/pproc.h +++ b/tools/d2c/pproc.h @@ -47,6 +47,9 @@ pre_processor *create_pre_processor(void);  /* Supprime de la mémoire un pré-processeur et ses macros. */  void delete_pre_processor(pre_processor *); +/* Enregistre une correspondance nule en matière d'encodage. */ +void register_empty_encoding(pre_processor *); +  /* Enregistre une correspondance en matière d'encodage. */  void register_encoding(pre_processor *, const char *, const char *); diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c index 30a412a..1692fd8 100644 --- a/tools/d2c/spec.c +++ b/tools/d2c/spec.c @@ -40,6 +40,8 @@ struct _encoding_spec      char *lprefix;                          /* Distinction en minuscules   */      unsigned int index;                     /* Distinction secondaire      */ +    operands_format *format;                /* Définition des opérandes    */ +      coding_bits *bits;                      /* Encodage des bits associés  */      asm_syntax *syntax;                     /* Calligraphe d'assemblage    */      conv_list *conversions;                 /* Conversions des données     */ @@ -68,6 +70,8 @@ encoding_spec *create_encoding_spec(void)      result = (encoding_spec *)calloc(1, sizeof(encoding_spec)); +    result->format = create_operands_format(); +      result->bits = create_coding_bits();      result->syntax = create_asm_syntax();      result->conversions = create_conv_list(); @@ -93,6 +97,8 @@ encoding_spec *create_encoding_spec(void)  void delete_encoding_spec(encoding_spec *spec)  { +    delete_operands_format(spec->format); +      delete_coding_bits(spec->bits);      delete_asm_syntax(spec->syntax);      delete_conv_list(spec->conversions); @@ -142,7 +148,37 @@ void define_encoding_spec_code_name(encoding_spec *spec, char *prefix, unsigned  bool has_encoding_spec_prefix(const encoding_spec *spec, const char *prefix)  { -    return (strcmp(spec->prefix, prefix) == 0); +    bool result;                            /* Bilan à renvoyer            */ + +    if (spec->prefix == NULL && prefix == NULL) +        result = true; + +    else if (spec->prefix != NULL && prefix != NULL) +        result = strcmp(spec->prefix, prefix) == 0; + +    else +        result = false; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : spec = spécification d'encodage à consulter.                 * +*                                                                             * +*  Description : Fournit le gestionnaire des définitions d'opérandes.         * +*                                                                             * +*  Retour      : Structure assurant la définition des opérandes               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +operands_format *get_format_in_encoding_spec(const encoding_spec *spec) +{ +    return spec->format;  } @@ -250,7 +286,6 @@ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *spec)  *                subarch = sous-catégorie de cette même architecture.         *  *                ins     = désignation première de l'instruction manipulée.   *  *                details = particularités de l'instruction.                   * -*                keyword = nom clef de l'instruction utilisable dans du code. *  *                wide    = taille des mots manipulés (en bits).               *  *                pp      = pré-processeur pour les échanges de chaînes.       *  *                                                                             * @@ -380,3 +415,98 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : spec    = spécification servant de base à l'opération.       * +*                fd      = descripteur d'un flux ouvert en écriture.          * +*                arch    = architecture visée par l'opération.                * +*                subarch = sous-catégorie de cette même architecture.         * +*                ins     = désignation première de l'instruction manipulée.   * +*                sep     = caractère de séparation avant les détails.         * +*                details = particularités de l'instruction.                   * +*                pp      = pré-processeur pour les échanges de chaînes.       * +*                prefix  = préfixe pour le type de définitions d'opérandes.   * +*                                                                             * +*  Description : Traduit en code une sous-fonction de désassemblage.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool write_encoding_spec_format_disass(const encoding_spec *spec, int fd, const char *arch, const char *subarch, const char *ins, char sep, const char *details, const pre_processor *pp, const char *prefix) +{ +    bool result;                            /* Bilan à retourner           */ +    bool quick_exit;                        /* Inclusion de sortie rapide ?*/ +    bool bad_exit;                          /* Ajout d'une sortie d'échec ?*/ +    const char *new_ins;                    /* Nouvelle définition de nom  */ + +    result = true; + +    /* Déclarations préalables */ + +    dprintf(fd, "\tGArchInstruction *result;               /* Instruction créée à renvoyer*/\n"); +    dprintf(fd, "\tSourceEndian endian;                    /* Boutisme lié au binaire     */\n"); + +    dprintf(fd, "\n"); + +    /* Création de l'instruction en elle-même */ + +    new_ins = get_new_keyword_from_syntax_items(spec->syntax); + +    if (new_ins != NULL) +        dprintf(fd, "\tresult = g_%s_instruction_new(\"%s\");\n", arch, new_ins); +    else +    { +        if (sep == '\0') +            dprintf(fd, "\tresult = g_%s_instruction_new(\"%s\");\n", arch, ins); +        else +            dprintf(fd, "\tresult = g_%s_instruction_new(\"%s%c%s\");\n", arch, ins, sep, details); +    } + +    dprintf(fd, "\n"); + +    /* Inscriptions des éventuelles fonctions ou propriété à lier */ + +    result &= write_hook_functions(spec->hooks, fd); + +    result &= write_decoding_rules(spec->rules, CAT_CHECKED_CALL, +                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &quick_exit); + +    result &= write_decoding_rules(spec->rules, CAT_CALL, +                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &quick_exit); + +    /* Création des opérandes */ + +    dprintf(fd, "\tendian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc));\n"); + +    dprintf(fd, "\n"); + +    bad_exit = false; + +    result &= define_operands_loading(spec->format, fd, arch, prefix, &bad_exit); + +    /* Conclusion de la procédure */ + +    dprintf(fd, "\treturn result;\n"); + +    dprintf(fd, "\n"); + +    if (bad_exit) +    { +        dprintf(fd, " bad_exit:\n"); +        dprintf(fd, "\n"); + +        dprintf(fd, "\tg_object_unref(G_OBJECT(result));\n"); +        dprintf(fd, "\treturn NULL;\n"); + +        dprintf(fd, "\n"); + +    } + +    return result; + +} diff --git a/tools/d2c/spec.h b/tools/d2c/spec.h index e09aa49..8c62fc3 100644 --- a/tools/d2c/spec.h +++ b/tools/d2c/spec.h @@ -31,6 +31,7 @@  #include "pproc.h"  #include "bits/manager.h"  #include "conv/manager.h" +#include "format/manager.h"  #include "hooks/manager.h"  #include "rules/manager.h"  #include "syntax/manager.h" @@ -53,6 +54,9 @@ void define_encoding_spec_code_name(encoding_spec *, char *, unsigned int);  /* Indique si une spécification se range dans une catégorie. */  bool has_encoding_spec_prefix(const encoding_spec *, const char *); +/* Fournit le gestionnaire des définitions d'opérandes. */ +operands_format *get_format_in_encoding_spec(const encoding_spec *); +  /* Fournit le gestionnaire des bits d'un encodage d'instruction. */  coding_bits *get_bits_in_encoding_spec(const encoding_spec *); @@ -71,6 +75,9 @@ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *);  /* Traduit en code une sous-fonction de désassemblage. */  bool write_encoding_spec_disass(const encoding_spec *, int, const char *, const char *, const char *, const char *, unsigned int, const pre_processor *); +/* Traduit en code une sous-fonction de désassemblage. */ +bool write_encoding_spec_format_disass(const encoding_spec *, int, const char *, const char *, const char *, char, const char *, const pre_processor *, const char *); +  #endif  /* _TOOLS_D2C_SPEC_H */ diff --git a/tools/d2c/tokens.l b/tools/d2c/tokens.l index e48d079..1e4b7b0 100644 --- a/tools/d2c/tokens.l +++ b/tools/d2c/tokens.l @@ -6,41 +6,19 @@  } -  %{ -    //typedef struct _rented_coder rented_coder; - - -//#include "d2c-d2c_gram.h" - -#include <ctype.h> -#include <string.h> - -  #include "manual.h" - -  %} +  %option noyywrap  %option nounput - //%option noinput  %option yylineno  %option stack  %option noyy_top_state - //%option reentrant - //%option bison-bridge - -/* %option bison-bridge */ -/* %option bison-locations */ -/* %option ecs */ -/* %option nodefault */ -/* %option noyywrap */ -/* %option reentrant */ -  %x comments @@ -52,81 +30,65 @@  %x raw_line -  %% -[ \t\n]+                            { } - -"/*"                                { BEGIN(comments); } -<comments>"*/"                      { BEGIN(INITIAL); } -<comments>[^*\n]                    { } -<comments>"Copyright"[^\n]*         { yylvalp->string = strdup(yytext); return COPYRIGHT; } -<comments>"*"                       { } -<comments>"\n"                      { } - - -"@title"                            { BEGIN(ins_name); return TITLE; } - -<ins_name>[ ][A-Za-z-]+             { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } -<try_details>[ ,/]                  { BEGIN(ins_details); } -<try_details>[\n]                   { BEGIN(INITIAL); } - -<ins_details>[^\n]*                 { yylvalp->cstring = yytext; return INS_DETAILS; } -<ins_details>[\n]                   { BEGIN(INITIAL); } - - - -"@encoding"                         { BEGIN(encoding); return ENCODING; } - -<encoding>[ ]                       { } -<encoding>"("                       { BEGIN(encoding_type); } - -<encoding_type>[A-Za-z]             { yylvalp->string = strdup(yytext); return TYPE; } -<encoding_type>[0-9]+               { yylvalp->integer = atoi(yytext); return NUMBER; } -<encoding_type>")"                  { BEGIN(encoding); } - -<encoding>"{"                       { BEGIN(encoding_content); } -<encoding_content>[ \t\n]+          { } -<encoding_content>"}"               { BEGIN(INITIAL); } - - - -<encoding_content>"@half "          { yy_push_state(raw_line); return HALF; } -<encoding_content>"@word "          { yy_push_state(raw_line); return WORD; } - - -<raw_line>[^\n]+                    { yylvalp->cstring = yytext; return RAW_LINE; } -<raw_line>"\n"                      { yy_pop_state(); } +[ \t\n]+                        { } +"/*"                            { BEGIN(comments); } +<comments>"*/"                  { BEGIN(INITIAL); } +<comments>[^*\n]                { } +<comments>"Copyright"[^\n]*     { yylvalp->string = strdup(yytext); return COPYRIGHT; } +<comments>"*"                   { } +<comments>"\n"                  { } +"@title"                        { BEGIN(ins_name); return TITLE; } -<encoding_content>"@syntax "        { yy_push_state(raw_line); return SYNTAX; } +<ins_name>[ ][A-Za-z-]+         { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } +<try_details>[ ,/-]             { BEGIN(ins_details); yylvalp->character = yytext[0]; return INS_SEP; } +<try_details>[\n]               { BEGIN(INITIAL); } +<ins_details>[^\n]*             { yylvalp->cstring = yytext; return INS_DETAILS; } +<ins_details>[\n]               { BEGIN(INITIAL); } +"@encoding"                     { BEGIN(encoding); return ENCODING; } -<encoding_content>"@conv"           { return CONV; } +<encoding>[ ]                   { } +<encoding>"("                   { BEGIN(encoding_type); } +<encoding_type>[A-Za-z]         { yylvalp->string = strdup(yytext); return TYPE; } +<encoding_type>[0-9]+           { yylvalp->integer = atoi(yytext); return NUMBER; } +<encoding_type>")"              { BEGIN(encoding); } +<encoding>"{"                   { BEGIN(encoding_content); } +<encoding_content>[ \t\n]+      { } +<encoding_content>"}"           { BEGIN(INITIAL); } -<encoding_content>"{" { -    read_block(temp); -    yylvalp->cstring = temp; return RAW_BLOCK; - } +<encoding_content>"@format"     { yy_push_state(raw_line); return FORMAT; } +<encoding_content>"@half"       { yy_push_state(raw_line); return HALF; } +<encoding_content>"@word"       { yy_push_state(raw_line); return WORD; } +<encoding_content>"@syntax"     { yy_push_state(raw_line); return SYNTAX; } +<encoding_content>"@conv"       { return CONV; } +<encoding_content>"@hooks"      { return HOOKS; } +<encoding_content>"@rules"      { return RULES; } -<encoding_content>"@hooks"          { return HOOKS; } +<raw_line>[^\n]+                { yylvalp->cstring = yytext; return RAW_LINE; } +<raw_line>"\n"                  { yy_pop_state(); } -<encoding_content>"@rules"          { return RULES; } +<encoding_content>"{"           { +                                    read_block(temp); +                                    yylvalp->cstring = temp; return RAW_BLOCK; +                                }  %%  | 
