src/c2html.c

Tue, 23 Aug 2016 12:06:46 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 23 Aug 2016 12:06:46 +0200
changeset 38
77c158821738
parent 37
1a67185e5496
child 39
ac35daceb24c
permissions
-rw-r--r--

use macros for exit codes

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2016 Mike Becker. All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  *
    28  */
    29 #include "c2html.h"
    31 inputfile_t *inputfilebuffer(size_t capacity) {
    32     inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t));
    33     inputfile->lines = (char**) malloc(capacity * sizeof(char*));
    34     inputfile->capacity = capacity;
    35     inputfile->count = 0;
    36     inputfile->maxlinewidth = 0;
    38     return inputfile;
    39 }
    41 void addline(inputfile_t *inputfile, char* line, size_t width) {
    42     char *l = (char*) malloc(width+1);
    43     memcpy(l, line, width);
    44     l[width] = 0;
    45     if (inputfile->count >= inputfile->capacity) {
    46         inputfile->capacity <<= 1;
    47         inputfile->lines = realloc(inputfile->lines,
    48             sizeof(char*)*inputfile->capacity);
    49     }
    50     inputfile->lines[inputfile->count] = l;
    51     inputfile->maxlinewidth =
    52         width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth;
    53     inputfile->count++;
    54 }
    56 void freeinputfilebuffer(inputfile_t *inputfile) {
    57     for (int i = 0 ; i < inputfile->count ; i++) {
    58         free(inputfile->lines[i]);
    59     }
    60     free(inputfile->lines);
    61     free(inputfile);
    62 }
    64 inputfile_t *readinput(char *filename) {
    66     int fd = open(filename, O_RDONLY);
    67     if (fd == -1) return NULL;
    69     inputfile_t *inputfile = inputfilebuffer(512);
    71     char buf[INPUTBUF_SIZE];
    72     ssize_t r;
    74     size_t maxlinewidth = 256;
    75     char *line = (char*) malloc(maxlinewidth);
    76     size_t col = 0;
    78     while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) {
    79         for (size_t i = 0 ; i < r ; i++) {
    80             if (col >= maxlinewidth-4) {
    81                 maxlinewidth <<= 1;
    82                 line = realloc(line, maxlinewidth);
    83             }
    85             if (buf[i] == '\n') {
    86                 line[col++] = '\n';
    87                 line[col] = 0;
    88                 addline(inputfile, line, col);
    89                 col = 0;
    90             } else {
    91                 line[col++] = buf[i];
    92             }
    93         }
    94     }
    96     free(line);
    98     close(fd);
   100     return inputfile;
   101 }
   103 void printhelp() {
   104     printf("Formats source code using HTML.\n\nUsage:\n"
   105         "  c2html [Options] FILE\n\n"
   106         " Options:\n"
   107         "  -h                    Prints this help message\n"
   108         "  -j                    Highlight Java instead of C source code\n"
   109         "  -o <output>           Output file (stdout, if not specified)\n"
   110         "  -H <header>           Prepend header file\n"
   111         "  -F <footer>           Append footer file\n"
   112         "  -p                    Disable highlighting (plain text)\n"
   113         "  -l                    Disable line numbers\n"
   114         "  -V, -v                Prints version and exits\n"
   115         "\n");
   116 }
   118 int lnint(size_t lnc) {
   119     int w = 1, p = 1;
   120     while ((p*=10) < lnc) w++;
   121     return w;
   122 }
   124 int copyfile(char *filename, FILE *dest) {
   125     if (!filename) {
   126         return 0;
   127     }
   129     FILE *src = fopen(filename, "r");
   130     if (src) {
   131         char buf[4096];
   132         int r;
   133         while ((r = fread(buf, 1, 4096, src)) > 0) {
   134             fwrite(buf, 1, r, dest);
   135         }
   136         fclose(src);
   137         return 0;
   138     } else {
   139         return -1;
   140     }
   141 }
   143 #define WRITECONST(stream, out, cstr) out(cstr, 1, sizeof(cstr)-1, stream)
   144 int formatfile(
   145         highlighter_t *highlighter,
   146         inputfile_t *in,
   147         fmt_write_func out,
   148         void *stream,
   149         _Bool showln) {
   150     // formats an input file and writes the result to out
   152     char *line = malloc(in->maxlinewidth*64);
   153     if(!line) {
   154         return 1;
   155     }
   156     WRITECONST(stream, out, "<pre>\n");
   158     int lnw = lnint(in->count);
   159     for (int i = 0 ; i < in->count ; i++) {
   160         if (highlighter) {
   161             highlighter->parser(in->lines[i], line, highlighter);
   162         } else {
   163             char *c = in->lines[i];
   164             size_t dp = 0;
   165             while (*c) {
   166                 dp = writeescapedchar(line, dp, *c);
   167                 c++;
   168             }
   169             line[dp] = '\0';
   170         }
   172         // write line number
   173         if (showln) {
   174             WRITECONST(stream, out, "<span class=\"c2html-lineno\">");
   175             char lnbuf[128];
   176             int len;
   177             // line number link
   178             len = snprintf(lnbuf, 128, "<a name=\"l%d\" href=\"#l%d\">",
   179                 i+1, i+1);
   180             out(lnbuf, 1, len, stream);
   181             // justified line number
   182             len = snprintf(lnbuf, 128, "%*d ", lnw, i+1);
   183             out(lnbuf, 1, len, stream);
   184             WRITECONST(stream, out, "</a></span> ");
   185         }
   187         // write formated (or plain) code line
   188         out(line, 1, strlen(line), stream);
   189     }
   191     WRITECONST(stream, out, "</pre>\n");
   192     free(line);
   193     return 0;
   194 }
   196 void init_c_highlighter(highlighter_t *highlighter) {
   197     memset(highlighter, 0, sizeof(highlighter_t));
   198     highlighter->isdirective = check_cdirective;
   199     highlighter->istype = check_ctype;
   200     highlighter->keywords = ckeywords;
   201     highlighter->parser = cparseline;
   202 }
   204 void init_java_highlighter(highlighter_t *highlighter) {
   205     memset(highlighter, 0, sizeof(highlighter_t));
   206     highlighter->isdirective = check_jdirective;
   207     highlighter->istype = check_jtype;
   208     highlighter->keywords = jkeywords;
   209     highlighter->parser = jparseline;
   210 }
   212 int main(int argc, char** argv) {
   213     int retcode = EXIT_SUCCESS;
   215     settings_t settings;
   216     memset(&settings, 0, sizeof(settings));
   217     settings.highlight = 1;
   218     settings.showlinenumbers = 1;
   220     int lang = C2HTML_C;
   222     char optc;
   223     while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) {
   224         switch (optc) {
   225             case 'o':
   226                 if (!(optarg[0] == '-' && optarg[1] == 0)) {
   227                     settings.outfilename = optarg;
   228                 }
   229                 break;
   230             case 'F':
   231                 settings.footerfile = optarg;
   232                 break;
   233             case 'H':
   234                 settings.headerfile = optarg;
   235                 break;
   236             case 'j':
   237                 lang = C2HTML_JAVA;
   238                 break;
   239             case 'p':
   240                 settings.highlight = 0;
   241                 break;
   242             case 'l':
   243                 settings.showlinenumbers = 0;
   244                 break;
   245             case 'h':
   246                 printhelp();
   247                 return EXIT_SUCCESS;
   248             case 'v':
   249             case 'V':
   250 #ifdef VERSION_DEVELOP
   251                 printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR);
   252 #else
   253                 printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
   254 #endif
   255                 return EXIT_SUCCESS;
   256             default:
   257                 return EXIT_FAILURE;
   258         }
   259     }
   261     if (optind != argc-1) {
   262         printhelp();
   263         return 1;
   264     } else {
   265         settings.infilename = argv[optind];
   266         FILE *fout;
   267         if (settings.outfilename) {
   268             fout = fopen(settings.outfilename, "w");
   269             if (!fout) {
   270                 perror("Error opening output file");
   271                 return EXIT_FAILURE;
   272             }
   273         } else {
   274             fout = stdout;
   275         }
   277         if (copyfile(settings.headerfile, fout)) {
   278             perror("Error opening header file");
   279             retcode = EXIT_FAILURE;
   280             goto prog_end;
   281         }
   283         highlighter_t highlighter;
   284         highlighter_t *hptr = &highlighter;
   285         switch (lang) {
   286             case C2HTML_C:
   287                 init_c_highlighter(&highlighter);
   288                 break;
   289             case C2HTML_JAVA:
   290                 init_java_highlighter(&highlighter);
   291                 break;
   292             default:
   293                 hptr = NULL;
   294                 break;
   295         }
   296         if (!settings.highlight) {
   297             hptr = NULL;
   298         }
   300         inputfile_t *inputfile = readinput(settings.infilename);
   301         if (inputfile) {
   302             formatfile(
   303                     hptr,
   304                     inputfile,
   305                     (fmt_write_func)fwrite,
   306                     fout,
   307                     settings.showlinenumbers);
   308             freeinputfilebuffer(inputfile);
   309         } else {
   310             perror("Error opening input file");
   311             retcode = EXIT_FAILURE;
   312         }
   314         if (copyfile(settings.footerfile, fout)) {
   315             perror("Error opening footer file");
   316             retcode = EXIT_FAILURE;
   317         }
   319         prog_end:        
   320         if (fout != stdout) {
   321             fclose(fout);
   322         }
   324         return retcode;
   325     }
   326 }

mercurial