src/frontend.c

Sun, 11 Jun 2023 15:21:44 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 11 Jun 2023 15:21:44 +0200
changeset 71
d5af9261231d
parent 70
60cecca5e484
child 78
719e3c6d4c9b
permissions
-rw-r--r--

fix incorrect highlighting when input file starts with line break

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2016 Mike Becker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "c2html.h"
#include <cx/utils.h>

typedef struct {
    char* outfilename;
    char* headerfile;
    char* footerfile;
    char* infilename;
    int showlinenumbers;
} Settings;

static int appendfile(const char *filename, FILE *fout, const char *errmsg) {
    FILE *fin = fopen(filename, "r");
    if (!fin) {
        perror(errmsg);
        if (fout != stdout) {
            fclose(fout);
        }
        return 1;
    }
    cx_stream_copy(fin, fout, (cx_read_func) fread, (cx_write_func) fwrite);
    fclose(fin);
    return 0;
}

static void printhelp() {
    printf("Formats source code using HTML.\n\nUsage:\n"
        "  c2html [Options] FILE\n\n"
        " Options:\n"
        "  -h                    Prints this help message\n"
        "  -j                    Highlight Java instead of C source code\n"
        "  -o <output>           Output file (stdout, if not specified)\n"
        "  -H <header>           Prepend header file\n"
        "  -F <footer>           Append footer file\n"
        "  -p                    Disable highlighting (plain text)\n"
        "  -l                    Disable line numbers\n"
        "  -V, -v                Prints version and exits\n"
        "\n");
}

int main(int argc, char** argv) {

    /* Default settings */
    Settings settings;
    memset(&settings, 0, sizeof(settings));
    settings.showlinenumbers = 1;
    c2html_highlighter_func hltr = c2html_c_highlighter;

    /* Parse command line */
    int optc;
    while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) {
        switch (optc) {
            case 'o':
                if (!(optarg[0] == '-' && optarg[1] == 0)) {
                    settings.outfilename = optarg;
                }
                break;
            case 'F':
                settings.footerfile = optarg;
                break;
            case 'H':
                settings.headerfile = optarg;
                break;
            case 'j':
                hltr = c2html_java_highlighter;
                break;
            case 'p':
                hltr = c2html_plain_highlighter;
                break;
            case 'l':
                settings.showlinenumbers = 0;
                break;
            case 'h':
                printhelp();
                return EXIT_SUCCESS;
            case 'v':
            case 'V':
#ifdef VERSION_DEVELOP
                printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR);
#else
                printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
#endif
                return EXIT_SUCCESS;
            default:
                return EXIT_FAILURE;
        }
    }

    if (optind != argc-1) {
        printhelp();
        return EXIT_FAILURE;
    } else {
        /* Open output file */
        settings.infilename = argv[optind];
        FILE *fout;
        if (settings.outfilename) {
            fout = fopen(settings.outfilename, "w");
            if (!fout) {
                perror("Error opening output file");
                return EXIT_FAILURE;
            }
        } else {
            fout = stdout;
        }
        
        /* Prepend header file */
        if (appendfile(settings.headerfile, fout,
                "Error opening header file")) {
            return EXIT_FAILURE;
        }

        /* Process input file */
        FILE *inputfile = fopen(settings.infilename, "r");
        if (inputfile) {
            CxBuffer fbuf;
            cxBufferInit(&fbuf, NULL, 4096, NULL, CX_BUFFER_AUTO_EXTEND);
            cx_stream_copy(inputfile, &fbuf, (cx_read_func) fread,
                           (cx_write_func) cxBufferWrite);
            cxBufferPut(&fbuf, 0);
            fclose(inputfile);
            c2html_textformat(
                    fbuf.space, fout, (cx_write_func ) fwrite, hltr,
                    settings.showlinenumbers
            );
            cxBufferDestroy(&fbuf);
        } else {
            perror("Error opening input file");
            if (fout != stdout) {
                fclose(fout);
            }
            return EXIT_FAILURE;
        }
        
        /* Append footer file */
        if (appendfile(settings.footerfile, fout,
                "Error opening footer file")) {
            return EXIT_FAILURE;
        }

        return EXIT_SUCCESS;
    }
}

mercurial