Skip to content

Commit 1a19c77

Browse files
committed
CPreProcessor: run subparsers for extrating interesting language objects in C comments
TODO: revise Tmain/optscript-preludes-stack.d/stderr-expected.txt
1 parent 4e11202 commit 1a19c77

File tree

4 files changed

+153
-8
lines changed

4 files changed

+153
-8
lines changed

Tmain/optscript-preludes-stack.d/stderr-expected.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@
2121
ctags: Warning: Because of an internal limitation, Making a sub parser based on the CPreProcessor parser is not allowed: CPreProcessor
2222
ctags: Warning: Because of an internal limitation, Making a sub parser based on the CPreProcessor parser is not allowed: CPreProcessor
2323
(enter CPreProcessor)
24+
(enter CPreProcessor)
25+
(leave CPreProcessor)
2426
(leave CPreProcessor)

main/parse.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4030,7 +4030,8 @@ static unsigned int parserCorkFlags (parserDefinition *parser)
40304030
return r;
40314031
}
40324032

4033-
static void setupLanguageSubparsersInUse (const langType language)
4033+
/* NOTE: Exported only for CPreProcessor */
4034+
extern void setupLanguageSubparsersInUse (const langType language)
40344035
{
40354036
subparser *tmp;
40364037

@@ -4044,7 +4045,8 @@ static void setupLanguageSubparsersInUse (const langType language)
40444045
}
40454046
}
40464047

4047-
static subparser* teardownLanguageSubparsersInUse (const langType language)
4048+
/* NOTE: Exported only for CPreProcessor */
4049+
extern subparser* teardownLanguageSubparsersInUse (const langType language)
40484050
{
40494051
subparser *tmp;
40504052

parsers/cpreprocessor.c

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "general.h" /* must always come first */
1515

1616
#include <string.h>
17+
#include <ctype.h>
1718

1819
#include "debug.h"
1920
#include "entry.h"
@@ -30,6 +31,14 @@
3031

3132
#include "cxx/cxx_debug.h"
3233

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+
3342
/*
3443
* MACROS
3544
*/
@@ -296,6 +305,9 @@ static void cppInitCommon(langType clientLang,
296305
t = getNamedLanguage ("CPreProcessor", 0);
297306
initializeParser (t);
298307
}
308+
pushLanguage(Cpp.lang);
309+
setupLanguageSubparsersInUse (Cpp.lang);
310+
popLanguage();
299311

300312
Cpp.clientLang = clientLang;
301313
Cpp.ungetBuffer = NULL;
@@ -377,6 +389,10 @@ static void cppInitCommon(langType clientLang,
377389
: clientLang) & CORK_SYMTAB))
378390
? makeMacroTable ()
379391
: NULL;
392+
393+
pushLanguage(Cpp.lang);
394+
notifyInputStart ();
395+
popLanguage();
380396
}
381397

382398
extern void cppInit (const bool state, const bool hasAtLiteralStrings,
@@ -412,6 +428,10 @@ static void cppClearMacroInUse (cppMacroInfo **pM)
412428

413429
extern void cppTerminate (void)
414430
{
431+
pushLanguage(Cpp.lang);
432+
notifyInputEnd ();
433+
popLanguage();
434+
415435
if (Cpp.directive.name != NULL)
416436
{
417437
vStringDelete (Cpp.directive.name);
@@ -439,6 +459,9 @@ extern void cppTerminate (void)
439459
hashTableDelete (Cpp.fileMacroTable);
440460
Cpp.fileMacroTable = NULL;
441461
}
462+
pushLanguage(Cpp.lang);
463+
teardownLanguageSubparsersInUse (Cpp.lang);
464+
popLanguage();
442465
}
443466

444467
extern void cppBeginStatement (void)
@@ -1243,30 +1266,135 @@ static Comment isComment (void)
12431266
return comment;
12441267
}
12451268

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+
12461339
/* Skips over a C style comment. According to ANSI specification a comment
12471340
* is treated as white space, so we perform this substitution.
1341+
*
1342+
* As side effects, running subparsers interested in comments.
12481343
*/
12491344
static int cppSkipOverCComment (void)
12501345
{
12511346
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+
}
12521363

12531364
while (c != EOF)
12541365
{
1255-
if (c != '*')
1256-
c = cppGetcFromUngetBufferOrFile ();
1257-
else
1366+
if (c == '*')
12581367
{
12591368
const int next = cppGetcFromUngetBufferOrFile ();
12601369

1261-
if (next != '/')
1262-
c = next;
1263-
else
1370+
if (next == '/')
12641371
{
12651372
c = SPACE; /* replace comment with space */
12661373
break;
12671374
}
1375+
cppUngetc (next);
12681376
}
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 ();
12691389
}
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 */
12701398
return c;
12711399
}
12721400

parsers/cpreprocessor.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "types.h"
1818
#include "vstring.h"
1919

20+
#include "subparser.h"
21+
2022
/*
2123
* MACROS
2224
*/
@@ -144,4 +146,15 @@ extern void cppBuildMacroReplacementWithPtrArrayAndUngetResult(
144146
cppMacroInfo * macro,
145147
const ptrArray * args);
146148

149+
/* Running a parser inside comments. */
150+
typedef struct sCPreProcessorSubparser cPreProcessorSubparser;
151+
152+
struct sCPreProcessorSubparser {
153+
subparser subparser;
154+
155+
bool (* firstLineNotify) (cPreProcessorSubparser *s, char firstchar, const char *line);
156+
void (* restLineNotify) (cPreProcessorSubparser *s, const char *line);
157+
void (* endOfCommentNotify) (cPreProcessorSubparser *s);
158+
};
159+
147160
#endif /* CTAGS_MAIN_GET_H */

0 commit comments

Comments
 (0)