#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]; int nestedinc = 0; bytestream_t * text, * data, * bss, * p_text, * p_data, * p_bss; int s_text = 0, s_data = 0, s_bss = 0; 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]; 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 = copyexpression(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")); } return s; } static void pushstring(char * s) { char marker = *s, valid, tstring[6]; 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); } 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) { 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} */ if (wc == 1) { trouve = 0; switch (downcase(*a)) { case 'd': if (!*(a + 2)) { trouve = 1; switch (downcase(*(a + 1))) { case 'b': case 'w': case 'd': case 's': break; default: trouve = 0; } } } if (trouve) { e->e_subtype = E_INTERNAL; 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) { 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); process_file(a); popcontext(); break; } wc++; } /* {',', 0, OP_NEST}, {'+', 2, OP_PLUS}, {'-', 2, OP_MOINS}, {'*', 3, OP_MUL}, {'/', 3, OP_DIV}, {'+' + 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: 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; } 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")); } } 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 | \*******************************************************************/ if (e->child->e_subtype == 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 { /* Le pire, c'est que je vois même pas comment on peut atterir ici... J'ai beau me creuser les méninges, je vois pas :) On va donc dire que c'est invalide */ exception(1, _("Expression too complex")); } } /* 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; } /* if operation */ break; } } void act_pile(int o) { expression_t *e, *e1, *e2; int i, nbargs; e = Emalloc(sizeof(expression_t)); 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_DECAL: e2 = e_current; e1 = e_current->prev; if (e_current->prev->prev) { e_current->prev->prev->next = NULL; } else { e_current = NULL; } e1->prev = 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; } void asm_eol(void) { /* Gros morceau encore ici... */ wc = 0; special = 0; } 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); } int process_file(char *name) { /* Petite chose à faire ici et cela sera bon */ return 0; }