|
14 | 14 | #include "general.h" /* must always come first */
|
15 | 15 |
|
16 | 16 | #include <string.h>
|
| 17 | +#include <ctype.h> |
17 | 18 |
|
18 | 19 | #include "debug.h"
|
19 | 20 | #include "entry.h"
|
|
30 | 31 |
|
31 | 32 | #include "cxx/cxx_debug.h"
|
32 | 33 |
|
| 34 | +/* Ideally these two should be private in "main" part. |
| 35 | + * Because the CPreProcessor parser is imperfect as a base parser, the |
| 36 | + * parser must call them directly. */ |
| 37 | +extern subparser* teardownLanguageSubparsersInUse (const langType language); |
| 38 | +extern void setupLanguageSubparsersInUse (const langType language); |
| 39 | + |
33 | 40 | /*
|
34 | 41 | * MACROS
|
35 | 42 | */
|
@@ -296,6 +303,9 @@ static void cppInitCommon(langType clientLang,
|
296 | 303 | t = getNamedLanguage ("CPreProcessor", 0);
|
297 | 304 | initializeParser (t);
|
298 | 305 | }
|
| 306 | + pushLanguage(Cpp.lang); |
| 307 | + setupLanguageSubparsersInUse (Cpp.lang); |
| 308 | + popLanguage(); |
299 | 309 |
|
300 | 310 | Cpp.clientLang = clientLang;
|
301 | 311 | Cpp.ungetBuffer = NULL;
|
@@ -439,6 +449,9 @@ extern void cppTerminate (void)
|
439 | 449 | hashTableDelete (Cpp.fileMacroTable);
|
440 | 450 | Cpp.fileMacroTable = NULL;
|
441 | 451 | }
|
| 452 | + pushLanguage(Cpp.lang); |
| 453 | + teardownLanguageSubparsersInUse (Cpp.lang); |
| 454 | + popLanguage(); |
442 | 455 | }
|
443 | 456 |
|
444 | 457 | extern void cppBeginStatement (void)
|
@@ -1243,30 +1256,135 @@ static Comment isComment (void)
|
1243 | 1256 | return comment;
|
1244 | 1257 | }
|
1245 | 1258 |
|
| 1259 | +static cPreProcessorSubparser *notifyLineToSubparsers (cPreProcessorSubparser *sub, |
| 1260 | + char firstchar, |
| 1261 | + vString *line, |
| 1262 | + bool *sentThe1stLine) |
| 1263 | +{ |
| 1264 | + if (sub == NULL && *sentThe1stLine == true) |
| 1265 | + return NULL; |
| 1266 | + |
| 1267 | + if (!*sentThe1stLine) |
| 1268 | + { |
| 1269 | + Assert (sub == NULL); |
| 1270 | + |
| 1271 | + subparser *s; |
| 1272 | + |
| 1273 | + *sentThe1stLine = true; |
| 1274 | + |
| 1275 | + pushLanguage (Cpp.lang); |
| 1276 | + foreachSubparser(s, false) |
| 1277 | + { |
| 1278 | + bool b = false; |
| 1279 | + cPreProcessorSubparser *cpp = (cPreProcessorSubparser *)s; |
| 1280 | + enterSubparser(s); |
| 1281 | + if (cpp->firstLineNotify) |
| 1282 | + b = cpp->firstLineNotify (cpp, firstchar, vStringValue(line)); |
| 1283 | + leaveSubparser(); |
| 1284 | + |
| 1285 | + if (b) |
| 1286 | + { |
| 1287 | + sub = cpp; |
| 1288 | + break; |
| 1289 | + } |
| 1290 | + } |
| 1291 | + popLanguage (); |
| 1292 | + return sub; |
| 1293 | + } |
| 1294 | + |
| 1295 | + enterSubparser(&sub->subparser); |
| 1296 | + if (sub->restLineNotify) |
| 1297 | + sub->restLineNotify (sub, vStringValue(line)); |
| 1298 | + leaveSubparser(); |
| 1299 | + return sub; |
| 1300 | +} |
| 1301 | + |
| 1302 | +static void notifyEndOfComment (cPreProcessorSubparser *cpp) |
| 1303 | +{ |
| 1304 | + enterSubparser(&cpp->subparser); |
| 1305 | + if (cpp->endOfCommentNotify) |
| 1306 | + cpp->endOfCommentNotify(cpp); |
| 1307 | + leaveSubparser(); |
| 1308 | +} |
| 1309 | + |
| 1310 | +static bool isDocCommentStarter(int c) |
| 1311 | +{ |
| 1312 | + return c == '*'; |
| 1313 | +} |
| 1314 | + |
| 1315 | +static bool isWhitespaceOnly (vString *line) |
| 1316 | +{ |
| 1317 | + const char *c = vStringValue(line); |
| 1318 | + |
| 1319 | + while (*c) |
| 1320 | + { |
| 1321 | + if (!isspace((unsigned char) *c) |
| 1322 | + && !isDocCommentStarter(*c)) |
| 1323 | + return false; |
| 1324 | + c++; |
| 1325 | + } |
| 1326 | + return true; |
| 1327 | +} |
| 1328 | + |
1246 | 1329 | /* Skips over a C style comment. According to ANSI specification a comment
|
1247 | 1330 | * is treated as white space, so we perform this substitution.
|
| 1331 | + * |
| 1332 | + * As side effects, running subparsers interested in comments. |
1248 | 1333 | */
|
1249 | 1334 | static int cppSkipOverCComment (void)
|
1250 | 1335 | {
|
1251 | 1336 | int c = cppGetcFromUngetBufferOrFile ();
|
| 1337 | + int c0 = 0; |
| 1338 | + vString *line = NULL; |
| 1339 | + bool sentThe1stLine = false; |
| 1340 | + cPreProcessorSubparser *sub = NULL; |
| 1341 | + |
| 1342 | + |
| 1343 | + if (isDocCommentStarter (c)) |
| 1344 | + { |
| 1345 | + c0 = c; |
| 1346 | + c = cppGetcFromUngetBufferOrFile (); |
| 1347 | + if (c0 == '*' && c == '/') |
| 1348 | + return SPACE; |
| 1349 | + cppUngetc (c); |
| 1350 | + c = c0; |
| 1351 | + line = vStringNew (); |
| 1352 | + } |
1252 | 1353 |
|
1253 | 1354 | while (c != EOF)
|
1254 | 1355 | {
|
1255 |
| - if (c != '*') |
1256 |
| - c = cppGetcFromUngetBufferOrFile (); |
1257 |
| - else |
| 1356 | + if (c == '*') |
1258 | 1357 | {
|
1259 | 1358 | const int next = cppGetcFromUngetBufferOrFile ();
|
1260 | 1359 |
|
1261 |
| - if (next != '/') |
1262 |
| - c = next; |
1263 |
| - else |
| 1360 | + if (next == '/') |
1264 | 1361 | {
|
1265 | 1362 | c = SPACE; /* replace comment with space */
|
1266 | 1363 | break;
|
1267 | 1364 | }
|
| 1365 | + cppUngetc (next); |
1268 | 1366 | }
|
| 1367 | + |
| 1368 | + if (line) |
| 1369 | + { |
| 1370 | + vStringPut (line, c); |
| 1371 | + if (c == '\n') |
| 1372 | + { |
| 1373 | + if (sub || !isWhitespaceOnly (line)) |
| 1374 | + sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine); |
| 1375 | + vStringClear (line); |
| 1376 | + } |
| 1377 | + } |
| 1378 | + c = cppGetcFromUngetBufferOrFile (); |
1269 | 1379 | }
|
| 1380 | + |
| 1381 | + if (line && !vStringIsEmpty(line) && (sub || !isWhitespaceOnly (line))) |
| 1382 | + sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine); |
| 1383 | + |
| 1384 | + if (sub) |
| 1385 | + notifyEndOfComment (sub); |
| 1386 | + |
| 1387 | + vStringDelete (line); /* NULL is acceptable */ |
1270 | 1388 | return c;
|
1271 | 1389 | }
|
1272 | 1390 |
|
|
0 commit comments