/* * Copyright (c) 1996 Gunther Schadow. All rights reserved. * * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include class UnitAtomMgr : public UnitAtom { public: UnitAtomMgr() : UnitAtom(odbm::read) { } UnitAtomMgr(unit_s &un, int mode = odbm::write) : UnitAtom(mode) { unit = un; unit.name = strdup(unit.name); if(un.cnv_name != NULL) unit.cnv_name = strdup(unit.cnv_name); } const UnitAtomMgr& operator = (unit_s &un) { unit = un; return *this; } void insert() { odbm::insert(); } static bool fexists(const char *s) { return UnitAtom::cnv_func::lookup(s) != NULL; } }; /* * base units */ #define BASE_CNT 9 UnitAtom::unit_s base_tab[BASE_CNT] = { {"1", NULL, NULL, NULL, { 0, 0, 0, 0, 0, 0, 0}, 1, 0}, {"10*", NULL, NULL, NULL, { 0, 0, 0, 0, 0, 0, 0}, 1, 1}, {"m", NULL, NULL, NULL, { 1, 0, 0, 0, 0, 0, 0}, 1, 0}, {"s", NULL, NULL, NULL, { 0, 1, 0, 0, 0, 0, 0}, 1, 0}, {"g", NULL, NULL, NULL, { 0, 0, 1, 0, 0, 0, 0}, 1, 0}, {"c", NULL, NULL, NULL, { 0, 0, 0, 1, 0, 0, 0}, 1, 0}, {"k", NULL, NULL, NULL, { 0, 0, 0, 0, 1, 0, 0}, 1, 0}, {"cd", NULL, NULL, NULL, { 0, 0, 0, 0, 0, 1, 0}, 1, 0}, {"circ", NULL, NULL, NULL, { 0, 0, 0, 0, 0, 0, 1}, 1, 0}, }; void create() { UnitAtomMgr un(base_tab[0], odbm::write | odbm::newdb); int i = 0; while(1) { un.insert(); if(++i >= BASE_CNT) break; un = base_tab[i]; } } u_int lineno = 1; char *file; char *parse_name(char *s, char **del) { char *d; // read to end of new unitname d = strpbrk(s, " \t="); if(d == NULL) { cerr << file << ':' << lineno << ": `=' expected at end of line" << endl; return NULL; } // did we stop at the = ? if(*d != '=') { // no, terminate the new unit name *d++ = '\0'; // and find the = do { if(*d != ' ' && *d != '\t' && *d != '=') { cerr << file << ':' << lineno << ": `=' expected at:" << d << endl; return NULL; } } while(*d++ != '='); } else // we stopped at the =, terminate the unit name *d++ = '\0'; // skip whitespace while(*d == ' ' || *d == '\t') d++; *del = d; return s; } char *parse_function(char *s, char **del) { // find end of function name char *d = strpbrk(s, " ("); if(d == NULL) { cerr << file << ':' << lineno << ": `(' expected at end of line, did you forget the value?" << endl; return NULL; } // did we stop at the '(' if(*d != '(') { // no, terminate function name *d++ = '\0'; // and find the '(' do { if(*d != ' ' && *d != '\t' && *d != '(') { cerr << file << ':' << lineno << ": `(' expected at:" << d << endl; return NULL; } } while(*d++ != '('); } else // we stopped at the '(', terminate the function name *d++ = '\0'; *del = d; // now end the line at the ')' while(*d != ')' && *d != '\0') d++; if(*d == '\0') { cerr << file << ':' << lineno << ": `)' expected at end of line" << d << endl; return NULL; } else *d++ = '\0'; // skip whitespace after '(' while(*s == ' ' || *s == '\t') s++; return s; } double parse_coeff(char *s, char **del) { // read the coefficient char *d; double res = strtod(s, &d); if(s == d) { cerr << file << ':' << lineno << ": numeric value expected: " << s << endl; return HUGE_VAL; } *del = d; return res; } char *parse_unit(char *s, char **del) { // skip whitespace after coefficient while(*s == ' ' || *s == '\t') s++; // search to end of known unit char *d = strpbrk(s, " \t"); // the known unit ends here (so the line does); if(d != NULL) *d++ = '\0'; *del = d; return s; } result define_unit(const char *name, double coeff, const char *unit, const char *func = NULL) { UnitAtom::unit_s new_unit = UnitAtom::null_unit; new_unit.name = (char *)name; // check if function exists if(func != NULL) if(! UnitAtomMgr::fexists(func)) { cerr << file << ':' << lineno << ": unknown function: " << func << endl; return FAIL; } else new_unit.cnv_name = (char *)func; else new_unit.cnv_name = NULL; { // lookup the known unit, set the values, check for ambiguity Unit known_unit(unit); new_unit.base = known_unit->base; new_unit.coeff_mantissa = coeff * known_unit->coeff_mantissa; new_unit.coeff_exponent = known_unit->coeff_exponent; /* Ambiguity: if name starts with valid prefix and the root * is found in database. */ int len = prefices::best_fit; const char *root; while(prefices::lookup(name, &len, &root) != prefices::not_found) { UnitAtom ua; if(ua.lookup(root)) { cerr << file << ':' << lineno << ": warning: ambiguous unit: "; new_unit.show(cerr) << endl; cerr << file << ':' << lineno << ": warning: interferes with: "; cerr.write(name, len) << "-"; ua->show(cerr) << endl; } if(--len <= 0) break; } } // and finally save it into the database { UnitAtomMgr ua(new_unit); // is the new unit already known? if(ua.exists()) { cerr << file << ':' << lineno << ": unit does already exist: "; ua->show(cerr) << endl; UnitAtom ub(new_unit.name); cerr << file << ':' << lineno << ": known as: "; ub->show(cerr) << endl; return FAIL; } else ua.insert(); } return SUCCESS; } int main(int argc, char *argv[]) { log_init(argv[0], "./units.log", "test"); log_level(L_JUNK); if(argc != 2) { cerr << "usage: " << argv[0] << " file" << endl; exit(1); } file = argv[1]; create(); fstream fin(file, ios::in); char *line = new char[1]; lineno = 1; while(fin.ipfx(1)) { fin.gets(&line); char *s = line; // convert to lower case, I don't want this, but HL7 says so! for(char *p = s; *p != 0; p++) *p = tolower(*p); while(*s == ' ' || *s == '\t') s++; if(*s == '#' || *s == '\0') goto next_line; char *name; double coeff; char *unit; char *func; if((name = parse_name(s, &s)) == NULL) goto next_line; if(isalpha(*s)) // a function follows { if((func = parse_function(s, &s)) == NULL) goto next_line; } else func = NULL; if((coeff = parse_coeff(s, &s)) == HUGE_VAL) goto next_line; if((unit = parse_unit(s, &s)) == NULL) goto next_line; define_unit(name, coeff, unit, func); next_line: lineno++; delete [] line; } return 0; }