--- a/src/c2html.c Wed Aug 31 12:58:48 2016 +0200 +++ b/src/c2html.c Wed Aug 31 14:41:56 2016 +0200 @@ -27,47 +27,21 @@ * */ -#include <unistd.h> - #include "c2html.h" -#include "highlighter.h" #include "ucx/list.h" - -static int appendfile(const char *filename, FILE *fout, - char *copybuf, size_t copybuflen, const char *errmsg) { - FILE *headerfile = fopen(filename, "r"); - if (!headerfile) { - perror(errmsg); - if (fout != stdout) { - fclose(fout); - } - return 1; - } - ucx_stream_copy(headerfile, fout, - (read_func) fread, (write_func) fwrite, - copybuf, copybuflen, (size_t)-1); - fclose(headerfile); - return 0; -} +#include "ucx/utils.h" -static void printhelp() { - printf("Formats source code using HTML.\n\nUsage:\n" - " c2html [Options] FILE\n\n" - " Options:\n" - " -h Prints this help message\n" - " -j Highlight Java instead of C source code\n" - " -o <output> Output file (stdout, if not specified)\n" - " -H <header> Prepend header file\n" - " -F <footer> Append footer file\n" - " -p Disable highlighting (plain text)\n" - " -l Disable line numbers\n" - " -V, -v Prints version and exits\n" - "\n"); -} +#define try_write(wfnc, str, n, buf, written, maxlen) \ + { \ + size_t m = maxlen-written; \ + written += wfnc(str, 1, n > m ? m : n, buf); \ + } -static void formatlines(highlighter_func highlighter, - UcxList *in, write_func out, void *stream, int showlineno) { +static size_t formatlines(c2html_highlighter_func highlighter, UcxList *in, + void *outbuf, write_func wfnc, size_t maxlen, int showlineno) { + /* total written bytes */ + size_t written = 0; /* compute width of line numbering */ int lnw = 0; @@ -77,16 +51,15 @@ } /* start monospace formatting */ - out("<pre>\n", 1, 6, stream); + try_write(wfnc, "<pre>\n", 6, outbuf, written, maxlen); /* process lines */ size_t lineno = 0; - HighlighterData *hd = new_highlighter_data(); + c2html_highlighter_data* hd = malloc(sizeof(c2html_highlighter_data)); + hd->multiline_comment = 0; + hd->primary_buffer = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); + hd->secondary_buffer = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND); UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); - if(!line || !hd) { - perror("Error allocating buffer for output"); - return; - } UCX_FOREACH(sourceline, in) { /* increase line number and clean line buffer */ @@ -104,163 +77,63 @@ highlighter(sourceline->data, line, hd); /* write code line */ - out(line->space, 1, line->size, stream); + try_write(wfnc, line->space, line->size, outbuf, written, maxlen); + + if (written == maxlen) break; } /* end monospace formatting */ - out("</pre>\n", 1, 7, stream); + try_write(wfnc, "</pre>\n", 7, outbuf, written, maxlen); /* cleanup and return */ - free_highlighter_data(hd); + ucx_buffer_free(hd->primary_buffer); + ucx_buffer_free(hd->secondary_buffer); + free(hd); ucx_buffer_free(line); + + return written; } -#define FILEBUF_SIZE 4096 - -enum source_type { - SOURCE_C, - SOURCE_JAVA, - SOURCE_PLAIN -}; - -int main(int argc, char** argv) { - - /* Default settings */ - Settings settings; - memset(&settings, 0, sizeof(settings)); - settings.showlinenumbers = 1; - enum source_type sourcetype = SOURCE_C; +size_t c2html_formatn(void* inputbuffer, read_func rfnc, + char* ibuf, size_t ibuflen, void* outputbuffer, write_func wfnc, + size_t maxlen, c2html_highlighter_func hltr, int showln) { + + UcxBuffer *content = ucx_buffer_new(NULL, ibuflen*2, UCX_BUFFER_AUTOEXTEND); + ucx_stream_copy(inputbuffer, content, rfnc, (write_func) ucx_buffer_write, + ibuf, ibuflen, (size_t)-1); - /* Parse command line */ - char optc; - while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) { - switch (optc) { - case 'o': - if (!(optarg[0] == '-' && optarg[1] == 0)) { - settings.outfilename = optarg; - } - break; - case 'F': - settings.footerfile = optarg; - break; - case 'H': - settings.headerfile = optarg; - break; - case 'j': - sourcetype = SOURCE_JAVA; - break; - case 'p': - sourcetype = SOURCE_PLAIN; - break; - case 'l': - settings.showlinenumbers = 0; - break; - case 'h': - printhelp(); - return EXIT_SUCCESS; - case 'v': - case 'V': -#ifdef VERSION_DEVELOP - printf("%d.%d (unstable)\n", VERSION_MAJOR, VERSION_MINOR); -#else - printf("%d.%d\n", VERSION_MAJOR, VERSION_MINOR); -#endif - return EXIT_SUCCESS; - default: - return EXIT_FAILURE; + UcxList *lines = ucx_list_append(NULL, content->space); + for (size_t i = 1 ; i < content->size ; i++) { + if (content->space[i] == '\r') { + content->space[i] = '\n'; i++; + } + if (content->space[i] == '\n' && i+1 < content->size) { + ucx_list_append(lines, content->space+i+1); } } - - if (optind != argc-1) { - printhelp(); - return EXIT_FAILURE; - } else { - /* Choose highlighter */ - highlighter_func hltr = NULL; - switch (sourcetype) { - case SOURCE_C: - hltr = c_highlighter; - break; - case SOURCE_JAVA: - hltr = java_highlighter; - break; - case SOURCE_PLAIN: - hltr = plain_highlighter; - break; - default: /* should be unreachable */ - fprintf(stderr, "error in enum source_type\n"); - return EXIT_FAILURE; - } - - /* Open output file */ - settings.infilename = argv[optind]; - FILE *fout; - if (settings.outfilename) { - fout = fopen(settings.outfilename, "w"); - if (!fout) { - perror("Error opening output file"); - return EXIT_FAILURE; - } - } else { - fout = stdout; - } - - /* Allocate file buffer */ - char *filebuf = malloc(FILEBUF_SIZE); - if (!filebuf) { - perror("Error allocating file buffer"); - return EXIT_FAILURE; - } - - /* Prepend header file */ - if (appendfile(settings.headerfile, fout, filebuf, FILEBUF_SIZE, - "Error opening header file")) { - return EXIT_FAILURE; - } - - /* Process input file */ - FILE *inputfile = fopen(settings.infilename, "r"); - if (inputfile) { - UcxBuffer *content = ucx_buffer_new(NULL, - FILEBUF_SIZE*2, UCX_BUFFER_AUTOEXTEND); - { - ucx_stream_copy(inputfile, content, (read_func) fread, - (write_func) ucx_buffer_write, - filebuf, FILEBUF_SIZE, (size_t)-1); - } - fclose(inputfile); - - UcxList *inputlines = ucx_list_append(NULL, content->space); - for (size_t i = 1 ; i < content->size ; i++) { - if (content->space[i] == '\r') { - content->space[i] = '\n'; i++; - } - if (content->space[i] == '\n' && i+1 < content->size) { - ucx_list_append(inputlines, content->space+i+1); - } - } - - formatlines(hltr, inputlines, - (write_func) fwrite, fout, settings.showlinenumbers); - - ucx_buffer_free(content); - } else { - perror("Error opening input file"); - if (fout != stdout) { - fclose(fout); - } - return EXIT_FAILURE; - } - - /* Append footer file */ - if (appendfile(settings.footerfile, fout, filebuf, FILEBUF_SIZE, - "Error opening footer file")) { - return EXIT_FAILURE; - } - - free(filebuf); - - return EXIT_SUCCESS; - } + + size_t n = formatlines(hltr, lines, outputbuffer, wfnc, maxlen, showln); + + ucx_buffer_free(content); + return n; } +size_t c2html_format(void* inputbuffer, read_func rfnc, + char* ibuf, size_t ibuflen, void* outputbuffer, write_func wfnc, + c2html_highlighter_func hltr, int showln) { + return c2html_formatn(inputbuffer, rfnc, ibuf, ibuflen, + outputbuffer, wfnc, (size_t)-1, hltr, showln); +} + +size_t c2html_format_file(FILE* inputfile, char *ibuf, size_t ibuflen, + void* outputbuffer, write_func wfnc, + c2html_highlighter_func hltr, int showln) { + return c2html_format(inputfile, (read_func) fread, ibuf, ibuflen, + outputbuffer, wfnc, hltr, showln); +} + +void c2html_fformat_file(FILE *inputfile, char *ibuf, size_t ibuflen, + FILE* outputfile, c2html_highlighter_func hltr, int showln) { + c2html_format(inputfile, (read_func) fread, ibuf, ibuflen, + outputfile, (write_func) fwrite, hltr, showln); +}