1 /*
2 *
3 * Copyright (c) 2016, Red Hat, Inc.
4 * Copyright (c) 2016, Masatake YAMATO
5 *
6 * Author: Masatake YAMATO <yamato@redhat.com>
7 *
8 * This source code is released for free distribution under the terms of the
9 * GNU General Public License version 2 or (at your option) any later version.
10 *
11 */
12
13 #include "general.h" /* must always come first */
14
15 #include "debug.h"
16 #include "dependency.h"
17 #include "options.h"
18 #include "parse_p.h"
19 #include "read.h"
20 #include "read_p.h"
21 #include "routines.h"
22 #include "subparser.h"
23 #include "subparser_p.h"
24 #include "xtag.h"
25
26 #include <string.h>
27
28 struct slaveControlBlock {
29 slaveParser *slaveParsers; /* The parsers on this list must be initialized when
30 this parser is initialized. */
31 subparser *subparsersDefault;
32 subparser *subparsersInUse;
33 langType owner;
34 };
35
linkDependencyAtInitializeParsing(depType dtype,parserDefinition * const master,struct slaveControlBlock * masterSCB,struct kindControlBlock * masterKCB,parserDefinition * const slave,struct kindControlBlock * slaveKCB,void * data)36 extern void linkDependencyAtInitializeParsing (depType dtype,
37 parserDefinition *const master,
38 struct slaveControlBlock *masterSCB,
39 struct kindControlBlock *masterKCB,
40 parserDefinition *const slave,
41 struct kindControlBlock *slaveKCB,
42 void *data)
43 {
44 if (dtype == DEPTYPE_KIND_OWNER)
45 linkKindDependency (masterKCB, slaveKCB);
46 else if (dtype == DEPTYPE_SUBPARSER || dtype == DEPTYPE_FOREIGNER)
47 {
48 slaveParser *s = xMalloc (1, slaveParser);
49
50 s->type = dtype;
51 s->id = slave->id;
52 s->data = data;
53
54 s->next = masterSCB->slaveParsers;
55 masterSCB->slaveParsers = s;
56 }
57 }
58
attachSubparser(struct slaveControlBlock * base_sb,subparser * subparser)59 static void attachSubparser (struct slaveControlBlock *base_sb, subparser *subparser)
60 {
61 subparser->next = base_sb->subparsersDefault;
62 base_sb->subparsersDefault = subparser;
63 }
64
65
allocSlaveControlBlock(parserDefinition * parser)66 extern struct slaveControlBlock *allocSlaveControlBlock (parserDefinition *parser)
67 {
68 struct slaveControlBlock *cb;
69
70 cb = xMalloc (1, struct slaveControlBlock);
71 cb->slaveParsers = NULL;
72 cb->subparsersDefault = NULL;
73 cb->subparsersInUse = NULL;
74 cb->owner = parser->id;
75
76 return cb;
77 }
78
freeSlaveControlBlock(struct slaveControlBlock * cb)79 extern void freeSlaveControlBlock (struct slaveControlBlock *cb)
80 {
81 eFree (cb);
82 }
83
initializeDependencies(parserDefinition * parser,struct slaveControlBlock * cb)84 extern void initializeDependencies (parserDefinition *parser,
85 struct slaveControlBlock *cb)
86 {
87 unsigned int i;
88 slaveParser *sp;
89
90 /* Initialize slaves */
91 sp = cb->slaveParsers;
92 while (sp != NULL)
93 {
94 if (sp->type == DEPTYPE_SUBPARSER)
95 {
96 subparser *sub;
97
98 sub = (subparser *)sp->data;
99 sub->slaveParser = sp;
100 }
101
102 if (sp->type == DEPTYPE_KIND_OWNER
103 || (sp->type == DEPTYPE_SUBPARSER &&
104 (((subparser *)sp->data)->direction & SUBPARSER_BASE_RUNS_SUB)))
105 {
106 initializeParser (sp->id);
107 if (sp->type == DEPTYPE_SUBPARSER
108 && isXtagEnabled (XTAG_SUBPARSER))
109 {
110 subparser *subparser = sp->data;
111 attachSubparser (cb, subparser);
112 }
113 }
114 sp = sp->next;
115 }
116
117 /* Initialize masters that act as base parsers. */
118 for (i = 0; i < parser->dependencyCount; i++)
119 {
120 parserDependency *d = parser->dependencies + i;
121 if ((d->type == DEPTYPE_SUBPARSER &&
122 ((subparser *)(d->data))->direction & SUBPARSER_SUB_RUNS_BASE)
123 || (d->type == DEPTYPE_FOREIGNER))
124 {
125 langType baseParser;
126 baseParser = getNamedLanguage (d->upperParser, 0);
127 Assert (baseParser != LANG_IGNORE);
128 initializeParser (baseParser);
129 }
130 }
131 }
132
finalizeDependencies(parserDefinition * parser,struct slaveControlBlock * cb)133 extern void finalizeDependencies (parserDefinition *parser,
134 struct slaveControlBlock *cb)
135 {
136 while (cb->slaveParsers)
137 {
138 slaveParser *sp = cb->slaveParsers;
139 cb->slaveParsers = sp->next;
140 sp->next = NULL;
141 eFree (sp);
142 }
143 }
144
notifyInputStart(void)145 extern void notifyInputStart (void)
146 {
147 subparser *s;
148
149 /* for running prelude of optlib */
150 langType lang = getInputLanguage ();
151 notifyLanguageRegexInputStart (lang);
152
153 foreachSubparser(s, true)
154 {
155 enterSubparser(s);
156 if (s->inputStart)
157 s->inputStart (s);
158 /* propagate the event recursively */
159 notifyInputStart ();
160 leaveSubparser();
161 }
162 }
163
notifyInputEnd(void)164 extern void notifyInputEnd (void)
165 {
166 subparser *s;
167
168 foreachSubparser(s, true)
169 {
170 enterSubparser(s);
171 /* propagate the event recursively */
172 notifyInputEnd ();
173 if (s->inputEnd)
174 s->inputEnd (s);
175 leaveSubparser();
176 }
177
178 /* for running sequel of optlib */
179 langType lang = getInputLanguage ();
180 notifyLanguageRegexInputEnd (lang);
181 }
182
notifyMakeTagEntry(const tagEntryInfo * tag,int corkIndex)183 extern void notifyMakeTagEntry (const tagEntryInfo *tag, int corkIndex)
184 {
185 subparser *s;
186
187 foreachSubparser(s, false)
188 {
189 if (s->makeTagEntryNotify)
190 {
191 enterSubparser(s);
192 s->makeTagEntryNotify (s, tag, corkIndex);
193 leaveSubparser();
194 }
195 }
196 }
197
getSubparserLanguage(subparser * s)198 extern langType getSubparserLanguage (subparser *s)
199 {
200 return s->slaveParser->id;
201 }
202
chooseExclusiveSubparser(subparser * s,void * data)203 extern void chooseExclusiveSubparser (subparser *s, void *data)
204 {
205 if (s->exclusiveSubparserChosenNotify)
206 {
207 s->chosenAsExclusiveSubparser = true;
208 enterSubparser(s);
209 s->exclusiveSubparserChosenNotify (s, data);
210 verbose ("%s is chosen as exclusive subparser\n",
211 getLanguageName (getSubparserLanguage (s)));
212 leaveSubparser();
213 }
214 }
215
getFirstSubparser(struct slaveControlBlock * controlBlock)216 extern subparser *getFirstSubparser(struct slaveControlBlock *controlBlock)
217 {
218 if (controlBlock)
219 return controlBlock->subparsersInUse;
220 return NULL;
221 }
222
useDefaultSubparsers(struct slaveControlBlock * controlBlock)223 extern void useDefaultSubparsers (struct slaveControlBlock *controlBlock)
224 {
225 controlBlock->subparsersInUse = controlBlock->subparsersDefault;
226 }
227
useSpecifiedSubparser(struct slaveControlBlock * controlBlock,subparser * s)228 extern void useSpecifiedSubparser (struct slaveControlBlock *controlBlock, subparser *s)
229 {
230 s->schedulingBaseparserExplicitly = true;
231 controlBlock->subparsersInUse = s;
232 }
233
setupSubparsersInUse(struct slaveControlBlock * controlBlock)234 extern void setupSubparsersInUse (struct slaveControlBlock *controlBlock)
235 {
236 if (!controlBlock->subparsersInUse)
237 useDefaultSubparsers(controlBlock);
238 }
239
teardownSubparsersInUse(struct slaveControlBlock * controlBlock)240 extern subparser* teardownSubparsersInUse (struct slaveControlBlock *controlBlock)
241 {
242 subparser *tmp;
243 subparser *s = NULL;
244
245 tmp = controlBlock->subparsersInUse;
246 controlBlock->subparsersInUse = NULL;
247
248 if (tmp && tmp->schedulingBaseparserExplicitly)
249 {
250 tmp->schedulingBaseparserExplicitly = false;
251 s = tmp;
252 }
253
254 if (s)
255 return s;
256
257 while (tmp)
258 {
259 if (tmp->chosenAsExclusiveSubparser)
260 {
261 s = tmp;
262 }
263 tmp = tmp->next;
264 }
265
266 return s;
267 }
268
269
270 static int subparserDepth;
271
enterSubparser(subparser * subparser)272 extern void enterSubparser(subparser *subparser)
273 {
274 subparserDepth++;
275 pushLanguage (getSubparserLanguage (subparser));
276 }
277
leaveSubparser(void)278 extern void leaveSubparser(void)
279 {
280 popLanguage ();
281 subparserDepth--;
282 }
283
doesSubparserRun(void)284 extern bool doesSubparserRun (void)
285 {
286 if (getLanguageForBaseParser () == getInputLanguage())
287 return false;
288 return subparserDepth;
289 }
290
getFirstSlaveParser(struct slaveControlBlock * scb)291 extern slaveParser *getFirstSlaveParser (struct slaveControlBlock *scb)
292 {
293 if (scb)
294 return scb->slaveParsers;
295 return NULL;
296 }
297
getLanguageSubparser(langType sublang,bool including_none_crafted_parser)298 extern subparser *getLanguageSubparser (langType sublang,
299 bool including_none_crafted_parser)
300 {
301 subparser *s;
302
303 foreachSubparser (s, including_none_crafted_parser)
304 {
305 if (getSubparserLanguage (s) == sublang)
306 return s;
307 }
308 return NULL;
309 }
310
subparserColprintTableNew(void)311 extern struct colprintTable * subparserColprintTableNew (void)
312 {
313 return colprintTableNew ("L:NAME", "L:BASEPARSER", "L:DIRECTIONS", NULL);
314 }
315
subparserColprintAddSubparsers(struct colprintTable * table,struct slaveControlBlock * scb)316 extern void subparserColprintAddSubparsers (struct colprintTable *table,
317 struct slaveControlBlock *scb)
318 {
319 slaveParser *tmp;
320
321 pushLanguage (scb->owner);
322 foreachSlaveParser(tmp)
323 {
324 if (tmp->type != DEPTYPE_SUBPARSER)
325 continue;
326
327 if (!isLanguageVisible (tmp->id))
328 continue;
329
330 struct colprintLine *line = colprintTableGetNewLine(table);
331
332 colprintLineAppendColumnCString (line, getLanguageName (tmp->id));
333 colprintLineAppendColumnCString (line, getLanguageName (scb->owner));
334
335 const char *direction;
336 switch (((subparser *)tmp->data)->direction)
337 {
338 case SUBPARSER_BASE_RUNS_SUB:
339 direction = "base => sub {shared}";
340 break;
341 case SUBPARSER_SUB_RUNS_BASE:
342 direction = "base <= sub {dedicated}";
343 break;
344 case SUBPARSER_BI_DIRECTION:
345 direction = "base <> sub {bidirectional}";
346 break;
347 default:
348 direction = "UNKNOWN(INTERNAL BUG)";
349 break;
350 }
351 colprintLineAppendColumnCString (line, direction);
352 }
353 popLanguage ();
354 }
355
subparserColprintCompareLines(struct colprintLine * a,struct colprintLine * b)356 static int subparserColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
357 {
358 const char *a_name = colprintLineGetColumn (a, 0);
359 const char *b_name = colprintLineGetColumn (b, 0);
360
361 int r;
362 r = strcmp (a_name, b_name);
363 if (r != 0)
364 return r;
365
366 const char *a_baseparser = colprintLineGetColumn (a, 1);
367 const char *b_baseparser = colprintLineGetColumn (b, 1);
368
369 return strcmp(a_baseparser, b_baseparser);
370 }
371
subparserColprintTablePrint(struct colprintTable * table,bool withListHeader,bool machinable,FILE * fp)372 extern void subparserColprintTablePrint (struct colprintTable *table,
373 bool withListHeader, bool machinable, FILE *fp)
374 {
375 colprintTableSort (table, subparserColprintCompareLines);
376 colprintTablePrint (table, 0, withListHeader, machinable, fp);
377 }
378