Date: 18 Apr 2002 05:53:51 -0700 From: Max Okumoto <okumoto@ucsd.edu> To: freebsd-libh@FreeBSD.ORG Subject: *.cd.cc parser Message-ID: <hf662p417k.fsf@multivac.sdsc.edu>
next in thread | raw e-mail | index | archive | help
Here is my *cd.cc parser can people check if it parses and generates the same kind of output as the perl version? Currently the only difference that I can find is the sort order of the header includes. The ordering is for perl hashs vs C++ map<>. Which should not cause any problems... I don't really plan to use it in the build process, since that would complicate matters. I am looking into merging it with HSystem. *.cd.cc -> build_systems_*.cc -> tcl_interface_gen_* -> LibTclInterface_*.cc would become *.cd.cc -> LibTclInterface_*.cc Max Okumoto ---------------------%<----------------%<-------------- /** * @file */ #include <fstream> #include <map> #include <set> #include <string> #include <vector> extern "C" { #include <unistd.h> /* getopt() */ #include <string.h> /* strlen() */ } class ClassDescParser { typedef string FilePath; typedef string DirPath; typedef string SysName; typedef string ClassDesc; typedef set<FilePath> FileSet; typedef vector<ClassDesc> ClassDescV; typedef map<FilePath, ClassDescV> MapV; typedef map<DirPath, SysName> Map; FileSet files; MapV classes; Map systems; public: /** * Process the contents of the ClassDescription file (*.cd.cc). * * @param filename name of file to process. */ void process_file(const string &filename) { ifstream file(filename.c_str()); char buff[4096]; while (file.getline(buff, sizeof(buff))) { string line(buff); /* remove C++ style comments from line */ string::size_type pos = line.find("//"); if (pos != string::npos) { line.erase(pos); } /* * LanguageInterface::Object::ClassDescription ([^\s]+)::sClassDescription[^A-Za-z0-9]/ */ string prefix("LanguageInterface::Object::ClassDescription "); string suffix("::sClassDescription"); /* Find lines which contain prefix */ pos = line.find(prefix); if (pos == string::npos) { continue; /* line does not contain prefix */ } string cd = line.substr(pos + prefix.length()); pos = cd.find(suffix); /* class description must also contain the suffix */ assert(pos != string::npos); /* char following suffix should not be alpha or number */ assert(!isalnum(cd[pos + suffix.length()])); cd.erase(pos); assert(cd.find_first_of(" \t") == string::npos); classes[filename].push_back(cd); } file.close(); files.insert(filename); } /** * Output the build_systems_*.cc file. * * @param prog Name of generator program. * @param the_only_system (Don't know yet.) */ void gen_file(const string &prog, const string *the_only_system) { cout << "/*\n" " * This file is automatically generated by " << prog << ",\n" " * do not edit!\n" " */\n" "\n" "#ifndef HSystem_hh\n" "#include \"HSystem.hh\"\n" "#endif\n" "\n" "#define H_BUILD_SYSTEMS 1\n" "\n"; for (MapV::iterator i = classes.begin(); i != classes.end(); ++i) { FilePath filename = i->first; string::size_type pos = filename.rfind('/'); assert(pos != string::npos); /* contains at least 1 slash */ string system = filename.substr(0, pos); string file = filename.substr(pos + 1); if (the_only_system == NULL) { pos = system.rfind('/'); assert(pos != string::npos); /* contains 1 slash */ systems[system] = system.substr(pos + 1); } else { systems[*the_only_system] = *the_only_system; } pos = system.rfind('/'); pos = system.rfind('/', pos); string systemdir = system.substr(pos + 1); /* remove ".cd.cc" suffix */ pos = file.find(".cd.cc"); assert(pos != string::npos); /* contains ".cd.cc" */ assert(file.length() == pos + strlen(".cd.cc")); /* at end */ file.erase(pos); if (systemdir == "common") { cout << "#ifndef " << file << "_hh\n" "#include \"" << file << ".hh\"\n" "#endif\n" "\n"; } else { cout << "#ifndef " << file << "_hh\n" "#include \"" << systemdir << "/" << file << ".hh\"\n" "#endif\n" "\n"; } } cout << "void\n" "build_systems(Systems& systems)\n" "{\n"; for (Map::iterator i = systems.begin(); i != systems.end(); ++i) { DirPath system = i->first; SysName sysname = i->second; cout << "\tpair<Systems::iterator,bool> s = systems.insert(HSystem(\"" << sysname << "\"));\n" "\tif (!s.second)\n" "\t throw runtime_error(string(\"System \") + s.first->name + \" already exists\");\n" "\tHSystem& system = const_cast<HSystem&>(*s.first);\n"; for (FileSet::iterator j = files.begin(); j != files.end(); ++j) { FilePath filename = *j; if ((the_only_system != NULL) || (filename.substr(0, system.length() + 1) == (system + '/'))) { ClassDescV cl = classes[filename]; for (ClassDescV::iterator k = cl.begin(); k != cl.end(); ++k) { cout << "\tsystem.add_class(" << *k << "::thisClassDescription(),\n" "\t\t\t" << *k << "::fileToInclude());\n"; } } } } cout << "} /* build systems */ \n" "\n"; } }; /** * Outputs usage information. * * @param prog Name of binary */ static void usage(const string &prog) { cout << "Usage: " << prog << " -s <system> <file-to-scan> ...\n"; } /** * The main program. * * It parses the command line arguments, and checks for input files. */ int main(int argc, char *argv[]) { /************************************************************************* * Parse command line args *************************************************************************/ const string prog(argv[0]); string *the_only_system = NULL; int c; while ((c = getopt(argc, argv, "s:")) != -1) { switch (c) { case 's': the_only_system = new string(optarg); break; case '?': default: usage(prog); return(1); /* bad cli options */ } } argc -= optind; argv += optind; if (argc < 1) { usage(prog); return(1); /* missing input files */ } /************************************************************************* * process files *************************************************************************/ ClassDescParser parser; for (int i = 0; i < argc; ++i) { parser.process_file(argv[i]); } parser.gen_file(prog, the_only_system); delete the_only_system; return(0); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-libh" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?hf662p417k.fsf>