src/c2html.c

Tue, 23 Aug 2016 15:07:29 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 23 Aug 2016 15:07:29 +0200
changeset 44
2b4ac35d061d
parent 43
a8cee98c8832
child 45
1f3835182aeb
permissions
-rw-r--r--

cleans up formatfile function up to the parser call

     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 #include "ucx/buffer.h"
    32 #include "ucx/list.h"
    33 #include "ucx/utils.h"
    35 void printhelp() {
    36     printf("Formats source code using HTML.\n\nUsage:\n"
    37         "  c2html [Options] FILE\n\n"
    38         " Options:\n"
    39         "  -h                    Prints this help message\n"
    40         "  -j                    Highlight Java instead of C source code\n"
    41         "  -o <output>           Output file (stdout, if not specified)\n"
    42         "  -H <header>           Prepend header file\n"
    43         "  -F <footer>           Append footer file\n"
    44         "  -p                    Disable highlighting (plain text)\n"
    45         "  -l                    Disable line numbers\n"
    46         "  -V, -v                Prints version and exits\n"
    47         "\n");
    48 }
    50 int formatfile(
    51         highlighter_t *highlighter,
    52         UcxList *in,
    53         write_func out, void *stream,
    54         int showlineno) {
    56     /* compute width of line numbering */
    57     int lnw;
    58     if (showlineno) {
    59         size_t lines = ucx_list_size(in);
    60         lnw = 1;
    61         int p = 1;
    62         while ((p*=10) < lines) lnw++;
    63     }
    65     /* allocate line buffer */
    66     UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND);
    67     if(!line) {
    68         return 1;
    69     }
    71     /* start monospace formatting */
    72     out("<pre>\n", 1, 6, stream);
    74     /* process lines */
    75     size_t lineno = 0;
    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         /* TODO: backwards compatibility: replace line->space in all occasions
    89          * and use UcxBuffer functions
    90          */
    91         char *buf = line->space + line->pos;
    92         if (highlighter) {
    93             highlighter->parser(sourceline->data, buf, highlighter);
    94         } else {
    95             char *c = sourceline->data;
    96             size_t dp = 0;
    97             while (*c && *c != '\n') {
    98                 dp = writeescapedchar(buf, dp, *c);
    99                 c++;
   100             }
   101             buf[dp++] = '\n';
   102             buf[dp] = '\0';
   103         }
   104         line->size = strlen(line->space);
   106         /* write code line */
   107         out(line->space, 1, line->size, stream);
   108     }
   110     /* end monospace formatting */
   111     out("</pre>\n", 1, 7, stream);
   113     /* cleanup and return */
   114     ucx_buffer_free(line);
   115     return 0;
   116 }
   118 void init_c_highlighter(highlighter_t *highlighter) {
   119     memset(highlighter, 0, sizeof(highlighter_t));
   120     highlighter->isdirective = check_cdirective;
   121     highlighter->istype = check_ctype;
   122     highlighter->keywords = ckeywords;
   123     highlighter->parser = cparseline;
   124 }
   126 void init_java_highlighter(highlighter_t *highlighter) {
   127     memset(highlighter, 0, sizeof(highlighter_t));
   128     highlighter->isdirective = check_jdirective;
   129     highlighter->istype = check_jtype;
   130     highlighter->keywords = jkeywords;
   131     highlighter->parser = jparseline;
   132 }
   134 #define FILEBUF_SIZE 4096
   136 enum source_type {
   137     SOURCE_C,
   138     SOURCE_JAVA,
   139     SOURCE_PLAIN
   140 };
   142 int main(int argc, char** argv) {
   144     /* Default settings */
   145     Settings settings;
   146     memset(&settings, 0, sizeof(settings));
   147     settings.showlinenumbers = 1;
   148     enum source_type sourcetype = SOURCE_C;
   150     /* Parse command line */
   151     char optc;
   152     while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) {
   153         switch (optc) {
   154             case 'o':
   155                 if (!(optarg[0] == '-' && optarg[1] == 0)) {
   156                     settings.outfilename = optarg;
   157                 }
   158                 break;
   159             case 'F':
   160                 settings.footerfile = optarg;
   161                 break;
   162             case 'H':
   163                 settings.headerfile = optarg;
   164                 break;
   165             case 'j':
   166                 sourcetype = SOURCE_JAVA;
   167                 break;
   168             case 'p':
   169                 sourcetype = SOURCE_PLAIN;
   170                 break;
   171             case 'l':
   172                 settings.showlinenumbers = 0;
   173                 break;
   174             case 'h':
   175                 printhelp();
   176                 return EXIT_SUCCESS;
   177             case 'v':
   178             case 'V':
   179 #ifdef VERSION_DEVELOP
   180                 printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR);
   181 #else
   182                 printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
   183 #endif
   184                 return EXIT_SUCCESS;
   185             default:
   186                 return EXIT_FAILURE;
   187         }
   188     }
   190     if (optind != argc-1) {
   191         printhelp();
   192         return EXIT_FAILURE;
   193     } else {
   194         /* Configure highlighter */
   195         highlighter_t highlighter;
   196         highlighter_t *hptr = &highlighter;
   197         switch (sourcetype) {
   198             case SOURCE_C:
   199                 init_c_highlighter(&highlighter);
   200                 break;
   201             case SOURCE_JAVA:
   202                 init_java_highlighter(&highlighter);
   203                 break;
   204             case SOURCE_PLAIN:
   205                 hptr = NULL;
   206                 break;
   207             default: /* should be unreachable */
   208                 fprintf(stderr, "error in enum source_type\n");
   209                 return EXIT_FAILURE;
   210         }
   212         /* Open output file */
   213         settings.infilename = argv[optind];
   214         FILE *fout;
   215         if (settings.outfilename) {
   216             fout = fopen(settings.outfilename, "w");
   217             if (!fout) {
   218                 perror("Error opening output file");
   219                 return EXIT_FAILURE;
   220             }
   221         } else {
   222             fout = stdout;
   223         }
   225         /* Allocate file buffer  */
   226         char *filebuf = malloc(FILEBUF_SIZE);
   227         if (!filebuf) {
   228             perror("Error allocating file buffer");
   229             return EXIT_FAILURE;
   230         }
   232         /* Prepend header file */
   233         {
   234             FILE *headerfile = fopen(settings.headerfile, "r");
   235             if (!headerfile) {
   236                 perror("Error opening header file");
   237                 if (fout != stdout) {
   238                     fclose(fout);
   239                 }
   240                 return EXIT_FAILURE;
   241             }
   242             ucx_stream_copy(headerfile, fout,
   243                     (read_func) fread, (write_func) fwrite,
   244                     filebuf, FILEBUF_SIZE, (size_t)-1);
   245             fclose(headerfile);
   246         }
   248         /* Process input file */
   249         FILE *inputfile = fopen(settings.infilename, "r");
   250         if (inputfile) {
   251             UcxBuffer *content = ucx_buffer_new(NULL,
   252                     FILEBUF_SIZE*2, UCX_BUFFER_AUTOEXTEND);
   253             {
   254                 ucx_stream_copy(inputfile, content, (read_func) fread,
   255                         (write_func) ucx_buffer_write,
   256                         filebuf, FILEBUF_SIZE, (size_t)-1);
   257             }
   258             fclose(inputfile);
   260             UcxList *inputlines = ucx_list_append(NULL, content->space);
   261             for (size_t i = 1 ; i < content->size ; i++) {
   262                 if (content->space[i] == '\r') {
   263                     content->space[i] = '\n'; i++;
   264                 }
   265                 if (content->space[i] == '\n' && i+1 < content->size) {
   266                     ucx_list_append(inputlines, content->space+i+1);
   267                 }
   268             }
   270             formatfile(
   271                     hptr,
   272                     inputlines,
   273                     (write_func) fwrite,
   274                     fout,
   275                     settings.showlinenumbers);
   276             ucx_buffer_free(content);
   277         } else {
   278             perror("Error opening input file");
   279             if (fout != stdout) {
   280                 fclose(fout);
   281             }
   282             return EXIT_FAILURE;
   283         }
   285         /* Append footer file */
   286         {
   287             FILE *footerfile = fopen(settings.footerfile, "r");
   288             if (!footerfile) {
   289                 perror("Error opening footer file");
   290                 if (fout != stdout) {
   291                     fclose(fout);
   292                 }
   293                 return EXIT_FAILURE;
   294             }
   295             ucx_stream_copy(footerfile, fout,
   296                     (read_func) fread, (write_func) fwrite,
   297                     filebuf, FILEBUF_SIZE, (size_t)-1);
   298             fclose(footerfile);
   299         }
   302         free(filebuf);
   304         return EXIT_SUCCESS;
   305     }
   306 }

mercurial