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\"><"); |
202 cxBufferPutString(dest, "<"); |
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>"); |
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 */ |