src/c2html.c

Fri, 26 Aug 2016 13:49:19 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 26 Aug 2016 13:49:19 +0200
changeset 52
33ded421c512
parent 51
f25ba6fd7a08
child 53
5e47a26a16f0
permissions
-rw-r--r--

merges all highlighter functions into one highlighter module

     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  */
    30 #include <unistd.h>
    32 #include "c2html.h"
    33 #include "highlighter.h"
    35 #include "ucx/list.h"
    37 void printhelp() {
    38     printf("Formats source code using HTML.\n\nUsage:\n"
    39         "  c2html [Options] FILE\n\n"
    40         " Options:\n"
    41         "  -h                    Prints this help message\n"
    42         "  -j                    Highlight Java instead of C source code\n"
    43         "  -o <output>           Output file (stdout, if not specified)\n"
    44         "  -H <header>           Prepend header file\n"
    45         "  -F <footer>           Append footer file\n"
    46         "  -p                    Disable highlighting (plain text)\n"
    47         "  -l                    Disable line numbers\n"
    48         "  -V, -v                Prints version and exits\n"
    49         "\n");
    50 }
    52 void formatlines(highlighter_func highlighter,
    53         UcxList *in, write_func out, void *stream, int showlineno) {
    55     /* compute width of line numbering */
    56     int lnw;
    57     if (showlineno) {
    58         size_t lines = ucx_list_size(in);
    59         lnw = 1;
    60         int p = 1;
    61         while ((p*=10) < lines) lnw++;
    62     }
    64     /* start monospace formatting */
    65     out("<pre>\n", 1, 6, stream);
    67     /* process lines */
    68     size_t lineno = 0;
    69     HighlighterData *hd = new_highlighter_data();
    70     UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND);
    71     if(!line || !hd) {
    72         perror("Error allocating buffer for output");
    73         return;
    74     }
    76     UCX_FOREACH(sourceline, in) {
    77         /* increase line number and clean line buffer */
    78         lineno++;
    79         ucx_buffer_clear(line);
    81         /* write line number */
    82         if (showlineno) {
    83             ucx_bprintf(line, "<span class=\"c2html-lineno\">"
    84                     "<a name=\"l%d\" href=\"#l%d\">%*d </a></span> ",
    85                     lineno, lineno, lnw, lineno);
    86         }
    88         /* process code line */
    89         highlighter(sourceline->data, line, hd);
    91         /* write code line */
    92         out(line->space, 1, line->size, stream);
    93     }
    95     /* end monospace formatting */
    96     out("</pre>\n", 1, 7, stream);
    98     /* cleanup and return */
    99     free_highlighter_data(hd);
   100     ucx_buffer_free(line);
   101 }
   103 #define FILEBUF_SIZE 4096
   105 enum source_type {
   106     SOURCE_C,
   107     SOURCE_JAVA,
   108     SOURCE_PLAIN
   109 };
   111 int main(int argc, char** argv) {
   113     /* Default settings */
   114     Settings settings;
   115     memset(&settings, 0, sizeof(settings));
   116     settings.showlinenumbers = 1;
   117     enum source_type sourcetype = SOURCE_C;
   119     /* Parse command line */
   120     char optc;
   121     while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) {
   122         switch (optc) {
   123             case 'o':
   124                 if (!(optarg[0] == '-' && optarg[1] == 0)) {
   125                     settings.outfilename = optarg;
   126                 }
   127                 break;
   128             case 'F':
   129                 settings.footerfile = optarg;
   130                 break;
   131             case 'H':
   132                 settings.headerfile = optarg;
   133                 break;
   134             case 'j':
   135                 sourcetype = SOURCE_JAVA;
   136                 break;
   137             case 'p':
   138                 sourcetype = SOURCE_PLAIN;
   139                 break;
   140             case 'l':
   141                 settings.showlinenumbers = 0;
   142                 break;
   143             case 'h':
   144                 printhelp();
   145                 return EXIT_SUCCESS;
   146             case 'v':
   147             case 'V':
   148 #ifdef VERSION_DEVELOP
   149                 printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR);
   150 #else
   151                 printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
   152 #endif
   153                 return EXIT_SUCCESS;
   154             default:
   155                 return EXIT_FAILURE;
   156         }
   157     }
   159     if (optind != argc-1) {
   160         printhelp();
   161         return EXIT_FAILURE;
   162     } else {
   163         /* Choose highlighter */
   164         highlighter_func hltr = NULL;
   165         switch (sourcetype) {
   166             case SOURCE_C:
   167                 hltr = c_highlighter;
   168                 break;
   169             case SOURCE_JAVA:
   170                 hltr = java_highlighter;
   171                 break;
   172             case SOURCE_PLAIN:
   173                 hltr = plain_highlighter;
   174                 break;
   175             default: /* should be unreachable */
   176                 fprintf(stderr, "error in enum source_type\n");
   177                 return EXIT_FAILURE;
   178         }
   180         /* Open output file */
   181         settings.infilename = argv[optind];
   182         FILE *fout;
   183         if (settings.outfilename) {
   184             fout = fopen(settings.outfilename, "w");
   185             if (!fout) {
   186                 perror("Error opening output file");
   187                 return EXIT_FAILURE;
   188             }
   189         } else {
   190             fout = stdout;
   191         }
   193         /* Allocate file buffer  */
   194         char *filebuf = malloc(FILEBUF_SIZE);
   195         if (!filebuf) {
   196             perror("Error allocating file buffer");
   197             return EXIT_FAILURE;
   198         }
   200         /* Prepend header file */
   201         {
   202             FILE *headerfile = fopen(settings.headerfile, "r");
   203             if (!headerfile) {
   204                 perror("Error opening header file");
   205                 if (fout != stdout) {
   206                     fclose(fout);
   207                 }
   208                 return EXIT_FAILURE;
   209             }
   210             ucx_stream_copy(headerfile, fout,
   211                     (read_func) fread, (write_func) fwrite,
   212                     filebuf, FILEBUF_SIZE, (size_t)-1);
   213             fclose(headerfile);
   214         }
   216         /* Process input file */
   217         FILE *inputfile = fopen(settings.infilename, "r");
   218         if (inputfile) {
   219             UcxBuffer *content = ucx_buffer_new(NULL,
   220                     FILEBUF_SIZE*2, UCX_BUFFER_AUTOEXTEND);
   221             {
   222                 ucx_stream_copy(inputfile, content, (read_func) fread,
   223                         (write_func) ucx_buffer_write,
   224                         filebuf, FILEBUF_SIZE, (size_t)-1);
   225             }
   226             fclose(inputfile);
   228             UcxList *inputlines = ucx_list_append(NULL, content->space);
   229             for (size_t i = 1 ; i < content->size ; i++) {
   230                 if (content->space[i] == '\r') {
   231                     content->space[i] = '\n'; i++;
   232                 }
   233                 if (content->space[i] == '\n' && i+1 < content->size) {
   234                     ucx_list_append(inputlines, content->space+i+1);
   235                 }
   236             }
   238             formatlines(hltr, inputlines,
   239                     (write_func) fwrite, fout, settings.showlinenumbers);
   241             ucx_buffer_free(content);
   242         } else {
   243             perror("Error opening input file");
   244             if (fout != stdout) {
   245                 fclose(fout);
   246             }
   247             return EXIT_FAILURE;
   248         }
   250         /* Append footer file */
   251         {
   252             FILE *footerfile = fopen(settings.footerfile, "r");
   253             if (!footerfile) {
   254                 perror("Error opening footer file");
   255                 if (fout != stdout) {
   256                     fclose(fout);
   257                 }
   258                 return EXIT_FAILURE;
   259             }
   260             ucx_stream_copy(footerfile, fout,
   261                     (read_func) fread, (write_func) fwrite,
   262                     filebuf, FILEBUF_SIZE, (size_t)-1);
   263             fclose(footerfile);
   264         }
   267         free(filebuf);
   269         return EXIT_SUCCESS;
   270     }
   271 }

mercurial