src/c2html.c

Tue, 23 Aug 2016 17:24:58 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 23 Aug 2016 17:24:58 +0200
changeset 48
b2724c711203
parent 47
c39ecbbca7c0
child 49
f86f0b054464
permissions
-rw-r--r--

highlighter now use the UcxBuffer API for writing to the destination buffer

universe@23 1 /*
universe@23 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@23 3 *
universe@35 4 * Copyright 2016 Mike Becker. All rights reserved.
universe@23 5 *
universe@23 6 * Redistribution and use in source and binary forms, with or without
universe@23 7 * modification, are permitted provided that the following conditions are met:
universe@23 8 *
universe@23 9 * 1. Redistributions of source code must retain the above copyright
universe@23 10 * notice, this list of conditions and the following disclaimer.
universe@23 11 *
universe@23 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@23 13 * notice, this list of conditions and the following disclaimer in the
universe@23 14 * documentation and/or other materials provided with the distribution.
universe@23 15 *
universe@23 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@23 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@23 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@23 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@23 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@23 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@23 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@23 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@23 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@23 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@23 26 * POSSIBILITY OF SUCH DAMAGE.
universe@23 27 *
universe@23 28 */
universe@22 29 #include "c2html.h"
universe@1 30
universe@39 31 #include "ucx/buffer.h"
universe@39 32 #include "ucx/list.h"
universe@39 33 #include "ucx/utils.h"
universe@1 34
universe@1 35 void printhelp() {
universe@19 36 printf("Formats source code using HTML.\n\nUsage:\n"
universe@19 37 " c2html [Options] FILE\n\n"
universe@19 38 " Options:\n"
universe@19 39 " -h Prints this help message\n"
universe@19 40 " -j Highlight Java instead of C source code\n"
universe@19 41 " -o <output> Output file (stdout, if not specified)\n"
universe@22 42 " -H <header> Prepend header file\n"
universe@22 43 " -F <footer> Append footer file\n"
universe@19 44 " -p Disable highlighting (plain text)\n"
olaf@24 45 " -l Disable line numbers\n"
universe@37 46 " -V, -v Prints version and exits\n"
universe@19 47 "\n");
universe@1 48 }
universe@1 49
universe@48 50 static void plain_highlighter(char *src, UcxBuffer *dest, int* x) {
universe@45 51 while (*src && *src != '\n') {
universe@48 52 put_htmlescaped(dest, *src);
universe@45 53 src++;
universe@45 54 }
universe@48 55 ucx_buffer_putc(dest, '\n');
universe@45 56 }
universe@45 57
universe@46 58 int formatlines(highlighter_func highlighter,
universe@46 59 UcxList *in, write_func out, void *stream, int showlineno) {
olaf@24 60
universe@44 61 /* compute width of line numbering */
universe@44 62 int lnw;
universe@44 63 if (showlineno) {
universe@44 64 size_t lines = ucx_list_size(in);
universe@44 65 lnw = 1;
universe@44 66 int p = 1;
universe@44 67 while ((p*=10) < lines) lnw++;
universe@44 68 }
universe@44 69
universe@44 70 /* allocate line buffer */
universe@39 71 UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND);
olaf@24 72 if(!line) {
olaf@24 73 return 1;
olaf@24 74 }
olaf@24 75
universe@44 76 /* start monospace formatting */
universe@44 77 out("<pre>\n", 1, 6, stream);
universe@39 78
universe@44 79 /* process lines */
universe@39 80 size_t lineno = 0;
universe@47 81 int multiline_comment = 0;
universe@46 82
universe@39 83 UCX_FOREACH(sourceline, in) {
universe@44 84 /* increase line number and clean line buffer */
universe@39 85 lineno++;
universe@44 86 ucx_buffer_clear(line);
universe@44 87
universe@44 88 /* write line number */
universe@44 89 if (showlineno) {
universe@44 90 ucx_bprintf(line, "<span class=\"c2html-lineno\">"
universe@44 91 "<a name=\"l%d\" href=\"#l%d\">%*d </a></span> ",
universe@44 92 lineno, lineno, lnw, lineno);
universe@44 93 }
universe@44 94
universe@45 95 /* process code line */
universe@47 96 highlighter(sourceline->data, line, &multiline_comment);
olaf@24 97
universe@48 98 /* write code line and reset buffer */
universe@44 99 out(line->space, 1, line->size, stream);
olaf@24 100 }
olaf@24 101
universe@44 102 /* end monospace formatting */
universe@44 103 out("</pre>\n", 1, 7, stream);
universe@44 104
universe@44 105 /* cleanup and return */
universe@39 106 ucx_buffer_free(line);
olaf@24 107 return 0;
olaf@24 108 }
olaf@24 109
universe@42 110 #define FILEBUF_SIZE 4096
universe@42 111
universe@39 112 enum source_type {
universe@39 113 SOURCE_C,
universe@39 114 SOURCE_JAVA,
universe@39 115 SOURCE_PLAIN
universe@39 116 };
universe@39 117
universe@1 118 int main(int argc, char** argv) {
universe@43 119
universe@43 120 /* Default settings */
universe@39 121 Settings settings;
universe@22 122 memset(&settings, 0, sizeof(settings));
olaf@24 123 settings.showlinenumbers = 1;
universe@39 124 enum source_type sourcetype = SOURCE_C;
universe@19 125
universe@43 126 /* Parse command line */
universe@19 127 char optc;
universe@37 128 while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) {
universe@19 129 switch (optc) {
universe@19 130 case 'o':
universe@19 131 if (!(optarg[0] == '-' && optarg[1] == 0)) {
universe@19 132 settings.outfilename = optarg;
universe@19 133 }
universe@19 134 break;
universe@22 135 case 'F':
universe@22 136 settings.footerfile = optarg;
universe@22 137 break;
universe@22 138 case 'H':
universe@22 139 settings.headerfile = optarg;
universe@22 140 break;
universe@19 141 case 'j':
universe@39 142 sourcetype = SOURCE_JAVA;
universe@19 143 break;
universe@19 144 case 'p':
universe@39 145 sourcetype = SOURCE_PLAIN;
universe@19 146 break;
olaf@24 147 case 'l':
olaf@24 148 settings.showlinenumbers = 0;
olaf@24 149 break;
universe@19 150 case 'h':
universe@19 151 printhelp();
universe@38 152 return EXIT_SUCCESS;
universe@37 153 case 'v':
universe@37 154 case 'V':
universe@37 155 #ifdef VERSION_DEVELOP
universe@37 156 printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR);
universe@37 157 #else
universe@37 158 printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
universe@37 159 #endif
universe@38 160 return EXIT_SUCCESS;
universe@19 161 default:
universe@38 162 return EXIT_FAILURE;
universe@11 163 }
universe@19 164 }
universe@19 165
universe@19 166 if (optind != argc-1) {
universe@11 167 printhelp();
universe@43 168 return EXIT_FAILURE;
universe@19 169 } else {
universe@47 170 /* Choose highlighter */
universe@46 171 highlighter_func hltr = NULL;
universe@39 172 switch (sourcetype) {
universe@39 173 case SOURCE_C:
universe@48 174 hltr = c_highlighter;
olaf@24 175 break;
universe@39 176 case SOURCE_JAVA:
universe@48 177 hltr = java_highlighter;
olaf@24 178 break;
universe@39 179 case SOURCE_PLAIN:
universe@48 180 hltr = plain_highlighter;
olaf@24 181 break;
universe@39 182 default: /* should be unreachable */
universe@39 183 fprintf(stderr, "error in enum source_type\n");
universe@43 184 return EXIT_FAILURE;
olaf@24 185 }
universe@42 186
universe@43 187 /* Open output file */
universe@43 188 settings.infilename = argv[optind];
universe@43 189 FILE *fout;
universe@43 190 if (settings.outfilename) {
universe@43 191 fout = fopen(settings.outfilename, "w");
universe@43 192 if (!fout) {
universe@43 193 perror("Error opening output file");
universe@43 194 return EXIT_FAILURE;
universe@43 195 }
universe@43 196 } else {
universe@43 197 fout = stdout;
universe@43 198 }
universe@43 199
universe@43 200 /* Allocate file buffer */
universe@43 201 char *filebuf = malloc(FILEBUF_SIZE);
universe@43 202 if (!filebuf) {
universe@43 203 perror("Error allocating file buffer");
universe@43 204 return EXIT_FAILURE;
universe@43 205 }
universe@43 206
universe@43 207 /* Prepend header file */
universe@42 208 {
universe@42 209 FILE *headerfile = fopen(settings.headerfile, "r");
universe@42 210 if (!headerfile) {
universe@42 211 perror("Error opening header file");
universe@43 212 if (fout != stdout) {
universe@43 213 fclose(fout);
universe@43 214 }
universe@43 215 return EXIT_FAILURE;
universe@42 216 }
universe@42 217 ucx_stream_copy(headerfile, fout,
universe@42 218 (read_func) fread, (write_func) fwrite,
universe@42 219 filebuf, FILEBUF_SIZE, (size_t)-1);
universe@42 220 fclose(headerfile);
universe@42 221 }
universe@19 222
universe@43 223 /* Process input file */
universe@39 224 FILE *inputfile = fopen(settings.infilename, "r");
universe@19 225 if (inputfile) {
universe@42 226 UcxBuffer *content = ucx_buffer_new(NULL,
universe@42 227 FILEBUF_SIZE*2, UCX_BUFFER_AUTOEXTEND);
universe@39 228 {
universe@42 229 ucx_stream_copy(inputfile, content, (read_func) fread,
universe@39 230 (write_func) ucx_buffer_write,
universe@42 231 filebuf, FILEBUF_SIZE, (size_t)-1);
universe@39 232 }
universe@39 233 fclose(inputfile);
universe@39 234
universe@42 235 UcxList *inputlines = ucx_list_append(NULL, content->space);
universe@42 236 for (size_t i = 1 ; i < content->size ; i++) {
universe@42 237 if (content->space[i] == '\r') {
universe@42 238 content->space[i] = '\n'; i++;
universe@39 239 }
universe@42 240 if (content->space[i] == '\n' && i+1 < content->size) {
universe@42 241 ucx_list_append(inputlines, content->space+i+1);
universe@39 242 }
universe@39 243 }
universe@39 244
universe@46 245 formatlines(hltr, inputlines,
universe@46 246 (write_func) fwrite, fout, settings.showlinenumbers);
universe@45 247
universe@42 248 ucx_buffer_free(content);
universe@22 249 } else {
universe@22 250 perror("Error opening input file");
universe@43 251 if (fout != stdout) {
universe@43 252 fclose(fout);
universe@43 253 }
universe@43 254 return EXIT_FAILURE;
olaf@24 255 }
olaf@24 256
universe@43 257 /* Append footer file */
universe@42 258 {
universe@42 259 FILE *footerfile = fopen(settings.footerfile, "r");
universe@42 260 if (!footerfile) {
universe@42 261 perror("Error opening footer file");
universe@43 262 if (fout != stdout) {
universe@43 263 fclose(fout);
universe@43 264 }
universe@43 265 return EXIT_FAILURE;
universe@42 266 }
universe@42 267 ucx_stream_copy(footerfile, fout,
universe@42 268 (read_func) fread, (write_func) fwrite,
universe@42 269 filebuf, FILEBUF_SIZE, (size_t)-1);
universe@42 270 fclose(footerfile);
universe@22 271 }
universe@43 272
universe@22 273
universe@42 274 free(filebuf);
universe@19 275
universe@43 276 return EXIT_SUCCESS;
universe@11 277 }
universe@1 278 }
universe@1 279

mercurial