src/c2html.c

Thu, 23 Jan 2014 14:44:20 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 23 Jan 2014 14:44:20 +0100
changeset 23
f44a185b678b
parent 22
f463693b5eeb
child 24
e43dee5892f4
permissions
-rw-r--r--

fixed licenses

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2014 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 <errno.h>

#include "c2html.h"

inputfile_t *inputfilebuffer(size_t capacity) {
    inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t));
    inputfile->lines = (char**) malloc(capacity * sizeof(char*));
    inputfile->capacity = capacity;
    inputfile->count = 0;
    inputfile->maxlinewidth = 0;

    return inputfile;
}

void addline(inputfile_t *inputfile, char* line, size_t width) {
    char *l = (char*) malloc(width+1);
    memcpy(l, line, width);
    l[width] = 0;
    if (inputfile->count >= inputfile->capacity) {
        inputfile->capacity <<= 1;
        inputfile->lines = realloc(inputfile->lines, inputfile->capacity);
    }
    inputfile->lines[inputfile->count] = l;
    inputfile->maxlinewidth =
        width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth;
    inputfile->count++;
}

void freeinputfilebuffer(inputfile_t *inputfile) {
    for (int i = 0 ; i < inputfile->count ; i++) {
        free(inputfile->lines[i]);
    }
    free(inputfile->lines);
    free(inputfile);
}

inputfile_t *readinput(char *filename) {

    int fd = open(filename, O_RDONLY);
    if (fd == -1) return NULL;

    inputfile_t *inputfile = inputfilebuffer(512);

    char buf[INPUTBUF_SIZE];
    ssize_t r;

    size_t maxlinewidth = 256;
    char *line = (char*) malloc(maxlinewidth);
    size_t col = 0;

    while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) {
        for (size_t i = 0 ; i < r ; i++) {
            if (col >= maxlinewidth-4) {
                maxlinewidth <<= 1;
                line = realloc(line, maxlinewidth);
            }

            if (buf[i] == '\n') {
                line[col++] = '\n';
                line[col] = 0;
                addline(inputfile, line, col);
                col = 0;
            } else {
                line[col++] = buf[i];
            }
        }
    }

    free(line);

    close(fd);

    return inputfile;
}

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"
        "\n");


}

int lnint(size_t lnc) {
    int w = 1, p = 1;
    while ((p*=10) < lnc) w++;
    return w;
}

int copyfile(char *filename, FILE *dest) {
    if (!filename) {
        return 0;
    }
    
    FILE *src = fopen(filename, "r");
    if (src) {
        char buf[4096];
        int r;
        while ((r = fread(buf, 1, 4096, src)) > 0) {
            fwrite(buf, 1, r, dest);
        }
        fclose(src);
        return 0;
    } else {
        return errno;
    }
}

int main(int argc, char** argv) {
    int retcode = EXIT_SUCCESS;
    
    settings_t settings;
    memset(&settings, 0, sizeof(settings));
    settings.highlight = 1;
    
    highlighter_t highlighter;
    memset(&highlighter, 0, sizeof(highlighter));
    highlighter.isdirective = iscdirective;
    highlighter.istype = isctype;
    highlighter.keywords = ckeywords;
    highlighter.parser = cparseline;

    char optc;
    while ((optc = getopt(argc, argv, "hjo:pH:F:")) != -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':
                highlighter.isdirective = isjdirective;
                highlighter.istype = isjtype;
                highlighter.keywords = jkeywords;
                highlighter.parser = jparseline;
                break;
            case 'p':
                settings.highlight = 0;
                break;
            case 'h':
                printhelp();
                return 0;
            default:
                return 1;
        }
    }

    if (optind != argc-1) {
        printhelp();
        return 1;
    } else {
        settings.infilename = argv[optind];
        FILE *fout;
        if (settings.outfilename) {
            fout = fopen(settings.outfilename, "w");
            if (!fout) {
                perror("Error opening output file");
                return errno;
            }
        } else {
            fout = stdout;
        }
        
        if (copyfile(settings.headerfile, fout)) {
            perror("Error opening header file");
            retcode = errno;
            goto prog_end;
        }

        inputfile_t *inputfile = readinput(settings.infilename);
        if (inputfile) {
            char *line;
            if (settings.highlight) {
                line = (char*) malloc(inputfile->maxlinewidth*64);
            } else {
                line = NULL;
            }
            fprintf(fout, "<pre>\n");
            int lnw = lnint(inputfile->count);
            for (int i = 0 ; i < inputfile->count ; i++) {
                if (settings.highlight) {
                    highlighter.parser(inputfile->lines[i], line, &highlighter);
                } else {
                    line = inputfile->lines[i];
                }
                fprintf(fout, "<span class=\"c2html-lineno\">%*d:</span> %s",
                    lnw, i+1, line);
            }
            if (settings.highlight) {
                free(line);
            }
            fprintf(fout, "</pre>\n");

            freeinputfilebuffer(inputfile);
            
            if (copyfile(settings.footerfile, fout)) {
                perror("Error opening footer file");
                retcode = errno;
            }
        } else {
            perror("Error opening input file");
            retcode = errno;
        }
        
        prog_end:        
        if (fout != stdout) {
            fclose(fout);
        }

        return retcode;
    }
}

mercurial