/* * * Interpreteur de ligne de commande * */ #include #include #ifdef HAVE_CONFIG_H #include "config.h" #else #define _(x) x #endif #include "interface.h" #include "exceptions.h" #include "pile.h" typedef unsigned char op_t; typedef struct operator_t { op_t op; int pri, func; } operator_t; op_t pile_operators[PILEOP_MAX]; int pile_nestedcall[PILECALL_MAX]; int pileop_pos = 0, pilecall_pos = 0; operator_t operators[] = { {',', 0, OP_NEST}, {'+', 2, OP_PLUS}, {'-', 2, OP_MOINS}, {'*', 3, OP_MUL}, {'/', 3, OP_DIV}, {'%', 3, OP_MOD}, {'^', 4, OP_EXP}, {'+' + 128, 5, OP_PLUS_UNARY}, {'-' + 128, 5, OP_MOINS_UNARY}, {'=', 1, OP_ASSIGN}, {'(', 6, OP_FUNC_CALL}, {'(' + 128, 6, OP_LPAREN}, {255, -1, -1} }; operator_t get_op(op_t op) { int i; for (i = 0; operators[i].op != 255; i++) { if (operators[i].op == op) return operators[i]; } return operators[i]; } int get_pri(op_t op) { return get_op(op).pri; } int get_func(op_t op) { return get_op(op).func; } op_t get_last_op(void) { if (pileop_pos) return pile_operators[pileop_pos - 1]; else return -1; } op_t pop_op(void) { if (pileop_pos) return pile_operators[--pileop_pos]; return -1; } void push_op(op_t op) { if (pileop_pos != PILEOP_MAX) pile_operators[pileop_pos++] = op; else exception(-1, _("Too many nested operators in expression.\n")); } int pop_call(void) { if (pilecall_pos) fprintf(stderr, "Dépilement du dernier appel de fonction: %i\n", pile_nestedcall[pilecall_pos - 1]); return pile_nestedcall[--pilecall_pos]; return -1; } void increment_call(void) { if (pilecall_pos) { fprintf(stderr, "Incrément du dernier appel de fonction: %i\n", pile_nestedcall[pilecall_pos - 1]); if (pile_nestedcall[pilecall_pos - 1] != -1) pile_nestedcall[pilecall_pos - 1]++; } } int get_last_call(void) { if (pilecall_pos) return pile_nestedcall[pilecall_pos - 1]; return -1; } void push_call(int call) { fprintf(stderr, "Empilement d'un appel de fonction: %i\n", call); if (pilecall_pos != PILECALL_MAX) pile_nestedcall[pilecall_pos++] = call; else exception(-1, _("Too many nested functions calls in expression.\n")); } char *getword(char *line, char *p) { char o; do { if (*(line) != ' ') { o = *(p++) = *line; fprintf(stderr, "getword(): a trouvé le caractère '%c'\n", o); } line++; } while ((*line) && (*line != ')') && (*line != ';') && (get_func(*line) == -1) && (get_func(o) == -1)); *p = '\0'; return line; } int parse_line(char *line) { char buffer[BUFSIZ]; op_t op; int got_unary = 128, nbrargs; fprintf(stderr, "Analyse de: \"%s\"...\n\n", line); while (*line) { line = getword(line, buffer); fprintf(stderr, "parse_line(): getword a trouvé le mot \"%s\"\n", buffer); if (get_func(buffer[0]) != -1) { fprintf(stderr, "Il s'agit d'un opérateur.\n"); buffer[0] += got_unary; if (got_unary) { fprintf(stderr, "Opérateur de type unaire\n"); } if (get_pri(buffer[0]) == -1) { if (got_unary) { exception(-1, _("Invalid unary operator")); } else { exception(-1, _("Invalid binary operator")); } } fprintf(stderr, "Priorité du dernier op: %i, priorité actu: %i\n", get_pri(get_last_op()), get_pri(buffer[0])); while (get_pri(get_last_op()) >= get_pri(buffer[0]) && ((get_last_op() & 127) != '(')) { fprintf(stderr, "Il y a un opérateur plus important sur la file.\n"); act_pile(get_func(pop_op())); got_unary = 0; fprintf(stderr, "Priorité du dernier op: %i, priorité actu: %i\n", get_pri(get_last_op()), get_pri(buffer[0])); } fprintf(stderr, "Mise sur la file\n"); if (buffer[0] == '(') { push_call(0); } if (buffer[0] == ',') { increment_call(); } else push_op(buffer[0]); got_unary = 128; } else if ((buffer[0] == ';') || (buffer[0] == ')')) { fprintf(stderr, "Caractère spécial\n"); switch (buffer[0]) { case ';': fprintf(stderr, "Vidage complet de la file (fin de commande).\n"); while (pileop_pos) { op = pop_op(); if (op == '(') exception(-1, _ ("Parse error: too much left parenthesis")); act_pile(get_func(op)); } break; case ')': fprintf(stderr, "Vidage de la file jusqu'à '(' car ')' trouvée.\n"); while (1) { if (!pileop_pos) exception(-1, _ ("Parse error: too much right parenthesis")); op = pop_op(); if (((op & 127) == '(')) break; act_pile(get_func(op)); } if (op == '(') { nbrargs = pop_call(); push_pile_int(nbrargs); 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] == '_')) { fprintf(stderr, "Symbole.\n"); push_pile(buffer); got_unary = 0; if (!get_last_call()) increment_call(); } else if (buffer[0]) { exception(-1, _("Invalid character")); } } }