int main()

in contrib/gen_html/gen_html.cpp [81:224]


int main(int argc, char *argv[]) {
    char exclam;
    int linenum, chapter = 1;
    vector<string> input, lines, comments, chapters;
    string line, version;
    size_t spos, l;
    stringstream sout;
    ifstream istream;
    ofstream ostream;

    if (argc < 4) {
        cout << "usage: " << argv[0] << " [zstd_version] [input_file] [output_html]" << endl;
        return 1;
    }

    version = "zstd " + string(argv[1]) + " Manual";

    istream.open(argv[2], ifstream::in);
    if (!istream.is_open()) {
        cout << "Error opening file " << argv[2] << endl;
        return 1;
    }

    ostream.open(argv[3], ifstream::out);
    if (!ostream.is_open()) {
        cout << "Error opening file " << argv[3] << endl;
        return 1;
   }

    while (getline(istream, line)) {
        input.push_back(line);
    }

    for (linenum=0; (size_t)linenum < input.size(); linenum++) {
        line = input[linenum];

        /* typedefs are detected and included even if uncommented */
        if (line.substr(0,7) == "typedef" && line.find("{")!=string::npos) {
            lines = get_lines(input, linenum, "}");
            sout << "<pre><b>";
            for (l=0; l<lines.size(); l++) {
                print_line(sout, lines[l]);
            }
            sout << "</b></pre><BR>" << endl;
            continue;
        }

        /* comments of type /**< and /*!< are detected and only function declaration is highlighted (bold) */
        if ((line.find("/**<")!=string::npos || line.find("/*!<")!=string::npos) && line.find("*/")!=string::npos) {
            sout << "<pre><b>";
            print_line(sout, line);
            sout << "</b></pre><BR>" << endl;
            continue;
        }

        spos = line.find("/**=");
        if (spos==string::npos) {
            spos = line.find("/*!");
            if (spos==string::npos)
                spos = line.find("/**");
            if (spos==string::npos)
                spos = line.find("/*-");
            if (spos==string::npos)
                spos = line.find("/*=");
            if (spos==string::npos)
                continue;
            exclam = line[spos+2];
        }
        else exclam = '=';

        comments = get_lines(input, linenum, "*/");
        if (!comments.empty()) comments[0] = line.substr(spos+3);
        if (!comments.empty()) comments[comments.size()-1] = comments[comments.size()-1].substr(0, comments[comments.size()-1].find("*/"));
        for (l=0; l<comments.size(); l++) {
            if (comments[l].find(" *")==0) comments[l] = comments[l].substr(2);
            else if (comments[l].find("  *")==0) comments[l] = comments[l].substr(3);
            trim(comments[l], "*-=");
        }
        while (!comments.empty() && comments[comments.size()-1].empty()) comments.pop_back(); // remove empty line at the end
        while (!comments.empty() && comments[0].empty()) comments.erase(comments.begin()); // remove empty line at the start

        /* comments of type /*! mean: this is a function declaration; switch comments with declarations */
        if (exclam == '!') {
            if (!comments.empty()) comments.erase(comments.begin()); /* remove first line like "ZSTD_XXX() :" */
            linenum++;
            lines = get_lines(input, linenum, "");

            sout << "<pre><b>";
            for (l=0; l<lines.size(); l++) {
              //  fprintf(stderr, "line[%d]=%s\n", l, lines[l].c_str());
                string fline = lines[l];
                if (fline.substr(0, 12) == "ZSTDLIB_API " ||
                    fline.substr(0, 12) == string(12, ' '))
                  fline = fline.substr(12);
                print_line(sout, fline);
            }
            sout << "</b><p>";
            for (l=0; l<comments.size(); l++) {
                print_line(sout, comments[l]);
            }
            sout << "</p></pre><BR>" << endl << endl;
        } else if (exclam == '=') { /* comments of type /*= and /**= mean: use a <H3> header and show also all functions until first empty line */
            trim(comments[0], " ");
            sout << "<h3>" << comments[0] << "</h3><pre>";
            for (l=1; l<comments.size(); l++) {
                print_line(sout, comments[l]);
            }
            sout << "</pre><b><pre>";
            lines = get_lines(input, ++linenum, "");
            for (l=0; l<lines.size(); l++) {
                print_line(sout, lines[l]);
            }
            sout << "</pre></b><BR>" << endl;
        } else { /* comments of type /** and /*- mean: this is a comment; use a <H2> header for the first line */
            if (comments.empty()) continue;

            trim(comments[0], " ");
            sout << "<a name=\"Chapter" << chapter << "\"></a><h2>" << comments[0] << "</h2><pre>";
            chapters.push_back(comments[0]);
            chapter++;

            for (l=1; l<comments.size(); l++) {
                print_line(sout, comments[l]);
            }
            if (comments.size() > 1)
                sout << "<BR></pre>" << endl << endl;
            else
                sout << "</pre>" << endl << endl;
        }
    }

    ostream << "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n<title>" << version << "</title>\n</head>\n<body>" << endl;
    ostream << "<h1>" << version << "</h1>\n";

    ostream << "<hr>\n<a name=\"Contents\"></a><h2>Contents</h2>\n<ol>\n";
    for (size_t i=0; i<chapters.size(); i++)
        ostream << "<li><a href=\"#Chapter" << i+1 << "\">" << chapters[i].c_str() << "</a></li>\n";
    ostream << "</ol>\n<hr>\n";

    ostream << sout.str();
    ostream << "</html>" << endl << "</body>" << endl;

    return 0;
}