|
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) |
@@ -1243,30 +1266,135 @@ static Comment isComment (void) |
1243 | 1266 | return comment; |
1244 | 1267 | } |
1245 | 1268 |
|
| 1269 | +static cPreProcessorSubparser *notifyLineToSubparsers (cPreProcessorSubparser *sub, |
| 1270 | + char firstchar, |
| 1271 | + vString *line, |
| 1272 | + bool *sentThe1stLine) |
| 1273 | +{ |
| 1274 | + if (sub == NULL && *sentThe1stLine == true) |
| 1275 | + return NULL; |
| 1276 | + |
| 1277 | + if (!*sentThe1stLine) |
| 1278 | + { |
| 1279 | + Assert (sub == NULL); |
| 1280 | + |
| 1281 | + subparser *s; |
| 1282 | + |
| 1283 | + *sentThe1stLine = true; |
| 1284 | + |
| 1285 | + pushLanguage (Cpp.lang); |
| 1286 | + foreachSubparser(s, false) |
| 1287 | + { |
| 1288 | + bool b = false; |
| 1289 | + cPreProcessorSubparser *cpp = (cPreProcessorSubparser *)s; |
| 1290 | + enterSubparser(s); |
| 1291 | + if (cpp->firstLineNotify) |
| 1292 | + b = cpp->firstLineNotify (cpp, firstchar, vStringValue(line)); |
| 1293 | + leaveSubparser(); |
| 1294 | + |
| 1295 | + if (b) |
| 1296 | + { |
| 1297 | + sub = cpp; |
| 1298 | + break; |
| 1299 | + } |
| 1300 | + } |
| 1301 | + popLanguage (); |
| 1302 | + return sub; |
| 1303 | + } |
| 1304 | + |
| 1305 | + enterSubparser(&sub->subparser); |
| 1306 | + if (sub->restLineNotify) |
| 1307 | + sub->restLineNotify (sub, vStringValue(line)); |
| 1308 | + leaveSubparser(); |
| 1309 | + return sub; |
| 1310 | +} |
| 1311 | + |
| 1312 | +static void notifyEndOfComment (cPreProcessorSubparser *cpp) |
| 1313 | +{ |
| 1314 | + enterSubparser(&cpp->subparser); |
| 1315 | + if (cpp->endOfCommentNotify) |
| 1316 | + cpp->endOfCommentNotify(cpp); |
| 1317 | + leaveSubparser(); |
| 1318 | +} |
| 1319 | + |
| 1320 | +static bool isDocCommentStarter(int c) |
| 1321 | +{ |
| 1322 | + return c == '*'; |
| 1323 | +} |
| 1324 | + |
| 1325 | +static bool isWhitespaceOnly (vString *line) |
| 1326 | +{ |
| 1327 | + const char *c = vStringValue(line); |
| 1328 | + |
| 1329 | + while (*c) |
| 1330 | + { |
| 1331 | + if (!isspace((unsigned char) *c) |
| 1332 | + && !isDocCommentStarter(*c)) |
| 1333 | + return false; |
| 1334 | + c++; |
| 1335 | + } |
| 1336 | + return true; |
| 1337 | +} |
| 1338 | + |
1246 | 1339 | /* Skips over a C style comment. According to ANSI specification a comment |
1247 | 1340 | * is treated as white space, so we perform this substitution. |
| 1341 | + * |
| 1342 | + * As side effects, running subparsers interested in comments. |
1248 | 1343 | */ |
1249 | 1344 | static int cppSkipOverCComment (void) |
1250 | 1345 | { |
1251 | 1346 | int c = cppGetcFromUngetBufferOrFile (); |
| 1347 | + int c0 = 0; |
| 1348 | + vString *line = NULL; |
| 1349 | + bool sentThe1stLine = false; |
| 1350 | + cPreProcessorSubparser *sub = NULL; |
| 1351 | + |
| 1352 | + |
| 1353 | + if (isDocCommentStarter (c)) |
| 1354 | + { |
| 1355 | + c0 = c; |
| 1356 | + c = cppGetcFromUngetBufferOrFile (); |
| 1357 | + if (c0 == '*' && c == '/') |
| 1358 | + return SPACE; |
| 1359 | + cppUngetc (c); |
| 1360 | + c = c0; |
| 1361 | + line = vStringNew (); |
| 1362 | + } |
1252 | 1363 |
|
1253 | 1364 | while (c != EOF) |
1254 | 1365 | { |
1255 | | - if (c != '*') |
1256 | | - c = cppGetcFromUngetBufferOrFile (); |
1257 | | - else |
| 1366 | + if (c == '*') |
1258 | 1367 | { |
1259 | 1368 | const int next = cppGetcFromUngetBufferOrFile (); |
1260 | 1369 |
|
1261 | | - if (next != '/') |
1262 | | - c = next; |
1263 | | - else |
| 1370 | + if (next == '/') |
1264 | 1371 | { |
1265 | 1372 | c = SPACE; /* replace comment with space */ |
1266 | 1373 | break; |
1267 | 1374 | } |
| 1375 | + cppUngetc (next); |
1268 | 1376 | } |
| 1377 | + |
| 1378 | + if (line) |
| 1379 | + { |
| 1380 | + vStringPut (line, c); |
| 1381 | + if (c == '\n') |
| 1382 | + { |
| 1383 | + if (sub || !isWhitespaceOnly (line)) |
| 1384 | + sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine); |
| 1385 | + vStringClear (line); |
| 1386 | + } |
| 1387 | + } |
| 1388 | + c = cppGetcFromUngetBufferOrFile (); |
1269 | 1389 | } |
| 1390 | + |
| 1391 | + if (line && !vStringIsEmpty(line) && (sub || !isWhitespaceOnly (line))) |
| 1392 | + sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine); |
| 1393 | + |
| 1394 | + if (sub) |
| 1395 | + notifyEndOfComment (sub); |
| 1396 | + |
| 1397 | + vStringDelete (line); /* NULL is acceptable */ |
1270 | 1398 | return c; |
1271 | 1399 | } |
1272 | 1400 |
|
|
0 commit comments