Mon, 13 Nov 2017 14:17:46 +0100
removes build/ucx from makefile
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2016 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 "highlighter.h"
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <ucx/string.h>
37 #include <ucx/utils.h>
39 static void put_htmlescaped(UcxBuffer *dest, char c) {
40 if (c == '>') {
41 ucx_buffer_puts(dest, ">");
42 } else if (c == '<') {
43 ucx_buffer_puts(dest, "<");
44 } else if (c) {
45 ucx_buffer_putc(dest, c);
46 }
47 }
49 static void put_htmlescapedstr(UcxBuffer *dest, sstr_t s) {
50 for (int i = 0 ; i < s.length ; i++) {
51 put_htmlescaped(dest, s.ptr[i]);
52 }
53 }
55 static int check_keyword(sstr_t word, const char** keywords) {
56 for (int i = 0 ; keywords[i] ; i++) {
57 if (sstrcmp(word, sstr((char*)keywords[i])) == 0) {
58 return 1;
59 }
60 }
61 return 0;
62 }
64 static int check_capsonly(sstr_t word) {
65 for (size_t i = 0 ; i < word.length ; i++) {
66 if (!isupper(word.ptr[i]) && !isdigit(word.ptr[i])
67 && word.ptr[i] != '_') {
68 return 0;
69 }
70 }
71 return 1;
72 }
74 /* Plaintext Highlighter */
76 void c2html_plain_highlighter(char *src, UcxBuffer *dest,
77 c2html_highlighter_data *hd) {
78 while (*src && *src != '\n') {
79 if (*src != '\r') {
80 put_htmlescaped(dest, *src);
81 }
82 src++;
83 }
84 ucx_buffer_putc(dest, '\n');
85 }
87 /* C Highlighter */
89 static const char* ckeywords[] = {
90 "auto", "break", "case", "char", "const", "continue", "default", "do",
91 "double", "else", "enum", "extern", "float", "for", "goto", "if", "int",
92 "long", "register", "return", "short", "signed", "sizeof", "static",
93 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile",
94 "while", NULL
95 };
97 void c2html_c_highlighter(char *src, UcxBuffer *dest,
98 c2html_highlighter_data *hd) {
99 /* reset buffers without clearing them */
100 hd->primary_buffer->size = hd->primary_buffer->pos = 0;
101 hd->secondary_buffer->size = hd->secondary_buffer->pos = 0;
103 /* alias the buffers for better handling */
104 UcxBuffer *wbuf = hd->primary_buffer;
105 UcxBuffer *ifilebuf = hd->secondary_buffer;
107 /* local information */
108 size_t sp = (size_t)-1;
109 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0;
110 char quote = '\0';
111 int isescaping = 0;
113 /* continue a multi line comment highlighting */
114 if (hd->multiline_comment) {
115 iscomment = 1;
116 ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
117 }
119 char c;
120 do {
121 c = src[++sp];
122 if (c == '\r') continue;
124 /* comments */
125 if (!isstring && c == '/') {
126 if (hd->multiline_comment && sp > 0 && src[sp-1] == '*') {
127 iscomment = 0;
128 hd->multiline_comment = 0;
129 ucx_buffer_puts(dest, "/</span>");
130 continue;
131 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) {
132 iscomment = 1;
133 hd->multiline_comment = (src[sp+1] == '*');
134 ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
135 }
136 }
138 if (iscomment) {
139 if (c == '\n') {
140 ucx_buffer_puts(dest, "</span>\n");
141 } else {
142 put_htmlescaped(dest, c);
143 }
144 } else if (isinclude) {
145 if (c == '<') {
146 ucx_buffer_puts(dest,
147 "<span class=\"c2html-stdinclude\"><");
148 } else if (c == '\"') {
149 if (parseinclude) {
150 ucx_buffer_puts(dest, "\">");
151 ucx_buffer_write(ifilebuf->space, 1, ifilebuf->size, dest);
152 ucx_buffer_puts(dest, "\"</a>");
153 parseinclude = 0;
154 } else {
155 ucx_buffer_puts(dest,
156 "<a class=\"c2html-userinclude\" href=\"");
157 ucx_buffer_putc(ifilebuf, '\"');
158 parseinclude = 1;
159 }
160 } else if (c == '>') {
161 ucx_buffer_puts(dest, "></span>");
162 } else {
163 if (parseinclude) {
164 ucx_buffer_putc(ifilebuf, c);
165 }
166 put_htmlescaped(dest, c);
167 }
168 } else {
169 /* strings */
170 if (!isescaping && (c == '\'' || c == '\"')) {
171 if (isstring) {
172 put_htmlescaped(dest, c);
173 if (c == quote) {
174 isstring = 0;
175 ucx_buffer_puts(dest, "</span>");
176 } else {
177 put_htmlescaped(dest, c);
178 }
179 } else {
180 isstring = 1;
181 quote = c;
182 ucx_buffer_puts(dest, "<span class=\"c2html-string\">");
183 put_htmlescaped(dest, c);
184 }
185 } else {
186 if (isstring) {
187 put_htmlescaped(dest, c);
188 } else if (isalnum(c) || c == '_' || c == '#') {
189 /* buffer the current word */
190 ucx_buffer_putc(wbuf, c);
191 } else {
192 /* write buffered word, if any */
193 if (wbuf->size > 0) {
194 sstr_t word = sstrn(wbuf->space, wbuf->size);
195 int closespan = 1;
196 sstr_t typesuffix = ST("_t");
197 if (check_keyword(word, ckeywords)) {
198 ucx_buffer_puts(dest,
199 "<span class=\"c2html-keyword\">");
200 } else if (sstrsuffix(word, typesuffix)) {
201 ucx_buffer_puts(dest,
202 "<span class=\"c2html-type\">");
203 } else if (word.ptr[0] == '#') {
204 isinclude = !sstrcmp(word, S("#include"));
205 ucx_buffer_puts(dest,
206 "<span class=\"c2html-directive\">");
207 } else if (check_capsonly(word)) {
208 ucx_buffer_puts(dest,
209 "<span class=\"c2html-macroconst\">");
210 } else {
211 closespan = 0;
212 }
213 put_htmlescapedstr(dest, word);
214 if (closespan) {
215 ucx_buffer_puts(dest, "</span>");
216 }
217 }
218 wbuf->pos = wbuf->size = 0; /* reset word buffer */
220 /* write current character */
221 put_htmlescaped(dest, c);
222 }
223 }
225 isescaping = !isescaping & (c == '\\');
226 }
227 } while (c && c != '\n');
228 }
230 /* Java Highlighter */
232 static const char* jkeywords[] = {
233 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto",
234 "package", "synchronized", "boolean", "do", "if", "private", "this",
235 "break", "double", "implements", "protected", "throw", "byte", "else",
236 "import", "public", "throws", "case", "enum", "instanceof", "return",
237 "transient", "catch", "extends", "int", "short", "try", "char", "final",
238 "interface", "static", "void", "class", "finally", "long", "strictfp",
239 "volatile", "const", "float", "native", "super", "while", NULL
240 };
242 void c2html_java_highlighter(char *src, UcxBuffer *dest,
243 c2html_highlighter_data *hd) {
244 /* reset buffers without clearing them */
245 hd->primary_buffer->size = hd->primary_buffer->pos = 0;
246 hd->secondary_buffer->size = hd->secondary_buffer->pos = 0;
248 /* alias the buffers for better handling */
249 UcxBuffer *wbuf = hd->primary_buffer;
251 /* local information */
252 size_t sp = (size_t)-1;
253 int isstring = 0, iscomment = 0, isimport = 0;
254 char quote = '\0';
255 int isescaping = 0;
257 if (hd->multiline_comment) {
258 iscomment = 1;
259 ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
260 }
262 char c;
263 do {
264 c = src[++sp];
265 if (c == '\r') continue;
267 /* comments */
268 if (!isstring && c == '/') {
269 if (hd->multiline_comment && sp > 0 && src[sp-1] == '*') {
270 iscomment = 0;
271 hd->multiline_comment = 0;
272 ucx_buffer_puts(dest, "/</span>");
273 continue;
274 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) {
275 iscomment = 1;
276 hd->multiline_comment = (src[sp+1] == '*');
277 ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
278 }
279 }
281 if (iscomment) {
282 if (c == '\n') {
283 ucx_buffer_puts(dest, "</span>\n");
284 } else {
285 put_htmlescaped(dest, c);
286 }
287 } else if (isimport) {
288 /* TODO: local imports */
289 } else {
290 /* strings */
291 if (!isescaping && (c == '\'' || c == '\"')) {
292 if (isstring) {
293 put_htmlescaped(dest, c);
294 if (c == quote) {
295 isstring = 0;
296 ucx_buffer_puts(dest, "</span>");
297 } else {
298 put_htmlescaped(dest, c);
299 }
300 } else {
301 isstring = 1;
302 quote = c;
303 ucx_buffer_puts(dest,
304 "<span class=\"c2html-string\">");
305 put_htmlescaped(dest, c);
306 }
307 } else {
308 if (isstring) {
309 put_htmlescaped(dest, c);
310 } else if (isalnum(c) || c == '_' || c == '@') {
311 /* buffer the current word */
312 ucx_buffer_putc(wbuf, c);
313 } else {
314 /* write buffered word, if any */
315 if (wbuf->size > 0) {
316 sstr_t word = sstrn(wbuf->space, wbuf->size);
317 int closespan = 1;
318 if (check_keyword(word, jkeywords)) {
319 ucx_buffer_puts(dest,
320 "<span class=\"c2html-keyword\">");
321 } else if (isupper(word.ptr[0])) {
322 ucx_buffer_puts(dest,
323 "<span class=\"c2html-type\">");
324 } else if (word.ptr[0] == '@') {
325 ucx_buffer_puts(dest,
326 "<span class=\"c2html-directive\">");
327 } else if (check_capsonly(word)) {
328 ucx_buffer_puts(dest,
329 "<span class=\"c2html-macroconst\">");
330 } else {
331 closespan = 0;
332 }
333 put_htmlescapedstr(dest, word);
335 if (closespan) {
336 ucx_buffer_puts(dest, "</span>");
337 }
338 }
339 wbuf->pos = wbuf->size = 0; /* reset buffer */
341 /* write current character */
342 put_htmlescaped(dest, c);
343 }
344 }
346 isescaping = !isescaping & (c == '\\');
347 }
348 } while (c && c != '\n');
349 }