1 /*
2 * Copyright (c) 2021, Masatake YAMATO
3 * Copyright (c) 2021, Red Hat, Inc.
4 *
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License version 2 or (at your option) any later version.
7 *
8 * This module contains functions for generating tags for Function::Parameters perl extension.
9 * https://metacpan.org/pod/Function::Parameters
10 *
11 * This parser is inspired by the pull request submitted by Jim Butler (@jimmygoogle).
12 */
13
14 /*
15 * INCLUDE FILES
16 */
17 #include "general.h" /* must always come first */
18
19 #include "entry.h"
20 #include "kind.h"
21 #include "parse.h"
22 #include "perl.h"
23
24 #include <string.h>
25
26 /*
27 * DATA DECLARATIONS
28 */
29
30 enum FParamsKind {
31 K_METHOD,
32 K_FUN,
33 };
34
35 static kindDefinition FParamsKinds[] = {
36 { true, 'm', "method", "methods" },
37 { true, 'f', "fun", "functions" },
38 };
39
40 struct FParamsSubparser {
41 perlSubparser perl;
42 bool notInFParams;
43 bool inPod;
44 };
45
46 /*
47 * FUNCTION PROTOTYPES
48 */
49
50 static void inputStart (subparser *s);
51 static void makeTagEntryNotify (subparser *s, const tagEntryInfo *tag, int corkIndex);
52 static void enterFParams (struct FParamsSubparser *fparms);
53 static void leaveFParams (struct FParamsSubparser *fparams);
54 static void enteringPodNotify (perlSubparser *perl);
55 static void leavingPodNotify (perlSubparser *perl);
56
57 /*
58 * DATA DEFINITIONS
59 */
60
61 static struct FParamsSubparser fparamsSubparser = {
62 .perl = {
63 .subparser = {
64 .direction = SUBPARSER_BI_DIRECTION,
65 .inputStart = inputStart,
66 .makeTagEntryNotify = makeTagEntryNotify,
67 },
68 .enteringPodNotify = enteringPodNotify,
69 .leavingPodNotify = leavingPodNotify,
70 }
71 };
72
73 /*
74 * FUNCTION DEFINITIONS
75 */
76
inputStart(subparser * s)77 static void inputStart (subparser *s)
78 {
79 struct FParamsSubparser *fparams = (struct FParamsSubparser *)s;
80
81 fparams->notInFParams = true;
82 fparams->inPod = false;
83 }
84
makeTagEntryNotify(subparser * s,const tagEntryInfo * tag,int corkIndex)85 static void makeTagEntryNotify (subparser *s, const tagEntryInfo *tag, int corkIndex)
86 {
87 perlSubparser *perl = (perlSubparser *)s;
88 struct FParamsSubparser *fparams = (struct FParamsSubparser *)perl;
89
90 if (isTagExtraBitMarked(tag, XTAG_QUALIFIED_TAGS))
91 return;
92
93 if (tag->kindIndex == KIND_PERL_MODULE)
94 {
95 if (isRoleAssigned(tag, ROLE_PERL_MODULE_USED)
96 && strcmp (tag->name, "Function::Parameters") == 0)
97 enterFParams (fparams);
98 else if (isRoleAssigned(tag, ROLE_PERL_MODULE_UNUSED)
99 && strcmp (tag->name, "Function::Parameters") == 0)
100 leaveFParams (fparams);
101 }
102 }
103
enterFParams(struct FParamsSubparser * fparams)104 static void enterFParams (struct FParamsSubparser *fparams)
105 {
106 fparams->notInFParams = false;
107 }
108
leaveFParams(struct FParamsSubparser * fparams)109 static void leaveFParams (struct FParamsSubparser *fparams)
110 {
111 fparams->notInFParams = true;
112 }
113
enteringPodNotify(perlSubparser * perl)114 static void enteringPodNotify (perlSubparser *perl)
115 {
116 struct FParamsSubparser *fparams = (struct FParamsSubparser *)perl;
117 fparams->inPod = true;
118 }
119
leavingPodNotify(perlSubparser * perl)120 static void leavingPodNotify (perlSubparser *perl)
121 {
122 struct FParamsSubparser *fparams = (struct FParamsSubparser *)perl;
123 fparams->inPod = false;
124 }
125
findFParamsObject(const char * line,const regexMatch * matches,unsigned int count,void * userData)126 static bool findFParamsObject (const char * line, const regexMatch *matches, unsigned int count,
127 void *userData)
128 {
129 struct FParamsSubparser *fparams = (struct FParamsSubparser *)userData;
130
131 if (fparams->inPod)
132 return false;
133
134
135 const char *kindHint = line + matches[1].start;
136 int kind = kindHint [0] == 'm'? K_METHOD: K_FUN;
137
138 char *name = eStrndup (line + matches[2].start, matches[2].length);
139 tagEntryInfo e;
140 initTagEntry (&e, name, kind);
141
142 makeTagEntry (&e);
143 eFree (name);
144 return true;
145 }
146
findFParamsTags(void)147 static void findFParamsTags (void)
148 {
149 scheduleRunningBaseparser (RUN_DEFAULT_SUBPARSERS);
150 }
151
initializeFParamsParser(langType language)152 static void initializeFParamsParser (langType language)
153 {
154 addLanguageCallbackRegex (language, "^[ \t]*(method|fun)[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*\\(",
155 NULL,
156 findFParamsObject, &fparamsSubparser.notInFParams,
157 &fparamsSubparser);
158 }
159
FunctionParametersParser(void)160 extern parserDefinition* FunctionParametersParser (void)
161 {
162 parserDefinition* const def = parserNew("FunctionParameters");
163
164 static parserDependency dependencies [] = {
165 [0] = { DEPTYPE_SUBPARSER, "Perl", &fparamsSubparser },
166 };
167
168 def->dependencies = dependencies;
169 def->dependencyCount = ARRAY_SIZE (dependencies);
170
171 def->kindTable = FParamsKinds;
172 def->kindCount = ARRAY_SIZE(FParamsKinds);
173
174 def->initialize = initializeFParamsParser;
175 def->parser = findFParamsTags;
176
177 return def;
178 }
179