Пример #1
0
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