int main(int argc, char* argv[]) { if (argc < 2) { return EXIT_FAILURE; } // Construct cpp options const char** argCpp = static_cast<const char**>(malloc(sizeof(char*) * (argc + 2))); if (!argCpp) { return EXIT_FAILURE; } int optCpp = 0; argCpp[optCpp++] = "cpp"; argCpp[optCpp++] = "-C"; // Use -C for cpp by default. bool skeleton = false; bool generic = false; bool isystem = false; bool useExceptions = true; bool useVirtualBase = false; bool useMultipleInheritance = true; bool messenger = false; bool messengerSrc = false; bool messengerImp = false; bool messengerImpSrc = false; bool java = false; bool sheet = false; const char* stringTypeName = "char*"; // C++ string type name to be used const char* objectTypeName = "Object"; // C++ object type name to be used const char* indent = "es"; for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (argv[i][1] == 'I') { argCpp[optCpp++] = argv[i]; if (argv[i][2] == '\0') { ++i; argCpp[optCpp++] = argv[i]; setIncludePath(argv[i]); } else { setIncludePath(&argv[i][2]); } } else if (strcmp(argv[i], "-messenger") == 0) { messenger = true; } else if (strcmp(argv[i], "-messenger-src") == 0) { messengerSrc = true; } else if (strcmp(argv[i], "-messenger-imp") == 0) { messengerImp = true; } else if (strcmp(argv[i], "-messenger-imp-src") == 0) { messengerImpSrc = true; } else if (strcmp(argv[i], "-fexceptions") == 0) { useExceptions = true; } else if (strcmp(argv[i], "-fno-exceptions") == 0) { useExceptions = false; } else if (strcmp(argv[i], "-fvirtualbase") == 0) { useVirtualBase = true; } else if (strcmp(argv[i], "-fno-virtualbase") == 0) { useVirtualBase = false; } else if (strcmp(argv[i], "-fmultipleinheritance") == 0) { useMultipleInheritance = true; } else if (strcmp(argv[i], "-fno-multipleinheritance") == 0) { useMultipleInheritance = false; } else if (strcmp(argv[i], "-include") == 0) { argCpp[optCpp++] = argv[i]; ++i; argCpp[optCpp++] = argv[i]; } else if (strcmp(argv[i], "-indent") == 0) { ++i; indent = argv[i]; } else if (strcmp(argv[i], "-isystem") == 0) { argCpp[optCpp++] = argv[i]; ++i; argCpp[optCpp++] = argv[i]; setIncludePath(argv[i]); isystem = true; } else if (strcmp(argv[i], "-java") == 0) { java = true; } else if (strcmp(argv[i], "-namespace") == 0) { ++i; Node::setFlatNamespace(argv[i]); } else if (strcmp(argv[i], "-object") == 0) { ++i; objectTypeName = argv[i]; } else if (strcmp(argv[i], "-prefix") == 0) { ++i; Node::setDefaultPrefix(argv[i]); } else if (strcmp(argv[i], "-template") == 0) { generic = true; } else if (strcmp(argv[i], "-sheet") == 0) { sheet = true; } else if (strcmp(argv[i], "-skeleton") == 0) { skeleton = true; } else if (strcmp(argv[i], "-string") == 0) { ++i; stringTypeName = argv[i]; } else if (strcmp(argv[i], "--help") == 0) { help(); return 0; } else if (strcmp(argv[i], "--version") == 0) { version(); return 0; } } } if (messenger || messengerSrc || messengerImp || messengerImpSrc) { // Multiple inheritance is not allowed in Web IDL. useMultipleInheritance = false; } argCpp[optCpp] = 0; // Set up the global module Module* node = new Module(""); setSpecification(node); setCurrent(node); // Manually install 'object' interface forward declaration. Interface* object = new Interface("object", 0, true); object->setRank(2); getCurrent()->add(object); if (Node::getFlatNamespace()) { Module* module = new Module(Node::getFlatNamespace()); getCurrent()->add(module); setCurrent(module); } // Load every IDL file at once int result = EXIT_SUCCESS; int cppStream[2]; pipe(cppStream); pid_t id = fork(); if (id == 0) { // Child process int catStream[2]; pipe(catStream); pid_t id = fork(); if (id == 0) { // cat every IDL file close(catStream[0]); FILE* out = fdopen(catStream[1], "w"); for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-I") == 0 || strcmp(argv[i], "-include") == 0 || strcmp(argv[i], "-indent") == 0 || strcmp(argv[i], "-isystem") == 0 || strcmp(argv[i], "-namespace") == 0 || strcmp(argv[i], "-object") == 0 || strcmp(argv[i], "-prefix") == 0 || strcmp(argv[i], "-string") == 0) { ++i; } continue; } if (const char* dot = strrchr(argv[i], '.')) { if (strcasecmp(dot + 1, "idl")) { continue; } } FILE* in = fopen(argv[i], "r"); if (!in) { return EXIT_FAILURE; } fprintf(out, "#pragma source \"%s\"\n", argv[i]); int ch; while ((ch = fgetc(in)) != EOF) { putc(ch, out); } fclose(in); } fclose(out); return EXIT_SUCCESS; } else if (0 < id) { // execute cpp close(0); dup(catStream[0]); close(catStream[0]); close(catStream[1]); close(1); dup(cppStream[1]); close(cppStream[0]); close(cppStream[1]); execvp(argCpp[0], const_cast<char**>(argCpp)); return EXIT_FAILURE; } else { return EXIT_FAILURE; } } else if (0 < id) { // Parent process - process an IDL file close(cppStream[1]); if (input(cppStream[0], isystem, useExceptions, stringTypeName) != EXIT_SUCCESS) { return EXIT_FAILURE; } close(cppStream[0]); int status; while (wait(&status) != id) { } if (result == EXIT_SUCCESS) { if (!WIFEXITED(status)) { result = EXIT_FAILURE; } else { result = WEXITSTATUS(status); } } } else { return EXIT_FAILURE; } setBaseFilename(""); if (java || sheet) { Node::setCtorScope("_"); } Interface::useMultipleInheritance = useMultipleInheritance; ProcessExtendedAttributes processExtendedAttributes; getSpecification()->accept(&processExtendedAttributes); AdjustMethodCount adjustMethodCount(!useMultipleInheritance || Node::getFlatNamespace()); getSpecification()->accept(&adjustMethodCount); Meta meta(objectTypeName); getSpecification()->accept(&meta); if (messenger) { result = printMessenger(stringTypeName, objectTypeName, useExceptions, useVirtualBase, indent); } else if (messengerSrc) { result = printMessengerSrc(stringTypeName, objectTypeName, useExceptions, useVirtualBase, indent); } else if (messengerImp) { result = printMessengerImp(stringTypeName, objectTypeName, useExceptions, useVirtualBase, indent); } else if (messengerImpSrc) { result = printMessengerImpSrc(stringTypeName, objectTypeName, useExceptions, useVirtualBase, indent); } else if (java) { result = printJava(indent); } else if (sheet) { Sheet visitor; getSpecification()->accept(&visitor); result = EXIT_SUCCESS; } else { for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-I") == 0 || strcmp(argv[i], "-include") == 0 || strcmp(argv[i], "-indent") == 0 || strcmp(argv[i], "-isystem") == 0 || strcmp(argv[i], "-namespace") == 0 || strcmp(argv[i], "-object") == 0 || strcmp(argv[i], "-prefix") == 0 || strcmp(argv[i], "-string") == 0) { ++i; } continue; } result = output(argv[i], isystem, useExceptions, useVirtualBase, stringTypeName, objectTypeName, indent, skeleton, generic); } } return result; }
/** * Main parser for a tdf file. Parses initialization data, creates the header and * source files, and passes parameter definitions to the appropriate function. * * @param fp file to parse * * @return 0 on success, -1 on fail */ int TemplateDefinitionFile::parse(File &fp) { static const int BUFFER_SIZE = 1024; int lineLen; char buffer[BUFFER_SIZE]; char token[BUFFER_SIZE]; TemplateData *currentTemplate = NULL; cleanup(); setTemplateFilename(fp.getFilename().getName()); for (;;) { lineLen = fp.readLine(buffer, BUFFER_SIZE); if (lineLen == -1) break; else if (lineLen == -2) return -1; const char *line = buffer; line = getNextWhitespaceToken(line, token); if (*token == '\0') break; if (strcmp(token, "version") == 0) { if (m_templateName.size() == 0) { fp.printError("no template name defined"); return -1; } else if (m_templateId.tag == NO_TAG) { fp.printError("no template id defined"); return -1; } else if (m_path.getPath().size() == 0) { fp.printError("no path defined"); return -1; } else if (m_compilerPath.getPath().size() == 0) { fp.printError("no compiler path defined"); return -1; } // if (m_baseName.size() == 0 && m_templateName != ROOT_TEMPLATE_NAME) // m_baseName = ROOT_TEMPLATE_NAME; line = getNextWhitespaceToken(line, token); int version = atoi(token); if (version < 0 || version > 9999) { fp.printError("version out of range"); return -1; } if (m_templateMap.find(version) != m_templateMap.end()) { fp.printError("version already defined"); return -1; } if (version > m_highestVersion) m_highestVersion = version; currentTemplate = new TemplateData(version, *this); m_templateMap[version] = currentTemplate; } else if (currentTemplate != NULL) { line = currentTemplate->parseLine(fp, buffer, token); if (line == CHAR_ERROR) return -1; } else if (*token == '/' && *(token + 1) == '/') { if (m_baseName.size() == 0 && m_templateId.tag == NO_TAG) m_fileComments.push_back(buffer); } else if (strcmp(token, "base") == 0) { if (m_baseName.size() != 0) { fp.printError("base name already defined"); return -1; } line = getNextWhitespaceToken(line, token); setBaseFilename(token); // load and parse the base template Filename baseFileName = fp.getFilename(); baseFileName.setName(token); File baseFp(baseFileName, "rt"); if (!baseFp.isOpened()) { fp.printError("unable to open base template definition"); return -1; } if (m_baseDefinitionFile == NULL) m_baseDefinitionFile = new TemplateDefinitionFile; else m_baseDefinitionFile->cleanup(); int result = m_baseDefinitionFile->parse(baseFp); if (result != 0) return result; } else if (strcmp(token, "id") == 0) { if (m_templateId.tag != NO_TAG) { fp.printError("template id already defined"); return -1; } line = getNextWhitespaceToken(line, token); if (strlen(token) != 4) { fp.printError("id not 4 characters"); return -1; } m_templateId.tag = ConvertStringToTag(token); m_templateId.tagString = ConvertStringToTagString(token); } else if (strcmp(token, "templatename") == 0) { line = getNextWhitespaceToken(line, token); m_templateNameFilter = token; //-- Attempt to compile the regex. if (m_filterCompiledRegex != NULL) { // First free the existing compiled regex. RegexServices::freeMemory(m_filterCompiledRegex); m_filterCompiledRegex = NULL; } //-- Compile the new regex. char const *errorString = NULL; int errorOffset = 0; m_filterCompiledRegex = pcre_compile(m_templateNameFilter.c_str(), 0, &errorString, &errorOffset, NULL); WARNING(m_filterCompiledRegex == NULL, ("TemplateDefinitionFile::parse(): pcre_compile() failed, error=[%s], errorOffset=[%d], regex text=[%s].", errorString, errorOffset, m_templateNameFilter.c_str())); } else if (strcmp(token, "clientpath") == 0 || strcmp(token, "serverpath") == 0 || strcmp(token, "sharedpath") == 0) { if (m_path.getPath().size() != 0) { fp.printError("path already defined"); return -1; } if (strcmp(token, "clientpath") == 0) m_templateLocation = LOC_CLIENT; else if (strcmp(token, "serverpath") == 0) m_templateLocation = LOC_SERVER; else m_templateLocation = LOC_SHARED; line = getNextWhitespaceToken(line, token); m_path.setPath(token); m_path.prependPath(fp.getFilename()); // reset the template name to add the corrent prefix to the template // name setTemplateFilename(m_templateFilename); if (!m_baseFilename.empty()) setBaseFilename(m_baseFilename); } else if (strcmp(token, "compilerpath") == 0) { if (m_compilerPath.getPath().size() != 0) { fp.printError("compiler path already defined"); return -1; } line = getNextWhitespaceToken(line, token); m_compilerPath.setPath(token); m_compilerPath.prependPath(fp.getFilename()); } else { char errbuf[2048]; sprintf(errbuf, "I don't know how to handle this line!: <%s>. " "Barfed on token <%s>.", buffer, token); fp.printError(errbuf); return -1; } } return 0; } // TemplateDefinitionFile::parse