diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/assembler.c | 1015 | ||||
-rw-r--r-- | lib/exceptions.c | 61 | ||||
-rw-r--r-- | lib/hash.c | 8 | ||||
-rw-r--r-- | lib/instructions.txt | 2 | ||||
-rw-r--r-- | lib/meta.c | 179 | ||||
-rw-r--r-- | lib/numbers.c | 12 | ||||
-rw-r--r-- | lib/parser.c | 151 |
7 files changed, 1256 insertions, 172 deletions
diff --git a/lib/assembler.c b/lib/assembler.c index 28bd714..2a3bb86 100644 --- a/lib/assembler.c +++ b/lib/assembler.c @@ -1,26 +1,1025 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> +#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)) -void push_pile(char * a) { - fprintf(stderr, "Push_pile(\"%s\")\n", a); +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++; } -void act_pile(int o) { - fprintf(stderr, "Act_pile(%i)\n", o); + +/* + {',', 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) { +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) { - fprintf(stderr, "End of line\n"); +void asm_eol(void) +{ + /* Gros morceau encore ici... */ + wc = 0; + special = 0; } -void assembler_flush(void) { +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; } diff --git a/lib/exceptions.c b/lib/exceptions.c index 231ca63..0bacb32 100644 --- a/lib/exceptions.c +++ b/lib/exceptions.c @@ -4,42 +4,61 @@ #include "config.h" #include "exceptions.h" -char * contexts[128]; +char *contexts[128]; int clevel = 0; -char * Estrdup(char * o) { - char * r; - - if (!(r = strdup(o))) { - exception(1, _("Out of memory.")); - } - return r; +/********************************\ +* * +* Gestionnaire d'exceptions * +* * +\********************************/ + +char *Estrdup(char *o) +{ + char *r; + + if (o) { + if (!(r = strdup(o))) { + exception(1, _("Out of memory.")); + } + } else { + return NULL; + } + return r; } -void * Emalloc(size_t s) { - void * r; - - if (!(r = malloc(s))) { - exception(1, _("Out of memory.")); - } - return r; +void *Emalloc(size_t s) +{ + void *r; + + if (s) { + if (!(r = malloc(s))) { + exception(1, _("Out of memory.")); + } + } else { + return NULL; + } + return r; } -void pushcontext(char * c) { +void pushcontext(char *c) +{ if (clevel == 128) { exception(1, _("Too much error contexts during pushcontext().")); } contexts[clevel++] = Estrdup(c); } -void popcontext(void) { +void popcontext(void) +{ if (clevel == 0) { exception(1, _("Error context empty, but popcontext() called.")); } free(contexts[--clevel]); } -void flushcontext(void) { +void flushcontext(void) +{ while (clevel) { popcontext(); } @@ -48,11 +67,11 @@ void flushcontext(void) { void exception(int level, char *msg) { int i; - + fprintf(stderr, "Error detected. Showing context.\n"); for (i = 0; i < clevel; i++) { fprintf(stderr, " (%i) - %s\n", i, contexts[i]); } - fprintf(stderr, " Error description: %s\n", msg); - exit(level); + fprintf(stderr, " Error description: %s\n", msg); + exit(level); } @@ -95,7 +95,8 @@ static void Supprimer(_ListeChaine * l, char *Nom) } } -static void Detruit(_ListeChaine * l) { +static void Detruit(_ListeChaine * l) +{ _ListeChaine l_aux = NULL; while (*l) { @@ -180,13 +181,14 @@ int Initialise(_TableauVariable * t) return (i); } -void DetruitTab(_TableauVariable * t){ +void DetruitTab(_TableauVariable * t) +{ int i; for (i = 0; i < strlen(CHAINEHACHAGE); i++) { Detruit(&((*t)[i])); } - + free(*t); *t = NULL; } diff --git a/lib/instructions.txt b/lib/instructions.txt index ab8e387..6522ffe 100644 --- a/lib/instructions.txt +++ b/lib/instructions.txt @@ -1,5 +1,5 @@ FI:c3,6;c2,6;c1,6;e,6;op,8 -Fa:reserved,4;rm,2 +Fa:reserved,4;rm, Pr:R0;R1;R2;R3;R4;R5;R6;R7;R8;R9;R10;R11;R12;R13;R14;R15;R16;R17;R18;R19;R20;R21;R22;R23;R24;R25;R26;R27;R28;R29;R30;R31;Rg;Rd;IP;Fl Pm:regop=.Pr;.I=.O;[regop=.Pr;.I=.O[regop=.Pr @@ -7,14 +7,17 @@ #include "config.h" #else #define _(x) x -void exception(int, char *); -char * Estrdup(char *); -void * Emalloc(size_t); #endif #include "exceptions.h" #include "numbers.h" #include "meta.h" +/*************************\ +* * +* Meta Parser * +* * +\*************************/ + static char meta_ops[] = ":.;(){}[=, "; static char meta_firsts[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; static char meta_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"; @@ -24,6 +27,8 @@ field_t *fields = NULL; pattern_t *patterns = NULL; instruct_t *instructs = NULL; +/* Fonction interne pour déterminer si une chaîne forme un identifier correct. */ + static int isident(char *word) { if (!strchr(meta_firsts, *word)) { @@ -37,6 +42,8 @@ static int isident(char *word) return 1; } +/* La fonction getword pour le meta parser. Beaucoup plus simple que le parser normal. */ + static char *getword(char *line, char *p) { char o; @@ -50,17 +57,21 @@ static char *getword(char *line, char *p) return line; } +/* La terrible fonction meta_parse_line. Elle lit une chaîne correspondant à une ligne du fichier texte d'entrée. +Le problème réside surtout dans le fait qu'il y a des variables globales et des effets de bords, ce qui empèche le +découpage en sous routines. */ + void meta_parse_line(char *line) { char buffer[BUFSIZ], *first = NULL, m = 0, *p1 = NULL, *p2 = NULL, *Fnames[MAXF], *Fimplicits[MAXF], - *Snames[MAXF], *Sinames[MAXF], gotname = 0, goteoi = 0, errbuff[BUFSIZ]; + *Snames[MAXF], *Sinames[MAXF], gotname = 0, goteoi = 0, errbuff[BUFSIZ]; phon_t *phon = NULL; field_t *field = NULL; pattern_t *pattern = NULL; instruct_t *instruct = NULL; metaexpr_t *metaexpr = NULL, *tmetaexpr, *tabmetaexpr[MAXM]; int Fsizes[MAXF], Fvalues[MAXF], Itypes[MAXF], Etypes[MAXF], nbfields = 0, valid, i, nbimplicit = 0; - + if (*line == '#') { return; } @@ -73,6 +84,7 @@ void meta_parse_line(char *line) sprintf(errbuff, _("Analysing word '%s'"), buffer); pushcontext(errbuff); if (!m) { + /* Premier mot lut de la chaîne */ if (*line != ':') { exception(1, _("Missing operator ':'")); } @@ -97,6 +109,7 @@ void meta_parse_line(char *line) break; } } else { + /* Nous avons lut le premier mot, nous savons ce qu'il faut faire. */ switch (m) { case 1: /* Champ */ if (gotname) { @@ -117,6 +130,7 @@ void meta_parse_line(char *line) field->name = first; field->names = (char **) Emalloc(nbfields * sizeof(char *)); field->sizes = (int *) Emalloc(nbfields * sizeof(int)); + for (i = 0; i < nbfields; i++) { field->names[i] = Fnames[i]; field->sizes[i] = Fsizes[i]; @@ -169,7 +183,7 @@ void meta_parse_line(char *line) } else { tmetaexpr->string = NULL; } - + if (metaexpr) { metaexpr->right = tmetaexpr; } else { @@ -177,7 +191,8 @@ void meta_parse_line(char *line) } if (*line == ';' || !*line) { tabmetaexpr[nbfields++] = metaexpr; - if (*line) line++; + if (*line) + line++; metaexpr = NULL; } if (!*line) { @@ -185,7 +200,8 @@ void meta_parse_line(char *line) pattern->next = patterns->next; patterns->next = pattern; pattern->name = first; - pattern->expr = (metaexpr_t **) Emalloc(nbfields * sizeof(metaexpr_t *)); + pattern->expr = + (metaexpr_t **) Emalloc(nbfields * sizeof(metaexpr_t *)); for (i = 0; i < nbfields; i++) { pattern->expr[i] = tabmetaexpr[i]; } @@ -311,6 +327,7 @@ void meta_parse_line(char *line) instruct->ivalues = (int *) Emalloc(nbimplicit * sizeof(int)); instruct->istrings = (char **) Emalloc(nbimplicit * sizeof(char *)); instruct->itypes = (int *) Emalloc(nbimplicit * sizeof(int)); + for (i = 0; i < nbfields; i++) { instruct->names[i] = Fnames[i]; instruct->strings[i] = Snames[i]; @@ -332,10 +349,12 @@ void meta_parse_line(char *line) } popcontext(); } - + popcontext(); } +/* Initialiseur et destructeur du meta parser */ + int meta_init(void) { if (!(phons = (phon_t *) malloc(sizeof(phon_t)))) { @@ -351,14 +370,14 @@ int meta_init(void) fields->names = NULL; fields->sizes = NULL; fields->next = NULL; - + if (!(patterns = (pattern_t *) malloc(sizeof(pattern_t)))) { return -1; } patterns->name = NULL; patterns->expr = NULL; patterns->next = NULL; - + if (!(instructs = (instruct_t *) malloc(sizeof(instruct_t)))) { return -1; } @@ -373,23 +392,25 @@ int meta_init(void) return 0; } -static void recurs_free_phon(phon_t * phon) { +static void recurs_free_phon(phon_t * phon) +{ if (phon->next) { recurs_free_phon(phon->next); } - + free(phon->p1); free(phon->p2); free(phon); } -static void recurs_free_field(field_t * field) { +static void recurs_free_field(field_t * field) +{ int i; - + if (field->next) { recurs_free_field(field->next); } - + free(field->name); for (i = 0; i < field->nbr; i++) { free(field->names[i]); @@ -399,11 +420,12 @@ static void recurs_free_field(field_t * field) { free(field); } -static void recurs_free_metaexpr(metaexpr_t * metaexpr) { +static void recurs_free_metaexpr(metaexpr_t * metaexpr) +{ if (metaexpr->left) { recurs_free_metaexpr(metaexpr->left); } - + if (metaexpr->right) { recurs_free_metaexpr(metaexpr->right); } @@ -411,21 +433,22 @@ static void recurs_free_metaexpr(metaexpr_t * metaexpr) { if (metaexpr->name) { free(metaexpr->name); } - + if (metaexpr->string) { free(metaexpr->string); } - + free(metaexpr); } -static void recurs_free_pattern(pattern_t * pattern) { +static void recurs_free_pattern(pattern_t * pattern) +{ int i; if (pattern->next) { recurs_free_pattern(pattern->next); } - + free(pattern->name); for (i = 0; i < pattern->nbr; i++) { recurs_free_metaexpr(pattern->expr[i]); @@ -434,20 +457,21 @@ static void recurs_free_pattern(pattern_t * pattern) { free(pattern); } -static void recurs_free_instruct(instruct_t * instruct) { +static void recurs_free_instruct(instruct_t * instruct) +{ int i; - + if (instruct->next) { recurs_free_instruct(instruct->next); } - + for (i = 0; i < instruct->nbexplicit; i++) { free(instruct->names[i]); if (instruct->strings[i]) { free(instruct->strings[i]); } } - + for (i = 0; i < instruct->nbimplicit; i++) { free(instruct->implicits[i]); free(instruct->istrings[i]); @@ -462,11 +486,16 @@ static void recurs_free_instruct(instruct_t * instruct) { free(instruct); } -void meta_flush(void) { - if (phons->next) recurs_free_phon(phons->next); - if (fields->next) recurs_free_field(fields->next); - if (patterns->next) recurs_free_pattern(patterns->next); - if (instructs->next) recurs_free_instruct(instructs->next); +void meta_flush(void) +{ + if (phons->next) + recurs_free_phon(phons->next); + if (fields->next) + recurs_free_field(fields->next); + if (patterns->next) + recurs_free_pattern(patterns->next); + if (instructs->next) + recurs_free_instruct(instructs->next); free(phons); free(fields); free(patterns); @@ -477,14 +506,16 @@ void meta_flush(void) { instructs = NULL; } -int meta_load(char * n) { - FILE * f; - char buf[BUFSIZ], *p; - +int meta_load(char *n) +{ + FILE *f; + char buf[BUFSIZ], errctx[BUFSIZ], *p; + int i = 0; + pushcontext("Loading meta file"); - sprintf(buf, "Opening file '%s'", n); - pushcontext(buf); - + sprintf(errctx, "Opening file '%s'", n); + pushcontext(errctx); + if (!(f = fopen(n, "r"))) { pushcontext(strerror(errno)); return 1; @@ -492,6 +523,8 @@ int meta_load(char * n) { popcontext(); pushcontext("Reading file"); while (fgets(buf, BUFSIZ, f)) { + sprintf(errctx, "Reading line %i", ++i); + pushcontext(errctx); if ((p = strchr(buf, '\r'))) { *p = '\0'; } @@ -499,39 +532,19 @@ int meta_load(char * n) { *p = '\0'; } meta_parse_line(buf); + popcontext(); } popcontext(); popcontext(); - - + + fclose(f); return 0; } #ifndef HAVE_CONFIG_H -char * Estrdup(char * o) { - char * r; - - if (!(r = strdup(o))) { - exception(1, _("Out of memory.")); - } - return r; -} - -void * Emalloc(size_t s) { - void * r; - - if (!(r = malloc(s))) { - exception(1, _("Out of memory.")); - } - return r; -} -void exception(int level, char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(level); -} +/* Programme de test si on compile le meta parser indépendament du reste du projet */ void main(void) { @@ -558,7 +571,7 @@ void main(void) fprintf(stderr, " + %s (%i bits)\n", field->names[i], field->sizes[i]); } } - + fprintf(stderr, "\nListe des patterns:\n"); for (pattern = patterns->next; pattern; pattern = pattern->next) { fprintf(stderr, " o Pattern nommée %s, contenant %i metaexpressions:\n", pattern->name, pattern->nbr); @@ -566,17 +579,20 @@ void main(void) fprintf(stderr, " + %s (%s) type: %s\n", pattern->expr[i]->name ? pattern->expr[i]->name : "Opérateur [", pattern->expr[i]->string ? pattern->expr[i]->string : "Aucune chaîne associée", - pattern->expr[i]->type ? "Constante prédéfinie" : pattern->expr[i]->left ? "Binaire" : pattern->expr[i]->right ? "Unaire" : "Feuille"); + pattern->expr[i]->type ? "Constante prédéfinie" : pattern->expr[i]-> + left ? "Binaire" : pattern->expr[i]->right ? "Unaire" : "Feuille"); if (pattern->expr[i]->left) { fprintf(stderr, " - gauche: %s (%s) type: %s\n", pattern->expr[i]->left->name ? pattern->expr[i]->left->name : "Opérateur [", - pattern->expr[i]->left->string ? pattern->expr[i]->left->string : "Aucune chaîne associée", + pattern->expr[i]->left->string ? pattern->expr[i]->left-> + string : "Aucune chaîne associée", pattern->expr[i]->left->type ? "Constante prédéfinie" : "Feuille"); } if (pattern->expr[i]->right) { fprintf(stderr, " - droite: %s (%s) type: %s\n", pattern->expr[i]->right->name ? pattern->expr[i]->right->name : "Opérateur [", - pattern->expr[i]->right->string ? pattern->expr[i]->right->string : "Aucune chaîne associée", + pattern->expr[i]->right->string ? pattern->expr[i]->right-> + string : "Aucune chaîne associée", pattern->expr[i]->right->type ? "Constante prédéfinie" : "Feuille"); } } @@ -584,29 +600,32 @@ void main(void) fprintf(stderr, "\nListe des instructions:\n"); for (instruct = instructs->next; instruct; instruct = instruct->next) { - fprintf(stderr, " o Instruction contenant %i champs explicites et %i champs implicites.\n", instruct->nbexplicit, instruct->nbimplicit); + fprintf(stderr, " o Instruction contenant %i champs explicites et %i champs implicites.\n", + instruct->nbexplicit, instruct->nbimplicit); fprintf(stderr, " => Champs explicites.\n"); for (i = 0; i < instruct->nbexplicit; i++) { fprintf(stderr, " + %s <= %s (type %s)\n", - instruct->names[i], - instruct->strings[i] ? instruct->strings[i] : "Pas de chaîne associée", - instruct->etypes[i] ? "prédéfinit" : "direct"); + instruct->names[i], + instruct->strings[i] ? instruct->strings[i] : "Pas de chaîne associée", + instruct->etypes[i] ? "prédéfinit" : "direct"); } fprintf(stderr, " => Champs implicites.\n"); for (i = 0; i < instruct->nbimplicit; i++) { switch (instruct->itypes[i]) { - case 0: - fprintf(stderr, " + %s <= %s (type direct)\n", instruct->implicits[i], instruct->istrings[i]); - break; - case 1: - fprintf(stderr, " + %s <= %i (type prédéfinit)\n", instruct->implicits[i], instruct->istrings[i]); - break; - case 2: - fprintf(stderr, " + %s <= %i (type valeur)\n", instruct->implicits[i], instruct->ivalues[i]); - break; + case 0: + fprintf(stderr, " + %s <= %s (type direct)\n", instruct->implicits[i], + instruct->istrings[i]); + break; + case 1: + fprintf(stderr, " + %s <= %i (type prédéfinit)\n", instruct->implicits[i], + instruct->istrings[i]); + break; + case 2: + fprintf(stderr, " + %s <= %i (type valeur)\n", instruct->implicits[i], + instruct->ivalues[i]); + break; } } } } - #endif diff --git a/lib/numbers.c b/lib/numbers.c index 8334dd4..9f032b5 100644 --- a/lib/numbers.c +++ b/lib/numbers.c @@ -1,11 +1,15 @@ #include "numbers.h" +/* Cette fonction lit un nombre. Elle va chercher absolument à traduire la chaîne passée en argument en un nombre. Si +ce nombre n'est pas valide, alors l'int valid est mis à faux. Cette fonction reconnais les nombres en décimaux, les nombres +en octal préfixés avec 0 et les nombres en hexadécimal préfixés avec 0x. */ + int char_to_number(char *st, int *valid) { int whattype = 0, result = 0; - + *valid = 0; - + if (*st == '0') { st++; if (*st == 'x') { @@ -18,7 +22,7 @@ int char_to_number(char *st, int *valid) return 0; } } - + while (*st) { switch (whattype) { case 0: @@ -52,7 +56,7 @@ int char_to_number(char *st, int *valid) } st++; } - + *valid = 1; return result; } diff --git a/lib/parser.c b/lib/parser.c index ee3e64c..2a9edd1 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -4,11 +4,16 @@ #include "config.h" #else #define _(x) x -void exception(int, char *); #endif #include "exceptions.h" #include "parser.h" +#include "assembler.h" +/*******************************\ +* * +* Parser * +* * +\*******************************/ typedef unsigned char op_t; @@ -22,8 +27,10 @@ static int pile_nestedcall[PILECALL_MAX]; static int pileop_pos = 0, pilecall_pos = 0; +/* La liste des opérateurs reconnus par le parser */ + static operator_t operators[] = { - {',', 0, OP_NEST}, + {',', 0, OP_NEST}, {'+', 2, OP_PLUS}, {'-', 2, OP_MOINS}, {'*', 3, OP_MUL}, @@ -37,6 +44,8 @@ static operator_t operators[] = { {255, -1, -1} }; +/* Fonction interne: convertit un operateur en sa structure */ + static operator_t get_op(op_t op) { int i; @@ -49,6 +58,8 @@ static operator_t get_op(op_t op) return operators[i]; } +/* Fonctions internes de lectures sur la structure */ + static int get_pri(op_t op) { return get_op(op).pri; @@ -59,6 +70,8 @@ static int get_func(op_t op) return get_op(op).func; } +/* Focntions internes d'empilement / dépilement */ + static op_t get_last_op(void) { if (pileop_pos) @@ -87,20 +100,22 @@ static int pop_call(void) { if (pilecall_pos) return pile_nestedcall[--pilecall_pos]; - return -1; + return -1; } -static void increment_call(void) { - if (pilecall_pos) { - if (pile_nestedcall[pilecall_pos - 1] != -1) - pile_nestedcall[pilecall_pos - 1]++; - } -} - -static int get_last_call(void) { - if (pilecall_pos) - return pile_nestedcall[pilecall_pos - 1]; - return -1; +static void increment_call(void) +{ + if (pilecall_pos) { + if (pile_nestedcall[pilecall_pos - 1] != -1) + pile_nestedcall[pilecall_pos - 1]++; + } +} + +static int get_last_call(void) +{ + if (pilecall_pos) + return pile_nestedcall[pilecall_pos - 1]; + return -1; } static void push_call(int call) @@ -111,6 +126,8 @@ static void push_call(int call) exception(-1, _("Too many nested functions calls in expression.\n")); } +/* Cette fonction lit un "mot" sur la chaine line et renvoit le nouveau pointeur */ + static char *getword(char *line, char *p) { char o = 0, *d = line, instring = 0, gotbslash = 0; @@ -120,18 +137,19 @@ static char *getword(char *line, char *p) o = *(p++) = *line; if (!gotbslash) { switch (instring) { - case 1: - if (*line == '\'') { - instring = 0; - } - break; - case 2: - if (*line == '"') { - instring = 0; - } - break; + case 1: + if (*line == '\'') { + instring = 0; + } + break; + case 2: + if (*line == '"') { + instring = 0; + } + break; } - if (*line == '\\') gotbslash = 1; + if (*line == '\\') + gotbslash = 1; } else { gotbslash = 0; } @@ -143,7 +161,7 @@ static char *getword(char *line, char *p) o = *(p++) = *line; instring = 2; } else { - if (*(line) != ' ') { + if (*(line) != ' ' && *(line) != '\t') { o = *(p++) = *line; } else if (d != line) { *p = '\0'; @@ -153,20 +171,28 @@ static char *getword(char *line, char *p) } line++; } while (((*line) && (*line != ')') && (*line != ']') && (*line != ';') && (get_func(*line) == -1) - && (get_func(o) == -1)) || (instring)); + && (get_func(o) == -1)) || (instring)); *p = '\0'; return line; } +/* Cette fonction va parcourire une chaine afin d'appeler les fonction push_pule() et act_pile() */ + void parse_line(char *line) { - char buffer[BUFSIZ], imm[BUFSIZ]; + char buffer[BUFSIZ], imm[BUFSIZ], *d = line; op_t op; int got_unary = 128, nbrargs; + sprintf(buffer, "Read line '%s'", line); + pushcontext(buffer); + while (*line) { line = getword(line, buffer); + sprintf(imm, "Analysing word '%s' at position %i", buffer, line - d); + pushcontext(imm); if (get_func(buffer[0]) != -1) { + /* Le mot lut est un operateur, on agit sur la pile */ buffer[0] += got_unary; if (got_unary) { } @@ -177,28 +203,35 @@ void parse_line(char *line) exception(-1, _("Invalid binary operator")); } } - while (get_pri(get_last_op()) >= get_pri(buffer[0]) && (((get_last_op() & 127) != '(') && ((get_last_op() & 127) != '['))) { + while (get_pri(get_last_op()) >= get_pri(buffer[0]) + && (((get_last_op() & 127) != '(') && ((get_last_op() & 127) != '['))) { act_pile(get_func(pop_op())); got_unary = 0; } if (buffer[0] == '(') { push_call(0); - } + } if (buffer[0] == ',') { - increment_call(); - } else push_op(buffer[0]); + increment_call(); + } else + push_op(buffer[0]); got_unary = 128; } else if ((buffer[0] == ';') || (buffer[0] == ')') || (buffer[0] == ']')) { + /* Le mot lut est un opérateur spécial, on vide la pile */ switch (buffer[0]) { case ';': + /* Equivalent a fin de ligne */ while (pileop_pos) { op = pop_op(); if (op == '(') exception(-1, _("Parse error: too much left parenthesis")); act_pile(get_func(op)); } - break; + popcontext(); + popcontext(); + return; case ')': + /* Fin de parenthese (Appel de fonction ou expression mathématique) */ while (1) { if (!pileop_pos) exception(-1, _("Parse error: too much right parenthesis")); @@ -209,15 +242,16 @@ void parse_line(char *line) exception(-1, _("Parse error: enclosure mismatch")); act_pile(get_func(op)); } - if (op == '(') { - nbrargs = pop_call(); - sprintf(imm, "%i", nbrargs); - push_pile(imm); - act_pile(get_func(op)); - } + if (op == '(') { + nbrargs = pop_call(); + sprintf(imm, "%i", nbrargs); + push_pile(imm); + act_pile(get_func(op)); + } got_unary = 0; break; case ']': + /* Fin d'opérateur de décalage */ while (1) { if (!pileop_pos) exception(-1, _("Parse error: too much right parenthesis")); @@ -228,28 +262,30 @@ void parse_line(char *line) exception(-1, _("Parse error: enclosure mismatch")); act_pile(get_func(op)); } - act_pile(get_func(op)); + act_pile(get_func(op)); got_unary = 0; break; } } else if (((buffer[0] >= 'A') && (buffer[0] <= 'Z')) || ((buffer[0] >= 'a') && (buffer[0] <= 'z')) - || ((buffer[0] >= '0') && (buffer[0] <= '9')) || (buffer[0] == '_') || (buffer[0] == '"') || (buffer[0] == '\'')) { + || ((buffer[0] >= '0') && (buffer[0] <= '9')) || (buffer[0] == '_') || (buffer[0] == '"') + || (buffer[0] == '\'')) { + /* Dans tous les autres cas, on a reçu un symbole, on le pose sur la pile */ push_pile(buffer); got_unary = 0; - if (!get_last_call()) increment_call(); + if (!get_last_call()) + increment_call(); } else if (buffer[0]) { exception(-1, _("Invalid character")); } + popcontext(); } + + popcontext(); } #ifndef HAVE_CONFIG_H -void exception(int level, char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(level); -} +/* Les quelques fonctions de test, lorsque le parser est compilé en dehors du projet. */ void push_pile(char *word) { @@ -279,9 +315,9 @@ void act_pile(int func) case OP_MOINS_UNARY: op = '|'; break; - case OP_FUNC_CALL: - op = '@'; - break; + case OP_FUNC_CALL: + op = '@'; + break; case OP_DECAL: op = '['; break; @@ -295,15 +331,20 @@ void act_pile(int func) void main(void) { parse_line("ADD R18, R20, 39;"); - printf("\n\n"); fflush(stdout); + printf("\n\n"); + fflush(stdout); parse_line("MOV R31, Bidule[48 + R12];"); - printf("\n\n"); fflush(stdout); + printf("\n\n"); + fflush(stdout); parse_line("MOV R12, [R3];"); - printf("\n\n"); fflush(stdout); + printf("\n\n"); + fflush(stdout); parse_line("MOV R22, Truc[(3+2)*8];"); - printf("\n\n"); fflush(stdout); + printf("\n\n"); + fflush(stdout); parse_line("Trucmuche DB \"Test de chaîne complète avec des opérateurs comme le + et le - ...\""); - printf("\n\n"); fflush(stdout); + printf("\n\n"); + fflush(stdout); } #endif |