static public void main (String[] args)
    {
        long startMS = System.currentTimeMillis();
        log("Invar start: " + new Date().toString() + " " + (Runtime.getRuntime().freeMemory() >> 20) + "MB");

        InvarMainArgs a = new InvarMainArgs();
        a.addDefault(ARG_RULE_PATH, "rule/");
        a.addDefault(ARG_XSD_PATH, "code/xsd/");
        a.addDefault(ARG_JAVA_PATH, "code/java/");
        a.addDefault(ARG_FLASH_PATH, "code/flash/");
        a.addDefault(ARG_CSHARP_PATH, "code/csharp/");
        a.addDefault(ARG_CPP_PATH, "code/cpp/");
        a.addDefault(ARG_PHP_PATH, "code/php/");
        a.parseArguments(args);

        if (a.has(ARG_HELP))
        {
            showHelp();
            return;
        }

        TreeMap<TypeID,String> basics = makeTypeIdMap();
        try
        {
            InvarContext ctx = new InvarContext();
            ctx.addBuildInTypes(basics);
            ctx.setRuleDir(a.get(ARG_RULE_PATH));
            log("");
            if (a.has(ARG_RULE_DOM))
            {
                InvarReadRule.start(ctx, ".xml");
            }
            else
            {
                TokensFromXml.start(ctx);
            }
            if (a.has(ARG_XSD_PATH))
            {
                log("");
                new InvarWriteXSD().write(ctx, basics, a.get(ARG_XSD_PATH));
            }
            if (a.has(ARG_CSHARP_PATH))
            {
                log("");
                new InvarWriteCode(ctx, a.get(ARG_CSHARP_PATH), "csharp/snippet.xml").write(".cs");
            }
            if (a.has(ARG_JAVA_PATH))
            {
                log("");
                new InvarWriteCode(ctx, a.get(ARG_JAVA_PATH), "java/snippet.xml").write(".java");
            }
            if (a.has(ARG_CPP_PATH))
            {
                log("");
                new InvarWriteCode(ctx, a.get(ARG_CPP_PATH), "cpp/snippet.h.xml").write(".h");
                new InvarWriteCode(ctx, a.get(ARG_CPP_PATH), "cpp/snippet.cc.xml").write(".cpp", true);
            }
            if (a.has(ARG_FLASH_PATH))
            {
                log("");
                new InvarWriteCode(ctx, a.get(ARG_FLASH_PATH), "flash/snippet.xml").write(".as");
            }
            if (a.has(ARG_PHP_PATH))
            {
                log("");
                new InvarWriteCode(ctx, a.get(ARG_PHP_PATH), "php/snippet.xml").write(".php");
            }
            long total = Runtime.getRuntime().totalMemory();
            long free = Runtime.getRuntime().freeMemory();
            log("\nInvar end: " + (System.currentTimeMillis() - startMS) + "ms, " + ((total - free) >> 20) + "/" + (total >> 20) + "MB");
        }
        catch (Throwable e)
        {
            e.printStackTrace();
        }
    }