Skip to content

Commit b086da7

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 6b06565 commit b086da7

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
@@ -4089,7 +4089,8 @@ static unsigned int parserCorkFlags (parserDefinition *parser)
40894089
return r;
40904090
}
40914091

4092-
static void setupLanguageSubparsersInUse (const langType language)
4092+
/* NOTE: Exported only for CPreProcessor */
4093+
extern void setupLanguageSubparsersInUse (const langType language)
40934094
{
40944095
subparser *tmp;
40954096

@@ -4103,7 +4104,8 @@ static void setupLanguageSubparsersInUse (const langType language)
41034104
}
41044105
}
41054106

4106-
static subparser* teardownLanguageSubparsersInUse (const langType language)
4107+
/* NOTE: Exported only for CPreProcessor */
4108+
extern subparser* teardownLanguageSubparsersInUse (const langType language)
41074109
{
41084110
subparser *tmp;
41094111

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)
@@ -1248,30 +1271,135 @@ static Comment isComment (void)
12481271
return comment;
12491272
}
12501273

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+
12511344
/* Skips over a C style comment. According to ANSI specification a comment
12521345
* is treated as white space, so we perform this substitution.
1346+
*
1347+
* As side effects, running subparsers interested in comments.
12531348
*/
12541349
static int cppSkipOverCComment (void)
12551350
{
12561351
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+
}
12571368

12581369
while (c != EOF)
12591370
{
1260-
if (c != '*')
1261-
c = cppGetcFromUngetBufferOrFile ();
1262-
else
1371+
if (c == '*')
12631372
{
12641373
const int next = cppGetcFromUngetBufferOrFile ();
12651374

1266-
if (next != '/')
1267-
c = next;
1268-
else
1375+
if (next == '/')
12691376
{
12701377
c = SPACE; /* replace comment with space */
12711378
break;
12721379
}
1380+
cppUngetc (next);
12731381
}
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 ();
12741394
}
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 */
12751403
return c;
12761404
}
12771405

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)