#include #include #include #include #include "config.h" #include "meta.h" #include "hash.h" #include "parser.h" #include "assembler.h" #include "exceptions.h" #include "types.h" #include "numbers.h" #define downcase(x) ((((x)>='A')&&((x)<='Z'))?((x)-'A'+'a'):(x)) #define upcase(x) ((((x)>='a')&&((x)<='z'))?((x)-'a'+'A'):(x)) int process_file(char *); typedef struct expression_t { int e_type; int e_subtype; Uint32 avalue; char *symbol; pattern_t *pattern; int index; int op; struct expression_t *next, *prev, *child, *father; } expression_t; typedef struct bytestream_t { unsigned long int Encoded; int offset, segment, size; char *Label; expression_t *Expr; struct bytestream_t *next; int line; char *filename; } bytestream_t; enum { SEG_TEXT, SEG_DATA, SEG_BSS }; enum { E_STRING, E_VALUE, E_OPERATION, E_LABEL, E_INTERNAL, E_PATTERN, E_INSTRUCT }; int wc = 0; expression_t *e_current = NULL, *e_line = NULL; int segment = -1; int special = 0; _TableauVariable defines, labels; int line = -1; char *filename = NULL, *filenames[32], *defined; int nestedinc = 0; bytestream_t *text, *data, *bss, *p_text, *p_data, *p_bss; int s_text = 0, s_data = 0, s_bss = 0; static void debug_print_expression(expression_t * e) { switch (e->e_subtype) { case E_OPERATION: switch (e->op) { case OP_PLUS: fprintf(stderr, "Operation plus\n"); break; case OP_MOINS: fprintf(stderr, "Operation moins\n"); break; case OP_DECAL: fprintf(stderr, "Operation decal\n"); break; case OP_DIRECT: fprintf(stderr, "Operation direct\n"); break; default: fprintf(stderr, "Operation diverse...\n"); break; } debug_print_expression(e->child); fprintf(stderr, "--\n"); break; case E_VALUE: fprintf(stderr, "Valeur: %li\n", e->avalue); break; case E_LABEL: fprintf(stderr, "Label: %s\n", e->symbol); break; case E_STRING: fprintf(stderr, "String: %s\n", e->symbol); break; case E_PATTERN: fprintf(stderr, "Pattern: %s, index %i\n", e->pattern->name, e->index); break; case E_INTERNAL: fprintf(stderr, "Instruction interne: %s\n", e->symbol); break; case E_INSTRUCT: fprintf(stderr, "Instruction: %s\n", e->symbol); break; } if (e->next) { debug_print_expression(e->next); } } static expression_t *copy_expression(expression_t * e); static bytestream_t *pushuninit(int size) { bytestream_t *s; s = (bytestream_t *) Emalloc(sizeof(bytestream_t)); s->next = NULL; s->Encoded = 0; s->segment = segment; s->size = size; s->Label = NULL; s->Expr = NULL; s->line = line; s->filename = filenames[nestedinc - 1]; switch (segment) { case SEG_TEXT: s->offset = s_text; p_text->next = s; p_text = s; s_text += size; break; case SEG_DATA: s->offset = s_data; p_data->next = s; p_data = s; s_data += size; break; case SEG_BSS: s->offset = s_bss; p_bss->next = s; p_bss = s; s_bss += size; break; } return s; } static bytestream_t *pushdword(unsigned long int d, expression_t * e) { bytestream_t *s; if ((segment < 0) || (segment > 1)) { exception(1, _("You have to be into the .text or the .data segment to define a value.")); } s = pushuninit(1); s->Encoded = d; if (e) { s->Expr = copy_expression(e); } return s; } static bytestream_t *pushlabel(char *label) { bytestream_t *s; char trouve; s = pushuninit(0); s->Label = Estrdup(label); NomVarToVar(label, labels, &trouve); if (trouve) { exception(1, _("Label already defined")); } InsererVarDansTab(&labels, CreerElement(label, s)); return s; } static void pushstring(char *s) { char marker = *s, tstring[6]; int valid; while ((*s) && (marker != *s)) { if (*s == '\\') { s++; switch (*s) { case '0': pushdword('\0', NULL); break; case 'a': pushdword('\a', NULL); break; case 'b': pushdword('\b', NULL); break; case 'f': pushdword('\f', NULL); break; case 'n': pushdword('\n', NULL); break; case 'r': pushdword('\r', NULL); break; case 't': pushdword('\t', NULL); break; case 'v': pushdword('\v', NULL); break; case '\'': case '\"': case '\\': pushdword(*s, NULL); break; case 'x': tstring[0] = '0'; strncpy(tstring + 1, s, 4); pushdword(char_to_number(tstring, &valid), NULL); break; } } else { pushdword(*s, NULL); } s++; } } static void pushstart(void) { if (segment != SEG_TEXT) { exception(1, _("You can't have the startpoint elsewhere than the .text segment")); } pushlabel("__start__"); } static void look4pattern(pattern_t * patterns, expression_t * expression) { int i; for (patterns = patterns->next; patterns; patterns = patterns->next) { for (i = 0; i < patterns->nbr; i++) { if (!(patterns->expr[i]->type || patterns->expr[i]->string || !patterns->expr[i]->name)) { if (!strcasecmp(patterns->expr[i]->name, expression->symbol)) { expression->e_subtype = E_PATTERN; expression->pattern = patterns; expression->index = i; return; } } } } } static void look4instr(phon_t * phons, instruct_t * instructs, expression_t * e) { char *stringtolook = e->symbol; for (phons = phons->next; phons; phons = phons->next) { if (!strcasecmp(phons->p1, stringtolook)) { stringtolook = phons->p2; break; } } for (instructs = instructs->next; instructs; instructs = instructs->next) { if (!strcasecmp(instructs->names[0], stringtolook)) { e->e_subtype = E_INSTRUCT; return; } } } static void free_expr(expression_t * e) { if (e->child) { free_expr(e->child); } if (e->next) { free_expr(e->next); } if (e->symbol) { free(e->symbol); } free(e); } static expression_t *copy_expression(expression_t * e) { expression_t *t, *e_t; char trouve; t = Emalloc(sizeof(expression_t)); *t = *e; if (t->symbol) { e_t = (expression_t *) NomVarToVar(e->symbol, defines, &trouve); if ((trouve) && (t->e_subtype = E_STRING)) { free(t); t = copy_expression(e_t); return t; } else { t->symbol = Estrdup(t->symbol); } } if (t->child) { t->child = copy_expression(t->child); } if (t->next) { t->next = copy_expression(t->next); } if (t->next) { t->next->prev = t; } return t; } void push_pile(char *a) { int valid, number; expression_t *e, *e_t; char trouve; static char err[BUFSIZ]; if (!wc) { special = 0; switch (downcase(*a)) { case '.': valid = 0; special = 1; switch (downcase(*(a + 1))) { case 'd': if (!(strcasecmp(a + 2, "ata"))) { segment = SEG_DATA; valid = 1; wc++; return; } break; case 't': if (!(strcasecmp(a + 2, "ext"))) { segment = SEG_TEXT; valid = 1; wc++; return; } break; case 'b': if (!(strcasecmp(a + 2, "ss"))) { segment = SEG_BSS; valid = 1; wc++; return; } break; case 's': if (!(strcasecmp(a + 2, "tart"))) { pushstart(); valid = 1; wc++; return; } break; } if (!valid) { exception(1, _("Not a valid . directive")); } break; case '#': valid = 0; switch (downcase(*(a + 1))) { case 'd': if (!(strcasecmp(a + 2, "efine"))) { special = 2; valid = 1; } wc++; return; case 'u': if (!(strcasecmp(a + 2, "ndef"))) { special = 3; valid = 1; } wc++; return; case 'i': if (!(strcasecmp(a + 2, "nclude"))) { special = 4; valid = 1; } wc++; return; } if (!valid) { exception(1, _("Not a valid # directive")); } break; } } switch (special) { case 1: /* Cas des directives . */ exception(1, _("Error: extra parameters to a . directive.")); break; case 2: /* Cas de #define */ if (wc == 1) { defined = Estrdup(a); break; } case 0: /* Cas normal */ e = (expression_t *) Emalloc(sizeof(expression_t)); if (!e_line) { e_line = e_current = e; } e->pattern = NULL; number = char_to_number(a, &valid); if (valid) { e->e_type = E_VALUE; e->e_subtype = E_VALUE; e->avalue = number; e->symbol = NULL; } else { e_t = (expression_t *) NomVarToVar(a, defines, &trouve); if (trouve) { e = copy_expression(e_t); } else { e->e_type = E_STRING; e->e_subtype = E_STRING; e->avalue = 0; e->symbol = Estrdup(a); } } e->op = -1; e->prev = e_current; e->next = NULL; if (e_current) { e_current->next = e; } e->father = NULL; e->child = NULL; /* On prédevine le subtype sur quelques cas */ /* Cas des labels (en nom:) */ if ((wc == 0) && (a[strlen(a) - 1] == ':')) { e->e_subtype = E_LABEL; } /* Cas des pseudos instructions {DB, DW, DD, DS, DR} */ if (wc <= 1) { trouve = 0; switch (downcase(*a)) { case 'd': if (!*(a + 2)) { trouve = 1; switch (downcase(*(a + 1))) { case 'b': e->op = 1; break; case 'w': e->op = 2; break; case 'd': e->op = 3; break; case 's': e->op = 4; break; case 'r' e->op = 5; break; default: trouve = 0; } } } if (trouve) { e->e_subtype = E_INTERNAL; if (e->prev) { e->prev->e_subtype = E_LABEL; } } } /* Cas des patterns */ if (e->e_subtype == E_STRING) { look4pattern(patterns, e); } /* On regarde si cela n'est pas une instruction connue dans le meta langage */ if (((wc == 0) && (e->e_subtype == E_STRING)) || ((wc == 1) && (e->prev->e_subtype == E_LABEL))) { look4instr(phons, instructs, e); } /* Dans tous les autres cas, nous considerons qu'il s'agit d'une référence à un label... */ if (e->e_subtype == E_STRING) { if (((e->symbol[0] != '\"') && (e->symbol[0] != '\'')) && (strcmp(e->symbol, "?"))) { e->e_subtype = E_LABEL; } } e_current = e; break; case 3: /* Cas de #undef */ if (wc != 1) { exception(1, _("Too much arguments to #undef")); } NomVarToVar(a, defines, &trouve); if (!trouve) { exception(1, _("Defined symbol not found.")); } SupprimerDansTab(&defines, a); break; case 4: /* Cas de #include */ if (wc != 1) { exception(1, _("Too much arguments to #include")); } sprintf(err, _("Including file at line %i"), line); pushcontext(err); if (process_file(a)) { exception(1, _("Error reading include file")); } popcontext(); break; } wc++; } /* {',', 0, OP_NEST}, {'+', 2, OP_PLUS}, {'-', 2, OP_MOINS}, {'*', 3, OP_MUL}, {'/', 3, OP_DIV}, {'%', 3, OP_MOD}, {'+' + 128, 4, OP_PLUS_UNARY}, {'-' + 128, 4, OP_MOINS_UNARY}, {'(', 5, OP_FUNC_CALL}, {'(' + 128, 5, OP_LPAREN}, {'[', 5, OP_DECAL}, {'[' + 128, 5, OP_DIRECT}, {255, -1, -1} */ static void evaluate(expression_t * e) { expression_t *t, *u; if (e->e_subtype != E_OPERATION) return; switch (e->op) { case OP_PLUS: case OP_MOINS: case OP_MUL: case OP_DIV: case OP_MOD: if ((e->child->e_subtype == E_VALUE) && (e->child->next->e_subtype == E_VALUE)) { switch (e->op) { case OP_PLUS: e->avalue = e->child->avalue + e->child->next->avalue; break; case OP_MOINS: e->avalue = e->child->avalue - e->child->next->avalue; break; case OP_MUL: e->avalue = e->child->avalue * e->child->next->avalue; break; case OP_DIV: if (!e->child->next->avalue) { exception(1, _("Zero divide.")); } e->avalue = e->child->avalue / e->child->next->avalue; break; case OP_MOD: if (!e->child->next->avalue) { exception(1, _("Zero divide.")); } e->avalue = e->child->avalue % e->child->next->avalue; break; } free(e->child->next); free(e->child); e->child = NULL; e->e_type = e->e_subtype = E_VALUE; } else { /* un seul cas particulier supporté... */ if (!((e->op == OP_PLUS) || ((e->op == OP_MOINS) && (e->child->next->e_subtype = E_VALUE)))) { exception(1, _("Error: unable to compute the immediate value")); } } break; case OP_PLUS_UNARY: case OP_MOINS_UNARY: if (!e->child->e_subtype == E_VALUE) { exception(1, _("Error: unable to compute the immediate value")); } e->avalue = (e->op == OP_MOINS_UNARY) ? -e->child->avalue : e->child->avalue; free(e->child); e->child = NULL; e->e_type = e->e_subtype = E_VALUE; break; case OP_FUNC_CALL: if (strcasecmp(e->symbol, "diff")) { exception(1, _("Function unknow")); } break; /* Jusqu'ici les évaluations étaient faciles. Nous allons attaquer la partie la plus ardue de l'évaluation, celle de l'évaluation (disons plutôt de la simplification) des adresses */ case OP_DECAL: if ((e->child->e_subtype == E_LABEL) && (e->child->next->e_subtype == E_LABEL)) { exception(1, _("Addresses addition not allowed")); } if (e->child->e_subtype != E_LABEL) { exception(1, _("You can only use the decal operator on labels")); } if (e->child->next->e_subtype == E_OPERATION) { if ((e->child->next->op != OP_MOINS) && (e->child->next->op != OP_PLUS)) { exception(1, _("Address operation invalid")); } if ((e->child->next->op == OP_MOINS) && (e->child->next->child->next->e_subtype != E_VALUE)) { exception(1, _("Address operation invalid")); } if (e->child->next->child->e_subtype == E_LABEL) { exception(1, _("Addresses operations not allowed")); } if (e->child->next->child->e_subtype == e->child->next->child->next->e_subtype) { exception(1, _("Expression too complex or invalid")); } /* On veut obtenir quelque chose sous la forme LABEL[VALUE + PATTERN] */ if (e->child->next->child->e_subtype == E_PATTERN) { t = e->child->next->child; e->child->next->child = t->next; t->next->prev = NULL; t->next->next = t; t->prev = t->next; t->next = NULL; } } break; case OP_DIRECT: /*******************************************************************\ | Le code qui suit est sans doute immonde mais il est nécessaire... | | Attention à la foret d'ifs, ça fait mal quand on s'y pert... | | Le truc c'est que l'on va tenter d'éliminer l'expression avec une | | batterie de tests pour vérifier si elle est correcte ou pas. | | Nous la modifierons au fur et a mesure de sorte à lui donner une | | forme canonique afin de pouvoir la traiter correctement plus tard | \*******************************************************************/ switch (e->child->e_subtype) { case E_OPERATION: if (!((e->child->op == OP_PLUS) || (e->child->op == OP_MOINS))) { exception(1, _("Address operation invalid")); } if ((e->child->child->e_subtype == E_LABEL) && (e->child->child->next->e_subtype == E_LABEL)) { exception(1, _("Addresses operations not allowed")); } if (e->child->child->next->e_subtype == E_LABEL) { if (e->child->op == OP_MOINS) { exception(1, _("Address type not supported")); } /* Sous la forme [A + LABEL], on inverse... */ t = e->child->child; e->child->child = t->next; t->next->prev = NULL; t->next->next = t; t->prev = t->next; t->next = NULL; } if (e->child->child->e_subtype == E_LABEL) { if ((e->child->op != OP_PLUS) && (e->child->child->next->e_subtype != E_VALUE)) { exception(1, _("Address type not supported")); } } else { if ((e->child->child->e_subtype == E_OPERATION) && ((e->child->child->op == OP_PLUS) || (e->child->child->op == OP_MOINS))) { /* On est sous la forme [(A +- B) +- C], on inverse... */ /***********************************************\ | | | L'arbre des expressions est sous la forme: | | | | Direct | | | | | Operation1 | | / \ | |Operation2 C | | / \ | | A B | | | | et l'on veut: | | | | Direct | | | | | Operation2 | | / \ | | A Operation1 | | / \ | | B C | | | \***********************************************/ t = e->child->child->child->next; /* t pointe sur B */ e->child->child->child->next = e->child; /* Op1 devient fils droit de Op2 */ e->child->father = e->child->child; e->child->prev = e->child->child->child; e->child = e->child->child; /* Fils de Direct devient Op2 */ e->child->father = e; e->child->child->next->child = t; /* B devient fils gauche de Op1 */ t->next = e->child->next; t->next->prev = t; t->father = t->next->father; t->prev = NULL; } if ((t = e->child->child->next)->e_subtype == E_OPERATION) { /* On est sous la forme [A +- (B +- C)], on vérifie l'intégrité de la sous opération. Cela ne peut pas être [A - (B +- C)] car il faut que (B +- C) soit une valeur immediate et donc aurait été calculé avant. */ if (e->child->op == OP_MOINS) { exception(1, _("Address type not supported")); } switch (e->child->child->e_subtype) { /* quoique similiares, les trois cas suivant nécessitent trois traitements différents */ case E_LABEL: /* On a donc [LABEL + (B +- C)], on va vérifier si C n'est pas une PATTERN, et si c'est le cas, il ne faut pas que ce soit - C. Sinon nous ne devons pas avoir de labels pour B ou C */ if ((e->child->child->next->child->next->e_subtype == E_PATTERN) && (e->child->child->next->op == OP_MOINS)) { exception(1, _("Address type not supported")); } if (e->child->child->next->child->e_subtype == E_LABEL) { exception(1, _("Address addition not supported")); } /* Si B et C sont du même type, on jette l'éponge... */ if (e->child->child->next->child->e_subtype == e->child->child->next->child->next->e_subtype) { exception(1, _("Expression too complex or invalid")); } /* Ok, si notre expression a réussi à franchir toutes ses étapes, c'est qu'elle est correcte.... Enfin j'espère :) Je vais modifier l'expression de sorte a ce qu'elle ait la forme [LABEL + (VALEUR +- PATTERN)] */ if ((t = e->child->child->next->child)->e_subtype == E_PATTERN) { t->prev = t->next; t->next = NULL; t->prev->next = t; t->prev->prev = NULL; t->father->child = t->prev; if (t->father->op == OP_MOINS) { t->father->op = OP_PLUS; t->prev->avalue = -t->prev->avalue; } } break; case E_PATTERN: /* On a donc [PATTERN + (B +- C)], on va vérifier si C n'est pas un LABEL, et si c'est le cas, il ne faut pas que ce soit - C. Sinon nous ne devons pas avoir de patterns pour B ou C. */ if ((e->child->child->next->child->next->e_subtype == E_LABEL) && (e->child->child->next->op == OP_MOINS)) { exception(1, _("Address type not supported")); } if (e->child->child->next->child->e_subtype == E_PATTERN) { exception(1, _("Expression invalid")); } /* Si B et C sont du même type, on jette l'éponge... */ if (e->child->child->next->child->e_subtype == e->child->child->next->child->next->e_subtype) { exception(1, _("Expression too complex or invalid")); } /* Ok, si notre expression a réussi à franchir toutes ses étapes, c'est qu'elle est correcte.... Enfin j'espère :) Je vais modifier l'expression de sorte a ce qu'elle ait la forme [LABEL + (VALEUR +- PATTERN)] */ /* Pas mal de boulot ici... */ if ((t = e->child->child->next->child)->e_subtype == E_LABEL) { /* Nous avons [PATTERN + (LABEL +- VALEUR)], on inverse LABEL et VALEUR */ t->prev = t->next; t->next = NULL; t->prev->next = t; t->prev->prev = NULL; t->father->child = t->prev; if (t->father->op == OP_MOINS) { t->father->op = OP_PLUS; t->prev->avalue = -t->prev->avalue; } } /* Nous avons [PATTERN + (VALEUR + LABEL)] */ /* On bouge le LABEL */ t = e->child->child->next->child->next; t->father = e->child; t->prev = NULL; t->next = e->child->child->next; /* On bouge le PATTERN */ t = e->child->child; t->father = t->next; t->prev = t->next->child; t->next = NULL; /* On rétablit l'arbre correct */ e->child->child = t->prev->next; e->child->child->next->prev = e->child->child; t->prev->next = t; break; case E_VALUE: /* On a donc [VALUE + (B +- C)], si B ou C sont des valeurs, on intervient. */ if (e->child->child->next->child->e_subtype == E_VALUE) { if (e->child->child->next->op == OP_MOINS) { exception(1, _("Expression invalid")); } e->child->child->avalue += e->child->child->next->child->avalue; t = e->child->child->next; e->child->child->next = t->child->next; free_expr(t); /* Magie, on a attérit sur le cas [VALUE + qquechose] ... On va pas s'embeter, on va réévaluer la chose :) */ evaluate(e); return; } else if (e->child->child->next->child->next->e_subtype == E_VALUE) { /* Quasiment la même chose qu'au dessus... */ if (e->child->child->next->op == OP_MOINS) { e->child->child->avalue -= e->child->child->next->child->avalue; } else { e->child->child->avalue += e->child->child->next->child->avalue; } t = e->child->child->next; e->child->child->next = t->child; free_expr(t); evaluate(e); return; } else { /* Si B et C sont du même type, on jette l'éponge... */ if (e->child->child->next->child->e_subtype == e->child->child->next->child->next->e_subtype) { exception(1, _("Expression too complex or invalid")); } /* Ok, si notre expression a réussi à franchir toutes ses étapes, c'est qu'elle est correcte.... Enfin j'espère :) Je vais modifier l'expression de sorte a ce qu'elle ait la forme [LABEL + (VALEUR +- PATTERN)] */ /* Pas mal de boulot ici... */ if ((t = e->child->child->next->child)->e_subtype == E_PATTERN) { /* Nous avons [VALEUR + (PATTERN + LABEL)], on inverse LABEL et PATTERN */ t->prev = t->next; t->next = NULL; t->prev->next = t; t->prev->prev = NULL; t->father->child = t->prev; if (t->father->op == OP_MOINS) { t->father->op = OP_PLUS; t->prev->avalue = -t->prev->avalue; } } /* Nous avons [VALEUR + (LABEL + PATTERN)] */ /* On bouge le LABEL */ t = e->child->child->next->child; t->father = e->child; t->prev = NULL; u = t->next; t->next = e->child->child->next; /* On bouge la VALEUR */ t = e->child->child; t->father = t->next; t->next = u; t->prev = NULL; /* On rétablit l'arbre correct */ e->child->child = u->prev; e->child->child->next->prev = e->child->child; e->child->child->next->child = t; u->prev = t; } default: /* Bon si l'on est ici, c'est pas bon signe non plus... */ exception(1, _("Expression too complex")); break; } } else { /* Bon si l'on est ici, c'est que l'on est dans le cas [PATTERN + VALUE] ou [VALUE + PATTERN]. On se met sur la forme [VALUE + PATTERN] */ if (e->child->child->e_subtype == E_PATTERN) { t = e->child->child; e->child->child = t->next; t->next->prev = NULL; t->next->next = t; t->prev = t->next; t->next = NULL; } } } /* Bon si on arrive ici sain et sauf, c'est que l'expression est sous la forme canonique: [LABEL + A] avec A quelque chose de valide. On va donc transformer l'expression en LABEL[A] */ t = e->child; e->child = t->child; e->child->father = e; e->child->next->father = e; if (t->op == OP_MOINS) { /* On est sous la forme [LABEL - IMM], on met LABEL[-A] */ e->child->next->avalue = -e->child->next->avalue; } free(t); e->op = OP_DECAL; break; /* case OPERATION */ case E_LABEL: /* On est sous la forme [LABEL], on va mettre sous la forme LABEL[0] */ t = (expression_t *) Emalloc(sizeof(expression_t)); t->e_type = t->e_subtype = E_VALUE; t->avalue = 0; t->pattern = NULL; t->next = t->child = NULL; t->prev = e->child; e->child->next = t; t->father = e; e->op = OP_DECAL; break; } break; } } void act_pile(int o) { expression_t *e, *e1, *e2; int i, nbargs; e = Emalloc(sizeof(expression_t)); e->pattern = NULL; e->op = o; e->avalue = 0; e->symbol = NULL; e->e_type = E_OPERATION; e->e_subtype = E_OPERATION; e->next = e->prev = e->father = e->child = NULL; switch (o) { case OP_NEST: exception(1, _("Something wrong, nested operator called...")); break; case OP_PLUS: case OP_MOINS: case OP_MUL: case OP_DIV: case OP_MOD: case OP_DECAL: e1 = e_current->prev; e2 = e_current; if (e_current->prev->prev) { e_current->prev->prev->next = NULL; e_current = e1->prev; } else { e_current = NULL; } e1->prev = NULL; e2->next = NULL; e->child = e1; e1->father = e2->father = e; break; case OP_PLUS_UNARY: case OP_MOINS_UNARY: case OP_DIRECT: e1 = e_current; if (e1->prev) { e_current->prev->next = NULL; e_current = e1->prev; } else { e_current = NULL; } e1->prev = NULL; e->child = e1; e1->father = e; break; case OP_FUNC_CALL: e1 = e_current; e_current->prev->next = NULL; e_current = e1->prev; nbargs = e1->avalue; free(e1); e1 = e2 = NULL; for (i = 0; i < nbargs; i++) { e1 = e_current; e_current->prev->next = NULL; e_current = e1->prev; if (e2) { e2->next = e1; e2->prev = NULL; e1->prev = e2; } else { e1->prev = NULL; } e2 = e1; } e2 = e_current; if (e2->prev) { e_current->prev->next = NULL; e_current = e1->prev; } e->symbol = e2->symbol; free(e2); e->avalue = nbargs; for (e2 = e1; e2; e2 = e2->next) { e2->father = e; } e->child = e1; break; case OP_LPAREN: exception(1, _("Something wrong, lparenthesis operator called...")); break; default: exception(1, _("Something wrong, should never got here...")); break; } if (e_current) { e_current->next = e; e->prev = e_current; } e_current = e; evaluate(e_current); } int assembler_init(void) { Initialise(&defines); if (!defines) return 1; Initialise(&labels); if (!defines) return 1; if (!(p_text = text = (bytestream_t *) malloc(sizeof(bytestream_t)))) return 1; if (!(p_data = data = (bytestream_t *) malloc(sizeof(bytestream_t)))) return 1; if (!(p_bss = bss = (bytestream_t *) malloc(sizeof(bytestream_t)))) return 1; text->next = data->next = bss->next = NULL; text->size = data->size = bss->size = 0; return 0; } static void super_pattern(pattern_t * patterns, expression_t * e) { int i; if (!(e->e_subtype == E_OPERATION)) return; if (!((e->op == OP_DECAL) || (e->op == OP_DIRECT))) return; for (patterns = patterns->next; patterns; patterns = patterns->next) { for (i = 0; i < patterns->nbr; i++) { if (!patterns->expr[i]->name) { if (e->e_subtype == E_OPERATION) { if (e->op == OP_DIRECT) { if (!patterns->expr[i]->left) { e->pattern = patterns; e->index = i; } } else { if (patterns->expr[i]->left) { e->pattern = patterns; e->index = i; } } } } else { if (patterns->expr[i]->string) { if (patterns->expr[i]->string[0] == 'O') { if (e->e_subtype == E_OPERATION) { if (((e->op == OP_DIRECT) && (e->child->e_subtype == E_VALUE)) || ((e->op == OP_DECAL) && (e->child->next->e_subtype == E_VALUE))) { e->pattern = patterns; e->index = i; } } else { if (e->e_subtype == E_LABEL) { e->pattern = patterns; e->index = i; } } } } } } } } static int islabel(expression_t *); static int islabel2(expression_t * e) { if (islabel(e)) return 1; if (e->next) { return islabel2(e->next); } return 0; } static int islabel(expression_t * e) { if (e->e_subtype == E_LABEL) return 1; if (e->child) { return islabel2(e->child); } return 0; } static instruct_t *e_match_i(phon_t * phons, instruct_t * instructs, expression_t * e) { char *stringtolook = e->symbol; expression_t *t; int i, go_out; for (t = e->next; t; t = t->next) { if (!t->pattern) super_pattern(patterns, t); } for (phons = phons->next; phons; phons = phons->next) { if (!strcasecmp(phons->p1, stringtolook)) { stringtolook = phons->p2; break; } } for (instructs = instructs->next; instructs; instructs = instructs->next) { t = e; go_out = 0; for (i = 0; (!go_out) && (i < instructs->nbexplicit); i++) { if (!instructs->strings[i]) { if (strcasecmp(instructs->names[i], i ? t->symbol : stringtolook)) { go_out = 1; } else fprintf(stderr, "On a reconnu le mot %s au %i eme mot\n", t->symbol, i); } else { switch (instructs->strings[i][0]) { case 'P': if (!t->pattern) { fprintf(stderr, "On a une pattern sur le mot %i, mais pas dans l'instruction...\n", i); go_out = 1; } else { fprintf(stderr, "On a la pattern %s sur le mot %i, on la compare avec %s\n", instructs->strings[i] + 1, i, t->pattern->name); if (strcasecmp(instructs->strings[i] + 1, t->pattern->name)) go_out = 1; else fprintf(stderr, "Ok, on ne sort pas.\n"); } break; case 'C': if (t->e_subtype != E_VALUE) { go_out = 1; if (t->e_subtype == E_OPERATION) { if (t->op == OP_FUNC_CALL) go_out = 0; } } break; case 'o': /* Pour que quelque chose soit absolu, il nous suffit d'avoir un label dans l'expression */ if (!islabel(t)) go_out = 1; break; case 'O': /* C'est le cas le plus simple ou presque, il suffit de tout prendre */ break; default: exception(1, _("Unknow predefined string into the meta language")); } } if (!(t = t->next) && ((i + 1) < instructs->nbexplicit)) { go_out = 1; fprintf(stderr, "On sort quand même... (t = %p et i = %i)\n", t, i); } } if (!go_out) { break; } } if (instructs) { fprintf(stderr, "Nous avons reconnu une instruction:\n"); fprintf(stderr, " o Instruction contenant %i champs explicites et %i champs implicites.\n", instructs->nbexplicit, instructs->nbimplicit); fprintf(stderr, " => Champs explicites.\n"); for (i = 0; i < instructs->nbexplicit; i++) { fprintf(stderr, " + %s <= %s (type %s)\n", instructs->names[i], instructs->strings[i] ? instructs->strings[i] : "Pas de chaîne associée", instructs->etypes[i] ? "prédéfinit" : "direct"); } fprintf(stderr, " => Champs implicites.\n"); for (i = 0; i < instructs->nbimplicit; i++) { switch (instructs->itypes[i]) { case 0: fprintf(stderr, " + %s <= %s (type direct)\n", instructs->implicits[i], instructs->istrings[i]); break; case 1: fprintf(stderr, " + %s <= %s (type prédéfinit)\n", instructs->implicits[i], instructs->istrings[i]); break; case 2: fprintf(stderr, " + %s <= %i (type valeur)\n", instructs->implicits[i], instructs->ivalues[i]); break; } } } else { fprintf(stderr, "Nous n'avons pas reconnu l'instruction.\n"); } return instructs; } static void evaluate_pattern(_TableauVariable * it, expression_t * e) { metaexpr_t *m, *n; expression_t *t; int tv; if (!e->pattern) { exception(1, _("Pattern not matching...")); } fprintf(stderr, "Evaluation de la pattern %s, index %i\n", e->pattern->name, e->index); m = e->pattern->expr[e->index]; if (m->name) { if (m->string) { if (m->type) { if (!strcmp(m->name, "I")) { exception(1, _("Unknow constant type in the meta language")); } if (e->e_subtype == E_VALUE) { pushdword(e->avalue, NULL); } else { pushdword(0, e); } } else { if (m->string) { if (m->string[0] != 'P') { exception(1, _ ("Error in the metalanguage (pattern should be here if not a constant type)")); } t = (expression_t *) Emalloc(sizeof(expression_t)); t->next = t->child = t->prev = t->father = NULL; t->e_type = t->e_subtype = E_VALUE; t->avalue = e->index; t->symbol = NULL; t->pattern = NULL; InsererVarDansTab(it, CreerElement(m->name, t)); free(t); } } } } else { n = m; if (m->left) { /* Binaire */ m = m->left; if (m->string) { if (m->type) { if (strcmp(m->name, "I") || strcmp(m->string, "O")) { exception(1, _("Unknow constant type in the meta language")); } tv = 0; if (e->child->next->e_subtype == E_VALUE) { tv = e->child->next->avalue; } if ((e->child->next->e_subtype == E_OPERATION) && (e->child->next->child->e_subtype == E_VALUE)) { tv = e->child->next->child->avalue; } pushdword(tv, e->child); } else { exception(1, _("Logical error in meta language")); } } m = n; m = m->right; if (m->string) { if (m->type) { } else { if (m->string) { if (m->string[0] != 'P') { exception(1, _ ("Error in the metalanguage (pattern should be here if not a constant type)")); } t = (expression_t *) Emalloc(sizeof(expression_t)); t->next = t->child = t->prev = t->father = NULL; t->e_type = t->e_subtype = E_VALUE; t->pattern = NULL; if (e->child->next->e_subtype == E_PATTERN) { t->avalue = e->child->next->index; } else { t->avalue = e->child->next->child->next->index; } t->symbol = NULL; InsererVarDansTab(it, CreerElement(m->name, t)); free(t); } else { exception(1, _("Logical error in meta language")); } } } } else { /* Unaire */ m = m->right; if (m->string) { if (m->type) { exception(1, _("Logical error in meta language")); } else { if (m->string) { if (m->string[0] != 'P') { exception(1, _ ("Error in the metalanguage (pattern should be here if not a constant type)")); } t = (expression_t *) Emalloc(sizeof(expression_t)); t->next = t->child = t->prev = t->father = NULL; t->e_type = t->e_subtype = E_VALUE; t->avalue = e->child->index; t->symbol = NULL; t->pattern = NULL; InsererVarDansTab(it, CreerElement(m->name, t)); free(t); } } } } } } static int evaluate_field(_TableauVariable it, char * field, field_t * fields) { int i, r, e, n; char trouve; expression_t * t; for (fields = fields->next; fields; fields = fields->next) { if (!strcmp(field + 1, fields->name)) { break; } } if (!(fields)) { exception(1, _("Unknow field in metalanguage")); } r = 0; n = 0; for (i = 0; i < fields->nbr; i++) { t = (expression_t *) NomVarToVar(fields->names[i], it, &trouve); e = 0; if (trouve) { if (t->e_subtype == E_VALUE) { exception(1, _("Can't evaluate directly expression")); } e = t->avalue; } n = fields->sizes[i]; if ((e & (n - 1)) != e) { exception(1, _("Value too large for field")); } r = (r << n) | e; } return r; } void asm_eol(void) { instruct_t *instr; expression_t *t; int i; char trouve; bytestream_t *pi; _TableauVariable it; switch (special) { case 2: /* Cas de #define */ InsererVarDansTab(&defines, CreerElement(defined, e_line)); free(defined); break; case 1: /* Cas des directives . */ case 3: /* Cas de #undef */ case 4: /* Cas de #include */ /* Rien à faire ici... tout est déjà fait dans la routine push_pile() */ break; case 0: /* Cas normal */ /* C'est ici la bonne histoire... Il faut reconnaitre l'instruction */ fprintf(stderr, "Fin de ligne sur:\n"); debug_print_expression(e_line); fprintf(stderr, "-----\n"); e_current = e_line; /* Est-ce que le premier mot est un label terminant par ':' ? */ if (e_current->e_subtype == E_LABEL) { if (e_current->symbol[strlen(e_current->symbol) - 1] == ':') { pushlabel(e_current->symbol); e_line = e_current->next; e_current->next = NULL; free_expr(e_current); e_current = e_line; } else { /* C'est peut-être une instruction spéciale */ if ((e_current->next) && (e_current->next->e_subtype == E_INTERNAL)) { pushlabel(e_current->symbol); e_line = e_current->next; e_current->next = NULL; free_expr(e_current); e_current = e_line; } else { exception(1, _("Unknow instruction")); } } } switch (e_current->e_subtype) { case E_INTERNAL: switch (e_current->op) { case 1: case 2: case 3: do { e_line = e_current->next; e_current->next = NULL; free_expr(e_current); e_current = e_line; if (!e_current) break; switch (e_current->e_subtype) { case E_VALUE: pushdword(e_current->avalue, NULL); break; case E_STRING: if (!strcmp(e_current->symbol, "?")) { exception(1, _("Unknow constant")); } pushuninit(1); break; case E_LABEL: case E_OPERATION: pushdword(0, e_current); break; default: exception(1, _("Bad constant for an immediate value")); } } while (1); break; case 4: do { e_line = e_current->next; e_current->next = NULL; free_expr(e_current); e_current = e_line; if (!e_current) break; switch (e_current->e_subtype) { case E_STRING: pushstring(e_current->symbol); break; default: exception(1, _("Bad constant for a string")); } } while (1); break; case 5: do { e_line = e_current->next; e_current->next = NULL; free_expr(e_current); e_current = e_line; if (!e_current) break; switch (e_current->e_subtype) { case E_VALUE: pushuninit(e_current->avalue); break; default: exception(1, _("Bad array size")); } } while (1); break; } break; case E_INSTRUCT: if (segment != SEG_TEXT) { exception(1, _("You can only have an instruction into a .text segment")); } if (!(instr = e_match_i(phons, instructs, e_current))) { exception(1, _("Unmatched instruction")); } /* Operation crutiale: nous avons l'instruction qui correspond le mieux à notre expression, on va tenter de l'évaluer */ Initialise(&it); pi = pushdword(0, NULL); for (i = 0; i < instr->nbexplicit; i++) { if (instr->strings[i]) { switch (instr->strings[i][0]) { case 'C': if (instr->etypes) { if (!strcmp(instr->names[i], "I")) { if (e_current->e_subtype == E_VALUE) { pushdword(e_current->avalue, 0); } else { pushdword(0, e_current); } } else { exception(1, _ ("Unknow constant type in the meta language")); } } else { InsererVarDansTab(&it, CreerElement(instr->names[i], e_current)); } break; case 'P': t = (expression_t *) Emalloc(sizeof(expression_t)); t->e_type = t->e_subtype = E_VALUE; t->avalue = e_current->index; t->child = t->next = NULL; t->pattern = NULL; InsererVarDansTab(&it, CreerElement(instr->names[i], t)); free(t); evaluate_pattern(&it, e_current); break; default: exception(1, _("Unknow constant type in the meta language")); } } e_line = e_current->next; e_current->next = NULL; free_expr(e_current); e_current = e_line; } for (i = 0; i < instr->nbimplicit; i++) { switch(instr->itypes[i]) { case 0: /* type direct */ t = (expression_t *) NomVarToVar(instr->istrings[i], it, &trouve); if (!trouve) { exception(1, _("Syntax error in meta language")); } InsererVarDansTab(&it, CreerElement(instr->implicits[i], t)); break; case 1: /* type prédéfinit */ t = (expression_t *) Emalloc(sizeof(expression_t)); t->e_type = t->e_subtype = E_VALUE; if (instr->istrings[i][0] != 'F') { exception(1, _("Logical error in meta language")); } t->avalue = evaluate_field(it, instr->istrings[i], fields);; t->child = t->next = NULL; t->pattern = NULL; InsererVarDansTab(&it, CreerElement(instr->implicits[i], t)); break; case 2: /* type valeur */ t = (expression_t *) Emalloc(sizeof(expression_t)); t->e_type = t->e_subtype = E_VALUE; t->avalue = instr->ivalues[i]; t->child = t->next = NULL; t->pattern = NULL; InsererVarDansTab(&it, CreerElement(instr->implicits[i], t)); break; } } fprintf(stderr, "Variables\n"); AfficheTableau(it); pushdword(evaluate_field(it, "FI", fields), NULL); DetruitTab(&it); break; default: exception(1, _("Unknow instruction")); break; } break; } wc = 0; special = 0; e_current = e_line = NULL; } void asm_eof(void) { } static void delete_bytestream(bytestream_t * s) { if (s->next) delete_bytestream(s->next); free(s); } void assembler_flush(void) { DetruitTab(&defines); DetruitTab(&labels); delete_bytestream(text); delete_bytestream(data); delete_bytestream(bss); } static int process_file(char *name) { FILE *f; char buf[BUFSIZ], errctx[BUFSIZ], *p; int i = 0; pushcontext(_("Loading file")); sprintf(errctx, _("Opening file '%s'"), name); pushcontext(errctx); filenames[nestedinc++] = Estrdup(name); if (!(f = fopen(name, "r"))) { pushcontext(strerror(errno)); return 1; } popcontext(); pushcontext(_("Reading file")); while (fgets(buf, BUFSIZ, f)) { sprintf(errctx, _("Reading line %i"), line = ++i); pushcontext(errctx); if ((p = strchr(buf, '\r'))) { *p = '\0'; } if ((p = strchr(buf, '\n'))) { *p = '\0'; } parse_line(buf); sprintf(errctx, _("Summering line %s"), buf); pushcontext(errctx); asm_eol(); popcontext(); popcontext(); } nestedinc--; popcontext(); popcontext(); fclose(f); return 0; } void assemble_file(char * iname, char * oname) { FILE * f; pushcontext(_("Opening output file")); if (!(f = fopen(oname, "wb"))) { pushcontext(stderror(errno)); exception(1, _("Error writing output file")); } popcontext(); if (!process_file(iname)) { exception(1, _("Error reading file")); } pushcontext(_("Writing output file")); asm_eof(f); fclose(f); popocontext(); }