/* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Released under the terms of the GNU GPL v2.0. */ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "cml1.h" struct file *file_list; struct file *current_file; struct symbol symbol_yes = { name: "y", curr: { "y", yes }, flags: SYMBOL_YES|SYMBOL_VALID, }, symbol_mod = { name: "m", curr: { "m", mod }, flags: SYMBOL_MOD|SYMBOL_VALID, }, symbol_no = { name: "n", curr: { "n", no }, flags: SYMBOL_NO|SYMBOL_VALID, }, symbol_empty = { name: "", curr: { "", no }, flags: SYMBOL_VALID, }; struct expr *expr_alloc_symbol(struct symbol *sym) { struct expr *e = malloc(sizeof(*e)); memset(e, 0, sizeof(*e)); e->token = T_WORD; e->left.sym = sym; return e; } struct expr *expr_alloc_one(int token, struct expr *ce) { struct expr *e = malloc(sizeof(*e)); memset(e, 0, sizeof(*e)); e->token = token; e->left.expr = ce; return e; } struct expr *expr_alloc_two(int token, struct expr *e1, struct expr *e2) { struct expr *e = malloc(sizeof(*e)); memset(e, 0, sizeof(*e)); e->token = token; e->left.expr = e1; e->right.expr = e2; return e; } struct expr *expr_alloc_comp(int token, struct symbol *s1, struct symbol *s2) { struct expr *e = malloc(sizeof(*e)); memset(e, 0, sizeof(*e)); e->token = token; e->left.sym = s1; e->right.sym = s2; return e; } struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) { if (!e1) return e2; return e2 ? expr_alloc_two(T_AND, e1, e2) : e1; } struct expr *expr_copy(struct expr *org) { struct expr *e; if (!org) return NULL; e = malloc(sizeof(*org)); memcpy(e, org, sizeof(*org)); switch (org->token) { case T_WORD: e->left = org->left; break; case '!': e->left.expr = expr_copy(org->left.expr); break; case '=': case T_UNEQUAL: e->left.sym = org->left.sym; e->right.sym = org->right.sym; break; case T_OR: case T_AND: case '&': case '|': case '^': case T_IF: case T_ELSE: e->left.expr = expr_copy(org->left.expr); e->right.expr = expr_copy(org->right.expr); break; default: printf("can't copy token %d\n", e->token); free(e); e = NULL; break; } return e; } void expr_free(struct expr *e) { if (!e) return; switch (e->token) { case T_WORD: break; case '!': expr_free(e->left.expr); return; case '=': case T_UNEQUAL: break; case '|': case T_OR: case T_AND: case '&': case T_IF: case T_ELSE: expr_free(e->left.expr); expr_free(e->right.expr); break; default: printf("how to free token %d?\n", e->token); break; } free(e); } static inline int token_gt(int t1, int t2) { #if 0 return 1; #else switch (t1) { case '=': case T_UNEQUAL: if (t2 == '!') return 1; case '!': if (t2 == T_AND || t2 == T_IF || t2 == T_ELSE || t2 == '&') return 1; case '&': case T_IF: case T_ELSE: case T_AND: if (t2 == T_OR || t2 == '|') return 1; case '|': case T_OR: if (t2 == '^') return 1; case '^': if (t2 == 0) return 1; case 0: return 0; } printf("[%dgt%d?]", t1, t2); return 0; #endif } int print_type = 1; static void print_sym(FILE *out, struct symbol *sym) { fprintf(out, "%s", sym->name); if (print_type) fprintf(out, "%s", sym->type == SYMBOL_BOOLEAN ? "?" : sym->type == SYMBOL_TRISTATE ? "??" : sym->type == SYMBOL_HEX ? "h" : sym->type == SYMBOL_INT ? "i" : sym->type == SYMBOL_STRING ? "s" : ""); } void fprint_expr(FILE *out, struct expr *e, int prevtoken) { if (!e) { fprintf(out, "<none>"); return; } switch (e->token) { case T_WORD: print_sym(out, e->left.sym); break; case '!': if (token_gt(prevtoken, '!')) fprintf(out, "("); fprintf(out, "!"); fprint_expr(out, e->left.expr, '!'); if (token_gt(prevtoken, '!')) fprintf(out, ")"); break; case '=': if (token_gt(prevtoken, '=')) fprintf(out, "("); print_sym(out, e->left.sym); fprintf(out, "="); print_sym(out, e->right.sym); if (token_gt(prevtoken, '=')) fprintf(out, ")"); break; case T_UNEQUAL: if (token_gt(prevtoken, T_UNEQUAL)) fprintf(out, "("); print_sym(out, e->left.sym); fprintf(out, "!="); print_sym(out, e->right.sym); if (token_gt(prevtoken, T_UNEQUAL)) fprintf(out, ")"); break; case T_OR: if (token_gt(prevtoken, T_OR)) fprintf(out, "("); fprint_expr(out, e->left.expr, T_OR); fprintf(out, " || "); fprint_expr(out, e->right.expr, T_OR); if (token_gt(prevtoken, T_OR)) fprintf(out, ")"); break; case T_AND: if (token_gt(prevtoken, T_AND)) fprintf(out, "("); fprint_expr(out, e->left.expr, T_AND); fprintf(out, " && "); fprint_expr(out, e->right.expr, T_AND); if (token_gt(prevtoken, T_AND)) fprintf(out, ")"); break; case '|': if (token_gt(prevtoken, '|')) fprintf(out, "("); fprint_expr(out, e->left.expr, '|'); fprintf(out, " || "); fprint_expr(out, e->right.expr, '|'); if (token_gt(prevtoken, '|')) fprintf(out, ")"); break; case '&': if (token_gt(prevtoken, '&')) fprintf(out, "("); fprint_expr(out, e->left.expr, '&'); if (print_type) fprintf(out, " & "); else fprintf(out, " && "); fprint_expr(out, e->right.expr, '&'); if (token_gt(prevtoken, '&')) fprintf(out, ")"); break; case '^': if (e->left.expr) { fprint_expr(out, e->left.expr, '^'); fprintf(out, " ^ "); } fprintf(out, "%s", e->right.sym->name); break; case T_IF: if (token_gt(prevtoken, T_IF)) fprintf(out, "["); if (e->right.expr) { fprint_expr(out, e->right.expr, T_IF); fprintf(out, " && "); } fprint_expr(out, e->left.expr, T_IF); if (token_gt(prevtoken, T_IF)) fprintf(out, "]"); break; case T_ELSE: if (token_gt(prevtoken, T_ELSE)) fprintf(out, "["); //fprintf(out, "["); if (e->right.expr) { fprint_expr(out, e->right.expr, T_ELSE); fprintf(out, " && "); } fprintf(out, "!"); fprint_expr(out, e->left.expr, '!'); if (token_gt(prevtoken, T_ELSE)) fprintf(out, "]"); break; default: fprintf(out, "<unknown token %d>", e->token); break; } } void print_expr(int mask, struct expr *e, int prevtoken) { if (!(cdebug & mask)) return; fprint_expr(stdout, e, prevtoken); } struct file *lookup_file(const char *name) { struct file *file; for (file = file_list; file; file = file->next) { if (!strcmp(name, file->name)) return file; } file = malloc(sizeof(*file)); memset(file, 0, sizeof(*file)); file->name = strdup(name); file->next = file_list; file_list = file; return file; }