Wed, 31 Aug 2016 14:41:56 +0200
adds appropriate public API
Makefile | file | annotate | diff | comparison | revisions | |
src/c2html.c | file | annotate | diff | comparison | revisions | |
src/c2html.h | file | annotate | diff | comparison | revisions | |
src/frontend.c | file | annotate | diff | comparison | revisions | |
src/highlighter.c | file | annotate | diff | comparison | revisions | |
src/highlighter.h | file | annotate | diff | comparison | revisions |
--- a/Makefile Wed Aug 31 12:58:48 2016 +0200 +++ b/Makefile Wed Aug 31 14:41:56 2016 +0200 @@ -31,8 +31,8 @@ include $(CONF).mk - -SRC = c2html.c +SRC = frontend.c +SRC += c2html.c SRC += highlighter.c SRC += ucx/allocator.c SRC += ucx/buffer.c
--- 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); +}
--- a/src/c2html.h Wed Aug 31 12:58:48 2016 +0200 +++ b/src/c2html.h Wed Aug 31 14:41:56 2016 +0200 @@ -30,6 +30,9 @@ #ifndef C2HTML_H #define C2HTML_H +#include <stdio.h> +#include "highlighter.h" + #ifdef __cplusplus extern "C" { #endif @@ -38,14 +41,102 @@ #define VERSION_MINOR 0 #define VERSION_DEVELOP 1 /* set this to zero for release version */ -typedef struct { - char* outfilename; - char* headerfile; - char* footerfile; - char* infilename; - int showlinenumbers; -} Settings; +/** + * Reads a source file from the input buffer and writes at most + * <code>maxlen</code> bytes of the formatted output to the output buffer. + * + * The output buffer must either be large enough to hold <code>maxlen</code> + * bytes or the write function must trigger an automatic extension of the buffer. + * + * @param inputbuffer the input buffer + * @param rfnc a read function operating for the input buffer + * @param ibuf intermediate processing buffer + * @param ibuflen length of intermediate processing buffer (recommended: 4 KB) + * @param outputbuffer the output buffer + * @param wfnc a write function for the output buffer + * @param maxlen the maximum amount bytes which will be written to the + * output buffer + * @param hltr the highlighter function + * @param showln zero, if line numbers shall be omitted, nonzero otherwise + * + * @return total amount of bytes written to the output buffer + * + * @see c2html_plain_highlighter() + * @see c2html_c_highlighter() + * @see c2html_java_highlighter() + */ +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); + +/** + * Reads a source file from the input buffer and writes the formatted output + * to an output buffer. + * + * The output buffer must either be large enough to hold the formatted data + * or the write function must trigger an automatic extension of the buffer. + * + * @param inputbuffer the input buffer + * @param rfnc a read function operating for the input buffer + * @param ibuf intermediate processing buffer + * @param ibuflen length of intermediate processing buffer (recommended: 4 KB) + * @param outputbuffer the output buffer + * @param wfnc a write function for the output buffer + * @param hltr the highlighter function + * @param showln zero, if line numbers shall be omitted, nonzero otherwise + * + * @return total amount of bytes written to the output buffer + * + * @see c2html_plain_highlighter() + * @see c2html_c_highlighter() + * @see c2html_java_highlighter() + */ +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); +/** + * Reads a source file from the specified input file stream and writes the + * formatted output to an output buffer. + * + * The output buffer must either be large enough to hold the formatted data + * or the write function must trigger an automatic extension of the buffer. + * + * @param inputfile the input file stream + * @param ibuf intermediate processing buffer + * @param ibuflen length of intermediate processing buffer (recommended: 4 KB) + * @param outputbuffer the output buffer + * @param wfnc a write function for the output buffer + * @param hltr the highlighter function + * @param showln zero, if line numbers shall be omitted, nonzero otherwise + * + * @return total amount of bytes written to the output buffer + * + * @see c2html_plain_highlighter() + * @see c2html_c_highlighter() + * @see c2html_java_highlighter() + */ +size_t c2html_format_file(FILE* inputfile, char *ibuf, size_t ibuflen, + void* outputbuffer, write_func wfnc, + c2html_highlighter_func hltr, int showln); + +/** + * Reads a source file from the specified input file stream and directly writes + * the formatted output to the output file stream. + * + * @param inputfile the input file stream + * @param ibuf intermediate processing buffer + * @param ibuflen length of intermediate processing buffer (recommended: 4 KB) + * @param outputfile the output file stream + * @param hltr the highlighter function + * @param showln zero, if line numbers shall be omitted, nonzero otherwise + * + * @see c2html_plain_highlighter() + * @see c2html_c_highlighter() + * @see c2html_java_highlighter() + */ +void c2html_fformat_file(FILE *inputfile, char *ibuf, size_t ibuflen, + FILE* outputfile, c2html_highlighter_func hltr, int showln); #ifdef __cplusplus }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/frontend.c Wed Aug 31 14:41:56 2016 +0200 @@ -0,0 +1,185 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2016 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "c2html.h" +#include "ucx/utils.h" + +#define FILEBUF_SIZE 4096 + +typedef struct { + char* outfilename; + char* headerfile; + char* footerfile; + char* infilename; + int showlinenumbers; +} Settings; + +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; +} + +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"); +} + +int main(int argc, char** argv) { + + /* Default settings */ + Settings settings; + memset(&settings, 0, sizeof(settings)); + settings.showlinenumbers = 1; + c2html_highlighter_func hltr = c2html_c_highlighter; + + /* 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': + hltr = c2html_java_highlighter; + break; + case 'p': + hltr = c2html_plain_highlighter; + 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; + } + } + + if (optind != argc-1) { + printhelp(); + return EXIT_FAILURE; + } else { + /* 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) { + c2html_fformat_file( + inputfile, filebuf, FILEBUF_SIZE, + fout, hltr, settings.showlinenumbers + ); + fclose(inputfile); + } 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; + } +} +
--- a/src/highlighter.c Wed Aug 31 12:58:48 2016 +0200 +++ b/src/highlighter.c Wed Aug 31 14:41:56 2016 +0200 @@ -29,23 +29,12 @@ #include "highlighter.h" -HighlighterData* new_highlighter_data() { - HighlighterData* hd = malloc(sizeof(HighlighterData)); - if (hd == NULL) { - return NULL; - } else { - 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); - return hd; - } -} - -void free_highlighter_data(HighlighterData *hd) { - ucx_buffer_free(hd->primary_buffer); - ucx_buffer_free(hd->secondary_buffer); - free(hd); -} +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "ucx/string.h" +#include "ucx/utils.h" static void put_htmlescaped(UcxBuffer *dest, char c) { if (c == '>') { @@ -84,7 +73,7 @@ /* Plaintext Highlighter */ -void plain_highlighter(char *src, UcxBuffer *dest, HighlighterData *hd) { +void c2html_plain_highlighter(char *src, UcxBuffer *dest, c2html_highlighter_data *hd) { while (*src && *src != '\n') { put_htmlescaped(dest, *src); src++; @@ -102,7 +91,7 @@ "while", NULL }; -void c_highlighter(char *src, UcxBuffer *dest, HighlighterData *hd) { +void c2html_c_highlighter(char *src, UcxBuffer *dest, c2html_highlighter_data *hd) { /* reset buffers without clearing them */ hd->primary_buffer->size = hd->primary_buffer->pos = 0; hd->secondary_buffer->size = hd->secondary_buffer->pos = 0; @@ -245,7 +234,7 @@ "volatile", "const", "float", "native", "super", "while", NULL }; -void java_highlighter(char *src, UcxBuffer *dest, HighlighterData *hd) { +void c2html_java_highlighter(char *src, UcxBuffer *dest, c2html_highlighter_data *hd) { /* reset buffers without clearing them */ hd->primary_buffer->size = hd->primary_buffer->pos = 0; hd->secondary_buffer->size = hd->secondary_buffer->pos = 0;
--- a/src/highlighter.h Wed Aug 31 12:58:48 2016 +0200 +++ b/src/highlighter.h Wed Aug 31 14:41:56 2016 +0200 @@ -30,13 +30,7 @@ #ifndef CODEGENS_H #define CODEGENS_H -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include "ucx/string.h" #include "ucx/buffer.h" -#include "ucx/utils.h" #ifdef __cplusplus extern "C" { @@ -46,16 +40,16 @@ int multiline_comment; UcxBuffer* primary_buffer; UcxBuffer* secondary_buffer; -} HighlighterData; +} c2html_highlighter_data; -HighlighterData* new_highlighter_data(); -void free_highlighter_data(HighlighterData*); +#define C2HTML_HIGHLIGHTER_SIGNATURE \ +char*,UcxBuffer*, c2html_highlighter_data* -typedef void(*highlighter_func)(char*,UcxBuffer*,HighlighterData*); +typedef void(*c2html_highlighter_func)(C2HTML_HIGHLIGHTER_SIGNATURE); -void plain_highlighter(char *src, UcxBuffer *dest, HighlighterData *hd); -void c_highlighter(char *src, UcxBuffer *dest, HighlighterData *hd); -void java_highlighter(char *src, UcxBuffer *dest, HighlighterData *hd); +void c2html_plain_highlighter(C2HTML_HIGHLIGHTER_SIGNATURE); +void c2html_c_highlighter(C2HTML_HIGHLIGHTER_SIGNATURE); +void c2html_java_highlighter(C2HTML_HIGHLIGHTER_SIGNATURE); #ifdef __cplusplus }