#include #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)) static int process_file(char *); /* Les differentes structures de données nécessaires au traitement */ 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, relog; 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 }; /* Nos variables globales */ 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; /* Cette fonction affiche une expression à l'écran. Elle n'est utile que pour des raisons de deboggage */ static void debug_print_expression(expression_t * e) { if (!e) return; 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); /* Les fonctions push* qui suivent rajoutent des mots dans le segment en cours */ 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 = 1; s->Label = NULL; s->Expr = NULL; s->relog = 1; 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); s->size = 0; 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; s++; 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 'e': pushdword(27, 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++; } pushdword(0, NULL); } static void pushstart(void) { if (segment != SEG_TEXT) { exception(1, _("You can't have the startpoint elsewhere than the .text segment")); } pushlabel("__start__"); } /* Nous recherchons si une string est une pattern "simple" (pas composée) */ 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; } } } } } /* Nous vérifions rapidement si la string en cours fait partie des instructions recensées */ 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; } } } /* Libère récursivement une expression */ 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); } /* Copie récursivement une expression */ 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) { trouve = 0; if (e->e_subtype == E_LABEL) { e_t = (expression_t *) NomVarToVar(e->symbol, defines, &trouve); } if ((trouve) && (t->e_type = 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; } /* Cette fonction est appelée par le parseur. Elle rajoute un symbole sur la pile des expressions pour la ligne en cours */ 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 { trouve = 0; if ((*a != '"') && (*a != '\'')) { 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; if (wc) { e->prev = e_current; } else { e->prev = NULL; } e->next = NULL; if (wc) { 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++; } /* Cette fonction évalue l'expression en cours. */ 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->symbol = NULL; 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; } } /* Cette fonction est appelée depuis le parseur. Elle ajit sur la pile en effectuant une opération */ 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); } /* Fonction d'initialisation de l'assembleur */ 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; text->Label = data->Label = bss->Label = NULL; return 0; } /* Nous vérifions si l'expression peut correspondre à une pattern "complexe" (composée) */ 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; return; } } else { if (patterns->expr[i]->left) { e->pattern = patterns; e->index = i; return; } } } } 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; return; } } else { if (e->e_subtype == E_LABEL) { e->pattern = patterns; e->index = i; return; } } } } } } } } /* Ces deux fonctions récursives croisées nous servent à déterminer su une expression est un label */ 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; } /* Cette fonction cherche une instruction pouvant correspondre à l'expression. */ 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; } } #ifdef DEBUG debug_print_expression(e); #endif 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 { switch (instructs->strings[i][0]) { case 'P': if (!t->pattern) { go_out = 1; } else { if (strcasecmp(instructs->strings[i] + 1, t->pattern->name)) go_out = 1; } break; case 'C': if ((t->e_subtype != E_VALUE) && (t->e_subtype != E_LABEL)) { go_out = 1; } if ((t->e_subtype == E_OPERATION) && ((t->op == OP_PLUS) || (t->op == OP_MOINS))) { if (((t->child->e_subtype == E_LABEL) && (t->child->next->e_subtype == E_VALUE)) || ((t->child->e_subtype == E_VALUE) && (t->child->next->e_subtype == E_LABEL))) { go_out = 0; } } if ((t->e_subtype == E_OPERATION) && (t->op == OP_FUNC_CALL)) { go_out = 0; } 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; } } if (!go_out && !t) { break; } } #ifdef DEBUG if (instructs) { 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; } } } #endif return instructs; } /* Cette fonction va évaluer une pattern et rajouter les variable dans la table de hachage correspondante */ 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...")); } 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)); } } } } 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)); } 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)); } } } } } } /* Cette fonction va évaluer un champ et en renvoyer la valeur, à l'aide de la table de hachage passée en argument */ 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 & ((1 << n) - 1)) != e) { exception(1, _("Value too large for field")); } r = (r << n) | e; } return r; } /* Fonction servant à effectuer une fin de ligne. Force l'évaluation complète de la ligne */ void asm_eol(void) { instruct_t *instr; expression_t *t; int i; char trouve; _TableauVariable it; bytestream_t *pi; 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 */ e_current = e_line; if (!(e_current)) break; /* 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: /* DB */ case 2: /* DW */ case 3: /* DD */ 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: /* DS */ 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: /* DR */ 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 (!e_current) break; 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 cruciale: nous avons l'instruction qui correspond le mieux à notre expression, on va tenter de l'évaluer */ pi = pushuninit(1); Initialise(&it); for (i = 0; i < instr->nbexplicit; i++) { if (instr->strings[i]) { switch (instr->strings[i][0]) { case 'C': if (instr->etypes[i]) { 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 'O': 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")); } } 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; t->symbol = NULL; InsererVarDansTab(&it, CreerElement(instr->names[i], t)); #ifdef DEBUG fprintf(stderr, "On a %s qui vaut %i\n", instr->names[i], e_current->index); #endif 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) { t = (expression_t *) Emalloc(sizeof(expression_t)); t->e_type = t->e_subtype = E_VALUE; t->avalue = 0; t->child = t->next = NULL; t->pattern = NULL; t->symbol = NULL; } #ifdef DEBUG fprintf(stderr, "On a %s qui vaut %i\n", instr->implicits[i], t->avalue); #endif 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; t->symbol = NULL; #ifdef DEBUG fprintf(stderr, "On a %s qui vaut %i\n", instr->implicits[i], t->avalue); #endif 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; t->symbol = NULL; #ifdef DEBUG fprintf(stderr, "On a %s qui vaut %i\n", instr->implicits[i], t->avalue); #endif InsererVarDansTab(&it, CreerElement(instr->implicits[i], t)); break; } } pi->Encoded = evaluate_field(it, "FI", fields); DetruitTab(&it); break; default: exception(1, _("Unknow instruction")); break; } break; } wc = 0; special = 0; e_current = e_line = NULL; } /* Ecrit un ou plusieurs mots dans le fichier spécifié, avec traitement des erreurs */ static void writeword(unsigned long int a, FILE * f, int n) { int i; #ifdef DEBUG fprintf(stderr, "ÉCriture de %08lX sur %i\n", a, fileno(f)); #endif if (fwrite(&a, sizeof(unsigned long int), 1, f) != 1) { if (ferror(f)) { pushcontext(strerror(errno)); } exception(1, _("Error writing file")); } for (i = 0; i < n - 1; i++) { writeword(0, f, 1); } } /* Ecrit une chaine dans le fichier spécifié, avec traitement des erreurs */ static void writestring(char *string, FILE * f) { for (; *string; string++) { writeword(*string, f, 1); } } /****************\ | | | Private Joke | | | | /\ | | / \ | | / ++ \ | | / ++ \ | | / \ | | |~~~~~~~~~~| | | | +-+ +-+ | | | | +-+ +-+ | | | | | | | | +--+ | | | | | .| | | | +---+--+---+ | | | \****************//* Cette fonction ajoute un fichier à un autre */ void appendfile(FILE * f, char *name) { unsigned long int a; FILE *g; if (!(g = fopen(name, "rb"))) { pushcontext(strerror(errno)); exception(1, _("Error writing file")); } while (fread(&a, sizeof(a), 1, g) == 1) { writeword(a, f, 1); } if (ferror(f)) { pushcontext(strerror(errno)); exception(1, _("Error reading file")); } fclose(g); } /* Cette fonction est appelée pour signaler la fin du fichier. Elle va écrire tous les segments dans le fichier de sortie, et tenter d'évaluer les dernières expressions restantes */ void asm_eof(FILE * f) { bytestream_t *t, *u; FILE *f1, *f2; int nbsymbols = 0, a, nbi = 0, nbe = 0; char errctx[BUFSIZ], trouve; bytestream_t *ttext = text, *tdata = data, *tbss = bss; pushcontext(_("Creating temporary files")); if (!(f1 = fopen("__text__", "wb"))) { pushcontext(strerror(errno)); exception(1, _("Error writing file __text__")); } if (!(f2 = fopen("__symbols__", "wb"))) { pushcontext(strerror(errno)); exception(1, _("Error writing file __symbols__")); } popcontext(); pushcontext(_("Dumping memory into object file")); /* Segment de texte */ pushcontext(_("Dumping text segment")); for (ttext = ttext->next; ttext; ttext = ttext->next) { sprintf(errctx, _ ("Processing word number %i coming from line %i of the file %s."), ttext->offset, ttext->line, ttext->filename); #ifdef DEBUG fprintf(stderr, "%s\n", errctx); #endif pushcontext(errctx); a = 0; if (ttext->Expr) { switch (ttext->Expr->e_subtype) { case E_VALUE: a = ttext->Expr->avalue; break; case E_LABEL: #ifdef DEBUG fprintf(stderr, "Symbole externe %s\n", ttext->Expr->symbol); #endif a = ttext->Expr->avalue; nbsymbols++; writeword(1, f2, 1); writeword(ttext->offset, f2, 1); writeword(strlen(ttext->Expr->symbol), f2, 1); writestring(ttext->Expr->symbol, f2); nbe++; break; case E_OPERATION: if (ttext->Expr->op == OP_DIRECT) { if (ttext->Expr->child->e_subtype == E_VALUE) { a = ttext->Expr->child->avalue; break; } } if (ttext->Expr->op == OP_DECAL) { if ((ttext->Expr->child->e_subtype == E_LABEL) && (ttext->Expr->child->next->e_subtype == E_VALUE)) { #ifdef DEBUG fprintf(stderr, "Symbole externe %s\n", ttext->Expr->child->symbol); #endif a = ttext->Expr->child->next->avalue; nbsymbols++; writeword(1, f2, 1); writeword(ttext->offset, f2, 1); writeword(strlen(ttext->Expr->child->symbol), f2, 1); writestring(ttext->Expr->child->symbol, f2); nbe++; break; } } if (ttext->Expr->op == OP_PLUS) { if (((ttext->Expr->child->e_subtype == E_LABEL) && (ttext->Expr->child->next->e_subtype == E_VALUE)) || ((ttext->Expr->child->e_subtype == E_VALUE) && (ttext->Expr->child->next->e_subtype == E_LABEL))) { if (ttext->Expr->child->e_subtype == E_LABEL) { #ifdef DEBUG fprintf(stderr, "Symbole externe %s\n", ttext->Expr->child->symbol); #endif a = ttext->Expr->child->next->avalue; nbsymbols++; writeword(1, f2, 1); writeword(ttext->offset, f2, 1); writeword(strlen(ttext->Expr->child->symbol), f2, 1); writestring(ttext->Expr->child->symbol, f2); nbe++; } else { #ifdef DEBUG fprintf(stderr, "Symbole externe %s\n", ttext->Expr->child->next->symbol); #endif a = ttext->Expr->child->avalue; nbsymbols++; writeword(1, f2, 1); writeword(ttext->offset, f2, 1); writeword(strlen(ttext->Expr->child->next->symbol), f2, 1); writestring(ttext->Expr->child->next->symbol, f2); nbe++; } break; } } if (ttext->Expr->op != OP_FUNC_CALL) { exception(1, _("Can't evaluate expression for a direct value")); } if (strcmp(ttext->Expr->symbol, "diff")) { exception(1, _("Can't evaluate expression for a direct value")); } if ((ttext->Expr->child->e_subtype != E_LABEL) || (ttext->Expr->child->next->e_subtype != E_LABEL)) { exception(1, _("Can only use the diff() function onto labels")); } t = (bytestream_t *) NomVarToVar(ttext->Expr->child->symbol, labels, &trouve); if (!trouve) { exception(1, _("Can only evaluate a diff on local symbols")); } u = (bytestream_t *) NomVarToVar(ttext->Expr->child->next->symbol, labels, &trouve); if (!trouve) { exception(1, _("Can only evaluate a diff on local symbols")); } if (t->segment != u->segment) { exception(1, _("Can only evaluate a diff on symbols from the same segment")); } a = t->offset - u->offset; break; default: exception(1, _("Can't evaluate expression")); } } a += ttext->Encoded; if (ttext->size) { writeword(a, f1, text->size); } else { if (ttext->Label) { nbsymbols++; #ifdef DEBUG fprintf(stderr, "Symbole interne %s\n", ttext->Label); #endif writeword(0, f2, 1); writeword(ttext->offset, f2, 1); if (ttext->Label[strlen(ttext->Label) - 1] == ':') { ttext->Label[strlen(ttext->Label) - 1] = '\0'; } writeword(strlen(ttext->Label), f2, 1); writestring(ttext->Label, f2); nbi++; } } popcontext(); } popcontext(); /* Segment de data */ pushcontext(_("Dumping data segment")); for (tdata = tdata->next; tdata; tdata = tdata->next) { sprintf(errctx, _ ("Processing word number %i coming from line %i of the file %s."), tdata->offset, tdata->line, tdata->filename); #ifdef DEBUG fprintf(stderr, "%s\n", errctx); #endif pushcontext(errctx); a = 0; if (tdata->Expr) { switch (tdata->Expr->e_subtype) { case E_VALUE: a = tdata->Expr->avalue; break; case E_LABEL: a = tdata->Expr->avalue; #ifdef DEBUG fprintf(stderr, "Symbole externe %s\n", tdata->Expr->child->symbol); #endif nbsymbols++; writeword(3, f2, 1); writeword(tdata->offset, f2, 1); writeword(strlen(tdata->Expr->symbol), f2, 1); writestring(tdata->Expr->symbol, f2); nbe++; break; case E_OPERATION: if (tdata->Expr->op != OP_FUNC_CALL) { exception(1, _("Can't evaluate expression for a direct value")); } if (strcmp(tdata->Expr->symbol, "diff")) { exception(1, _("Can't evaluate expression for a direct value")); } if ((tdata->Expr->child->e_subtype != E_LABEL) || (tdata->Expr->child->next->e_subtype != E_LABEL)) { exception(1, _("Can only use the diff() function onto labels")); } t = (bytestream_t *) NomVarToVar(tdata->Expr->child->symbol, labels, &trouve); if (!trouve) { exception(1, _("Can only evaluate a diff on local symbols")); } u = (bytestream_t *) NomVarToVar(tdata->Expr->child->next->symbol, labels, &trouve); if (!trouve) { exception(1, _("Can only evaluate a diff on local symbols")); } if (t->segment != u->segment) { exception(1, _("Can only evaluate a diff on symbols from the same segment")); } a = t->offset - u->offset; break; default: exception(1, _("Can't evaluate expression")); } } a += tdata->Encoded; if (tdata->size) { writeword(a, f1, text->size); } else { if (tdata->Label) { nbsymbols++; #ifdef DEBUG fprintf(stderr, "Symbole interne %s\n", tdata->Label); #endif writeword(2, f2, 1); writeword(tdata->offset, f2, 1); writeword(strlen(tdata->Label), f2, 1); writestring(tdata->Label, f2); nbi++; } } popcontext(); } popcontext(); fclose(f1); /* Segment bss */ pushcontext(_("Dumping bss segment")); for (tbss = tbss->next; tbss; tbss = tbss->next) { sprintf(errctx, _ ("Processing word number %i coming from line %i of the file %s."), tbss->offset, tbss->line, tbss->filename); pushcontext(errctx); if (!tbss->size) { if (tbss->Label) { nbsymbols++; writeword(4, f2, 1); #ifdef DEBUG fprintf(stderr, "Symbole interne %s\n", tbss->Label); #endif writeword(tbss->offset, f2, 1); writeword(strlen(tbss->Label), f2, 1); writestring(tbss->Label, f2); nbi++; } } popcontext(); } popcontext(); popcontext(); writeword(0x4f424e4e, f, 1); writeword((ftell(f2) >> 2)+ s_data + s_text + 7, f, 1); t = (bytestream_t *) NomVarToVar("__start__", labels, &trouve); if (trouve) { writeword(t->offset, f, 1); } else { writeword(-1, f, 1); } writeword(s_text, f, 1); writeword(s_data, f, 1); writeword(s_bss, f, 1); writeword((ftell(f2) >> 2) + 1, f, 1); fclose(f2); writeword(nbsymbols, f, 1); appendfile(f, "__symbols__"); appendfile(f, "__text__"); fclose(f); unlink("__symbols__"); unlink("__text__"); fprintf(stderr, _ ("Statistics: %i words of text, %i words of data, and %i words reserved.\n%i symbols generated with %i internal and %i external.\n"), s_text, s_data, s_bss, nbsymbols, nbi, nbe); } /* Diverses fonctions pour faire plein de free() partout */ static void delete_bytestream(bytestream_t * s) { if (s->next) delete_bytestream(s->next); if (s->Label) free(s->Label); free(s); } void assembler_flush(void) { DetruitTab(&defines); DetruitTab(&labels); delete_bytestream(text); delete_bytestream(data); delete_bytestream(bss); } /* Fonction générique qui va traiter un fichier entier */ 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; } /* Fonction d'api pour assembler un fichier d'entrée */ void assemble_file(char *iname, char *oname) { FILE *f; fprintf(stderr, _("Assembling file %s...\n"), iname); pushcontext(_("Opening output file")); if (!(f = fopen(oname, "wb"))) { pushcontext(strerror(errno)); exception(1, _("Error writing output file")); } popcontext(); if (process_file(iname)) { exception(1, _("Error reading file")); } pushcontext(_("Writing output file")); fprintf(stderr, _("Generating output file %s...\n"), oname); asm_eof(f); popcontext(); }