src/highlighter.c

changeset 75
c72b250866ab
parent 67
5da2cb5aea6b
child 76
44c7423d6ce2
equal deleted inserted replaced
74:831928419249 75:c72b250866ab
27 * 27 *
28 */ 28 */
29 29
30 #include "highlighter.h" 30 #include "highlighter.h"
31 31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h> 32 #include <string.h>
35 #include <ctype.h> 33 #include <ctype.h>
36 34
37 #include <cx/string.h> 35 #include <cx/string.h>
36 #include <cx/printf.h>
38 37
39 static void put_htmlescaped(CxBuffer *dest, char c) { 38 static void put_htmlescaped(CxBuffer *dest, char c) {
40 if (c == '>') { 39 if (c == '>') {
41 cxBufferPutString(dest, "&gt;"); 40 cxBufferPutString(dest, "&gt;");
42 } else if (c == '<') { 41 } else if (c == '<') {
104 CxBuffer *wbuf = &hd->primary_buffer; 103 CxBuffer *wbuf = &hd->primary_buffer;
105 CxBuffer *ifilebuf = &hd->secondary_buffer; 104 CxBuffer *ifilebuf = &hd->secondary_buffer;
106 105
107 /* local information */ 106 /* local information */
108 size_t sp = (size_t)-1; 107 size_t sp = (size_t)-1;
108
109 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0; 109 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0;
110 char quote = '\0'; 110 char quote = '\0';
111 int isescaping = 0; 111 int isescaping = 0;
112 112
113 int continuation_enabled = 0;
114 const char* current_highlight = NULL;
115
116 /* define convenience macros */
117 #define start_span(cl) \
118 current_highlight = cl; \
119 cx_bprintf(dest, "<span class=\"c2html-%s\">", current_highlight)
120 #define stop_span \
121 current_highlight = NULL;\
122 cxBufferPutString(dest, "</span>")
123
113 /* continue a multi line comment highlighting */ 124 /* continue a multi line comment highlighting */
114 if (hd->multiline_comment) { 125 if (hd->multiline_comment) {
115 iscomment = 1; 126 iscomment = 1;
116 cxBufferPutString(dest, "<span class=\"c2html-comment\">"); 127 start_span("comment");
128 }
129
130 /* continue highlighting in case of line continuation */
131 if (hd->continue_highlight) {
132 start_span(hd->continue_highlight);
133 hd->continue_highlight = NULL;
134 isinclude = hd->continuation_info & 0x1;
135 isstring = hd->continuation_info & 0x2;
136 iscomment = hd->continuation_info & 0x4;
137 if (hd->continuation_info & 0x10) {
138 quote = '\'';
139 } else if (hd->continuation_info & 0x20) {
140 quote = '\"';
141 }
142 hd->continuation_info = 0;
117 } 143 }
118 144
119 char c; 145 char c;
120 do { 146 do {
121 c = src[++sp]; 147 c = src[++sp];
122 if (c == '\r') continue; 148 if (c == '\r') continue;
149
150 /* line continuation */
151 if (c == '\\') {
152 /* currently do not support continuations in user includes */
153 // TODO: also support user includes
154 if (!parseinclude) {
155 continuation_enabled = 1;
156 }
157 } else if (continuation_enabled) {
158 if (!isspace(c)) {
159 continuation_enabled = 0;
160 } else if (c == '\n') {
161 cxBufferPut(dest, '\n');
162 hd->continue_highlight = current_highlight;
163 hd->continuation_info = \
164 isinclude | \
165 (isstring << 1) | \
166 (iscomment << 2);
167 if (quote == '\'') {
168 hd->continuation_info |= 0x10;
169 } else if (quote == '\"') {
170 hd->continuation_info |= 0x20;
171 }
172 stop_span;
173 continue;
174 }
175 }
123 176
124 /* comments */ 177 /* comments */
125 if (!isstring && c == '/') { 178 if (!isstring && c == '/') {
126 if (hd->multiline_comment && sp > 0 && src[sp-1] == '*') { 179 if (hd->multiline_comment && sp > 0 && src[sp-1] == '*') {
127 iscomment = 0; 180 iscomment = 0;
128 hd->multiline_comment = 0; 181 hd->multiline_comment = 0;
129 cxBufferPutString(dest, "/</span>"); 182 cxBufferPut(dest, '/');
183 stop_span;
130 continue; 184 continue;
131 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) { 185 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) {
132 iscomment = 1; 186 iscomment = 1;
133 hd->multiline_comment = (src[sp+1] == '*'); 187 hd->multiline_comment = (src[sp+1] == '*');
134 cxBufferPutString(dest, "<span class=\"c2html-comment\">"); 188 start_span("comment");
135 } 189 }
136 } 190 }
137 191
138 if (iscomment) { 192 if (iscomment) {
139 if (c == '\n') { 193 if (c == '\n') {
140 cxBufferPutString(dest, "</span>\n"); 194 stop_span;
195 cxBufferPut(dest, '\n');
141 } else { 196 } else {
142 put_htmlescaped(dest, c); 197 put_htmlescaped(dest, c);
143 } 198 }
144 } else if (isinclude) { 199 } else if (isinclude) {
145 if (c == '<') { 200 if (c == '<') {
146 cxBufferPutString(dest, 201 start_span("stdinclude");
147 "<span class=\"c2html-stdinclude\">&lt;"); 202 cxBufferPutString(dest, "&lt;");
148 } else if (c == '\"') { 203 } else if (c == '\"') {
149 if (parseinclude) { 204 if (parseinclude) {
150 cxBufferPutString(dest, "\">"); 205 cxBufferPutString(dest, "\">");
151 cxBufferWrite(ifilebuf->space, 1, ifilebuf->size, dest); 206 cxBufferWrite(ifilebuf->space, 1, ifilebuf->size, dest);
152 cxBufferPutString(dest, "\"</a>"); 207 cxBufferPutString(dest, "\"</a>");
156 "<a class=\"c2html-userinclude\" href=\""); 211 "<a class=\"c2html-userinclude\" href=\"");
157 cxBufferPut(ifilebuf, '\"'); 212 cxBufferPut(ifilebuf, '\"');
158 parseinclude = 1; 213 parseinclude = 1;
159 } 214 }
160 } else if (c == '>') { 215 } else if (c == '>') {
161 cxBufferPutString(dest, "&gt;</span>"); 216 cxBufferPutString(dest, "&gt;");
217 stop_span;
162 } else { 218 } else {
163 if (parseinclude) { 219 if (parseinclude) {
164 cxBufferPut(ifilebuf, c); 220 cxBufferPut(ifilebuf, c);
165 } 221 }
166 put_htmlescaped(dest, c); 222 put_htmlescaped(dest, c);
170 if (!isescaping && (c == '\'' || c == '\"')) { 226 if (!isescaping && (c == '\'' || c == '\"')) {
171 if (isstring) { 227 if (isstring) {
172 put_htmlescaped(dest, c); 228 put_htmlescaped(dest, c);
173 if (c == quote) { 229 if (c == quote) {
174 isstring = 0; 230 isstring = 0;
175 cxBufferPutString(dest, "</span>"); 231 stop_span;
176 } else { 232 } else {
177 put_htmlescaped(dest, c); 233 put_htmlescaped(dest, c);
178 } 234 }
179 } else { 235 } else {
180 isstring = 1; 236 isstring = 1;
181 quote = c; 237 quote = c;
182 cxBufferPutString(dest, "<span class=\"c2html-string\">"); 238 start_span("string");
183 put_htmlescaped(dest, c); 239 put_htmlescaped(dest, c);
184 } 240 }
185 } else { 241 } else {
186 if (isstring) { 242 if (isstring) {
187 put_htmlescaped(dest, c); 243 put_htmlescaped(dest, c);
193 if (wbuf->size > 0) { 249 if (wbuf->size > 0) {
194 cxstring word = cx_strn(wbuf->space, wbuf->size); 250 cxstring word = cx_strn(wbuf->space, wbuf->size);
195 int closespan = 1; 251 int closespan = 1;
196 cxstring typesuffix = CX_STR("_t"); 252 cxstring typesuffix = CX_STR("_t");
197 if (check_keyword(word, ckeywords)) { 253 if (check_keyword(word, ckeywords)) {
198 cxBufferPutString(dest, 254 start_span("keyword");
199 "<span class=\"c2html-keyword\">");
200 } else if (cx_strsuffix(word, typesuffix)) { 255 } else if (cx_strsuffix(word, typesuffix)) {
201 cxBufferPutString(dest, 256 start_span("type");
202 "<span class=\"c2html-type\">");
203 } else if (word.ptr[0] == '#') { 257 } else if (word.ptr[0] == '#') {
204 isinclude = !cx_strcmp(word, CX_STR("#include")); 258 isinclude = !cx_strcmp(word, CX_STR("#include"));
205 cxBufferPutString(dest, 259 start_span("directive");
206 "<span class=\"c2html-directive\">");
207 } else if (check_capsonly(word)) { 260 } else if (check_capsonly(word)) {
208 cxBufferPutString(dest, 261 start_span("macroconst");
209 "<span class=\"c2html-macroconst\">");
210 } else { 262 } else {
211 closespan = 0; 263 closespan = 0;
212 } 264 }
213 put_htmlescapedstr(dest, word); 265 put_htmlescapedstr(dest, word);
214 if (closespan) { 266 if (closespan) {
215 cxBufferPutString(dest, "</span>"); 267 stop_span;
216 } 268 }
217 } 269 }
218 wbuf->pos = wbuf->size = 0; /* reset word buffer */ 270 wbuf->pos = wbuf->size = 0; /* reset word buffer */
219 271
220 /* write current character */ 272 /* write current character */
223 } 275 }
224 276
225 isescaping = !isescaping & (c == '\\'); 277 isescaping = !isescaping & (c == '\\');
226 } 278 }
227 } while (c && c != '\n'); 279 } while (c && c != '\n');
280
281 #undef start_span
282 #undef stop_span
228 } 283 }
229 284
230 /* Java Highlighter */ 285 /* Java Highlighter */
231 286
232 static const char* jkeywords[] = { 287 static const char* jkeywords[] = {

mercurial