// // aegis - project change supervisor // Copyright (C) 1991-1995, 1998, 1999, 2001-2008 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include #include #include #include #include #include #include #include static sem_ty *sem_root; void * parse(string_ty *filename, meta_type *type) { void *addr; trace(("parse(filename = \"%s\", type = %08lX)\n{\n", filename->str_text, (long)type)); lex_open(filename); assert(type); assert(type->alloc); assert(type->struct_parse); addr = type->alloc(); sem_push(type, addr); trace(("gram_parse()\n{\n")); gram_parse(); trace(("}\n")); while (sem_root) sem_pop(); lex_close(); trace(("return %08lX;\n", (long)addr)); trace(("}\n")); return addr; } void * parse_env(const char *name, meta_type *type) { void *addr; trace(("parse_env(name = \"%s\", type = %08lx)\n{\n", name, (long)type)); lex_open_env(name); assert(type); assert(type->alloc); assert(type->struct_parse); addr = type->alloc(); sem_push(type, addr); trace(("gram_parse()\n{\n")); gram_parse(); trace(("}\n")); while (sem_root) sem_pop(); lex_close(); trace(("return %08lX;\n", (long)addr)); trace(("}\n")); return addr; } void * parse_input(input &ifp, meta_type *type) { trace(("parse_input(ifp = *%08lX, type = %08lx)\n{\n", (long)&ifp, (long)type)); lex_open_input(ifp); assert(type); assert(type->alloc); assert(type->struct_parse); void *addr = type->alloc(); sem_push(type, addr); trace(("gram_parse()\n{\n")); gram_parse(); trace(("}\n")); while (sem_root) sem_pop(); lex_close(); trace(("return %08lX;\n", (long)addr)); trace(("}\n")); return addr; } void sem_push(meta_type *type, void *addr) { sem_ty *sp; trace(("sem_push(type = %08lX, addr = %08lX)\n{\n", (long)type, (long)addr)); trace(("type->name == \"%s\";\n", type ? type->name : "void")); sp = (sem_ty *)mem_alloc(sizeof(sem_ty)); sp->type = type; sp->addr = addr; sp->next = sem_root; sem_root = sp; trace(("}\n")); } void sem_pop(void) { sem_ty *x; trace(("sem_pop()\n{\n")); x = sem_root; sem_root = x->next; x->type = 0; x->addr = 0; x->next = 0; mem_free((char *)x); trace(("}\n")); } void sem_integer(long n) { trace(("sem_integer(n = %ld)\n{\n", n)); if (!sem_root->type) // do nothing ; else if (sem_root->type == &integer_type) *(long *)sem_root->addr = n; else if (sem_root->type == &real_type) *(double *)sem_root->addr = n; else if (sem_root->type == &time_type) { // // Time is always arithmetic, never a structure. // This works on every system the author has seen, // without loss of precision. // *(time_t *)sem_root->addr = n; trace(("time is %s", ctime((time_t *)sem_root->addr))); } else { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_charstar(scp, "Name", sem_root->type->name); lex_error(scp, i18n("value of type $name required")); sub_context_delete(scp); } trace(("}\n")); } void sem_real(double n) { trace(("sem_real(n = %g)\n{\n", n)); if (!sem_root->type) // do nothing ; else if (sem_root->type == &integer_type) { // Precision may be lost. *(long *)sem_root->addr = (long int)n; } else if (sem_root->type == &real_type) *(double *)sem_root->addr = n; else if (sem_root->type == &time_type) { // // Time is always arithmetic, never a structure. // Precision may be lost. // *(time_t *)sem_root->addr = (long int)n; } else { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_charstar(scp, "Name", sem_root->type->name); lex_error(scp, i18n("value of type $name required")); sub_context_delete(scp); } trace(("}\n")); } void sem_string(string_ty *s) { trace(("sem_string(s = %08lX)\n{\n", (long)s)); trace_string(s->str_text); if (!sem_root->type) // do nothing ; else if (sem_root->type != &string_type) { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_charstar(scp, "Name", sem_root->type->name); lex_error(scp, i18n("value of type $name required")); sub_context_delete(scp); } else { trace(("addr = %08lX->%08lX\n", (long)sem_root->addr, (long)*(void **)sem_root->addr)); *(string_ty **)sem_root->addr = s; } trace(("}\n")); } void sem_enum(string_ty *s) { trace(("sem_enum(s = %08lX)\n{\n", (long)s)); trace_string(s->str_text); if (!sem_root->type) { // do nothing } else if (!sem_root->type->enum_parse) { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_charstar(scp, "Name", sem_root->type->name); lex_error(scp, i18n("value of type $name required")); sub_context_delete(scp); } else if (!sem_root->type->enum_parse(s, sem_root->addr)) { sub_context_ty *scp; string_ty *suggest; assert(sem_root->type->fuzzy); suggest = sem_root->type->fuzzy(s); if (suggest) { scp = sub_context_new(); sub_var_set_string(scp, "Name", s); sub_var_set_string(scp, "Guess", suggest); lex_error(scp, i18n("no \"$name\", guessing \"$guess\"")); sub_context_delete(scp); sem_root->type->enum_parse(suggest, sem_root->addr); } else { scp = sub_context_new(); sub_var_set_string(scp, "Name", s); lex_error(scp, i18n("the name \"$name\" is undefined")); sub_context_delete(scp); } } trace(("}\n")); } void sem_list(void) { trace(("sem_list()\n{\n")); if (!sem_root->type) sem_push(0, 0); else if (!sem_root->type->list_parse) { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_charstar(scp, "Name", sem_root->type->name); lex_error(scp, i18n("value of type $name required")); sub_context_delete(scp); sem_push(0, 0); } else { meta_type *type; void *addr; addr = sem_root->type->list_parse(sem_root->addr, &type); // // allocate the storage if necessary // if (type->alloc) { void *contents; contents = type->alloc(); *(generic_struct **)addr = (generic_struct *)contents; addr = contents; } sem_push(type, addr); } trace(("}\n")); } void sem_field(string_ty *name) { trace(("sem_field(name = %08lX)\n{\n", (long)name)); trace_string(name->str_text); trace(("sem_root == %08lX;\n", (long)sem_root)); trace(("sem_root->type == %08lX;\n", (long)sem_root->type)); trace(("sem_root->addr == %08lX;\n", (long)sem_root->addr)); if (!sem_root->type) sem_push(0, 0); else if (!sem_root->type->struct_parse) { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_charstar(scp, "Name", sem_root->type->name); lex_error(scp, i18n("value of type $name required")); sub_context_delete(scp); sem_push(0, 0); } else { meta_type *type; void *addr; unsigned long mask; generic_struct *gsp; int redefok; gsp = (generic_struct *)sem_root->addr; redefok = 0; addr = sem_root->type->struct_parse(gsp, name, &type, &mask, &redefok); if (!addr) { sub_context_ty *scp; string_ty *suggest; assert(sem_root->type->fuzzy); suggest = sem_root->type->fuzzy(name); if (suggest) { scp = sub_context_new(); sub_var_set_string(scp, "Name", name); sub_var_set_string(scp, "Guess", suggest); lex_error(scp, i18n("no \"$name\", guessing \"$guess\"")); sub_context_delete(scp); addr = sem_root->type->struct_parse ( gsp, suggest, &type, &mask, &redefok ); assert(addr); goto use_suggestion; } scp = sub_context_new(); sub_var_set_string(scp, "Name", name); lex_error(scp, i18n("the name \"$name\" is undefined")); sub_context_delete(scp); sem_push(0, 0); } else { // // The first element of all the generated // structures is the mask field. // use_suggestion: trace(("mask = 0x%08lX;\n", mask)); if (mask ? (gsp->mask & mask) : type->is_set(addr)) { sub_context_ty *scp; if (redefok) { gsp->mask |= mask; trace(("gsp->mask == 0x%08lX;\n", gsp->mask)); if (type->alloc) addr = (void *)*(generic_struct **)addr; sem_push(type, addr); trace(("}\n")); return; } scp = sub_context_new(); sub_var_set_string(scp, "Name", name); lex_error(scp, i18n("field \"$name\" redefined")); sub_context_delete(scp); } gsp->mask |= mask; trace(("gsp->mask == 0x%08lX;\n", gsp->mask)); // // allocate the storage if necessary // if (type->alloc) { void *contents; contents = type->alloc(); *(generic_struct **)addr = (generic_struct *)contents; addr = contents; } sem_push(type, addr); } } trace(("}\n")); }