1.1 --- a/src/c2html.c Wed Aug 31 12:58:48 2016 +0200 1.2 +++ b/src/c2html.c Wed Aug 31 14:41:56 2016 +0200 1.3 @@ -27,47 +27,21 @@ 1.4 * 1.5 */ 1.6 1.7 -#include <unistd.h> 1.8 - 1.9 #include "c2html.h" 1.10 -#include "highlighter.h" 1.11 1.12 #include "ucx/list.h" 1.13 +#include "ucx/utils.h" 1.14 1.15 -static int appendfile(const char *filename, FILE *fout, 1.16 - char *copybuf, size_t copybuflen, const char *errmsg) { 1.17 - FILE *headerfile = fopen(filename, "r"); 1.18 - if (!headerfile) { 1.19 - perror(errmsg); 1.20 - if (fout != stdout) { 1.21 - fclose(fout); 1.22 - } 1.23 - return 1; 1.24 +#define try_write(wfnc, str, n, buf, written, maxlen) \ 1.25 + { \ 1.26 + size_t m = maxlen-written; \ 1.27 + written += wfnc(str, 1, n > m ? m : n, buf); \ 1.28 } 1.29 - ucx_stream_copy(headerfile, fout, 1.30 - (read_func) fread, (write_func) fwrite, 1.31 - copybuf, copybuflen, (size_t)-1); 1.32 - fclose(headerfile); 1.33 - return 0; 1.34 -} 1.35 1.36 -static void printhelp() { 1.37 - printf("Formats source code using HTML.\n\nUsage:\n" 1.38 - " c2html [Options] FILE\n\n" 1.39 - " Options:\n" 1.40 - " -h Prints this help message\n" 1.41 - " -j Highlight Java instead of C source code\n" 1.42 - " -o <output> Output file (stdout, if not specified)\n" 1.43 - " -H <header> Prepend header file\n" 1.44 - " -F <footer> Append footer file\n" 1.45 - " -p Disable highlighting (plain text)\n" 1.46 - " -l Disable line numbers\n" 1.47 - " -V, -v Prints version and exits\n" 1.48 - "\n"); 1.49 -} 1.50 - 1.51 -static void formatlines(highlighter_func highlighter, 1.52 - UcxList *in, write_func out, void *stream, int showlineno) { 1.53 +static size_t formatlines(c2html_highlighter_func highlighter, UcxList *in, 1.54 + void *outbuf, write_func wfnc, size_t maxlen, int showlineno) { 1.55 + /* total written bytes */ 1.56 + size_t written = 0; 1.57 1.58 /* compute width of line numbering */ 1.59 int lnw = 0; 1.60 @@ -77,16 +51,15 @@ 1.61 } 1.62 1.63 /* start monospace formatting */ 1.64 - out("<pre>\n", 1, 6, stream); 1.65 + try_write(wfnc, "<pre>\n", 6, outbuf, written, maxlen); 1.66 1.67 /* process lines */ 1.68 size_t lineno = 0; 1.69 - HighlighterData *hd = new_highlighter_data(); 1.70 + c2html_highlighter_data* hd = malloc(sizeof(c2html_highlighter_data)); 1.71 + hd->multiline_comment = 0; 1.72 + hd->primary_buffer = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); 1.73 + hd->secondary_buffer = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND); 1.74 UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); 1.75 - if(!line || !hd) { 1.76 - perror("Error allocating buffer for output"); 1.77 - return; 1.78 - } 1.79 1.80 UCX_FOREACH(sourceline, in) { 1.81 /* increase line number and clean line buffer */ 1.82 @@ -104,163 +77,63 @@ 1.83 highlighter(sourceline->data, line, hd); 1.84 1.85 /* write code line */ 1.86 - out(line->space, 1, line->size, stream); 1.87 + try_write(wfnc, line->space, line->size, outbuf, written, maxlen); 1.88 + 1.89 + if (written == maxlen) break; 1.90 } 1.91 1.92 /* end monospace formatting */ 1.93 - out("</pre>\n", 1, 7, stream); 1.94 + try_write(wfnc, "</pre>\n", 7, outbuf, written, maxlen); 1.95 1.96 /* cleanup and return */ 1.97 - free_highlighter_data(hd); 1.98 + ucx_buffer_free(hd->primary_buffer); 1.99 + ucx_buffer_free(hd->secondary_buffer); 1.100 + free(hd); 1.101 ucx_buffer_free(line); 1.102 + 1.103 + return written; 1.104 } 1.105 1.106 -#define FILEBUF_SIZE 4096 1.107 +size_t c2html_formatn(void* inputbuffer, read_func rfnc, 1.108 + char* ibuf, size_t ibuflen, void* outputbuffer, write_func wfnc, 1.109 + size_t maxlen, c2html_highlighter_func hltr, int showln) { 1.110 + 1.111 + UcxBuffer *content = ucx_buffer_new(NULL, ibuflen*2, UCX_BUFFER_AUTOEXTEND); 1.112 + ucx_stream_copy(inputbuffer, content, rfnc, (write_func) ucx_buffer_write, 1.113 + ibuf, ibuflen, (size_t)-1); 1.114 1.115 -enum source_type { 1.116 - SOURCE_C, 1.117 - SOURCE_JAVA, 1.118 - SOURCE_PLAIN 1.119 -}; 1.120 - 1.121 -int main(int argc, char** argv) { 1.122 - 1.123 - /* Default settings */ 1.124 - Settings settings; 1.125 - memset(&settings, 0, sizeof(settings)); 1.126 - settings.showlinenumbers = 1; 1.127 - enum source_type sourcetype = SOURCE_C; 1.128 - 1.129 - /* Parse command line */ 1.130 - char optc; 1.131 - while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) { 1.132 - switch (optc) { 1.133 - case 'o': 1.134 - if (!(optarg[0] == '-' && optarg[1] == 0)) { 1.135 - settings.outfilename = optarg; 1.136 - } 1.137 - break; 1.138 - case 'F': 1.139 - settings.footerfile = optarg; 1.140 - break; 1.141 - case 'H': 1.142 - settings.headerfile = optarg; 1.143 - break; 1.144 - case 'j': 1.145 - sourcetype = SOURCE_JAVA; 1.146 - break; 1.147 - case 'p': 1.148 - sourcetype = SOURCE_PLAIN; 1.149 - break; 1.150 - case 'l': 1.151 - settings.showlinenumbers = 0; 1.152 - break; 1.153 - case 'h': 1.154 - printhelp(); 1.155 - return EXIT_SUCCESS; 1.156 - case 'v': 1.157 - case 'V': 1.158 -#ifdef VERSION_DEVELOP 1.159 - printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR); 1.160 -#else 1.161 - printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR); 1.162 -#endif 1.163 - return EXIT_SUCCESS; 1.164 - default: 1.165 - return EXIT_FAILURE; 1.166 + UcxList *lines = ucx_list_append(NULL, content->space); 1.167 + for (size_t i = 1 ; i < content->size ; i++) { 1.168 + if (content->space[i] == '\r') { 1.169 + content->space[i] = '\n'; i++; 1.170 + } 1.171 + if (content->space[i] == '\n' && i+1 < content->size) { 1.172 + ucx_list_append(lines, content->space+i+1); 1.173 } 1.174 } 1.175 - 1.176 - if (optind != argc-1) { 1.177 - printhelp(); 1.178 - return EXIT_FAILURE; 1.179 - } else { 1.180 - /* Choose highlighter */ 1.181 - highlighter_func hltr = NULL; 1.182 - switch (sourcetype) { 1.183 - case SOURCE_C: 1.184 - hltr = c_highlighter; 1.185 - break; 1.186 - case SOURCE_JAVA: 1.187 - hltr = java_highlighter; 1.188 - break; 1.189 - case SOURCE_PLAIN: 1.190 - hltr = plain_highlighter; 1.191 - break; 1.192 - default: /* should be unreachable */ 1.193 - fprintf(stderr, "error in enum source_type\n"); 1.194 - return EXIT_FAILURE; 1.195 - } 1.196 - 1.197 - /* Open output file */ 1.198 - settings.infilename = argv[optind]; 1.199 - FILE *fout; 1.200 - if (settings.outfilename) { 1.201 - fout = fopen(settings.outfilename, "w"); 1.202 - if (!fout) { 1.203 - perror("Error opening output file"); 1.204 - return EXIT_FAILURE; 1.205 - } 1.206 - } else { 1.207 - fout = stdout; 1.208 - } 1.209 - 1.210 - /* Allocate file buffer */ 1.211 - char *filebuf = malloc(FILEBUF_SIZE); 1.212 - if (!filebuf) { 1.213 - perror("Error allocating file buffer"); 1.214 - return EXIT_FAILURE; 1.215 - } 1.216 - 1.217 - /* Prepend header file */ 1.218 - if (appendfile(settings.headerfile, fout, filebuf, FILEBUF_SIZE, 1.219 - "Error opening header file")) { 1.220 - return EXIT_FAILURE; 1.221 - } 1.222 - 1.223 - /* Process input file */ 1.224 - FILE *inputfile = fopen(settings.infilename, "r"); 1.225 - if (inputfile) { 1.226 - UcxBuffer *content = ucx_buffer_new(NULL, 1.227 - FILEBUF_SIZE*2, UCX_BUFFER_AUTOEXTEND); 1.228 - { 1.229 - ucx_stream_copy(inputfile, content, (read_func) fread, 1.230 - (write_func) ucx_buffer_write, 1.231 - filebuf, FILEBUF_SIZE, (size_t)-1); 1.232 - } 1.233 - fclose(inputfile); 1.234 - 1.235 - UcxList *inputlines = ucx_list_append(NULL, content->space); 1.236 - for (size_t i = 1 ; i < content->size ; i++) { 1.237 - if (content->space[i] == '\r') { 1.238 - content->space[i] = '\n'; i++; 1.239 - } 1.240 - if (content->space[i] == '\n' && i+1 < content->size) { 1.241 - ucx_list_append(inputlines, content->space+i+1); 1.242 - } 1.243 - } 1.244 - 1.245 - formatlines(hltr, inputlines, 1.246 - (write_func) fwrite, fout, settings.showlinenumbers); 1.247 - 1.248 - ucx_buffer_free(content); 1.249 - } else { 1.250 - perror("Error opening input file"); 1.251 - if (fout != stdout) { 1.252 - fclose(fout); 1.253 - } 1.254 - return EXIT_FAILURE; 1.255 - } 1.256 - 1.257 - /* Append footer file */ 1.258 - if (appendfile(settings.footerfile, fout, filebuf, FILEBUF_SIZE, 1.259 - "Error opening footer file")) { 1.260 - return EXIT_FAILURE; 1.261 - } 1.262 - 1.263 - free(filebuf); 1.264 - 1.265 - return EXIT_SUCCESS; 1.266 - } 1.267 + 1.268 + size_t n = formatlines(hltr, lines, outputbuffer, wfnc, maxlen, showln); 1.269 + 1.270 + ucx_buffer_free(content); 1.271 + return n; 1.272 } 1.273 1.274 +size_t c2html_format(void* inputbuffer, read_func rfnc, 1.275 + char* ibuf, size_t ibuflen, void* outputbuffer, write_func wfnc, 1.276 + c2html_highlighter_func hltr, int showln) { 1.277 + return c2html_formatn(inputbuffer, rfnc, ibuf, ibuflen, 1.278 + outputbuffer, wfnc, (size_t)-1, hltr, showln); 1.279 +} 1.280 + 1.281 +size_t c2html_format_file(FILE* inputfile, char *ibuf, size_t ibuflen, 1.282 + void* outputbuffer, write_func wfnc, 1.283 + c2html_highlighter_func hltr, int showln) { 1.284 + return c2html_format(inputfile, (read_func) fread, ibuf, ibuflen, 1.285 + outputbuffer, wfnc, hltr, showln); 1.286 +} 1.287 + 1.288 +void c2html_fformat_file(FILE *inputfile, char *ibuf, size_t ibuflen, 1.289 + FILE* outputfile, c2html_highlighter_func hltr, int showln) { 1.290 + c2html_format(inputfile, (read_func) fread, ibuf, ibuflen, 1.291 + outputfile, (write_func) fwrite, hltr, showln); 1.292 +}