|
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 four functions 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 | +extern void notifyInputStart (void); |
| 40 | +extern void notifyInputEnd (void); |
| 41 | + |
33 | 42 | /*
|
34 | 43 | * MACROS
|
35 | 44 | */
|
@@ -296,6 +305,9 @@ static void cppInitCommon(langType clientLang,
|
296 | 305 | t = getNamedLanguage ("CPreProcessor", 0);
|
297 | 306 | initializeParser (t);
|
298 | 307 | }
|
| 308 | + pushLanguage(Cpp.lang); |
| 309 | + setupLanguageSubparsersInUse (Cpp.lang); |
| 310 | + popLanguage(); |
299 | 311 |
|
300 | 312 | Cpp.clientLang = clientLang;
|
301 | 313 | Cpp.ungetBuffer = NULL;
|
@@ -377,6 +389,10 @@ static void cppInitCommon(langType clientLang,
|
377 | 389 | : clientLang) & CORK_SYMTAB))
|
378 | 390 | ? makeMacroTable ()
|
379 | 391 | : NULL;
|
| 392 | + |
| 393 | + pushLanguage(Cpp.lang); |
| 394 | + notifyInputStart (); |
| 395 | + popLanguage(); |
380 | 396 | }
|
381 | 397 |
|
382 | 398 | extern void cppInit (const bool state, const bool hasAtLiteralStrings,
|
@@ -412,6 +428,10 @@ static void cppClearMacroInUse (cppMacroInfo **pM)
|
412 | 428 |
|
413 | 429 | extern void cppTerminate (void)
|
414 | 430 | {
|
| 431 | + pushLanguage(Cpp.lang); |
| 432 | + notifyInputEnd (); |
| 433 | + popLanguage(); |
| 434 | + |
415 | 435 | if (Cpp.directive.name != NULL)
|
416 | 436 | {
|
417 | 437 | vStringDelete (Cpp.directive.name);
|
@@ -439,6 +459,9 @@ extern void cppTerminate (void)
|
439 | 459 | hashTableDelete (Cpp.fileMacroTable);
|
440 | 460 | Cpp.fileMacroTable = NULL;
|
441 | 461 | }
|
| 462 | + pushLanguage(Cpp.lang); |
| 463 | + teardownLanguageSubparsersInUse (Cpp.lang); |
| 464 | + popLanguage(); |
442 | 465 | }
|
443 | 466 |
|
444 | 467 | extern void cppBeginStatement (void)
|
@@ -1248,30 +1271,135 @@ static Comment isComment (void)
|
1248 | 1271 | return comment;
|
1249 | 1272 | }
|
1250 | 1273 |
|
| 1274 | +static cPreProcessorSubparser *notifyLineToSubparsers (cPreProcessorSubparser *sub, |
| 1275 | + char firstchar, |
| 1276 | + vString *line, |
| 1277 | + bool *sentThe1stLine) |
| 1278 | +{ |
| 1279 | + if (sub == NULL && *sentThe1stLine == true) |
| 1280 | + return NULL; |
| 1281 | + |
| 1282 | + if (!*sentThe1stLine) |
| 1283 | + { |
| 1284 | + Assert (sub == NULL); |
| 1285 | + |
| 1286 | + subparser *s; |
| 1287 | + |
| 1288 | + *sentThe1stLine = true; |
| 1289 | + |
| 1290 | + pushLanguage (Cpp.lang); |
| 1291 | + foreachSubparser(s, false) |
| 1292 | + { |
| 1293 | + bool b = false; |
| 1294 | + cPreProcessorSubparser *cpp = (cPreProcessorSubparser *)s; |
| 1295 | + enterSubparser(s); |
| 1296 | + if (cpp->firstLineNotify) |
| 1297 | + b = cpp->firstLineNotify (cpp, firstchar, vStringValue(line)); |
| 1298 | + leaveSubparser(); |
| 1299 | + |
| 1300 | + if (b) |
| 1301 | + { |
| 1302 | + sub = cpp; |
| 1303 | + break; |
| 1304 | + } |
| 1305 | + } |
| 1306 | + popLanguage (); |
| 1307 | + return sub; |
| 1308 | + } |
| 1309 | + |
| 1310 | + enterSubparser(&sub->subparser); |
| 1311 | + if (sub->restLineNotify) |
| 1312 | + sub->restLineNotify (sub, vStringValue(line)); |
| 1313 | + leaveSubparser(); |
| 1314 | + return sub; |
| 1315 | +} |
| 1316 | + |
| 1317 | +static void notifyEndOfComment (cPreProcessorSubparser *cpp) |
| 1318 | +{ |
| 1319 | + enterSubparser(&cpp->subparser); |
| 1320 | + if (cpp->endOfCommentNotify) |
| 1321 | + cpp->endOfCommentNotify(cpp); |
| 1322 | + leaveSubparser(); |
| 1323 | +} |
| 1324 | + |
| 1325 | +static bool isDocCommentStarter(int c) |
| 1326 | +{ |
| 1327 | + return c == '*'; |
| 1328 | +} |
| 1329 | + |
| 1330 | +static bool isWhitespaceOnly (vString *line) |
| 1331 | +{ |
| 1332 | + const char *c = vStringValue(line); |
| 1333 | + |
| 1334 | + while (*c) |
| 1335 | + { |
| 1336 | + if (!isspace((unsigned char) *c) |
| 1337 | + && !isDocCommentStarter(*c)) |
| 1338 | + return false; |
| 1339 | + c++; |
| 1340 | + } |
| 1341 | + return true; |
| 1342 | +} |
| 1343 | + |
1251 | 1344 | /* Skips over a C style comment. According to ANSI specification a comment
|
1252 | 1345 | * is treated as white space, so we perform this substitution.
|
| 1346 | + * |
| 1347 | + * As side effects, running subparsers interested in comments. |
1253 | 1348 | */
|
1254 | 1349 | static int cppSkipOverCComment (void)
|
1255 | 1350 | {
|
1256 | 1351 | int c = cppGetcFromUngetBufferOrFile ();
|
| 1352 | + int c0 = 0; |
| 1353 | + vString *line = NULL; |
| 1354 | + bool sentThe1stLine = false; |
| 1355 | + cPreProcessorSubparser *sub = NULL; |
| 1356 | + |
| 1357 | + |
| 1358 | + if (isDocCommentStarter (c)) |
| 1359 | + { |
| 1360 | + c0 = c; |
| 1361 | + c = cppGetcFromUngetBufferOrFile (); |
| 1362 | + if (c0 == '*' && c == '/') |
| 1363 | + return SPACE; |
| 1364 | + cppUngetc (c); |
| 1365 | + c = c0; |
| 1366 | + line = vStringNew (); |
| 1367 | + } |
1257 | 1368 |
|
1258 | 1369 | while (c != EOF)
|
1259 | 1370 | {
|
1260 |
| - if (c != '*') |
1261 |
| - c = cppGetcFromUngetBufferOrFile (); |
1262 |
| - else |
| 1371 | + if (c == '*') |
1263 | 1372 | {
|
1264 | 1373 | const int next = cppGetcFromUngetBufferOrFile ();
|
1265 | 1374 |
|
1266 |
| - if (next != '/') |
1267 |
| - c = next; |
1268 |
| - else |
| 1375 | + if (next == '/') |
1269 | 1376 | {
|
1270 | 1377 | c = SPACE; /* replace comment with space */
|
1271 | 1378 | break;
|
1272 | 1379 | }
|
| 1380 | + cppUngetc (next); |
1273 | 1381 | }
|
| 1382 | + |
| 1383 | + if (line) |
| 1384 | + { |
| 1385 | + vStringPut (line, c); |
| 1386 | + if (c == '\n') |
| 1387 | + { |
| 1388 | + if (sub || !isWhitespaceOnly (line)) |
| 1389 | + sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine); |
| 1390 | + vStringClear (line); |
| 1391 | + } |
| 1392 | + } |
| 1393 | + c = cppGetcFromUngetBufferOrFile (); |
1274 | 1394 | }
|
| 1395 | + |
| 1396 | + if (line && !vStringIsEmpty(line) && (sub || !isWhitespaceOnly (line))) |
| 1397 | + sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine); |
| 1398 | + |
| 1399 | + if (sub) |
| 1400 | + notifyEndOfComment (sub); |
| 1401 | + |
| 1402 | + vStringDelete (line); /* NULL is acceptable */ |
1275 | 1403 | return c;
|
1276 | 1404 | }
|
1277 | 1405 |
|
|
0 commit comments