Thu, 23 Jan 2014 09:19:37 +0100
structured source code
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2014 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 */
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <ctype.h>
37 #include "javacodegen.h"
38 #include "ccodegen.h"
40 #define INPUTBUF_SIZE 2048
42 typedef struct {
43 char* outfilename;
44 char* infilename;
45 int highlight;
46 } settings_t;
48 typedef struct {
49 size_t count;
50 size_t capacity;
51 size_t maxlinewidth;
52 char** lines;
53 } inputfile_t;
55 inputfile_t *inputfilebuffer(size_t capacity) {
56 inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t));
57 inputfile->lines = (char**) malloc(capacity * sizeof(char*));
58 inputfile->capacity = capacity;
59 inputfile->count = 0;
60 inputfile->maxlinewidth = 0;
62 return inputfile;
63 }
65 void addline(inputfile_t *inputfile, char* line, size_t width) {
66 char *l = (char*) malloc(width+1);
67 memcpy(l, line, width);
68 l[width] = 0;
69 if (inputfile->count >= inputfile->capacity) {
70 inputfile->capacity <<= 1;
71 inputfile->lines = realloc(inputfile->lines, inputfile->capacity);
72 }
73 inputfile->lines[inputfile->count] = l;
74 inputfile->maxlinewidth =
75 width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth;
76 inputfile->count++;
77 }
79 void freeinputfilebuffer(inputfile_t *inputfile) {
80 for (int i = 0 ; i < inputfile->count ; i++) {
81 free(inputfile->lines[i]);
82 }
83 free(inputfile->lines);
84 free(inputfile);
85 }
87 inputfile_t *readinput(char *filename) {
89 int fd = open(filename, O_RDONLY);
90 if (fd == -1) return NULL;
92 inputfile_t *inputfile = inputfilebuffer(512);
94 char buf[INPUTBUF_SIZE];
95 ssize_t r;
97 size_t maxlinewidth = 256;
98 char *line = (char*) malloc(maxlinewidth);
99 size_t col = 0;
101 while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) {
102 for (size_t i = 0 ; i < r ; i++) {
103 if (col >= maxlinewidth-4) {
104 maxlinewidth <<= 1;
105 line = realloc(line, maxlinewidth);
106 }
108 if (buf[i] == '\n') {
109 line[col++] = '\n';
110 line[col] = 0;
111 addline(inputfile, line, col);
112 col = 0;
113 } else {
114 line[col++] = buf[i];
115 }
116 }
117 }
119 free(line);
121 close(fd);
123 return inputfile;
124 }
126 void printhelp() {
127 printf("Formats source code using HTML.\n\nUsage:\n"
128 " c2html [Options] FILE\n\n"
129 " Options:\n"
130 " -h Prints this help message\n"
131 " -j Highlight Java instead of C source code\n"
132 " -o <output> Output file (stdout, if not specified)\n"
133 " -p Disable highlighting (plain text)\n"
134 "\n");
137 }
139 int lnint(size_t lnc) {
140 int w = 1, p = 1;
141 while ((p*=10) < lnc) w++;
142 return w;
143 }
145 int main(int argc, char** argv) {
146 settings_t settings;
147 settings.outfilename = NULL;
148 settings.highlight = 1;
150 highlighter_t highlighter;
151 memset(&highlighter, 0, sizeof(highlighter));
152 highlighter.isdirective = iscdirective;
153 highlighter.istype = isctype;
154 highlighter.keywords = ckeywords;
155 highlighter.parser = cparseline;
157 char optc;
158 while ((optc = getopt(argc, argv, "hjo:p")) != -1) {
159 switch (optc) {
160 case 'o':
161 if (!(optarg[0] == '-' && optarg[1] == 0)) {
162 settings.outfilename = optarg;
163 }
164 break;
165 case 'j':
166 highlighter.isdirective = isjdirective;
167 highlighter.istype = isjtype;
168 highlighter.keywords = jkeywords;
169 highlighter.parser = jparseline;
170 break;
171 case 'p':
172 settings.highlight = 0;
173 break;
174 case 'h':
175 printhelp();
176 return 0;
177 default:
178 return 1;
179 }
180 }
182 if (optind != argc-1) {
183 printhelp();
184 return 1;
185 } else {
186 settings.infilename = argv[optind];
188 inputfile_t *inputfile = readinput(settings.infilename);
189 if (inputfile) {
190 FILE *fout;
191 char *line;
192 if (settings.highlight) {
193 line = (char*) malloc(inputfile->maxlinewidth*64);
194 } else {
195 line = NULL;
196 }
197 if (settings.outfilename) {
198 fout = fopen(settings.outfilename, "w");
199 } else {
200 fout = stdout;
201 }
202 fprintf(fout, "<pre>\n");
203 int lnw = lnint(inputfile->count);
204 for (int i = 0 ; i < inputfile->count ; i++) {
205 if (settings.highlight) {
206 highlighter.parser(inputfile->lines[i], line, &highlighter);
207 } else {
208 line = inputfile->lines[i];
209 }
210 fprintf(fout, "<span class=\"c2html-lineno\">%*d:</span> %s",
211 lnw, i+1, line);
212 }
213 if (settings.highlight) {
214 free(line);
215 }
216 fprintf(fout, "</pre>\n");
218 if (fout != stdout) {
219 fclose(fout);
220 }
222 freeinputfilebuffer(inputfile);
223 }
225 return 0;
226 }
227 }