src/c2html.c

Thu, 23 Jan 2014 09:19:37 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 23 Jan 2014 09:19:37 +0100
changeset 21
537aec525835
parent 20
ebbf0776c1bc
child 22
f463693b5eeb
permissions
-rw-r--r--

structured source code

/*
 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>

#include "javacodegen.h"
#include "ccodegen.h"

#define INPUTBUF_SIZE 2048

typedef struct {
    char* outfilename;
    char* infilename;
    int highlight;
} settings_t;

typedef struct {
    size_t count;
    size_t capacity;
    size_t maxlinewidth;
    char** lines;
} inputfile_t;

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"
        "  -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 main(int argc, char** argv) {
    settings_t settings;
    settings.outfilename = NULL;
    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:p")) != -1) {
        switch (optc) {
            case 'o':
                if (!(optarg[0] == '-' && optarg[1] == 0)) {
                    settings.outfilename = 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];

        inputfile_t *inputfile = readinput(settings.infilename);
        if (inputfile) {
            FILE *fout;
            char *line;
            if (settings.highlight) {
                line = (char*) malloc(inputfile->maxlinewidth*64);
            } else {
                line = NULL;
            }
            if (settings.outfilename) {
                fout = fopen(settings.outfilename, "w");
            } else {
                fout = stdout;
            }
            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");

            if (fout != stdout) {
                fclose(fout);
            }

            freeinputfilebuffer(inputfile);
        }

        return 0;
    }
}

mercurial