1d4c6f1e6SMasatake YAMATO /*
2d4c6f1e6SMasatake YAMATO * Copyright (c) 1996-2003, Darren Hiebert
3d4c6f1e6SMasatake YAMATO *
4d4c6f1e6SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
6d4c6f1e6SMasatake YAMATO *
7d316cd59SMasatake YAMATO * This module contains functions for managing input languages and
8d4c6f1e6SMasatake YAMATO * dispatching files to the appropriate language parser.
9d4c6f1e6SMasatake YAMATO */
10d4c6f1e6SMasatake YAMATO
11d4c6f1e6SMasatake YAMATO /*
12d4c6f1e6SMasatake YAMATO * INCLUDE FILES
13d4c6f1e6SMasatake YAMATO */
14d4c6f1e6SMasatake YAMATO #include "general.h" /* must always come first */
15d4c6f1e6SMasatake YAMATO
1621996d92SMasatake YAMATO /* TODO: This definition should be removed. */
1721996d92SMasatake YAMATO #define OPTION_WRITE
1821996d92SMasatake YAMATO #include "options_p.h"
1921996d92SMasatake YAMATO
20d4c6f1e6SMasatake YAMATO #include <string.h>
21d4c6f1e6SMasatake YAMATO
22db2bf481SMasatake YAMATO #include "ctags.h"
23d4c6f1e6SMasatake YAMATO #include "debug.h"
248cbf052bSMasatake YAMATO #include "entry_p.h"
25c08c70d0SMasatake YAMATO #include "field_p.h"
26bf281e9cSMasatake YAMATO #include "flags_p.h"
27f140c7c3SMasatake YAMATO #include "htable.h"
28c379c5d2SMasatake YAMATO #include "keyword.h"
29ec40f18bSMasatake YAMATO #include "lxpath_p.h"
300d502ef0SMasatake YAMATO #include "param.h"
3199ac24f8SMasatake YAMATO #include "param_p.h"
320d502ef0SMasatake YAMATO #include "parse_p.h"
3315c69d21SMasatake YAMATO #include "parsers_p.h"
344fa68e36SMasatake YAMATO #include "promise.h"
35e3416868SMasatake YAMATO #include "promise_p.h"
360d81da14SMasatake YAMATO #include "ptag_p.h"
373c91b1eaSMasatake YAMATO #include "ptrarray.h"
38d4c6f1e6SMasatake YAMATO #include "read.h"
39b5df137eSMasatake YAMATO #include "read_p.h"
40d4c6f1e6SMasatake YAMATO #include "routines.h"
4129e40fb6SMasatake YAMATO #include "routines_p.h"
42df2449f1SMasatake YAMATO #include "stats_p.h"
43a53e10d8SMasatake YAMATO #include "subparser.h"
44bc924efdSMasatake YAMATO #include "subparser_p.h"
45d33423e3SSzymon Tomasz Stefanek #include "trace.h"
466749a76eSMasatake YAMATO #include "trashbox.h"
47869a1bbcSMasatake YAMATO #include "trashbox_p.h"
48d4c6f1e6SMasatake YAMATO #include "vstring.h"
492acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
50f38d6693SMasatake YAMATO # include "mbcs_p.h"
512acdcfa1SYasuhiro Matsumoto #endif
5267d1f12fSJiří Techet #include "writer_p.h"
53e2a3289bSMasatake YAMATO #include "xtag_p.h"
54d4c6f1e6SMasatake YAMATO
55d4c6f1e6SMasatake YAMATO /*
5695512ba5SMasatake YAMATO * DATA TYPES
5795512ba5SMasatake YAMATO */
5895512ba5SMasatake YAMATO enum specType {
5995512ba5SMasatake YAMATO SPEC_NONE,
6095512ba5SMasatake YAMATO SPEC_NAME,
6195512ba5SMasatake YAMATO SPEC_ALIAS = SPEC_NAME,
6295512ba5SMasatake YAMATO SPEC_EXTENSION,
6395512ba5SMasatake YAMATO SPEC_PATTERN,
6495512ba5SMasatake YAMATO };
6595512ba5SMasatake YAMATO const char *specTypeName [] = {
6695512ba5SMasatake YAMATO "none", "name", "extension", "pattern"
6795512ba5SMasatake YAMATO };
6895512ba5SMasatake YAMATO
6995512ba5SMasatake YAMATO typedef struct {
7095512ba5SMasatake YAMATO langType lang;
7195512ba5SMasatake YAMATO const char* spec;
7295512ba5SMasatake YAMATO enum specType specType;
7395512ba5SMasatake YAMATO } parserCandidate;
7495512ba5SMasatake YAMATO
75e02be843SMasatake YAMATO typedef struct sParserObject {
76e02be843SMasatake YAMATO parserDefinition *def;
77efe089d4SMasatake YAMATO
78b29ae60fSMasatake YAMATO kindDefinition* fileKind;
79b29ae60fSMasatake YAMATO
80efe089d4SMasatake YAMATO stringList* currentPatterns; /* current list of file name patterns */
81efe089d4SMasatake YAMATO stringList* currentExtensions; /* current list of extensions */
82efe089d4SMasatake YAMATO stringList* currentAliases; /* current list of aliases */
83efe089d4SMasatake YAMATO
84e61266e4SMasatake YAMATO unsigned int initialized:1; /* initialize() is called or not */
85bf013ea8SMasatake YAMATO unsigned int dontEmit:1; /* run but don't emit tags.
86bf013ea8SMasatake YAMATO This parser was disabled but a subparser on
87bf013ea8SMasatake YAMATO this parser makes this parser run (to drive
88bf013ea8SMasatake YAMATO the subparser). */
898df191b2SMasatake YAMATO unsigned int pseudoTagPrinted:1; /* pseudo tags about this parser
908df191b2SMasatake YAMATO is emitted or not. */
91a9c91f4dSMasatake YAMATO unsigned int used; /* Used for printing language specific statistics. */
92e61266e4SMasatake YAMATO
9397a77b13SMasatake YAMATO unsigned int anonymousIdentiferId; /* managed by anon* functions */
94faa60990SMasatake YAMATO
95edc12faeSMasatake YAMATO struct slaveControlBlock *slaveControlBlock;
967bef4da4SMasatake YAMATO struct kindControlBlock *kindControlBlock;
97bce55cc7SMasatake YAMATO struct lregexControlBlock *lregexControlBlock;
98f02166dcSMasatake YAMATO
99f02166dcSMasatake YAMATO langType pretendingAsLanguage; /* OLDLANG in --_pretend-<NEWLANG>=<OLDLANG>
100f02166dcSMasatake YAMATO is set here if this parser is NEWLANG.
101f02166dcSMasatake YAMATO LANG_IGNORE is set if no pretending. */
102f02166dcSMasatake YAMATO langType pretendedAsLanguage; /* NEWLANG in --_pretend-<NEWLANG>=<OLDLANG>
103f02166dcSMasatake YAMATO is set here if this parser is OLDLANG.
104f02166dcSMasatake YAMATO LANG_IGNORE is set if no being pretended. */
105f02166dcSMasatake YAMATO
106e02be843SMasatake YAMATO } parserObject;
107e02be843SMasatake YAMATO
10895512ba5SMasatake YAMATO /*
10903270f1eSMasatake YAMATO * FUNCTION PROTOTYPES
11003270f1eSMasatake YAMATO */
111ad1a3891SMasatake YAMATO
112d0471042SMasatake YAMATO static void lazyInitialize (langType language);
113bc1a5e1bSMasatake YAMATO static void addParserPseudoTags (langType language);
114d453869fSMasatake YAMATO static void installKeywordTable (const langType language);
115d453869fSMasatake YAMATO static void installTagRegexTable (const langType language);
116d453869fSMasatake YAMATO static void installTagXpathTable (const langType language);
11797a77b13SMasatake YAMATO static void anonResetMaybe (parserObject *parser);
11887b7bfceSMasatake YAMATO static void setupAnon (void);
11987b7bfceSMasatake YAMATO static void teardownAnon (void);
120eb480042SMasatake YAMATO static void uninstallTagXpathTable (const langType language);
12103270f1eSMasatake YAMATO
12203270f1eSMasatake YAMATO /*
123d4c6f1e6SMasatake YAMATO * DATA DEFINITIONS
124d4c6f1e6SMasatake YAMATO */
12582791c20SMasatake YAMATO static parserDefinition *FallbackParser (void);
126b9636b4dSMasatake YAMATO static parserDefinition *CTagsParser (void);
1270435a2b5SMasatake YAMATO static parserDefinition *CTagsSelfTestParser (void);
1280435a2b5SMasatake YAMATO static parserDefinitionFunc* BuiltInParsers[] = {
12978d1a3f3SJiří Techet #ifdef EXTERNAL_PARSER_LIST
13078d1a3f3SJiří Techet EXTERNAL_PARSER_LIST
13178d1a3f3SJiří Techet #else /* ! EXTERNAL_PARSER_LIST */
13221153b4dSJiří Techet CTagsParser, /* This must be first entry. */
13321153b4dSJiří Techet FallbackParser, /* LANG_FALLBACK */
13421153b4dSJiří Techet CTagsSelfTestParser,
13582791c20SMasatake YAMATO
136a086aff1SMasatake YAMATO PARSER_LIST,
137a086aff1SMasatake YAMATO XML_PARSER_LIST
138288cd67dSMasatake YAMATO #ifdef HAVE_LIBXML
139288cd67dSMasatake YAMATO ,
140288cd67dSMasatake YAMATO #endif
141288cd67dSMasatake YAMATO YAML_PARSER_LIST
142288cd67dSMasatake YAMATO #ifdef HAVE_LIBYAML
143288cd67dSMasatake YAMATO ,
144288cd67dSMasatake YAMATO #endif
1450c014297SMasatake YAMATO PEG_PARSER_LIST
1460c014297SMasatake YAMATO #ifdef HAVE_PACKCC
1470c014297SMasatake YAMATO ,
1480c014297SMasatake YAMATO #endif
149*d876d176SMasatake YAMATO OPTLIB2C_PCRE2_PARSER_LIST
150*d876d176SMasatake YAMATO #ifdef HAVE_PCRE2
151*d876d176SMasatake YAMATO ,
152*d876d176SMasatake YAMATO #endif
15378d1a3f3SJiří Techet #endif /* EXTERNAL_PARSER_LIST */
1540435a2b5SMasatake YAMATO };
155e02be843SMasatake YAMATO static parserObject* LanguageTable = NULL;
156d4c6f1e6SMasatake YAMATO static unsigned int LanguageCount = 0;
157f140c7c3SMasatake YAMATO static hashTable* LanguageHTable = NULL;
158e112e8abSMasatake YAMATO static kindDefinition defaultFileKind = {
159ce990805SThomas Braun .enabled = false,
1607e1bd430SMasatake YAMATO .letter = KIND_FILE_DEFAULT_LETTER,
1617e1bd430SMasatake YAMATO .name = KIND_FILE_DEFAULT_NAME,
1627e1bd430SMasatake YAMATO .description = KIND_FILE_DEFAULT_NAME,
1636ed0ba68SMasatake YAMATO };
164d4c6f1e6SMasatake YAMATO
165d4c6f1e6SMasatake YAMATO /*
166d4c6f1e6SMasatake YAMATO * FUNCTION DEFINITIONS
167d4c6f1e6SMasatake YAMATO */
168d4c6f1e6SMasatake YAMATO
isLanguageNameChar(int c)169da8c4965SMasatake YAMATO static bool isLanguageNameChar(int c)
170da8c4965SMasatake YAMATO {
171da8c4965SMasatake YAMATO if (isgraph(c))
172da8c4965SMasatake YAMATO {
173da8c4965SMasatake YAMATO if (c == '\'' || c == '"' || c == ';')
174da8c4965SMasatake YAMATO return false;
175da8c4965SMasatake YAMATO return true;
176da8c4965SMasatake YAMATO }
177da8c4965SMasatake YAMATO else
178da8c4965SMasatake YAMATO return false;
179da8c4965SMasatake YAMATO }
180da8c4965SMasatake YAMATO
countParsers(void)181ad1a3891SMasatake YAMATO extern unsigned int countParsers (void)
182ad1a3891SMasatake YAMATO {
183ad1a3891SMasatake YAMATO return LanguageCount;
184ad1a3891SMasatake YAMATO }
185ad1a3891SMasatake YAMATO
makeSimpleTag(const vString * const name,const int kindIndex)1867049fd45SMasatake YAMATO extern int makeSimpleTag (
18716a2541cSMasatake YAMATO const vString* const name, const int kindIndex)
188d4c6f1e6SMasatake YAMATO {
18924b256e3SMasatake YAMATO return makeSimpleRefTag (name, kindIndex, ROLE_DEFINITION_INDEX);
190d4c6f1e6SMasatake YAMATO }
191d4c6f1e6SMasatake YAMATO
makeSimpleRefTag(const vString * const name,const int kindIndex,int roleIndex)19216a2541cSMasatake YAMATO extern int makeSimpleRefTag (const vString* const name, const int kindIndex,
1937868fb2eSMasatake YAMATO int roleIndex)
1947868fb2eSMasatake YAMATO {
195f6027918SMasatake YAMATO int r = CORK_NIL;
1967868fb2eSMasatake YAMATO
1974c64e833SMasatake YAMATO Assert (roleIndex < (int)countInputLanguageRoles(kindIndex));
1987868fb2eSMasatake YAMATO
199250d94d4SMasatake YAMATO /* do not check for kind being disabled - that happens later in makeTagEntry() */
200250d94d4SMasatake YAMATO if (name != NULL && vStringLength (name) > 0)
2017868fb2eSMasatake YAMATO {
2027868fb2eSMasatake YAMATO tagEntryInfo e;
20316a2541cSMasatake YAMATO initRefTagEntry (&e, vStringValue (name), kindIndex, roleIndex);
2047868fb2eSMasatake YAMATO
2057868fb2eSMasatake YAMATO r = makeTagEntry (&e);
2067868fb2eSMasatake YAMATO }
2077868fb2eSMasatake YAMATO return r;
2087868fb2eSMasatake YAMATO }
2097868fb2eSMasatake YAMATO
makeSimplePlaceholder(const vString * const name)210a7c2b428SMasatake YAMATO extern int makeSimplePlaceholder(const vString* const name)
211a7c2b428SMasatake YAMATO {
212a7c2b428SMasatake YAMATO return makePlaceholder (vStringValue (name));
213a7c2b428SMasatake YAMATO }
214a7c2b428SMasatake YAMATO
isLanguageEnabled(const langType language)215ce990805SThomas Braun extern bool isLanguageEnabled (const langType language)
216d4c6f1e6SMasatake YAMATO {
217d8a63e0bSMasatake YAMATO const parserDefinition* const def = LanguageTable [language].def;
218d8a63e0bSMasatake YAMATO return def->enabled;
219d4c6f1e6SMasatake YAMATO }
220d4c6f1e6SMasatake YAMATO
isLanguageVisible(const langType language)22183f24c3bSMasatake YAMATO extern bool isLanguageVisible (const langType language)
22283f24c3bSMasatake YAMATO {
22383f24c3bSMasatake YAMATO const parserDefinition* const lang = LanguageTable [language].def;
22483f24c3bSMasatake YAMATO
22583f24c3bSMasatake YAMATO return !lang->invisible;
22683f24c3bSMasatake YAMATO }
22783f24c3bSMasatake YAMATO
228d4c6f1e6SMasatake YAMATO /*
229d4c6f1e6SMasatake YAMATO * parserDescription mapping management
230d4c6f1e6SMasatake YAMATO */
231d4c6f1e6SMasatake YAMATO
parserNew(const char * name)232b29ae60fSMasatake YAMATO extern parserDefinition* parserNew (const char* name)
2336ed0ba68SMasatake YAMATO {
234d4c6f1e6SMasatake YAMATO parserDefinition* result = xCalloc (1, parserDefinition);
235d4c6f1e6SMasatake YAMATO result->name = eStrdup (name);
2366ed0ba68SMasatake YAMATO
237ce990805SThomas Braun result->enabled = true;
238d4c6f1e6SMasatake YAMATO return result;
239d4c6f1e6SMasatake YAMATO }
240d4c6f1e6SMasatake YAMATO
doesLanguageAllowNullTag(const langType language)241ce990805SThomas Braun extern bool doesLanguageAllowNullTag (const langType language)
2427bd64c1dSMasatake YAMATO {
2437bd64c1dSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
244e02be843SMasatake YAMATO return LanguageTable [language].def->allowNullTag;
2457bd64c1dSMasatake YAMATO }
2467bd64c1dSMasatake YAMATO
doesLanguageRequestAutomaticFQTag(const langType language)247ce990805SThomas Braun extern bool doesLanguageRequestAutomaticFQTag (const langType language)
248bd7610b4SMasatake YAMATO {
249bd7610b4SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
250e02be843SMasatake YAMATO return LanguageTable [language].def->requestAutomaticFQTag;
251bd7610b4SMasatake YAMATO }
252bd7610b4SMasatake YAMATO
getLanguageNameFull(const langType language,bool noPretending)253f02166dcSMasatake YAMATO static const char *getLanguageNameFull (const langType language, bool noPretending)
254d4c6f1e6SMasatake YAMATO {
255d4c6f1e6SMasatake YAMATO const char* result;
256f02166dcSMasatake YAMATO
257d4c6f1e6SMasatake YAMATO if (language == LANG_IGNORE)
258d4c6f1e6SMasatake YAMATO result = "unknown";
259d4c6f1e6SMasatake YAMATO else
260d4c6f1e6SMasatake YAMATO {
261d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
262f02166dcSMasatake YAMATO if (noPretending)
263e02be843SMasatake YAMATO result = LanguageTable [language].def->name;
264f02166dcSMasatake YAMATO else
265f02166dcSMasatake YAMATO {
266f02166dcSMasatake YAMATO langType real_language = LanguageTable [language].pretendingAsLanguage;
267f02166dcSMasatake YAMATO if (real_language == LANG_IGNORE)
268f02166dcSMasatake YAMATO result = LanguageTable [language].def->name;
269f02166dcSMasatake YAMATO else
270f02166dcSMasatake YAMATO {
271f02166dcSMasatake YAMATO Assert (0 <= real_language && real_language < (int) LanguageCount);
272f02166dcSMasatake YAMATO result = LanguageTable [real_language].def->name;
273f02166dcSMasatake YAMATO }
274f02166dcSMasatake YAMATO }
275d4c6f1e6SMasatake YAMATO }
276d4c6f1e6SMasatake YAMATO return result;
277d4c6f1e6SMasatake YAMATO }
278d4c6f1e6SMasatake YAMATO
getLanguageName(const langType language)279f02166dcSMasatake YAMATO extern const char *getLanguageName (const langType language)
280f02166dcSMasatake YAMATO {
281f02166dcSMasatake YAMATO return getLanguageNameFull (language, false);
282f02166dcSMasatake YAMATO }
283f02166dcSMasatake YAMATO
getLanguageKindName(const langType language,const int kindIndex)284bea76990SMasatake YAMATO extern const char *getLanguageKindName (const langType language, const int kindIndex)
285bea76990SMasatake YAMATO {
286bea76990SMasatake YAMATO kindDefinition* kdef = getLanguageKind (language, kindIndex);
287bea76990SMasatake YAMATO return kdef->name;
288bea76990SMasatake YAMATO }
28911cbaeceSMasatake YAMATO
29011cbaeceSMasatake YAMATO static kindDefinition kindGhost = {
2917e1bd430SMasatake YAMATO .letter = KIND_GHOST_LETTER,
2927e1bd430SMasatake YAMATO .name = KIND_GHOST_NAME,
2937e1bd430SMasatake YAMATO .description = KIND_GHOST_NAME,
29411cbaeceSMasatake YAMATO };
29511cbaeceSMasatake YAMATO
defineLanguageKind(const langType language,kindDefinition * def,freeKindDefFunc freeKindDef)296cd2c516cSMasatake YAMATO extern int defineLanguageKind (const langType language, kindDefinition *def,
297cd2c516cSMasatake YAMATO freeKindDefFunc freeKindDef)
298cd2c516cSMasatake YAMATO {
299cd2c516cSMasatake YAMATO return defineKind (LanguageTable [language].kindControlBlock, def, freeKindDef);
300cd2c516cSMasatake YAMATO }
301cd2c516cSMasatake YAMATO
countLanguageKinds(const langType language)3020f23950dSMasatake YAMATO extern unsigned int countLanguageKinds (const langType language)
3030f23950dSMasatake YAMATO {
3040f23950dSMasatake YAMATO return countKinds (LanguageTable [language].kindControlBlock);
3050f23950dSMasatake YAMATO }
3060f23950dSMasatake YAMATO
countLanguageRoles(const langType language,int kindIndex)3070f23950dSMasatake YAMATO extern unsigned int countLanguageRoles (const langType language, int kindIndex)
3080f23950dSMasatake YAMATO {
3090f23950dSMasatake YAMATO return countRoles (LanguageTable [language].kindControlBlock, kindIndex);
3100f23950dSMasatake YAMATO }
3110f23950dSMasatake YAMATO
getLanguageKind(const langType language,int kindIndex)312f92e6bf2SMasatake YAMATO extern kindDefinition* getLanguageKind (const langType language, int kindIndex)
313e6c10a73SMasatake YAMATO {
3147e1b89c3SMasatake YAMATO kindDefinition* kdef;
3158dc26879SMasatake YAMATO
3168dc26879SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3178dc26879SMasatake YAMATO
3187e1b89c3SMasatake YAMATO switch (kindIndex)
3197e1b89c3SMasatake YAMATO {
3207e1b89c3SMasatake YAMATO case KIND_FILE_INDEX:
3217e1b89c3SMasatake YAMATO kdef = LanguageTable [language].fileKind;
3227e1b89c3SMasatake YAMATO break;
32311cbaeceSMasatake YAMATO case KIND_GHOST_INDEX:
32411cbaeceSMasatake YAMATO kdef = &kindGhost;
32511cbaeceSMasatake YAMATO break;
3267e1b89c3SMasatake YAMATO default:
327037a0e99SMasatake YAMATO Assert (kindIndex >= 0);
3287e1b89c3SMasatake YAMATO kdef = getKind (LanguageTable [language].kindControlBlock, kindIndex);
3297e1b89c3SMasatake YAMATO }
3307e1b89c3SMasatake YAMATO return kdef;
3317e1b89c3SMasatake YAMATO }
3328dc26879SMasatake YAMATO
getLanguageKindForLetter(const langType language,char kindLetter)3337e1b89c3SMasatake YAMATO extern kindDefinition* getLanguageKindForLetter (const langType language, char kindLetter)
3347e1b89c3SMasatake YAMATO {
3357e1b89c3SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3367e1b89c3SMasatake YAMATO if (kindLetter == LanguageTable [language].fileKind->letter)
3377e1b89c3SMasatake YAMATO return LanguageTable [language].fileKind;
3387e1bd430SMasatake YAMATO else if (kindLetter == KIND_GHOST_LETTER)
33911cbaeceSMasatake YAMATO return &kindGhost;
3407e1b89c3SMasatake YAMATO else
3417e1b89c3SMasatake YAMATO return getKindForLetter (LanguageTable [language].kindControlBlock, kindLetter);
3428dc26879SMasatake YAMATO }
3438dc26879SMasatake YAMATO
getLanguageKindForName(const langType language,const char * kindName)344c9dd5111SMasatake YAMATO extern kindDefinition* getLanguageKindForName (const langType language, const char *kindName)
345c9dd5111SMasatake YAMATO {
346c9dd5111SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
347c9dd5111SMasatake YAMATO Assert (kindName);
348c9dd5111SMasatake YAMATO
349c9dd5111SMasatake YAMATO if (strcmp(kindName, LanguageTable [language].fileKind->name) == 0)
350c9dd5111SMasatake YAMATO return LanguageTable [language].fileKind;
3517e1bd430SMasatake YAMATO else if (strcmp(kindName, KIND_GHOST_NAME) == 0)
352c9dd5111SMasatake YAMATO return &kindGhost;
353c9dd5111SMasatake YAMATO else
354c9dd5111SMasatake YAMATO return getKindForName (LanguageTable [language].kindControlBlock, kindName);
355c9dd5111SMasatake YAMATO }
356c9dd5111SMasatake YAMATO
getLanguageRole(const langType language,int kindIndex,int roleIndex)35713457258SMasatake YAMATO extern roleDefinition* getLanguageRole(const langType language, int kindIndex, int roleIndex)
35813457258SMasatake YAMATO {
35913457258SMasatake YAMATO return getRole (LanguageTable [language].kindControlBlock, kindIndex, roleIndex);
36013457258SMasatake YAMATO }
36113457258SMasatake YAMATO
getLanguageRoleForName(const langType language,int kindIndex,const char * roleName)36284f3a057SMasatake YAMATO extern roleDefinition* getLanguageRoleForName (const langType language, int kindIndex,
36384f3a057SMasatake YAMATO const char *roleName)
36484f3a057SMasatake YAMATO {
36584f3a057SMasatake YAMATO return getRoleForName (LanguageTable [language].kindControlBlock, kindIndex, roleName);
36684f3a057SMasatake YAMATO }
36784f3a057SMasatake YAMATO
getNamedLanguageFull(const char * const name,size_t len,bool noPretending,bool include_aliases)3689a391711SMasatake YAMATO extern langType getNamedLanguageFull (const char *const name, size_t len, bool noPretending,
3699a391711SMasatake YAMATO bool include_aliases)
370d4c6f1e6SMasatake YAMATO {
371d4c6f1e6SMasatake YAMATO langType result = LANG_IGNORE;
372d4c6f1e6SMasatake YAMATO unsigned int i;
373d4c6f1e6SMasatake YAMATO Assert (name != NULL);
3745a55f03bSMasatake YAMATO
375f140c7c3SMasatake YAMATO if (len == 0)
376f140c7c3SMasatake YAMATO {
377f140c7c3SMasatake YAMATO parserDefinition *def = (parserDefinition *)hashTableGetItem (LanguageHTable, name);
378f140c7c3SMasatake YAMATO if (def)
379f140c7c3SMasatake YAMATO result = def->id;
380f140c7c3SMasatake YAMATO }
381f140c7c3SMasatake YAMATO else
382d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount && result == LANG_IGNORE ; ++i)
383d4c6f1e6SMasatake YAMATO {
384e02be843SMasatake YAMATO const parserDefinition* const lang = LanguageTable [i].def;
385f140c7c3SMasatake YAMATO Assert (lang->name);
3865a55f03bSMasatake YAMATO vString* vstr = vStringNewInit (name);
3875a55f03bSMasatake YAMATO vStringTruncate (vstr, len);
3885a55f03bSMasatake YAMATO
3895a55f03bSMasatake YAMATO if (strcasecmp (vStringValue (vstr), lang->name) == 0)
3905a55f03bSMasatake YAMATO result = i;
3919a391711SMasatake YAMATO else if (include_aliases)
3929a391711SMasatake YAMATO {
3939a391711SMasatake YAMATO stringList* const aliases = LanguageTable [i].currentAliases;
3949a391711SMasatake YAMATO if (aliases && stringListCaseMatched (aliases, vStringValue (vstr)))
3959a391711SMasatake YAMATO result = i;
3969a391711SMasatake YAMATO }
3975a55f03bSMasatake YAMATO vStringDelete (vstr);
3985a55f03bSMasatake YAMATO }
399f02166dcSMasatake YAMATO
400f02166dcSMasatake YAMATO if (result != LANG_IGNORE
401f02166dcSMasatake YAMATO && (!noPretending)
402f02166dcSMasatake YAMATO && LanguageTable [result].pretendedAsLanguage != LANG_IGNORE)
403f02166dcSMasatake YAMATO result = LanguageTable [result].pretendedAsLanguage;
404f02166dcSMasatake YAMATO
405d4c6f1e6SMasatake YAMATO return result;
406d4c6f1e6SMasatake YAMATO }
407d4c6f1e6SMasatake YAMATO
getNamedLanguage(const char * const name,size_t len)408f02166dcSMasatake YAMATO extern langType getNamedLanguage (const char *const name, size_t len)
409f02166dcSMasatake YAMATO {
4109a391711SMasatake YAMATO return getNamedLanguageFull (name, len, false, false);
4119a391711SMasatake YAMATO }
4129a391711SMasatake YAMATO
getNamedLanguageOrAlias(const char * const name,size_t len)4139a391711SMasatake YAMATO extern langType getNamedLanguageOrAlias (const char *const name, size_t len)
4149a391711SMasatake YAMATO {
4159a391711SMasatake YAMATO return getNamedLanguageFull (name, len, false, true);
416f02166dcSMasatake YAMATO }
417f02166dcSMasatake YAMATO
getNameOrAliasesLanguageAndSpec(const char * const key,langType start_index,const char ** const spec,enum specType * specType)41895512ba5SMasatake YAMATO static langType getNameOrAliasesLanguageAndSpec (const char *const key, langType start_index,
41995512ba5SMasatake YAMATO const char **const spec, enum specType *specType)
420d4c6f1e6SMasatake YAMATO {
421d4c6f1e6SMasatake YAMATO langType result = LANG_IGNORE;
422d4c6f1e6SMasatake YAMATO unsigned int i;
423d4c6f1e6SMasatake YAMATO
424d4c6f1e6SMasatake YAMATO
425d4c6f1e6SMasatake YAMATO if (start_index == LANG_AUTO)
426d4c6f1e6SMasatake YAMATO start_index = 0;
427d4c6f1e6SMasatake YAMATO else if (start_index == LANG_IGNORE || start_index >= (int) LanguageCount)
428d4c6f1e6SMasatake YAMATO return result;
429d4c6f1e6SMasatake YAMATO
430d4c6f1e6SMasatake YAMATO for (i = start_index ; i < LanguageCount && result == LANG_IGNORE ; ++i)
431d4c6f1e6SMasatake YAMATO {
432d8a63e0bSMasatake YAMATO if (! isLanguageEnabled (i))
433d8a63e0bSMasatake YAMATO continue;
434d8a63e0bSMasatake YAMATO
435efe089d4SMasatake YAMATO const parserObject* const parser = LanguageTable + i;
436efe089d4SMasatake YAMATO stringList* const aliases = parser->currentAliases;
437d4c6f1e6SMasatake YAMATO vString* tmp;
438d4c6f1e6SMasatake YAMATO
439efe089d4SMasatake YAMATO if (parser->def->name != NULL && strcasecmp (key, parser->def->name) == 0)
440d4c6f1e6SMasatake YAMATO {
441d4c6f1e6SMasatake YAMATO result = i;
442efe089d4SMasatake YAMATO *spec = parser->def->name;
44395512ba5SMasatake YAMATO *specType = SPEC_NAME;
444d4c6f1e6SMasatake YAMATO }
445d4c6f1e6SMasatake YAMATO else if (aliases != NULL && (tmp = stringListFileFinds (aliases, key)))
446d4c6f1e6SMasatake YAMATO {
447d4c6f1e6SMasatake YAMATO result = i;
448d4c6f1e6SMasatake YAMATO *spec = vStringValue(tmp);
44995512ba5SMasatake YAMATO *specType = SPEC_ALIAS;
450d4c6f1e6SMasatake YAMATO }
451d4c6f1e6SMasatake YAMATO }
452d4c6f1e6SMasatake YAMATO return result;
453d4c6f1e6SMasatake YAMATO }
454d4c6f1e6SMasatake YAMATO
getLanguageForCommand(const char * const command,langType startFrom)455334e072fSMasatake YAMATO extern langType getLanguageForCommand (const char *const command, langType startFrom)
456334e072fSMasatake YAMATO {
457334e072fSMasatake YAMATO const char *const tmp_command = baseFilename (command);
458334e072fSMasatake YAMATO char *tmp_spec;
459334e072fSMasatake YAMATO enum specType tmp_specType;
460334e072fSMasatake YAMATO
461334e072fSMasatake YAMATO return getNameOrAliasesLanguageAndSpec (tmp_command, startFrom,
462334e072fSMasatake YAMATO (const char **const)&tmp_spec,
463334e072fSMasatake YAMATO &tmp_specType);
464334e072fSMasatake YAMATO }
465334e072fSMasatake YAMATO
getPatternLanguageAndSpec(const char * const baseName,langType start_index,const char ** const spec,enum specType * specType)46695512ba5SMasatake YAMATO static langType getPatternLanguageAndSpec (const char *const baseName, langType start_index,
46795512ba5SMasatake YAMATO const char **const spec, enum specType *specType)
468d4c6f1e6SMasatake YAMATO {
469d4c6f1e6SMasatake YAMATO langType result = LANG_IGNORE;
470d4c6f1e6SMasatake YAMATO unsigned int i;
471d4c6f1e6SMasatake YAMATO
472d4c6f1e6SMasatake YAMATO if (start_index == LANG_AUTO)
473d4c6f1e6SMasatake YAMATO start_index = 0;
474d4c6f1e6SMasatake YAMATO else if (start_index == LANG_IGNORE || start_index >= (int) LanguageCount)
475d4c6f1e6SMasatake YAMATO return result;
476d4c6f1e6SMasatake YAMATO
477d4c6f1e6SMasatake YAMATO *spec = NULL;
478d4c6f1e6SMasatake YAMATO for (i = start_index ; i < LanguageCount && result == LANG_IGNORE ; ++i)
479d4c6f1e6SMasatake YAMATO {
480d8a63e0bSMasatake YAMATO if (! isLanguageEnabled (i))
481d8a63e0bSMasatake YAMATO continue;
482d8a63e0bSMasatake YAMATO
483efe089d4SMasatake YAMATO parserObject *parser = LanguageTable + i;
484efe089d4SMasatake YAMATO stringList* const ptrns = parser->currentPatterns;
485d4c6f1e6SMasatake YAMATO vString* tmp;
486d4c6f1e6SMasatake YAMATO
487d4c6f1e6SMasatake YAMATO if (ptrns != NULL && (tmp = stringListFileFinds (ptrns, baseName)))
488d4c6f1e6SMasatake YAMATO {
489d4c6f1e6SMasatake YAMATO result = i;
490d4c6f1e6SMasatake YAMATO *spec = vStringValue(tmp);
49195512ba5SMasatake YAMATO *specType = SPEC_PATTERN;
49295512ba5SMasatake YAMATO goto found;
493d4c6f1e6SMasatake YAMATO }
494d4c6f1e6SMasatake YAMATO }
49595512ba5SMasatake YAMATO
49695512ba5SMasatake YAMATO for (i = start_index ; i < LanguageCount && result == LANG_IGNORE ; ++i)
49795512ba5SMasatake YAMATO {
498d8a63e0bSMasatake YAMATO if (! isLanguageEnabled (i))
499d8a63e0bSMasatake YAMATO continue;
500d8a63e0bSMasatake YAMATO
501efe089d4SMasatake YAMATO parserObject *parser = LanguageTable + i;
502efe089d4SMasatake YAMATO stringList* const exts = parser->currentExtensions;
50395512ba5SMasatake YAMATO vString* tmp;
50495512ba5SMasatake YAMATO
50595512ba5SMasatake YAMATO if (exts != NULL && (tmp = stringListExtensionFinds (exts,
50695512ba5SMasatake YAMATO fileExtension (baseName))))
50795512ba5SMasatake YAMATO {
50895512ba5SMasatake YAMATO result = i;
50995512ba5SMasatake YAMATO *spec = vStringValue(tmp);
51095512ba5SMasatake YAMATO *specType = SPEC_EXTENSION;
51195512ba5SMasatake YAMATO goto found;
51295512ba5SMasatake YAMATO }
51395512ba5SMasatake YAMATO }
51495512ba5SMasatake YAMATO found:
515d4c6f1e6SMasatake YAMATO return result;
516d4c6f1e6SMasatake YAMATO }
517d4c6f1e6SMasatake YAMATO
getLanguageForFilename(const char * const filename,langType startFrom)518416c5e6bSMasatake YAMATO extern langType getLanguageForFilename (const char *const filename, langType startFrom)
519416c5e6bSMasatake YAMATO {
520416c5e6bSMasatake YAMATO const char *const tmp_filename = baseFilename (filename);
521416c5e6bSMasatake YAMATO char *tmp_spec;
522416c5e6bSMasatake YAMATO enum specType tmp_specType;
523416c5e6bSMasatake YAMATO
524416c5e6bSMasatake YAMATO return getPatternLanguageAndSpec (tmp_filename, startFrom,
525416c5e6bSMasatake YAMATO (const char **const)&tmp_spec,
526416c5e6bSMasatake YAMATO &tmp_specType);
527416c5e6bSMasatake YAMATO }
528416c5e6bSMasatake YAMATO
scopeSeparatorFor(langType language,int kindIndex,int parentKindIndex)529314c9d31SMasatake YAMATO const char *scopeSeparatorFor (langType language, int kindIndex, int parentKindIndex)
530314c9d31SMasatake YAMATO {
531314c9d31SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
532314c9d31SMasatake YAMATO
533314c9d31SMasatake YAMATO parserObject *parser = LanguageTable + language;
534314c9d31SMasatake YAMATO struct kindControlBlock *kcb = parser->kindControlBlock;
535314c9d31SMasatake YAMATO
536314c9d31SMasatake YAMATO const scopeSeparator *sep = getScopeSeparator (kcb, kindIndex, parentKindIndex);
537314c9d31SMasatake YAMATO return sep? sep->separator: NULL;
538314c9d31SMasatake YAMATO }
539314c9d31SMasatake YAMATO
processLangDefineScopesep(const langType language,const char * const option,const char * const parameter)540acf93fd6SMasatake YAMATO static bool processLangDefineScopesep(const langType language,
541acf93fd6SMasatake YAMATO const char *const option,
542acf93fd6SMasatake YAMATO const char *const parameter)
543acf93fd6SMasatake YAMATO {
544acf93fd6SMasatake YAMATO parserObject *parser;
545acf93fd6SMasatake YAMATO const char * p = parameter;
546acf93fd6SMasatake YAMATO
547acf93fd6SMasatake YAMATO
548acf93fd6SMasatake YAMATO char parentKletter;
549acf93fd6SMasatake YAMATO int parentKindex = KIND_FILE_INDEX;
550acf93fd6SMasatake YAMATO char kletter;
551acf93fd6SMasatake YAMATO int kindex = KIND_FILE_INDEX;
552acf93fd6SMasatake YAMATO const char *separator;
553acf93fd6SMasatake YAMATO
554acf93fd6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
555acf93fd6SMasatake YAMATO parser = LanguageTable + language;
556acf93fd6SMasatake YAMATO
557acf93fd6SMasatake YAMATO
558acf93fd6SMasatake YAMATO /*
559acf93fd6SMasatake YAMATO * Parent
560acf93fd6SMasatake YAMATO */
561acf93fd6SMasatake YAMATO parentKletter = p[0];
562acf93fd6SMasatake YAMATO
563acf93fd6SMasatake YAMATO if (parentKletter == '\0')
564acf93fd6SMasatake YAMATO error (FATAL, "no scope separator specified in \"--%s\" option", option);
565acf93fd6SMasatake YAMATO else if (parentKletter == '/')
566acf93fd6SMasatake YAMATO parentKindex = KIND_GHOST_INDEX;
5677e1bd430SMasatake YAMATO else if (parentKletter == KIND_WILDCARD_LETTER)
568acf93fd6SMasatake YAMATO parentKindex = KIND_WILDCARD_INDEX;
5697e1bd430SMasatake YAMATO else if (parentKletter == KIND_FILE_DEFAULT_LETTER)
570acf93fd6SMasatake YAMATO error (FATAL,
57147df83bdSMasatake YAMATO "the kind letter `%c' in \"--%s\" option is reserved for \"%s\" kind and no separator can be assigned to",
57247df83bdSMasatake YAMATO KIND_FILE_DEFAULT_LETTER, option, KIND_FILE_DEFAULT_NAME);
573acf93fd6SMasatake YAMATO else if (isalpha (parentKletter))
574acf93fd6SMasatake YAMATO {
575acf93fd6SMasatake YAMATO kindDefinition *kdef = getKindForLetter (parser->kindControlBlock, parentKletter);
576acf93fd6SMasatake YAMATO if (kdef == NULL)
577acf93fd6SMasatake YAMATO error (FATAL,
578acf93fd6SMasatake YAMATO "the kind for letter `%c' specified in \"--%s\" option is not defined.",
579acf93fd6SMasatake YAMATO parentKletter, option);
580acf93fd6SMasatake YAMATO parentKindex = kdef->id;
581acf93fd6SMasatake YAMATO }
582acf93fd6SMasatake YAMATO else
583acf93fd6SMasatake YAMATO error (FATAL,
584acf93fd6SMasatake YAMATO "the kind letter `%c` given in \"--%s\" option is not an alphabet",
585acf93fd6SMasatake YAMATO parentKletter, option);
586acf93fd6SMasatake YAMATO
587acf93fd6SMasatake YAMATO
588acf93fd6SMasatake YAMATO /*
589acf93fd6SMasatake YAMATO * Child
590acf93fd6SMasatake YAMATO */
591acf93fd6SMasatake YAMATO if (parentKindex == KIND_GHOST_INDEX)
592acf93fd6SMasatake YAMATO kletter = p[1];
593acf93fd6SMasatake YAMATO else
594acf93fd6SMasatake YAMATO {
595acf93fd6SMasatake YAMATO if (p[1] != '/')
596acf93fd6SMasatake YAMATO error (FATAL,
597acf93fd6SMasatake YAMATO "wrong separator specification in \"--%s\" option: no slash after parent kind letter `%c'",
598acf93fd6SMasatake YAMATO option, parentKletter);
599acf93fd6SMasatake YAMATO kletter = p[2];
600acf93fd6SMasatake YAMATO }
601acf93fd6SMasatake YAMATO
602acf93fd6SMasatake YAMATO if (kletter == '\0')
603acf93fd6SMasatake YAMATO error (FATAL, "no child kind letter in \"--%s\" option", option);
604acf93fd6SMasatake YAMATO else if (kletter == '/')
605acf93fd6SMasatake YAMATO error (FATAL,
606acf93fd6SMasatake YAMATO "wrong separator specification in \"--%s\" option: don't specify slash char twice: %s",
607acf93fd6SMasatake YAMATO option, parameter);
608acf93fd6SMasatake YAMATO else if (kletter == ':')
609acf93fd6SMasatake YAMATO error (FATAL,
610acf93fd6SMasatake YAMATO "no child kind letter in \"--%s\" option", option);
6117e1bd430SMasatake YAMATO else if (kletter == KIND_WILDCARD_LETTER)
612acf93fd6SMasatake YAMATO {
613acf93fd6SMasatake YAMATO if (parentKindex != KIND_WILDCARD_INDEX
614acf93fd6SMasatake YAMATO && parentKindex != KIND_GHOST_INDEX)
615acf93fd6SMasatake YAMATO error (FATAL,
616acf93fd6SMasatake YAMATO "cannot use wild card for child kind unless parent kind is also wild card or empty");
617acf93fd6SMasatake YAMATO kindex = KIND_WILDCARD_INDEX;
618acf93fd6SMasatake YAMATO }
6197e1bd430SMasatake YAMATO else if (kletter == KIND_FILE_DEFAULT_LETTER)
620acf93fd6SMasatake YAMATO error (FATAL,
62147df83bdSMasatake YAMATO "the kind letter `%c' in \"--%s\" option is reserved for \"%s\" kind and no separator can be assigned to",
62247df83bdSMasatake YAMATO KIND_FILE_DEFAULT_LETTER, option, KIND_FILE_DEFAULT_NAME);
623acf93fd6SMasatake YAMATO else if (isalpha (kletter))
624acf93fd6SMasatake YAMATO {
625acf93fd6SMasatake YAMATO kindDefinition *kdef = getKindForLetter (parser->kindControlBlock, kletter);
626acf93fd6SMasatake YAMATO if (kdef == NULL)
627acf93fd6SMasatake YAMATO error (FATAL,
628acf93fd6SMasatake YAMATO "the kind for letter `%c' specified in \"--%s\" option is not defined.",
629acf93fd6SMasatake YAMATO kletter, option);
630acf93fd6SMasatake YAMATO kindex = kdef->id;
631acf93fd6SMasatake YAMATO }
632acf93fd6SMasatake YAMATO else
633acf93fd6SMasatake YAMATO error (FATAL,
634acf93fd6SMasatake YAMATO "the kind letter `%c` given in \"--%s\" option is not an alphabet",
635acf93fd6SMasatake YAMATO kletter, option);
636acf93fd6SMasatake YAMATO
637acf93fd6SMasatake YAMATO /*
638acf93fd6SMasatake YAMATO * Separator
639acf93fd6SMasatake YAMATO */
640acf93fd6SMasatake YAMATO if (parentKindex == KIND_GHOST_INDEX)
641acf93fd6SMasatake YAMATO {
642acf93fd6SMasatake YAMATO if (p[2] != ':')
643acf93fd6SMasatake YAMATO error (FATAL,
644acf93fd6SMasatake YAMATO "wrong separator specification in \"--%s\" option: cannot find a colon after child kind: %s",
645acf93fd6SMasatake YAMATO option, parameter);
646acf93fd6SMasatake YAMATO separator = p + 3;
647acf93fd6SMasatake YAMATO }
648acf93fd6SMasatake YAMATO else
649acf93fd6SMasatake YAMATO {
650acf93fd6SMasatake YAMATO if (p[3] != ':')
651acf93fd6SMasatake YAMATO error (FATAL,
652acf93fd6SMasatake YAMATO "wrong separator specification in \"--%s\" option: cannot find a colon after child kind: %s",
653acf93fd6SMasatake YAMATO option, parameter);
654acf93fd6SMasatake YAMATO separator = p + 4;
655acf93fd6SMasatake YAMATO }
656acf93fd6SMasatake YAMATO
657acf93fd6SMasatake YAMATO Assert (parentKindex != KIND_FILE_INDEX);
658acf93fd6SMasatake YAMATO Assert (kindex != KIND_FILE_INDEX);
659acf93fd6SMasatake YAMATO defineScopeSeparator (parser->kindControlBlock, kindex, parentKindex, separator);
660acf93fd6SMasatake YAMATO return true;
661acf93fd6SMasatake YAMATO }
662acf93fd6SMasatake YAMATO
processScopesepOption(const char * const option,const char * const parameter)663acf93fd6SMasatake YAMATO extern bool processScopesepOption (const char *const option, const char * const parameter)
664acf93fd6SMasatake YAMATO {
665acf93fd6SMasatake YAMATO langType language;
666acf93fd6SMasatake YAMATO
667acf93fd6SMasatake YAMATO language = getLanguageComponentInOption (option, "_scopesep-");
668acf93fd6SMasatake YAMATO if (language == LANG_IGNORE)
669acf93fd6SMasatake YAMATO return false;
670acf93fd6SMasatake YAMATO
671acf93fd6SMasatake YAMATO return processLangDefineScopesep (language, option, parameter);
672acf93fd6SMasatake YAMATO }
673acf93fd6SMasatake YAMATO
parserCandidateNew(unsigned int count CTAGS_ATTR_UNUSED)6748ccb7ee9SJiří Techet static parserCandidate* parserCandidateNew(unsigned int count CTAGS_ATTR_UNUSED)
675d4c6f1e6SMasatake YAMATO {
676d4c6f1e6SMasatake YAMATO parserCandidate* candidates;
677d4c6f1e6SMasatake YAMATO unsigned int i;
678d4c6f1e6SMasatake YAMATO
679d4c6f1e6SMasatake YAMATO candidates= xMalloc(LanguageCount, parserCandidate);
680d4c6f1e6SMasatake YAMATO for (i = 0; i < LanguageCount; i++)
681d4c6f1e6SMasatake YAMATO {
682d4c6f1e6SMasatake YAMATO candidates[i].lang = LANG_IGNORE;
683d4c6f1e6SMasatake YAMATO candidates[i].spec = NULL;
68495512ba5SMasatake YAMATO candidates[i].specType = SPEC_NONE;
685d4c6f1e6SMasatake YAMATO }
686d4c6f1e6SMasatake YAMATO return candidates;
687d4c6f1e6SMasatake YAMATO }
688d4c6f1e6SMasatake YAMATO
689d4c6f1e6SMasatake YAMATO /* If multiple parsers are found, return LANG_AUTO */
nominateLanguageCandidates(const char * const key,parserCandidate ** candidates)690d4c6f1e6SMasatake YAMATO static unsigned int nominateLanguageCandidates (const char *const key, parserCandidate** candidates)
691d4c6f1e6SMasatake YAMATO {
692d4c6f1e6SMasatake YAMATO unsigned int count;
693d4c6f1e6SMasatake YAMATO langType i;
6944e174950SVitor Antunes const char* spec = NULL;
69595512ba5SMasatake YAMATO enum specType specType = SPEC_NONE;
696d4c6f1e6SMasatake YAMATO
697d4c6f1e6SMasatake YAMATO *candidates = parserCandidateNew(LanguageCount);
698d4c6f1e6SMasatake YAMATO
699d4c6f1e6SMasatake YAMATO for (count = 0, i = LANG_AUTO; i != LANG_IGNORE; )
700d4c6f1e6SMasatake YAMATO {
70195512ba5SMasatake YAMATO i = getNameOrAliasesLanguageAndSpec (key, i, &spec, &specType);
702d4c6f1e6SMasatake YAMATO if (i != LANG_IGNORE)
703d4c6f1e6SMasatake YAMATO {
704d4c6f1e6SMasatake YAMATO (*candidates)[count].lang = i++;
70595512ba5SMasatake YAMATO (*candidates)[count].spec = spec;
70695512ba5SMasatake YAMATO (*candidates)[count++].specType = specType;
707d4c6f1e6SMasatake YAMATO }
708d4c6f1e6SMasatake YAMATO }
709d4c6f1e6SMasatake YAMATO
710d4c6f1e6SMasatake YAMATO return count;
711d4c6f1e6SMasatake YAMATO }
712d4c6f1e6SMasatake YAMATO
713d4c6f1e6SMasatake YAMATO static unsigned int
nominateLanguageCandidatesForPattern(const char * const baseName,parserCandidate ** candidates)714d4c6f1e6SMasatake YAMATO nominateLanguageCandidatesForPattern(const char *const baseName, parserCandidate** candidates)
715d4c6f1e6SMasatake YAMATO {
716d4c6f1e6SMasatake YAMATO unsigned int count;
717d4c6f1e6SMasatake YAMATO langType i;
718d4c6f1e6SMasatake YAMATO const char* spec;
71995512ba5SMasatake YAMATO enum specType specType = SPEC_NONE;
720d4c6f1e6SMasatake YAMATO
721d4c6f1e6SMasatake YAMATO *candidates = parserCandidateNew(LanguageCount);
722d4c6f1e6SMasatake YAMATO
723d4c6f1e6SMasatake YAMATO for (count = 0, i = LANG_AUTO; i != LANG_IGNORE; )
724d4c6f1e6SMasatake YAMATO {
72595512ba5SMasatake YAMATO i = getPatternLanguageAndSpec (baseName, i, &spec, &specType);
726d4c6f1e6SMasatake YAMATO if (i != LANG_IGNORE)
727d4c6f1e6SMasatake YAMATO {
728d4c6f1e6SMasatake YAMATO (*candidates)[count].lang = i++;
72995512ba5SMasatake YAMATO (*candidates)[count].spec = spec;
73095512ba5SMasatake YAMATO (*candidates)[count++].specType = specType;
731d4c6f1e6SMasatake YAMATO }
732d4c6f1e6SMasatake YAMATO }
733d4c6f1e6SMasatake YAMATO return count;
734d4c6f1e6SMasatake YAMATO }
735d4c6f1e6SMasatake YAMATO
736509a47dbSJiří Techet static vString* extractEmacsModeAtFirstLine(MIO* input);
737d4c6f1e6SMasatake YAMATO
738d4c6f1e6SMasatake YAMATO /* The name of the language interpreter, either directly or as the argument
739d4c6f1e6SMasatake YAMATO * to "env".
740d4c6f1e6SMasatake YAMATO */
determineInterpreter(const char * const cmd)741d4c6f1e6SMasatake YAMATO static vString* determineInterpreter (const char* const cmd)
742d4c6f1e6SMasatake YAMATO {
743d4c6f1e6SMasatake YAMATO vString* const interpreter = vStringNew ();
744d4c6f1e6SMasatake YAMATO const char* p = cmd;
745d4c6f1e6SMasatake YAMATO do
746d4c6f1e6SMasatake YAMATO {
747d4c6f1e6SMasatake YAMATO vStringClear (interpreter);
748d4c6f1e6SMasatake YAMATO for ( ; isspace ((int) *p) ; ++p)
749d4c6f1e6SMasatake YAMATO ; /* no-op */
750d4c6f1e6SMasatake YAMATO for ( ; *p != '\0' && ! isspace ((int) *p) ; ++p)
751d4c6f1e6SMasatake YAMATO vStringPut (interpreter, (int) *p);
752d4c6f1e6SMasatake YAMATO } while (strcmp (vStringValue (interpreter), "env") == 0);
753d4c6f1e6SMasatake YAMATO return interpreter;
754d4c6f1e6SMasatake YAMATO }
755d4c6f1e6SMasatake YAMATO
extractInterpreter(MIO * input)756509a47dbSJiří Techet static vString* extractInterpreter (MIO* input)
757d4c6f1e6SMasatake YAMATO {
758d4c6f1e6SMasatake YAMATO vString* const vLine = vStringNew ();
75978e93ff0SMasatake YAMATO const char* const line = readLineRaw (vLine, input);
760d4c6f1e6SMasatake YAMATO vString* interpreter = NULL;
761d4c6f1e6SMasatake YAMATO
762d4c6f1e6SMasatake YAMATO if (line != NULL && line [0] == '#' && line [1] == '!')
763d4c6f1e6SMasatake YAMATO {
764d4c6f1e6SMasatake YAMATO /* "48.2.4.1 Specifying File Variables" of Emacs info:
765d4c6f1e6SMasatake YAMATO ---------------------------------------------------
766d4c6f1e6SMasatake YAMATO In shell scripts, the first line is used to
767d4c6f1e6SMasatake YAMATO identify the script interpreter, so you
768d4c6f1e6SMasatake YAMATO cannot put any local variables there. To
769d4c6f1e6SMasatake YAMATO accommodate this, Emacs looks for local
770d4c6f1e6SMasatake YAMATO variable specifications in the _second_
771d4c6f1e6SMasatake YAMATO line if the first line specifies an
772d4c6f1e6SMasatake YAMATO interpreter. */
773d4c6f1e6SMasatake YAMATO
774100a966cSMasatake YAMATO interpreter = extractEmacsModeAtFirstLine(input);
775d4c6f1e6SMasatake YAMATO if (!interpreter)
776d4c6f1e6SMasatake YAMATO {
777d4c6f1e6SMasatake YAMATO const char* const lastSlash = strrchr (line, '/');
778d4c6f1e6SMasatake YAMATO const char *const cmd = lastSlash != NULL ? lastSlash+1 : line+2;
779d4c6f1e6SMasatake YAMATO interpreter = determineInterpreter (cmd);
780d4c6f1e6SMasatake YAMATO }
781d4c6f1e6SMasatake YAMATO }
782d4c6f1e6SMasatake YAMATO vStringDelete (vLine);
783d4c6f1e6SMasatake YAMATO return interpreter;
784d4c6f1e6SMasatake YAMATO }
785d4c6f1e6SMasatake YAMATO
determineEmacsModeAtFirstLine(const char * const line)786d4c6f1e6SMasatake YAMATO static vString* determineEmacsModeAtFirstLine (const char* const line)
787d4c6f1e6SMasatake YAMATO {
788d4c6f1e6SMasatake YAMATO vString* mode = vStringNew ();
789d4c6f1e6SMasatake YAMATO
790d4c6f1e6SMasatake YAMATO const char* p = strstr(line, "-*-");
791d4c6f1e6SMasatake YAMATO if (p == NULL)
792fba4ae34SMasatake YAMATO goto out;
793d4c6f1e6SMasatake YAMATO p += strlen("-*-");
794d4c6f1e6SMasatake YAMATO
795d4c6f1e6SMasatake YAMATO for ( ; isspace ((int) *p) ; ++p)
796d4c6f1e6SMasatake YAMATO ; /* no-op */
797d4c6f1e6SMasatake YAMATO
798d5f594ccSMasatake YAMATO if (strncasecmp(p, "mode:", strlen("mode:")) == 0)
799d4c6f1e6SMasatake YAMATO {
800d4c6f1e6SMasatake YAMATO /* -*- mode: MODE; -*- */
801d4c6f1e6SMasatake YAMATO p += strlen("mode:");
802d4c6f1e6SMasatake YAMATO for ( ; isspace ((int) *p) ; ++p)
803d4c6f1e6SMasatake YAMATO ; /* no-op */
804da8c4965SMasatake YAMATO for ( ; *p != '\0' && isLanguageNameChar ((int) *p) ; ++p)
805d4c6f1e6SMasatake YAMATO vStringPut (mode, (int) *p);
806d4c6f1e6SMasatake YAMATO }
807d4c6f1e6SMasatake YAMATO else
808d4c6f1e6SMasatake YAMATO {
809d4c6f1e6SMasatake YAMATO /* -*- MODE -*- */
810fba4ae34SMasatake YAMATO const char* end = strstr (p, "-*-");
811fba4ae34SMasatake YAMATO
812fba4ae34SMasatake YAMATO if (end == NULL)
813fba4ae34SMasatake YAMATO goto out;
814fba4ae34SMasatake YAMATO
815da8c4965SMasatake YAMATO for ( ; p < end && isLanguageNameChar ((int) *p) ; ++p)
816d4c6f1e6SMasatake YAMATO vStringPut (mode, (int) *p);
817d4c6f1e6SMasatake YAMATO
818d4c6f1e6SMasatake YAMATO for ( ; isspace ((int) *p) ; ++p)
819d4c6f1e6SMasatake YAMATO ; /* no-op */
820d4c6f1e6SMasatake YAMATO if (strncmp(p, "-*-", strlen("-*-")) != 0)
821d4c6f1e6SMasatake YAMATO vStringClear (mode);
822d4c6f1e6SMasatake YAMATO }
823d4c6f1e6SMasatake YAMATO
824fba4ae34SMasatake YAMATO vStringLower (mode);
825fba4ae34SMasatake YAMATO
826fba4ae34SMasatake YAMATO out:
827d4c6f1e6SMasatake YAMATO return mode;
828d4c6f1e6SMasatake YAMATO
829d4c6f1e6SMasatake YAMATO }
830d4c6f1e6SMasatake YAMATO
extractEmacsModeAtFirstLine(MIO * input)831509a47dbSJiří Techet static vString* extractEmacsModeAtFirstLine(MIO* input)
832d4c6f1e6SMasatake YAMATO {
833d4c6f1e6SMasatake YAMATO vString* const vLine = vStringNew ();
83478e93ff0SMasatake YAMATO const char* const line = readLineRaw (vLine, input);
835d4c6f1e6SMasatake YAMATO vString* mode = NULL;
836d4c6f1e6SMasatake YAMATO if (line != NULL)
837d4c6f1e6SMasatake YAMATO mode = determineEmacsModeAtFirstLine (line);
838d4c6f1e6SMasatake YAMATO vStringDelete (vLine);
839d4c6f1e6SMasatake YAMATO
840d4c6f1e6SMasatake YAMATO if (mode && (vStringLength(mode) == 0))
841d4c6f1e6SMasatake YAMATO {
842d4c6f1e6SMasatake YAMATO vStringDelete(mode);
843d4c6f1e6SMasatake YAMATO mode = NULL;
844d4c6f1e6SMasatake YAMATO }
845d4c6f1e6SMasatake YAMATO return mode;
846d4c6f1e6SMasatake YAMATO }
847d4c6f1e6SMasatake YAMATO
determineEmacsModeAtEOF(MIO * const fp)848509a47dbSJiří Techet static vString* determineEmacsModeAtEOF (MIO* const fp)
849d4c6f1e6SMasatake YAMATO {
850d4c6f1e6SMasatake YAMATO vString* const vLine = vStringNew ();
851d4c6f1e6SMasatake YAMATO const char* line;
852ce990805SThomas Braun bool headerFound = false;
853d4c6f1e6SMasatake YAMATO const char* p;
854d4c6f1e6SMasatake YAMATO vString* mode = vStringNew ();
855d4c6f1e6SMasatake YAMATO
85678e93ff0SMasatake YAMATO while ((line = readLineRaw (vLine, fp)) != NULL)
857d4c6f1e6SMasatake YAMATO {
858d4c6f1e6SMasatake YAMATO if (headerFound && ((p = strstr (line, "mode:")) != NULL))
859d4c6f1e6SMasatake YAMATO {
860d4c6f1e6SMasatake YAMATO vStringClear (mode);
861ce990805SThomas Braun headerFound = false;
862d4c6f1e6SMasatake YAMATO
863d4c6f1e6SMasatake YAMATO p += strlen ("mode:");
864d4c6f1e6SMasatake YAMATO for ( ; isspace ((int) *p) ; ++p)
865d4c6f1e6SMasatake YAMATO ; /* no-op */
866da8c4965SMasatake YAMATO for ( ; *p != '\0' && isLanguageNameChar ((int) *p) ; ++p)
867d4c6f1e6SMasatake YAMATO vStringPut (mode, (int) *p);
868d4c6f1e6SMasatake YAMATO }
869d4c6f1e6SMasatake YAMATO else if (headerFound && (p = strstr(line, "End:")))
870ce990805SThomas Braun headerFound = false;
871d4c6f1e6SMasatake YAMATO else if (strstr (line, "Local Variables:"))
872ce990805SThomas Braun headerFound = true;
873d4c6f1e6SMasatake YAMATO }
874d4c6f1e6SMasatake YAMATO vStringDelete (vLine);
875d4c6f1e6SMasatake YAMATO return mode;
876d4c6f1e6SMasatake YAMATO }
877d4c6f1e6SMasatake YAMATO
extractEmacsModeLanguageAtEOF(MIO * input)878509a47dbSJiří Techet static vString* extractEmacsModeLanguageAtEOF (MIO* input)
879d4c6f1e6SMasatake YAMATO {
880d4c6f1e6SMasatake YAMATO vString* mode;
881d4c6f1e6SMasatake YAMATO
882d4c6f1e6SMasatake YAMATO /* "48.2.4.1 Specifying File Variables" of Emacs info:
883d4c6f1e6SMasatake YAMATO ---------------------------------------------------
884d4c6f1e6SMasatake YAMATO you can define file local variables using a "local
885d4c6f1e6SMasatake YAMATO variables list" near the end of the file. The start of the
886d4c6f1e6SMasatake YAMATO local variables list should be no more than 3000 characters
887d4c6f1e6SMasatake YAMATO from the end of the file, */
888509a47dbSJiří Techet mio_seek(input, -3000, SEEK_END);
889d4c6f1e6SMasatake YAMATO
890d4c6f1e6SMasatake YAMATO mode = determineEmacsModeAtEOF (input);
891d4c6f1e6SMasatake YAMATO if (mode && (vStringLength (mode) == 0))
892d4c6f1e6SMasatake YAMATO {
893d4c6f1e6SMasatake YAMATO vStringDelete (mode);
894d4c6f1e6SMasatake YAMATO mode = NULL;
895d4c6f1e6SMasatake YAMATO }
896d4c6f1e6SMasatake YAMATO
897d4c6f1e6SMasatake YAMATO return mode;
898d4c6f1e6SMasatake YAMATO }
899d4c6f1e6SMasatake YAMATO
determineVimFileType(const char * const modeline)900d4c6f1e6SMasatake YAMATO static vString* determineVimFileType (const char *const modeline)
901d4c6f1e6SMasatake YAMATO {
902d4c6f1e6SMasatake YAMATO /* considerable combinations:
903d4c6f1e6SMasatake YAMATO --------------------------
904d4c6f1e6SMasatake YAMATO ... filetype=
905d4c6f1e6SMasatake YAMATO ... ft= */
906d4c6f1e6SMasatake YAMATO
907d4c6f1e6SMasatake YAMATO unsigned int i;
908d4c6f1e6SMasatake YAMATO const char* p;
909d4c6f1e6SMasatake YAMATO
910d4c6f1e6SMasatake YAMATO const char* const filetype_prefix[] = {"filetype=", "ft="};
911d4c6f1e6SMasatake YAMATO vString* const filetype = vStringNew ();
912d4c6f1e6SMasatake YAMATO
913d4c6f1e6SMasatake YAMATO for (i = 0; i < ARRAY_SIZE(filetype_prefix); i++)
914d4c6f1e6SMasatake YAMATO {
915d4c6f1e6SMasatake YAMATO if ((p = strrstr(modeline, filetype_prefix[i])) == NULL)
916d4c6f1e6SMasatake YAMATO continue;
917d4c6f1e6SMasatake YAMATO
918d4c6f1e6SMasatake YAMATO p += strlen(filetype_prefix[i]);
919d4c6f1e6SMasatake YAMATO for ( ; *p != '\0' && isalnum ((int) *p) ; ++p)
920d4c6f1e6SMasatake YAMATO vStringPut (filetype, (int) *p);
921d4c6f1e6SMasatake YAMATO break;
922d4c6f1e6SMasatake YAMATO }
923d4c6f1e6SMasatake YAMATO return filetype;
924d4c6f1e6SMasatake YAMATO }
925d4c6f1e6SMasatake YAMATO
extractVimFileType(MIO * input)926509a47dbSJiří Techet static vString* extractVimFileType(MIO* input)
927d4c6f1e6SMasatake YAMATO {
928d4c6f1e6SMasatake YAMATO /* http://vimdoc.sourceforge.net/htmldoc/options.html#modeline
929d4c6f1e6SMasatake YAMATO
930d4c6f1e6SMasatake YAMATO [text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text]
931d4c6f1e6SMasatake YAMATO options=> filetype=TYPE or ft=TYPE
932d4c6f1e6SMasatake YAMATO
933d4c6f1e6SMasatake YAMATO 'modelines' 'mls' number (default 5)
934d4c6f1e6SMasatake YAMATO global
935d4c6f1e6SMasatake YAMATO {not in Vi}
936d4c6f1e6SMasatake YAMATO If 'modeline' is on 'modelines' gives the number of lines that is
937d4c6f1e6SMasatake YAMATO checked for set commands. */
938d4c6f1e6SMasatake YAMATO
939d4c6f1e6SMasatake YAMATO vString* filetype = NULL;
940d4c6f1e6SMasatake YAMATO #define RING_SIZE 5
941d4c6f1e6SMasatake YAMATO vString* ring[RING_SIZE];
942d4c6f1e6SMasatake YAMATO int i, j;
943d4c6f1e6SMasatake YAMATO unsigned int k;
944d4c6f1e6SMasatake YAMATO const char* const prefix[] = {
945d4c6f1e6SMasatake YAMATO "vim:", "vi:", "ex:"
946d4c6f1e6SMasatake YAMATO };
947d4c6f1e6SMasatake YAMATO
948d4c6f1e6SMasatake YAMATO for (i = 0; i < RING_SIZE; i++)
949d4c6f1e6SMasatake YAMATO ring[i] = vStringNew ();
950d4c6f1e6SMasatake YAMATO
951d4c6f1e6SMasatake YAMATO i = 0;
95278e93ff0SMasatake YAMATO while ((readLineRaw (ring[i++], input)) != NULL)
953d4c6f1e6SMasatake YAMATO if (i == RING_SIZE)
954d4c6f1e6SMasatake YAMATO i = 0;
955d4c6f1e6SMasatake YAMATO
956d4c6f1e6SMasatake YAMATO j = i;
957d4c6f1e6SMasatake YAMATO do
958d4c6f1e6SMasatake YAMATO {
959d4c6f1e6SMasatake YAMATO const char* p;
960d4c6f1e6SMasatake YAMATO
961d4c6f1e6SMasatake YAMATO j--;
962d4c6f1e6SMasatake YAMATO if (j < 0)
963d4c6f1e6SMasatake YAMATO j = RING_SIZE - 1;
964d4c6f1e6SMasatake YAMATO
965d4c6f1e6SMasatake YAMATO for (k = 0; k < ARRAY_SIZE(prefix); k++)
966d4c6f1e6SMasatake YAMATO if ((p = strstr (vStringValue (ring[j]), prefix[k])) != NULL)
967d4c6f1e6SMasatake YAMATO {
968d4c6f1e6SMasatake YAMATO p += strlen(prefix[k]);
969d4c6f1e6SMasatake YAMATO for ( ; isspace ((int) *p) ; ++p)
970d4c6f1e6SMasatake YAMATO ; /* no-op */
971d4c6f1e6SMasatake YAMATO filetype = determineVimFileType(p);
972d4c6f1e6SMasatake YAMATO break;
973d4c6f1e6SMasatake YAMATO }
974d4c6f1e6SMasatake YAMATO } while (((i == RING_SIZE)? (j != RING_SIZE - 1): (j != i)) && (!filetype));
975d4c6f1e6SMasatake YAMATO
976d4c6f1e6SMasatake YAMATO for (i = RING_SIZE - 1; i >= 0; i--)
977d4c6f1e6SMasatake YAMATO vStringDelete (ring[i]);
978d4c6f1e6SMasatake YAMATO #undef RING_SIZE
979d4c6f1e6SMasatake YAMATO
980d4c6f1e6SMasatake YAMATO if (filetype && (vStringLength (filetype) == 0))
981d4c6f1e6SMasatake YAMATO {
982d4c6f1e6SMasatake YAMATO vStringDelete (filetype);
983d4c6f1e6SMasatake YAMATO filetype = NULL;
984d4c6f1e6SMasatake YAMATO }
985d4c6f1e6SMasatake YAMATO return filetype;
986d4c6f1e6SMasatake YAMATO
987d4c6f1e6SMasatake YAMATO /* TODO:
988d4c6f1e6SMasatake YAMATO [text]{white}{vi:|vim:|ex:}[white]{options} */
989d4c6f1e6SMasatake YAMATO }
990d4c6f1e6SMasatake YAMATO
extractMarkGeneric(MIO * input,vString * (* determiner)(const char * const,void *),void * data)991e5025b6dSMasatake YAMATO static vString* extractMarkGeneric (MIO* input,
992e5025b6dSMasatake YAMATO vString * (* determiner)(const char *const, void *),
993e5025b6dSMasatake YAMATO void *data)
994e5025b6dSMasatake YAMATO {
995e5025b6dSMasatake YAMATO vString* const vLine = vStringNew ();
996e5025b6dSMasatake YAMATO const char* const line = readLineRaw (vLine, input);
997e5025b6dSMasatake YAMATO vString* mode = NULL;
998e5025b6dSMasatake YAMATO
999e5025b6dSMasatake YAMATO if (line)
1000e5025b6dSMasatake YAMATO mode = determiner (line, data);
1001e5025b6dSMasatake YAMATO
1002e5025b6dSMasatake YAMATO vStringDelete (vLine);
1003e5025b6dSMasatake YAMATO return mode;
1004e5025b6dSMasatake YAMATO }
1005e5025b6dSMasatake YAMATO
determineZshAutoloadTag(const char * const modeline,void * data CTAGS_ATTR_UNUSED)1006e5025b6dSMasatake YAMATO static vString* determineZshAutoloadTag (const char *const modeline,
1007e5025b6dSMasatake YAMATO void *data CTAGS_ATTR_UNUSED)
1008d4c6f1e6SMasatake YAMATO {
1009d4c6f1e6SMasatake YAMATO /* See "Autoloaded files" in zsh info.
1010d4c6f1e6SMasatake YAMATO -------------------------------------
1011d4c6f1e6SMasatake YAMATO #compdef ...
1012d4c6f1e6SMasatake YAMATO #autoload [ OPTIONS ] */
1013d4c6f1e6SMasatake YAMATO
1014d4c6f1e6SMasatake YAMATO if (((strncmp (modeline, "#compdef", 8) == 0) && isspace (*(modeline + 8)))
1015d4c6f1e6SMasatake YAMATO || ((strncmp (modeline, "#autoload", 9) == 0)
1016d4c6f1e6SMasatake YAMATO && (isspace (*(modeline + 9)) || *(modeline + 9) == '\0')))
1017d4c6f1e6SMasatake YAMATO return vStringNewInit ("zsh");
1018d4c6f1e6SMasatake YAMATO else
1019d4c6f1e6SMasatake YAMATO return NULL;
1020d4c6f1e6SMasatake YAMATO }
1021d4c6f1e6SMasatake YAMATO
extractZshAutoloadTag(MIO * input)1022509a47dbSJiří Techet static vString* extractZshAutoloadTag(MIO* input)
1023d4c6f1e6SMasatake YAMATO {
1024e5025b6dSMasatake YAMATO return extractMarkGeneric (input, determineZshAutoloadTag, NULL);
1025d4c6f1e6SMasatake YAMATO }
1026d4c6f1e6SMasatake YAMATO
determinePHPMark(const char * const modeline,void * data CTAGS_ATTR_UNUSED)1027e5025b6dSMasatake YAMATO static vString* determinePHPMark(const char *const modeline,
1028e5025b6dSMasatake YAMATO void *data CTAGS_ATTR_UNUSED)
1029e5025b6dSMasatake YAMATO {
1030e5025b6dSMasatake YAMATO if (strncmp (modeline, "<?php", 5) == 0)
1031e5025b6dSMasatake YAMATO return vStringNewInit ("php");
1032e5025b6dSMasatake YAMATO else
1033e5025b6dSMasatake YAMATO return NULL;
1034e5025b6dSMasatake YAMATO }
1035e5025b6dSMasatake YAMATO
extractPHPMark(MIO * input)1036e5025b6dSMasatake YAMATO static vString* extractPHPMark(MIO* input)
1037e5025b6dSMasatake YAMATO {
1038e5025b6dSMasatake YAMATO return extractMarkGeneric (input, determinePHPMark, NULL);
1039e5025b6dSMasatake YAMATO }
1040e5025b6dSMasatake YAMATO
1041e5025b6dSMasatake YAMATO
1042d4c6f1e6SMasatake YAMATO struct getLangCtx {
1043d4c6f1e6SMasatake YAMATO const char *fileName;
1044509a47dbSJiří Techet MIO *input;
1045ce990805SThomas Braun bool err;
1046d4c6f1e6SMasatake YAMATO };
1047d4c6f1e6SMasatake YAMATO
1048ad63d66dSMasatake YAMATO #define GLC_FOPEN_IF_NECESSARY0(_glc_, _label_) do { \
1049d4c6f1e6SMasatake YAMATO if (!(_glc_)->input) { \
1050ce990805SThomas Braun (_glc_)->input = getMio((_glc_)->fileName, "rb", false); \
1051d4c6f1e6SMasatake YAMATO if (!(_glc_)->input) { \
1052ce990805SThomas Braun (_glc_)->err = true; \
1053d4c6f1e6SMasatake YAMATO goto _label_; \
1054d4c6f1e6SMasatake YAMATO } \
1055d4c6f1e6SMasatake YAMATO } \
1056d4c6f1e6SMasatake YAMATO } while (0) \
1057d4c6f1e6SMasatake YAMATO
1058ad63d66dSMasatake YAMATO #define GLC_FOPEN_IF_NECESSARY(_glc_, _label_, _doesParserRequireMemoryStream_) \
1059ad63d66dSMasatake YAMATO do { \
1060ad63d66dSMasatake YAMATO if (!(_glc_)->input) \
1061ad63d66dSMasatake YAMATO GLC_FOPEN_IF_NECESSARY0 (_glc_, _label_); \
1062ad63d66dSMasatake YAMATO if ((_doesParserRequireMemoryStream_) && \
10631cffa7e6SMasatake YAMATO (mio_memory_get_data((_glc_)->input, NULL) == NULL)) \
1064ad63d66dSMasatake YAMATO { \
1065ad63d66dSMasatake YAMATO MIO *tmp_ = (_glc_)->input; \
1066915d6979SJiří Techet (_glc_)->input = mio_new_mio (tmp_, 0, -1); \
1067b978efd6SMasatake YAMATO mio_unref (tmp_); \
1068ad63d66dSMasatake YAMATO if (!(_glc_)->input) { \
1069ce990805SThomas Braun (_glc_)->err = true; \
1070ad63d66dSMasatake YAMATO goto _label_; \
1071ad63d66dSMasatake YAMATO } \
1072ad63d66dSMasatake YAMATO } \
1073ad63d66dSMasatake YAMATO } while (0)
1074ad63d66dSMasatake YAMATO
1075d4c6f1e6SMasatake YAMATO #define GLC_FCLOSE(_glc_) do { \
1076d4c6f1e6SMasatake YAMATO if ((_glc_)->input) { \
1077b978efd6SMasatake YAMATO mio_unref((_glc_)->input); \
1078d4c6f1e6SMasatake YAMATO (_glc_)->input = NULL; \
1079d4c6f1e6SMasatake YAMATO } \
1080d4c6f1e6SMasatake YAMATO } while (0)
1081d4c6f1e6SMasatake YAMATO
1082d4c6f1e6SMasatake YAMATO static const struct taster {
1083509a47dbSJiří Techet vString* (* taste) (MIO *);
1084d4c6f1e6SMasatake YAMATO const char *msg;
1085d4c6f1e6SMasatake YAMATO } eager_tasters[] = {
1086d4c6f1e6SMasatake YAMATO {
1087d4c6f1e6SMasatake YAMATO .taste = extractInterpreter,
1088d4c6f1e6SMasatake YAMATO .msg = "interpreter",
1089d4c6f1e6SMasatake YAMATO },
1090d4c6f1e6SMasatake YAMATO {
1091d4c6f1e6SMasatake YAMATO .taste = extractZshAutoloadTag,
1092d4c6f1e6SMasatake YAMATO .msg = "zsh autoload tag",
1093d4c6f1e6SMasatake YAMATO },
1094d4c6f1e6SMasatake YAMATO {
1095100a966cSMasatake YAMATO .taste = extractEmacsModeAtFirstLine,
1096d4c6f1e6SMasatake YAMATO .msg = "emacs mode at the first line",
1097d4c6f1e6SMasatake YAMATO },
1098d4c6f1e6SMasatake YAMATO {
1099d4c6f1e6SMasatake YAMATO .taste = extractEmacsModeLanguageAtEOF,
1100d4c6f1e6SMasatake YAMATO .msg = "emacs mode at the EOF",
1101d4c6f1e6SMasatake YAMATO },
1102d4c6f1e6SMasatake YAMATO {
1103d4c6f1e6SMasatake YAMATO .taste = extractVimFileType,
1104d4c6f1e6SMasatake YAMATO .msg = "vim modeline",
1105d4c6f1e6SMasatake YAMATO },
1106e5025b6dSMasatake YAMATO {
1107e5025b6dSMasatake YAMATO .taste = extractPHPMark,
1108e5025b6dSMasatake YAMATO .msg = "PHP marker",
1109e5025b6dSMasatake YAMATO }
1110d4c6f1e6SMasatake YAMATO };
1111fbbe6498SMasatake YAMATO static langType tasteLanguage (struct getLangCtx *glc, const struct taster *const tasters, int n_tasters,
1112fbbe6498SMasatake YAMATO langType *fallback);
1113d4c6f1e6SMasatake YAMATO
11148e73dfedSDmitri Tikhonov /* If all the candidates have the same specialized language selector, return
11158e73dfedSDmitri Tikhonov * it. Otherwise, return NULL.
11168e73dfedSDmitri Tikhonov */
1117ce990805SThomas Braun static bool
hasTheSameSelector(langType lang,selectLanguage candidate_selector)11185a38b5ceSMasatake YAMATO hasTheSameSelector (langType lang, selectLanguage candidate_selector)
11195a38b5ceSMasatake YAMATO {
11205a38b5ceSMasatake YAMATO selectLanguage *selector;
11215a38b5ceSMasatake YAMATO
1122e02be843SMasatake YAMATO selector = LanguageTable[ lang ].def->selectLanguage;
11235a38b5ceSMasatake YAMATO if (selector == NULL)
1124ce990805SThomas Braun return false;
11255a38b5ceSMasatake YAMATO
11265a38b5ceSMasatake YAMATO while (*selector)
11275a38b5ceSMasatake YAMATO {
11285a38b5ceSMasatake YAMATO if (*selector == candidate_selector)
1129ce990805SThomas Braun return true;
11305a38b5ceSMasatake YAMATO selector++;
11315a38b5ceSMasatake YAMATO }
1132ce990805SThomas Braun return false;
11335a38b5ceSMasatake YAMATO }
11345a38b5ceSMasatake YAMATO
11358e73dfedSDmitri Tikhonov static selectLanguage
commonSelector(const parserCandidate * candidates,int n_candidates)11368e73dfedSDmitri Tikhonov commonSelector (const parserCandidate *candidates, int n_candidates)
11378e73dfedSDmitri Tikhonov {
11388e73dfedSDmitri Tikhonov Assert (n_candidates > 1);
11395a38b5ceSMasatake YAMATO selectLanguage *selector;
11408e73dfedSDmitri Tikhonov int i;
11415a38b5ceSMasatake YAMATO
1142e02be843SMasatake YAMATO selector = LanguageTable[ candidates[0].lang ].def->selectLanguage;
11435a38b5ceSMasatake YAMATO if (selector == NULL)
11448e73dfedSDmitri Tikhonov return NULL;
11455a38b5ceSMasatake YAMATO
11465a38b5ceSMasatake YAMATO while (*selector)
11475a38b5ceSMasatake YAMATO {
11485a38b5ceSMasatake YAMATO for (i = 1; i < n_candidates; ++i)
11495a38b5ceSMasatake YAMATO if (! hasTheSameSelector (candidates[i].lang, *selector))
11505a38b5ceSMasatake YAMATO break;
11515a38b5ceSMasatake YAMATO if (i == n_candidates)
11525a38b5ceSMasatake YAMATO return *selector;
11535a38b5ceSMasatake YAMATO selector++;
11548e73dfedSDmitri Tikhonov }
11555a38b5ceSMasatake YAMATO return NULL;
11565a38b5ceSMasatake YAMATO }
11575a38b5ceSMasatake YAMATO
11588e73dfedSDmitri Tikhonov
11598e73dfedSDmitri Tikhonov /* Calls the selector and returns the integer value of the parser for the
11608e73dfedSDmitri Tikhonov * language associated with the string returned by the selector.
11618e73dfedSDmitri Tikhonov */
11628e73dfedSDmitri Tikhonov static int
pickLanguageBySelection(selectLanguage selector,MIO * input,parserCandidate * candidates,unsigned int nCandidates)11634d58dfe8SMasatake YAMATO pickLanguageBySelection (selectLanguage selector, MIO *input,
11644d58dfe8SMasatake YAMATO parserCandidate *candidates,
11654d58dfe8SMasatake YAMATO unsigned int nCandidates)
11668e73dfedSDmitri Tikhonov {
11674d58dfe8SMasatake YAMATO const char *lang;
11684d58dfe8SMasatake YAMATO langType *cs = xMalloc(nCandidates, langType);
116946ab94ccSMasatake YAMATO unsigned int i;
11704d58dfe8SMasatake YAMATO
11714d58dfe8SMasatake YAMATO for (i = 0; i < nCandidates; i++)
11724d58dfe8SMasatake YAMATO cs[i] = candidates[i].lang;
11734d58dfe8SMasatake YAMATO lang = selector(input, cs, nCandidates);
11744d58dfe8SMasatake YAMATO eFree (cs);
11754d58dfe8SMasatake YAMATO
1176792c8196SDmitri Tikhonov if (lang)
1177cc8eef97SMasatake YAMATO {
1178cc8eef97SMasatake YAMATO verbose (" selection: %s\n", lang);
11795a55f03bSMasatake YAMATO return getNamedLanguage(lang, 0);
1180cc8eef97SMasatake YAMATO }
1181792c8196SDmitri Tikhonov else
1182cc8eef97SMasatake YAMATO {
11838213b2c6SMasatake YAMATO verbose (" no selection\n");
1184792c8196SDmitri Tikhonov return LANG_IGNORE;
11858e73dfedSDmitri Tikhonov }
1186cc8eef97SMasatake YAMATO }
11878e73dfedSDmitri Tikhonov
compareParsersByName(const void * a,const void * b)11885d1ff680SMasatake YAMATO static int compareParsersByName (const void *a, const void* b)
11895d1ff680SMasatake YAMATO {
119059f256efSK.Takata const parserDefinition *const *la = a, *const *lb = b;
11915d1ff680SMasatake YAMATO return strcasecmp ((*la)->name, (*lb)->name);
11925d1ff680SMasatake YAMATO }
11935d1ff680SMasatake YAMATO
sortParserCandidatesBySpecType(const void * a,const void * b)119495512ba5SMasatake YAMATO static int sortParserCandidatesBySpecType (const void *a, const void *b)
119595512ba5SMasatake YAMATO {
119695512ba5SMasatake YAMATO const parserCandidate *ap = a, *bp = b;
119795512ba5SMasatake YAMATO if (ap->specType > bp->specType)
119895512ba5SMasatake YAMATO return -1;
119995512ba5SMasatake YAMATO else if (ap->specType == bp->specType)
12005d1ff680SMasatake YAMATO {
12015d1ff680SMasatake YAMATO /* qsort, the function calling this function,
12025d1ff680SMasatake YAMATO doesn't do "stable sort". To make the result of
12035d1ff680SMasatake YAMATO sorting predictable, compare the names of parsers
12045d1ff680SMasatake YAMATO when their specType is the same. */
1205e02be843SMasatake YAMATO parserDefinition *la = LanguageTable [ap->lang].def;
1206e02be843SMasatake YAMATO parserDefinition *lb = LanguageTable [bp->lang].def;
12075d1ff680SMasatake YAMATO return compareParsersByName (&la, &lb);
12085d1ff680SMasatake YAMATO }
120995512ba5SMasatake YAMATO else
121095512ba5SMasatake YAMATO return 1;
121195512ba5SMasatake YAMATO }
121295512ba5SMasatake YAMATO
sortAndFilterParserCandidates(parserCandidate * candidates,unsigned int n_candidates)121395512ba5SMasatake YAMATO static unsigned int sortAndFilterParserCandidates (parserCandidate *candidates,
121495512ba5SMasatake YAMATO unsigned int n_candidates)
121595512ba5SMasatake YAMATO {
121695512ba5SMasatake YAMATO enum specType highestSpecType;
1217e5f9cc19SMasatake YAMATO unsigned int i;
121895512ba5SMasatake YAMATO unsigned int r;
121995512ba5SMasatake YAMATO
122095512ba5SMasatake YAMATO if (n_candidates < 2)
122195512ba5SMasatake YAMATO return n_candidates;
122295512ba5SMasatake YAMATO
122395512ba5SMasatake YAMATO qsort (candidates, n_candidates, sizeof(*candidates),
122495512ba5SMasatake YAMATO sortParserCandidatesBySpecType);
122595512ba5SMasatake YAMATO
122695512ba5SMasatake YAMATO highestSpecType = candidates [0].specType;
122795512ba5SMasatake YAMATO r = 1;
122895512ba5SMasatake YAMATO for (i = 1; i < n_candidates; i++)
122995512ba5SMasatake YAMATO {
123095512ba5SMasatake YAMATO if (candidates[i].specType == highestSpecType)
123195512ba5SMasatake YAMATO r++;
123295512ba5SMasatake YAMATO }
123395512ba5SMasatake YAMATO return r;
123495512ba5SMasatake YAMATO }
123595512ba5SMasatake YAMATO
verboseReportCandidate(const char * header,parserCandidate * candidates,unsigned int n_candidates)123695512ba5SMasatake YAMATO static void verboseReportCandidate (const char *header,
123795512ba5SMasatake YAMATO parserCandidate *candidates,
123895512ba5SMasatake YAMATO unsigned int n_candidates)
123995512ba5SMasatake YAMATO {
1240e5f9cc19SMasatake YAMATO unsigned int i;
124195512ba5SMasatake YAMATO verbose (" #%s: %u\n", header, n_candidates);
124295512ba5SMasatake YAMATO for (i = 0; i < n_candidates; i++)
124395512ba5SMasatake YAMATO verbose (" %u: %s (%s: \"%s\")\n",
124495512ba5SMasatake YAMATO i,
1245e02be843SMasatake YAMATO LanguageTable[candidates[i].lang].def->name,
124695512ba5SMasatake YAMATO specTypeName [candidates[i].specType],
124795512ba5SMasatake YAMATO candidates[i].spec);
124895512ba5SMasatake YAMATO }
124995512ba5SMasatake YAMATO
doesCandidatesRequireMemoryStream(const parserCandidate * candidates,int n_candidates)1250ce990805SThomas Braun static bool doesCandidatesRequireMemoryStream(const parserCandidate *candidates,
1251ad63d66dSMasatake YAMATO int n_candidates)
1252ad63d66dSMasatake YAMATO {
1253ad63d66dSMasatake YAMATO int i;
1254ad63d66dSMasatake YAMATO
1255ad63d66dSMasatake YAMATO for (i = 0; i < n_candidates; i++)
1256ad63d66dSMasatake YAMATO if (doesParserRequireMemoryStream (candidates[i].lang))
1257ce990805SThomas Braun return true;
1258ad63d66dSMasatake YAMATO
1259ce990805SThomas Braun return false;
1260ad63d66dSMasatake YAMATO }
1261ad63d66dSMasatake YAMATO
getSpecLanguageCommon(const char * const spec,struct getLangCtx * glc,unsigned int nominate (const char * const,parserCandidate **),langType * fallback)1262d4c6f1e6SMasatake YAMATO static langType getSpecLanguageCommon (const char *const spec, struct getLangCtx *glc,
1263fbbe6498SMasatake YAMATO unsigned int nominate (const char *const, parserCandidate**),
1264fbbe6498SMasatake YAMATO langType *fallback)
1265d4c6f1e6SMasatake YAMATO {
1266d4c6f1e6SMasatake YAMATO langType language;
1267d4c6f1e6SMasatake YAMATO parserCandidate *candidates;
1268d4c6f1e6SMasatake YAMATO unsigned int n_candidates;
126995512ba5SMasatake YAMATO
1270fbbe6498SMasatake YAMATO if (fallback)
1271fbbe6498SMasatake YAMATO *fallback = LANG_IGNORE;
1272fbbe6498SMasatake YAMATO
1273d4c6f1e6SMasatake YAMATO n_candidates = (*nominate)(spec, &candidates);
127495512ba5SMasatake YAMATO verboseReportCandidate ("candidates",
127595512ba5SMasatake YAMATO candidates, n_candidates);
1276d4c6f1e6SMasatake YAMATO
127795512ba5SMasatake YAMATO n_candidates = sortAndFilterParserCandidates (candidates, n_candidates);
127895512ba5SMasatake YAMATO verboseReportCandidate ("candidates after sorting and filtering",
127995512ba5SMasatake YAMATO candidates, n_candidates);
1280672d7311SMasatake YAMATO
1281d4c6f1e6SMasatake YAMATO if (n_candidates == 1)
1282d4c6f1e6SMasatake YAMATO {
1283d4c6f1e6SMasatake YAMATO language = candidates[0].lang;
1284d4c6f1e6SMasatake YAMATO }
1285d4c6f1e6SMasatake YAMATO else if (n_candidates > 1)
1286d4c6f1e6SMasatake YAMATO {
12878e73dfedSDmitri Tikhonov selectLanguage selector = commonSelector(candidates, n_candidates);
1288ce990805SThomas Braun bool memStreamRequired = doesCandidatesRequireMemoryStream (candidates,
1289ad63d66dSMasatake YAMATO n_candidates);
1290ad63d66dSMasatake YAMATO
1291ad63d66dSMasatake YAMATO GLC_FOPEN_IF_NECESSARY(glc, fopen_error, memStreamRequired);
12928e73dfedSDmitri Tikhonov if (selector) {
12935a3d25e6SMasatake YAMATO verbose (" selector: %p\n", selector);
12944d58dfe8SMasatake YAMATO language = pickLanguageBySelection(selector, glc->input, candidates, n_candidates);
12958e73dfedSDmitri Tikhonov } else {
12965a3d25e6SMasatake YAMATO verbose (" selector: NONE\n");
129781226553SMasatake YAMATO fopen_error:
129838a0a38cSMasatake YAMATO language = LANG_IGNORE;
12998e73dfedSDmitri Tikhonov }
130038a0a38cSMasatake YAMATO
13010bc128d2SMasatake YAMATO Assert(language != LANG_AUTO);
13020bc128d2SMasatake YAMATO
1303fbbe6498SMasatake YAMATO if (fallback)
1304fbbe6498SMasatake YAMATO *fallback = candidates[0].lang;
1305d4c6f1e6SMasatake YAMATO }
1306d4c6f1e6SMasatake YAMATO else
1307d4c6f1e6SMasatake YAMATO {
1308d4c6f1e6SMasatake YAMATO language = LANG_IGNORE;
1309d4c6f1e6SMasatake YAMATO }
1310d4c6f1e6SMasatake YAMATO
1311d4c6f1e6SMasatake YAMATO eFree(candidates);
1312d4c6f1e6SMasatake YAMATO candidates = NULL;
1313d4c6f1e6SMasatake YAMATO
1314d4c6f1e6SMasatake YAMATO return language;
1315d4c6f1e6SMasatake YAMATO }
1316d4c6f1e6SMasatake YAMATO
getSpecLanguage(const char * const spec,struct getLangCtx * glc,langType * fallback)1317d4c6f1e6SMasatake YAMATO static langType getSpecLanguage (const char *const spec,
1318fbbe6498SMasatake YAMATO struct getLangCtx *glc,
1319fbbe6498SMasatake YAMATO langType *fallback)
1320d4c6f1e6SMasatake YAMATO {
1321fbbe6498SMasatake YAMATO return getSpecLanguageCommon(spec, glc, nominateLanguageCandidates,
1322fbbe6498SMasatake YAMATO fallback);
1323d4c6f1e6SMasatake YAMATO }
1324d4c6f1e6SMasatake YAMATO
getPatternLanguage(const char * const baseName,struct getLangCtx * glc,langType * fallback)1325d4c6f1e6SMasatake YAMATO static langType getPatternLanguage (const char *const baseName,
1326fbbe6498SMasatake YAMATO struct getLangCtx *glc,
1327fbbe6498SMasatake YAMATO langType *fallback)
1328d4c6f1e6SMasatake YAMATO {
1329d4c6f1e6SMasatake YAMATO return getSpecLanguageCommon(baseName, glc,
1330fbbe6498SMasatake YAMATO nominateLanguageCandidatesForPattern,
1331fbbe6498SMasatake YAMATO fallback);
1332d4c6f1e6SMasatake YAMATO }
1333d4c6f1e6SMasatake YAMATO
1334d4c6f1e6SMasatake YAMATO /* This function tries to figure out language contained in a file by
1335d4c6f1e6SMasatake YAMATO * running a series of tests, trying to find some clues in the file.
1336d4c6f1e6SMasatake YAMATO */
1337d4c6f1e6SMasatake YAMATO static langType
tasteLanguage(struct getLangCtx * glc,const struct taster * const tasters,int n_tasters,langType * fallback)1338fbbe6498SMasatake YAMATO tasteLanguage (struct getLangCtx *glc, const struct taster *const tasters, int n_tasters,
1339fbbe6498SMasatake YAMATO langType *fallback)
1340d4c6f1e6SMasatake YAMATO {
1341d4c6f1e6SMasatake YAMATO int i;
1342d4c6f1e6SMasatake YAMATO
1343fbbe6498SMasatake YAMATO if (fallback)
1344fbbe6498SMasatake YAMATO *fallback = LANG_IGNORE;
1345d4c6f1e6SMasatake YAMATO for (i = 0; i < n_tasters; ++i) {
1346d4c6f1e6SMasatake YAMATO langType language;
1347d4c6f1e6SMasatake YAMATO vString* spec;
13484f61e7d5SMasatake YAMATO
1349509a47dbSJiří Techet mio_rewind(glc->input);
13504f61e7d5SMasatake YAMATO spec = tasters[i].taste(glc->input);
13514f61e7d5SMasatake YAMATO
13524f61e7d5SMasatake YAMATO if (NULL != spec) {
1353d4c6f1e6SMasatake YAMATO verbose (" %s: %s\n", tasters[i].msg, vStringValue (spec));
1354fbbe6498SMasatake YAMATO language = getSpecLanguage (vStringValue (spec), glc,
1355fbbe6498SMasatake YAMATO (fallback && (*fallback == LANG_IGNORE))? fallback: NULL);
1356d4c6f1e6SMasatake YAMATO vStringDelete (spec);
1357d4c6f1e6SMasatake YAMATO if (language != LANG_IGNORE)
1358d4c6f1e6SMasatake YAMATO return language;
1359d4c6f1e6SMasatake YAMATO }
1360d4c6f1e6SMasatake YAMATO }
1361d4c6f1e6SMasatake YAMATO
1362d4c6f1e6SMasatake YAMATO return LANG_IGNORE;
1363d4c6f1e6SMasatake YAMATO }
1364d4c6f1e6SMasatake YAMATO
1365cfac930dSMasatake YAMATO
1366cfac930dSMasatake YAMATO struct GetLanguageRequest {
1367cfac930dSMasatake YAMATO enum { GLR_OPEN, GLR_DISCARD, GLR_REUSE, } type;
1368cfac930dSMasatake YAMATO const char *const fileName;
1369cfac930dSMasatake YAMATO MIO *mio;
1370ce1f2415SMasatake YAMATO time_t mtime;
1371cfac930dSMasatake YAMATO };
1372cfac930dSMasatake YAMATO
1373d4c6f1e6SMasatake YAMATO static langType
getFileLanguageForRequestInternal(struct GetLanguageRequest * req)1374cfac930dSMasatake YAMATO getFileLanguageForRequestInternal (struct GetLanguageRequest *req)
1375d4c6f1e6SMasatake YAMATO {
1376cfac930dSMasatake YAMATO const char *const fileName = req->fileName;
1377d4c6f1e6SMasatake YAMATO langType language;
1378fbbe6498SMasatake YAMATO
1379fbbe6498SMasatake YAMATO /* ctags tries variety ways(HINTS) to choose a proper language
1380fbbe6498SMasatake YAMATO for given fileName. If multiple candidates are chosen in one of
1381fbbe6498SMasatake YAMATO the hint, a SELECTOR common between the candidate languages
1382fbbe6498SMasatake YAMATO is called.
1383fbbe6498SMasatake YAMATO
1384fbbe6498SMasatake YAMATO "selection failure" means a selector common between the
1385fbbe6498SMasatake YAMATO candidates doesn't exist or the common selector returns NULL.
1386fbbe6498SMasatake YAMATO
1387fbbe6498SMasatake YAMATO "hint failure" means the hint finds no candidate or
1388fbbe6498SMasatake YAMATO "selection failure" occurs though the hint finds multiple
1389fbbe6498SMasatake YAMATO candidates.
1390fbbe6498SMasatake YAMATO
1391fbbe6498SMasatake YAMATO If a hint chooses multiple candidates, and selection failure is
1392759d281dSK.Takata occurred, the hint records one of the candidates as FALLBACK for
1393fbbe6498SMasatake YAMATO the hint. (The candidates are stored in an array. The first
1394fbbe6498SMasatake YAMATO element of the array is recorded. However, there is no
1395fbbe6498SMasatake YAMATO specification about the order of elements in the array.)
1396fbbe6498SMasatake YAMATO
1397fbbe6498SMasatake YAMATO If all hints are failed, FALLBACKs of the hints are examined.
1398fbbe6498SMasatake YAMATO Which fallbacks should be chosen? `enum hint' defines the order. */
1399fbbe6498SMasatake YAMATO enum hint {
1400fbbe6498SMasatake YAMATO HINT_INTERP,
1401fbbe6498SMasatake YAMATO HINT_OTHER,
1402fbbe6498SMasatake YAMATO HINT_FILENAME,
1403fbbe6498SMasatake YAMATO HINT_TEMPLATE,
1404fbbe6498SMasatake YAMATO N_HINTS,
1405fbbe6498SMasatake YAMATO };
1406fbbe6498SMasatake YAMATO langType fallback[N_HINTS];
1407fbbe6498SMasatake YAMATO int i;
1408d4c6f1e6SMasatake YAMATO struct getLangCtx glc = {
1409d4c6f1e6SMasatake YAMATO .fileName = fileName,
1410cfac930dSMasatake YAMATO .input = (req->type == GLR_REUSE)? mio_ref (req->mio): NULL,
1411ce990805SThomas Braun .err = false,
1412d4c6f1e6SMasatake YAMATO };
1413d4c6f1e6SMasatake YAMATO const char* const baseName = baseFilename (fileName);
1414d4c6f1e6SMasatake YAMATO char *templateBaseName = NULL;
1415d4c6f1e6SMasatake YAMATO fileStatus *fstatus = NULL;
1416d4c6f1e6SMasatake YAMATO
1417fbbe6498SMasatake YAMATO for (i = 0; i < N_HINTS; i++)
1418fbbe6498SMasatake YAMATO fallback [i] = LANG_IGNORE;
1419fbbe6498SMasatake YAMATO
1420d4c6f1e6SMasatake YAMATO verbose ("Get file language for %s\n", fileName);
1421d4c6f1e6SMasatake YAMATO
1422d4c6f1e6SMasatake YAMATO verbose (" pattern: %s\n", baseName);
1423fbbe6498SMasatake YAMATO language = getPatternLanguage (baseName, &glc,
1424fbbe6498SMasatake YAMATO fallback + HINT_FILENAME);
1425d4c6f1e6SMasatake YAMATO if (language != LANG_IGNORE || glc.err)
1426d4c6f1e6SMasatake YAMATO goto cleanup;
1427d4c6f1e6SMasatake YAMATO
1428d4c6f1e6SMasatake YAMATO {
1429d4c6f1e6SMasatake YAMATO const char* const tExt = ".in";
1430d4c6f1e6SMasatake YAMATO templateBaseName = baseFilenameSansExtensionNew (fileName, tExt);
1431d4c6f1e6SMasatake YAMATO if (templateBaseName)
1432d4c6f1e6SMasatake YAMATO {
1433d4c6f1e6SMasatake YAMATO verbose (" pattern + template(%s): %s\n", tExt, templateBaseName);
1434ce990805SThomas Braun GLC_FOPEN_IF_NECESSARY(&glc, cleanup, false);
1435509a47dbSJiří Techet mio_rewind(glc.input);
1436fbbe6498SMasatake YAMATO language = getPatternLanguage(templateBaseName, &glc,
1437fbbe6498SMasatake YAMATO fallback + HINT_TEMPLATE);
1438d4c6f1e6SMasatake YAMATO if (language != LANG_IGNORE)
1439d4c6f1e6SMasatake YAMATO goto cleanup;
1440d4c6f1e6SMasatake YAMATO }
1441d4c6f1e6SMasatake YAMATO }
1442d4c6f1e6SMasatake YAMATO
14431bd2ff77SMasatake YAMATO /* If the input is already opened, we don't have to verify the existence. */
14441bd2ff77SMasatake YAMATO if (glc.input || ((fstatus = eStat (fileName)) && fstatus->exists))
1445d4c6f1e6SMasatake YAMATO {
14461bd2ff77SMasatake YAMATO if ((fstatus && fstatus->isExecutable) || Option.guessLanguageEagerly)
1447d4c6f1e6SMasatake YAMATO {
1448ce990805SThomas Braun GLC_FOPEN_IF_NECESSARY (&glc, cleanup, false);
1449fbbe6498SMasatake YAMATO language = tasteLanguage(&glc, eager_tasters, 1,
1450fbbe6498SMasatake YAMATO fallback + HINT_INTERP);
1451d4c6f1e6SMasatake YAMATO }
1452d4c6f1e6SMasatake YAMATO if (language != LANG_IGNORE)
1453d4c6f1e6SMasatake YAMATO goto cleanup;
1454d4c6f1e6SMasatake YAMATO
1455d4c6f1e6SMasatake YAMATO if (Option.guessLanguageEagerly)
1456d4c6f1e6SMasatake YAMATO {
1457ce990805SThomas Braun GLC_FOPEN_IF_NECESSARY(&glc, cleanup, false);
1458d4c6f1e6SMasatake YAMATO language = tasteLanguage(&glc,
1459d4c6f1e6SMasatake YAMATO eager_tasters + 1,
1460fbbe6498SMasatake YAMATO ARRAY_SIZE(eager_tasters) - 1,
1461fbbe6498SMasatake YAMATO fallback + HINT_OTHER);
1462d4c6f1e6SMasatake YAMATO }
1463d4c6f1e6SMasatake YAMATO }
1464d4c6f1e6SMasatake YAMATO
1465d4c6f1e6SMasatake YAMATO
1466d4c6f1e6SMasatake YAMATO cleanup:
1467cfac930dSMasatake YAMATO if (req->type == GLR_OPEN && glc.input)
1468ce1f2415SMasatake YAMATO {
1469cfac930dSMasatake YAMATO req->mio = mio_ref (glc.input);
1470ce1f2415SMasatake YAMATO if (!fstatus)
1471ce1f2415SMasatake YAMATO fstatus = eStat (fileName);
1472ce1f2415SMasatake YAMATO if (fstatus)
1473ce1f2415SMasatake YAMATO req->mtime = fstatus->mtime;
1474ce1f2415SMasatake YAMATO }
1475d4c6f1e6SMasatake YAMATO GLC_FCLOSE(&glc);
1476d4c6f1e6SMasatake YAMATO if (fstatus)
1477d4c6f1e6SMasatake YAMATO eStatFree (fstatus);
1478d4c6f1e6SMasatake YAMATO if (templateBaseName)
1479d4c6f1e6SMasatake YAMATO eFree (templateBaseName);
1480fbbe6498SMasatake YAMATO
1481fbbe6498SMasatake YAMATO for (i = 0;
1482fbbe6498SMasatake YAMATO language == LANG_IGNORE && i < N_HINTS;
1483fbbe6498SMasatake YAMATO i++)
1484fbbe6498SMasatake YAMATO {
1485fbbe6498SMasatake YAMATO language = fallback [i];
1486fbbe6498SMasatake YAMATO if (language != LANG_IGNORE)
1487fbbe6498SMasatake YAMATO verbose (" fallback[hint = %d]: %s\n", i, getLanguageName (language));
1488fbbe6498SMasatake YAMATO }
1489fbbe6498SMasatake YAMATO
149082791c20SMasatake YAMATO if (language == LANG_IGNORE
1491d8a63e0bSMasatake YAMATO && isLanguageEnabled (LANG_FALLBACK))
149282791c20SMasatake YAMATO {
149382791c20SMasatake YAMATO language = LANG_FALLBACK;
149482791c20SMasatake YAMATO verbose (" last resort: using \"%s\" parser\n",
149582791c20SMasatake YAMATO getLanguageName (LANG_FALLBACK));
149682791c20SMasatake YAMATO }
1497d4c6f1e6SMasatake YAMATO return language;
1498d4c6f1e6SMasatake YAMATO }
1499d4c6f1e6SMasatake YAMATO
getFileLanguageForRequest(struct GetLanguageRequest * req)1500cfac930dSMasatake YAMATO static langType getFileLanguageForRequest (struct GetLanguageRequest *req)
1501d4c6f1e6SMasatake YAMATO {
150242b60e7aSMasatake YAMATO langType l = Option.language;
150342b60e7aSMasatake YAMATO
150442b60e7aSMasatake YAMATO if (l == LANG_AUTO)
1505cfac930dSMasatake YAMATO return getFileLanguageForRequestInternal(req);
150642b60e7aSMasatake YAMATO else if (! isLanguageEnabled (l))
150742b60e7aSMasatake YAMATO {
150842b60e7aSMasatake YAMATO error (FATAL,
15093e7e9e07SMasatake YAMATO "%s parser specified with --language-force is disabled",
151042b60e7aSMasatake YAMATO getLanguageName (l));
151142b60e7aSMasatake YAMATO /* For suppressing warnings. */
151242b60e7aSMasatake YAMATO return LANG_AUTO;
151342b60e7aSMasatake YAMATO }
1514d4c6f1e6SMasatake YAMATO else
1515d4c6f1e6SMasatake YAMATO return Option.language;
1516d4c6f1e6SMasatake YAMATO }
1517d4c6f1e6SMasatake YAMATO
getLanguageForFilenameAndContents(const char * const fileName)15185329ae51SMasatake YAMATO extern langType getLanguageForFilenameAndContents (const char *const fileName)
1519e9d4c72cSMasatake YAMATO {
1520cfac930dSMasatake YAMATO struct GetLanguageRequest req = {
1521cfac930dSMasatake YAMATO .type = GLR_DISCARD,
1522cfac930dSMasatake YAMATO .fileName = fileName,
1523ce1f2415SMasatake YAMATO .mtime = (time_t)0,
1524cfac930dSMasatake YAMATO };
1525cfac930dSMasatake YAMATO
1526cfac930dSMasatake YAMATO return getFileLanguageForRequest (&req);
1527e9d4c72cSMasatake YAMATO }
1528e9d4c72cSMasatake YAMATO
1529d4c6f1e6SMasatake YAMATO typedef void (*languageCallback) (langType language, void* user_data);
foreachLanguage(languageCallback callback,void * user_data)1530d4c6f1e6SMasatake YAMATO static void foreachLanguage(languageCallback callback, void *user_data)
1531d4c6f1e6SMasatake YAMATO {
1532d4c6f1e6SMasatake YAMATO langType result = LANG_IGNORE;
1533d4c6f1e6SMasatake YAMATO
1534d4c6f1e6SMasatake YAMATO unsigned int i;
1535d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount && result == LANG_IGNORE ; ++i)
1536d4c6f1e6SMasatake YAMATO {
1537e02be843SMasatake YAMATO const parserDefinition* const lang = LanguageTable [i].def;
1538d4c6f1e6SMasatake YAMATO if (lang->name != NULL)
1539d4c6f1e6SMasatake YAMATO callback(i, user_data);
1540d4c6f1e6SMasatake YAMATO }
1541d4c6f1e6SMasatake YAMATO }
1542d4c6f1e6SMasatake YAMATO
printLanguageMap(const langType language,FILE * fp)1543a21d5fcdSMasatake YAMATO static void printLanguageMap (const langType language, FILE *fp)
1544d4c6f1e6SMasatake YAMATO {
1545ce990805SThomas Braun bool first = true;
1546d4c6f1e6SMasatake YAMATO unsigned int i;
1547efe089d4SMasatake YAMATO parserObject *parser = LanguageTable + language;
1548efe089d4SMasatake YAMATO stringList* map = parser->currentPatterns;
1549d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1550d4c6f1e6SMasatake YAMATO for (i = 0 ; map != NULL && i < stringListCount (map) ; ++i)
1551d4c6f1e6SMasatake YAMATO {
1552d4c6f1e6SMasatake YAMATO fprintf (fp, "%s(%s)", (first ? "" : " "),
1553d4c6f1e6SMasatake YAMATO vStringValue (stringListItem (map, i)));
1554ce990805SThomas Braun first = false;
1555d4c6f1e6SMasatake YAMATO }
1556efe089d4SMasatake YAMATO map = parser->currentExtensions;
1557d4c6f1e6SMasatake YAMATO for (i = 0 ; map != NULL && i < stringListCount (map) ; ++i)
1558d4c6f1e6SMasatake YAMATO {
1559d4c6f1e6SMasatake YAMATO fprintf (fp, "%s.%s", (first ? "" : " "),
1560d4c6f1e6SMasatake YAMATO vStringValue (stringListItem (map, i)));
1561ce990805SThomas Braun first = false;
1562d4c6f1e6SMasatake YAMATO }
1563d4c6f1e6SMasatake YAMATO }
1564d4c6f1e6SMasatake YAMATO
installLanguageMapDefault(const langType language)1565d4c6f1e6SMasatake YAMATO extern void installLanguageMapDefault (const langType language)
1566d4c6f1e6SMasatake YAMATO {
1567efe089d4SMasatake YAMATO parserObject* parser;
1568d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1569efe089d4SMasatake YAMATO parser = LanguageTable + language;
1570efe089d4SMasatake YAMATO if (parser->currentPatterns != NULL)
1571efe089d4SMasatake YAMATO stringListDelete (parser->currentPatterns);
1572efe089d4SMasatake YAMATO if (parser->currentExtensions != NULL)
1573efe089d4SMasatake YAMATO stringListDelete (parser->currentExtensions);
1574d4c6f1e6SMasatake YAMATO
1575efe089d4SMasatake YAMATO if (parser->def->patterns == NULL)
1576efe089d4SMasatake YAMATO parser->currentPatterns = stringListNew ();
1577d4c6f1e6SMasatake YAMATO else
1578d4c6f1e6SMasatake YAMATO {
1579efe089d4SMasatake YAMATO parser->currentPatterns =
1580efe089d4SMasatake YAMATO stringListNewFromArgv (parser->def->patterns);
1581d4c6f1e6SMasatake YAMATO }
1582efe089d4SMasatake YAMATO if (parser->def->extensions == NULL)
1583efe089d4SMasatake YAMATO parser->currentExtensions = stringListNew ();
1584d4c6f1e6SMasatake YAMATO else
1585d4c6f1e6SMasatake YAMATO {
1586efe089d4SMasatake YAMATO parser->currentExtensions =
1587efe089d4SMasatake YAMATO stringListNewFromArgv (parser->def->extensions);
1588d4c6f1e6SMasatake YAMATO }
1589d4c6f1e6SMasatake YAMATO BEGIN_VERBOSE(vfp);
1590d4c6f1e6SMasatake YAMATO {
1591d4c6f1e6SMasatake YAMATO printLanguageMap (language, vfp);
1592d4c6f1e6SMasatake YAMATO putc ('\n', vfp);
1593d4c6f1e6SMasatake YAMATO }
1594d4c6f1e6SMasatake YAMATO END_VERBOSE();
1595d4c6f1e6SMasatake YAMATO }
1596d4c6f1e6SMasatake YAMATO
installLanguageMapDefaults(void)1597d4c6f1e6SMasatake YAMATO extern void installLanguageMapDefaults (void)
1598d4c6f1e6SMasatake YAMATO {
1599d4c6f1e6SMasatake YAMATO unsigned int i;
1600d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
1601d4c6f1e6SMasatake YAMATO {
1602d4c6f1e6SMasatake YAMATO verbose (" %s: ", getLanguageName (i));
1603d4c6f1e6SMasatake YAMATO installLanguageMapDefault (i);
1604d4c6f1e6SMasatake YAMATO }
1605d4c6f1e6SMasatake YAMATO }
1606d4c6f1e6SMasatake YAMATO
installLanguageAliasesDefault(const langType language)1607d4c6f1e6SMasatake YAMATO extern void installLanguageAliasesDefault (const langType language)
1608d4c6f1e6SMasatake YAMATO {
1609efe089d4SMasatake YAMATO parserObject* parser;
1610d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1611efe089d4SMasatake YAMATO parser = LanguageTable + language;
1612efe089d4SMasatake YAMATO if (parser->currentAliases != NULL)
1613efe089d4SMasatake YAMATO stringListDelete (parser->currentAliases);
1614d4c6f1e6SMasatake YAMATO
1615efe089d4SMasatake YAMATO if (parser->def->aliases == NULL)
1616efe089d4SMasatake YAMATO parser->currentAliases = stringListNew ();
1617d4c6f1e6SMasatake YAMATO else
1618d4c6f1e6SMasatake YAMATO {
1619efe089d4SMasatake YAMATO parser->currentAliases =
1620efe089d4SMasatake YAMATO stringListNewFromArgv (parser->def->aliases);
1621d4c6f1e6SMasatake YAMATO }
1622d4c6f1e6SMasatake YAMATO BEGIN_VERBOSE(vfp);
16233de0d210SMasatake YAMATO if (parser->currentAliases != NULL)
16243de0d210SMasatake YAMATO for (unsigned int i = 0 ; i < stringListCount (parser->currentAliases) ; ++i)
16253de0d210SMasatake YAMATO fprintf (vfp, " %s", vStringValue (
16263de0d210SMasatake YAMATO stringListItem (parser->currentAliases, i)));
1627d4c6f1e6SMasatake YAMATO putc ('\n', vfp);
1628d4c6f1e6SMasatake YAMATO END_VERBOSE();
1629d4c6f1e6SMasatake YAMATO }
16303de0d210SMasatake YAMATO
installLanguageAliasesDefaults(void)1631d4c6f1e6SMasatake YAMATO extern void installLanguageAliasesDefaults (void)
1632d4c6f1e6SMasatake YAMATO {
1633d4c6f1e6SMasatake YAMATO unsigned int i;
1634d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
1635d4c6f1e6SMasatake YAMATO {
1636d4c6f1e6SMasatake YAMATO verbose (" %s: ", getLanguageName (i));
1637d4c6f1e6SMasatake YAMATO installLanguageAliasesDefault (i);
1638d4c6f1e6SMasatake YAMATO }
1639d4c6f1e6SMasatake YAMATO }
1640d4c6f1e6SMasatake YAMATO
clearLanguageMap(const langType language)1641d4c6f1e6SMasatake YAMATO extern void clearLanguageMap (const langType language)
1642d4c6f1e6SMasatake YAMATO {
1643d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1644efe089d4SMasatake YAMATO stringListClear ((LanguageTable + language)->currentPatterns);
1645efe089d4SMasatake YAMATO stringListClear ((LanguageTable + language)->currentExtensions);
1646d4c6f1e6SMasatake YAMATO }
1647d4c6f1e6SMasatake YAMATO
clearLanguageAliases(const langType language)1648d4c6f1e6SMasatake YAMATO extern void clearLanguageAliases (const langType language)
1649d4c6f1e6SMasatake YAMATO {
1650d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1651237651d1SMasatake YAMATO
1652237651d1SMasatake YAMATO parserObject* parser = (LanguageTable + language);
1653237651d1SMasatake YAMATO if (parser->currentAliases)
1654237651d1SMasatake YAMATO stringListClear (parser->currentAliases);
1655d4c6f1e6SMasatake YAMATO }
1656d4c6f1e6SMasatake YAMATO
removeLanguagePatternMap1(const langType language,const char * const pattern)1657ce990805SThomas Braun static bool removeLanguagePatternMap1(const langType language, const char *const pattern)
16585455a701SMasatake YAMATO {
1659ce990805SThomas Braun bool result = false;
1660efe089d4SMasatake YAMATO stringList* const ptrn = (LanguageTable + language)->currentPatterns;
1661d815b8c3SMasatake YAMATO
1662af2ee6f2SMasatake YAMATO if (ptrn != NULL && stringListDeleteItemExtension (ptrn, pattern))
16635455a701SMasatake YAMATO {
1664d815b8c3SMasatake YAMATO verbose (" (removed from %s)", getLanguageName (language));
1665ce990805SThomas Braun result = true;
16665455a701SMasatake YAMATO }
1667d815b8c3SMasatake YAMATO return result;
16685455a701SMasatake YAMATO }
1669d815b8c3SMasatake YAMATO
removeLanguagePatternMap(const langType language,const char * const pattern)1670ce990805SThomas Braun extern bool removeLanguagePatternMap (const langType language, const char *const pattern)
1671d815b8c3SMasatake YAMATO {
1672ce990805SThomas Braun bool result = false;
1673d815b8c3SMasatake YAMATO
1674d815b8c3SMasatake YAMATO if (language == LANG_AUTO)
1675d815b8c3SMasatake YAMATO {
1676d815b8c3SMasatake YAMATO unsigned int i;
1677d815b8c3SMasatake YAMATO for (i = 0 ; i < LanguageCount && ! result ; ++i)
1678d815b8c3SMasatake YAMATO result = removeLanguagePatternMap1 (i, pattern) || result;
1679d815b8c3SMasatake YAMATO }
1680d815b8c3SMasatake YAMATO else
1681d815b8c3SMasatake YAMATO result = removeLanguagePatternMap1 (language, pattern);
16825455a701SMasatake YAMATO return result;
16835455a701SMasatake YAMATO }
16845455a701SMasatake YAMATO
addLanguagePatternMap(const langType language,const char * ptrn,bool exclusiveInAllLanguages)1685d932931fSMasatake YAMATO extern void addLanguagePatternMap (const langType language, const char* ptrn,
1686ce990805SThomas Braun bool exclusiveInAllLanguages)
1687d4c6f1e6SMasatake YAMATO {
1688d4c6f1e6SMasatake YAMATO vString* const str = vStringNewInit (ptrn);
1689efe089d4SMasatake YAMATO parserObject* parser;
1690d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1691efe089d4SMasatake YAMATO parser = LanguageTable + language;
1692d932931fSMasatake YAMATO if (exclusiveInAllLanguages)
1693d932931fSMasatake YAMATO removeLanguagePatternMap (LANG_AUTO, ptrn);
1694efe089d4SMasatake YAMATO stringListAdd (parser->currentPatterns, str);
1695d4c6f1e6SMasatake YAMATO }
1696d4c6f1e6SMasatake YAMATO
removeLanguageExtensionMap1(const langType language,const char * const extension)1697ce990805SThomas Braun static bool removeLanguageExtensionMap1 (const langType language, const char *const extension)
1698d4c6f1e6SMasatake YAMATO {
1699ce990805SThomas Braun bool result = false;
1700efe089d4SMasatake YAMATO stringList* const exts = (LanguageTable + language)->currentExtensions;
1701d815b8c3SMasatake YAMATO
1702af2ee6f2SMasatake YAMATO if (exts != NULL && stringListDeleteItemExtension (exts, extension))
1703d4c6f1e6SMasatake YAMATO {
1704d815b8c3SMasatake YAMATO verbose (" (removed from %s)", getLanguageName (language));
1705ce990805SThomas Braun result = true;
1706d4c6f1e6SMasatake YAMATO }
1707d815b8c3SMasatake YAMATO return result;
1708d4c6f1e6SMasatake YAMATO }
1709d815b8c3SMasatake YAMATO
removeLanguageExtensionMap(const langType language,const char * const extension)1710ce990805SThomas Braun extern bool removeLanguageExtensionMap (const langType language, const char *const extension)
1711d815b8c3SMasatake YAMATO {
1712ce990805SThomas Braun bool result = false;
1713d815b8c3SMasatake YAMATO
1714d815b8c3SMasatake YAMATO if (language == LANG_AUTO)
1715d815b8c3SMasatake YAMATO {
1716d815b8c3SMasatake YAMATO unsigned int i;
1717d815b8c3SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
1718d815b8c3SMasatake YAMATO result = removeLanguageExtensionMap1 (i, extension) || result;
1719d815b8c3SMasatake YAMATO }
1720d815b8c3SMasatake YAMATO else
1721d815b8c3SMasatake YAMATO result = removeLanguageExtensionMap1 (language, extension);
1722d4c6f1e6SMasatake YAMATO return result;
1723d4c6f1e6SMasatake YAMATO }
1724d4c6f1e6SMasatake YAMATO
addLanguageExtensionMap(const langType language,const char * extension,bool exclusiveInAllLanguages)1725d4c6f1e6SMasatake YAMATO extern void addLanguageExtensionMap (
1726d932931fSMasatake YAMATO const langType language, const char* extension,
1727ce990805SThomas Braun bool exclusiveInAllLanguages)
1728d4c6f1e6SMasatake YAMATO {
1729d4c6f1e6SMasatake YAMATO vString* const str = vStringNewInit (extension);
1730d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1731d932931fSMasatake YAMATO if (exclusiveInAllLanguages)
1732d932931fSMasatake YAMATO removeLanguageExtensionMap (LANG_AUTO, extension);
1733efe089d4SMasatake YAMATO stringListAdd ((LanguageTable + language)->currentExtensions, str);
1734d4c6f1e6SMasatake YAMATO }
1735d4c6f1e6SMasatake YAMATO
addLanguageAlias(const langType language,const char * alias)1736d4c6f1e6SMasatake YAMATO extern void addLanguageAlias (const langType language, const char* alias)
1737d4c6f1e6SMasatake YAMATO {
1738d4c6f1e6SMasatake YAMATO vString* const str = vStringNewInit (alias);
1739efe089d4SMasatake YAMATO parserObject* parser;
1740d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1741efe089d4SMasatake YAMATO parser = LanguageTable + language;
1742efe089d4SMasatake YAMATO if (parser->currentAliases == NULL)
1743efe089d4SMasatake YAMATO parser->currentAliases = stringListNew ();
1744efe089d4SMasatake YAMATO stringListAdd (parser->currentAliases, str);
1745d4c6f1e6SMasatake YAMATO }
1746d4c6f1e6SMasatake YAMATO
enableLanguage(const langType language,const bool state)1747ce990805SThomas Braun extern void enableLanguage (const langType language, const bool state)
1748d4c6f1e6SMasatake YAMATO {
1749d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1750e02be843SMasatake YAMATO LanguageTable [language].def->enabled = state;
1751d4c6f1e6SMasatake YAMATO }
1752d4c6f1e6SMasatake YAMATO
1753782707aeSMasatake YAMATO #ifdef DO_TRACING
traceLanguage(langType language)1754782707aeSMasatake YAMATO extern void traceLanguage (langType language)
1755782707aeSMasatake YAMATO {
1756782707aeSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1757782707aeSMasatake YAMATO LanguageTable [language].def->traced = true;
1758782707aeSMasatake YAMATO }
isLanguageTraced(langType language)1759782707aeSMasatake YAMATO extern bool isLanguageTraced (langType language)
1760782707aeSMasatake YAMATO {
1761782707aeSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1762782707aeSMasatake YAMATO return LanguageTable [language].def->traced;
1763782707aeSMasatake YAMATO }
1764782707aeSMasatake YAMATO #endif /* DO_TRACING */
1765782707aeSMasatake YAMATO
enableLanguages(const bool state)1766ce990805SThomas Braun extern void enableLanguages (const bool state)
1767d4c6f1e6SMasatake YAMATO {
1768d4c6f1e6SMasatake YAMATO unsigned int i;
1769d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
1770d4c6f1e6SMasatake YAMATO enableLanguage (i, state);
1771d4c6f1e6SMasatake YAMATO }
1772d4c6f1e6SMasatake YAMATO
installFieldDefinition(const langType language)1773b56bd065SMasatake YAMATO static void installFieldDefinition (const langType language)
1774ad1a3891SMasatake YAMATO {
1775fd1f9e69SMasatake YAMATO unsigned int i;
1776ad1a3891SMasatake YAMATO parserDefinition * parser;
1777ad1a3891SMasatake YAMATO
1778ad1a3891SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1779e02be843SMasatake YAMATO parser = LanguageTable [language].def;
1780ad1a3891SMasatake YAMATO
1781a739fa5fSMasatake YAMATO if (parser->fieldTable != NULL)
1782ad1a3891SMasatake YAMATO {
1783a739fa5fSMasatake YAMATO for (i = 0; i < parser->fieldCount; i++)
1784a739fa5fSMasatake YAMATO defineField (& parser->fieldTable [i], language);
1785ad1a3891SMasatake YAMATO }
1786ad1a3891SMasatake YAMATO }
1787ad1a3891SMasatake YAMATO
installXtagDefinition(const langType language)1788e3712f53SMasatake YAMATO static void installXtagDefinition (const langType language)
17898643c5b5SMasatake YAMATO {
17908643c5b5SMasatake YAMATO unsigned int i;
17918643c5b5SMasatake YAMATO parserDefinition * parser;
17928643c5b5SMasatake YAMATO
17938643c5b5SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
1794e02be843SMasatake YAMATO parser = LanguageTable [language].def;
17958643c5b5SMasatake YAMATO
1796a02a9600SMasatake YAMATO if (parser->xtagTable != NULL)
17978643c5b5SMasatake YAMATO {
1798a02a9600SMasatake YAMATO for (i = 0; i < parser->xtagCount; i++)
1799a02a9600SMasatake YAMATO defineXtag (& parser->xtagTable [i], language);
18008643c5b5SMasatake YAMATO }
18018643c5b5SMasatake YAMATO }
18028643c5b5SMasatake YAMATO
initializeParserOne(langType lang)18035a26e8b2SMasatake YAMATO static void initializeParserOne (langType lang)
1804d9ff6343SMasatake YAMATO {
1805e61266e4SMasatake YAMATO parserObject *const parser = LanguageTable + lang;
1806f35d9939SMasatake YAMATO
1807d453869fSMasatake YAMATO if (parser->initialized)
1808d0471042SMasatake YAMATO goto out;
1809d453869fSMasatake YAMATO
1810e61266e4SMasatake YAMATO verbose ("Initialize parser: %s\n", parser->def->name);
1811ce990805SThomas Braun parser->initialized = true;
1812d453869fSMasatake YAMATO
1813f5779afeSMasatake YAMATO installKeywordTable (lang);
1814a086aff1SMasatake YAMATO installTagXpathTable (lang);
1815b56bd065SMasatake YAMATO installFieldDefinition (lang);
1816e3712f53SMasatake YAMATO installXtagDefinition (lang);
1817f5779afeSMasatake YAMATO
18182b6707b2SMasatake YAMATO /* regex definitions refers xtag definitions.
18192b6707b2SMasatake YAMATO So installing RegexTable must be after installing
18202b6707b2SMasatake YAMATO xtag definitions. */
18212b6707b2SMasatake YAMATO installTagRegexTable (lang);
18222b6707b2SMasatake YAMATO
1823e61266e4SMasatake YAMATO if (parser->def->initialize != NULL)
1824e61266e4SMasatake YAMATO parser->def->initialize (lang);
18258d8d8e3bSMasatake YAMATO
1826edc12faeSMasatake YAMATO initializeDependencies (parser->def, parser->slaveControlBlock);
18278d8d8e3bSMasatake YAMATO
1828a3851331SMasatake YAMATO Assert (parser->fileKind != NULL);
1829b271b49dSMasatake YAMATO Assert (!doesParserUseKind (parser->kindControlBlock, parser->fileKind->letter));
1830d0471042SMasatake YAMATO
1831d0471042SMasatake YAMATO return;
1832d0471042SMasatake YAMATO
1833d0471042SMasatake YAMATO out:
1834d0471042SMasatake YAMATO /* lazyInitialize() installs findRegexTags() to parser->parser.
1835d0471042SMasatake YAMATO findRegexTags() should be installed to a parser if the parser is
1836d0471042SMasatake YAMATO optlib based(created by --langdef) and has some regex patterns(defined
1837d0471042SMasatake YAMATO with --regex-<LANG>). findRegexTags() makes regex matching work.
1838d0471042SMasatake YAMATO
1839d0471042SMasatake YAMATO If a parser can be initialized during evaluating options,
1840d0471042SMasatake YAMATO --fields-<LANG>=+{something}, for an example.
1841d0471042SMasatake YAMATO If such option is evaluated first, evaluating --regex-<LANG>=...
1842d0471042SMasatake YAMATO option doesn't cause installing findRegexTags. As the result
1843d0471042SMasatake YAMATO regex matching doesn't work. lazyInitialize was called only
1844d0471042SMasatake YAMATO once when --fields-<LANG>=+{something} was evaluated. In the
1845d0471042SMasatake YAMATO timing ctags had not seen --regex-<LANG>=.... Even though
1846d0471042SMasatake YAMATO ctags saw --regex-<LANG>=.... after initializing, there
1847d0471042SMasatake YAMATO was no chance to install findRegexTags() to parser->parser.
1848d0471042SMasatake YAMATO
184955cd1033SMasatake YAMATO Following code block gives extra chances to call lazyInitialize)
1850d0471042SMasatake YAMATO which installs findRegexTags() to parser->parser. */
1851d0471042SMasatake YAMATO if (parser->def->initialize == lazyInitialize)
1852d0471042SMasatake YAMATO parser->def->initialize (lang);
1853dc0f490fSMasatake YAMATO }
1854dc0f490fSMasatake YAMATO
initializeParser(langType lang)18555a26e8b2SMasatake YAMATO extern void initializeParser (langType lang)
18565a26e8b2SMasatake YAMATO {
18575a26e8b2SMasatake YAMATO if (lang == LANG_AUTO)
18585a26e8b2SMasatake YAMATO {
185946ab94ccSMasatake YAMATO unsigned int i;
18605a26e8b2SMasatake YAMATO for (i = 0; i < countParsers(); i++)
18615a26e8b2SMasatake YAMATO initializeParserOne (i);
18625a26e8b2SMasatake YAMATO }
18635a26e8b2SMasatake YAMATO else
18645a26e8b2SMasatake YAMATO initializeParserOne (lang);
18655a26e8b2SMasatake YAMATO }
1866dc0f490fSMasatake YAMATO
linkDependenciesAtInitializeParsing(parserDefinition * const parser)186778143775SMasatake YAMATO static void linkDependenciesAtInitializeParsing (parserDefinition *const parser)
186878143775SMasatake YAMATO {
186978143775SMasatake YAMATO unsigned int i;
187078143775SMasatake YAMATO parserDependency *d;
187178143775SMasatake YAMATO langType upper;
1872d86d3772SMasatake YAMATO parserDefinition *lowerParser;
1873edc12faeSMasatake YAMATO parserObject *upperParser;
187478143775SMasatake YAMATO
187578143775SMasatake YAMATO for (i = 0; i < parser->dependencyCount; i++)
187678143775SMasatake YAMATO {
187778143775SMasatake YAMATO d = parser->dependencies + i;
1878d86d3772SMasatake YAMATO
1879d86d3772SMasatake YAMATO if (d->type == DEPTYPE_FOREIGNER)
1880d86d3772SMasatake YAMATO {
1881d86d3772SMasatake YAMATO upper = parser->id;
1882d86d3772SMasatake YAMATO langType lower = getNamedLanguage (d->upperParser, 0);
1883d86d3772SMasatake YAMATO if (lower == LANG_IGNORE)
1884d86d3772SMasatake YAMATO error (FATAL,
1885d86d3772SMasatake YAMATO "Unknown language: \"%s\" as a foreigner for %s",
1886d86d3772SMasatake YAMATO d->upperParser, parser->name);
1887d86d3772SMasatake YAMATO
1888d86d3772SMasatake YAMATO lowerParser = LanguageTable [lower].def;
1889d86d3772SMasatake YAMATO }
1890d86d3772SMasatake YAMATO else
1891d86d3772SMasatake YAMATO {
189278143775SMasatake YAMATO upper = getNamedLanguage (d->upperParser, 0);
1893d86d3772SMasatake YAMATO lowerParser = parser;
1894d86d3772SMasatake YAMATO }
1895d86d3772SMasatake YAMATO
1896edc12faeSMasatake YAMATO upperParser = LanguageTable + upper;
189778143775SMasatake YAMATO
1898edc12faeSMasatake YAMATO linkDependencyAtInitializeParsing (d->type, upperParser->def,
1899edc12faeSMasatake YAMATO upperParser->slaveControlBlock,
19009a5a18e6SMasatake YAMATO upperParser->kindControlBlock,
1901d86d3772SMasatake YAMATO lowerParser,
1902d86d3772SMasatake YAMATO (LanguageTable + lowerParser->id)->kindControlBlock,
19039a5a18e6SMasatake YAMATO d->data);
190478143775SMasatake YAMATO }
190578143775SMasatake YAMATO }
190678143775SMasatake YAMATO
19079f303cbfSMasatake YAMATO /* Used in both builtin and optlib parsers. */
initializeParsingCommon(parserDefinition * def,bool is_builtin)19089f303cbfSMasatake YAMATO static void initializeParsingCommon (parserDefinition *def, bool is_builtin)
19099f303cbfSMasatake YAMATO {
1910edc12faeSMasatake YAMATO parserObject *parser;
19119f303cbfSMasatake YAMATO
19129f303cbfSMasatake YAMATO if (is_builtin)
19139f303cbfSMasatake YAMATO verbose ("%s%s", LanguageCount > 0 ? ", " : "", def->name);
19149f303cbfSMasatake YAMATO else
19159f303cbfSMasatake YAMATO verbose ("Add optlib parser: %s\n", def->name);
19169f303cbfSMasatake YAMATO
19179f303cbfSMasatake YAMATO def->id = LanguageCount++;
1918edc12faeSMasatake YAMATO parser = LanguageTable + def->id;
1919edc12faeSMasatake YAMATO parser->def = def;
19209f303cbfSMasatake YAMATO
1921f140c7c3SMasatake YAMATO hashTablePutItem (LanguageHTable, def->name, def);
1922f140c7c3SMasatake YAMATO
1923edc12faeSMasatake YAMATO parser->fileKind = &defaultFileKind;
1924edc12faeSMasatake YAMATO
19257bef4da4SMasatake YAMATO parser->kindControlBlock = allocKindControlBlock (def);
1926a641e930SMasatake YAMATO parser->slaveControlBlock = allocSlaveControlBlock (def);
1927bce55cc7SMasatake YAMATO parser->lregexControlBlock = allocLregexControlBlock (def);
19289f303cbfSMasatake YAMATO }
19299f303cbfSMasatake YAMATO
initializeParsing(void)1930d4c6f1e6SMasatake YAMATO extern void initializeParsing (void)
1931d4c6f1e6SMasatake YAMATO {
1932d4c6f1e6SMasatake YAMATO unsigned int builtInCount;
1933d4c6f1e6SMasatake YAMATO unsigned int i;
1934d4c6f1e6SMasatake YAMATO
1935d4c6f1e6SMasatake YAMATO builtInCount = ARRAY_SIZE (BuiltInParsers);
1936e02be843SMasatake YAMATO LanguageTable = xMalloc (builtInCount, parserObject);
1937efe089d4SMasatake YAMATO memset(LanguageTable, 0, builtInCount * sizeof (parserObject));
1938f02166dcSMasatake YAMATO for (i = 0; i < builtInCount; ++i)
1939f02166dcSMasatake YAMATO {
1940f02166dcSMasatake YAMATO LanguageTable [i].pretendingAsLanguage = LANG_IGNORE;
1941f02166dcSMasatake YAMATO LanguageTable [i].pretendedAsLanguage = LANG_IGNORE;
1942f02166dcSMasatake YAMATO }
1943d4c6f1e6SMasatake YAMATO
1944f140c7c3SMasatake YAMATO LanguageHTable = hashTableNew (127,
1945f140c7c3SMasatake YAMATO hashCstrcasehash,
1946f140c7c3SMasatake YAMATO hashCstrcaseeq,
1947f140c7c3SMasatake YAMATO NULL,
1948f140c7c3SMasatake YAMATO NULL);
1949f8cb8817SMasatake YAMATO DEFAULT_TRASH_BOX(LanguageHTable, hashTableDelete);
1950f140c7c3SMasatake YAMATO
1951d4c6f1e6SMasatake YAMATO verbose ("Installing parsers: ");
1952d4c6f1e6SMasatake YAMATO for (i = 0 ; i < builtInCount ; ++i)
1953d4c6f1e6SMasatake YAMATO {
1954d4c6f1e6SMasatake YAMATO parserDefinition* const def = (*BuiltInParsers [i]) ();
1955d4c6f1e6SMasatake YAMATO if (def != NULL)
1956d4c6f1e6SMasatake YAMATO {
19571b788e0dSMasatake YAMATO Assert (def->name);
19581b788e0dSMasatake YAMATO Assert (def->name[0] != '\0');
19591b788e0dSMasatake YAMATO Assert (strcmp (def->name, RSV_LANG_ALL));
19600278c2a1SMasatake YAMATO Assert (strpbrk (def->name, "!\"$%&'()*,-./:;<=>?@[\\]^`|~") == NULL);
19611b788e0dSMasatake YAMATO
19621b788e0dSMasatake YAMATO if (def->method & METHOD_NOT_CRAFTED)
1963d4c6f1e6SMasatake YAMATO def->parser = findRegexTags;
1964d4c6f1e6SMasatake YAMATO else
19651b788e0dSMasatake YAMATO /* parser definition must define one and only one parsing routine */
19661b788e0dSMasatake YAMATO Assert ((!!def->parser) + (!!def->parser2) == 1);
19671b788e0dSMasatake YAMATO
19689f303cbfSMasatake YAMATO initializeParsingCommon (def, true);
1969d4c6f1e6SMasatake YAMATO }
1970d4c6f1e6SMasatake YAMATO }
1971d4c6f1e6SMasatake YAMATO verbose ("\n");
197278143775SMasatake YAMATO
197378143775SMasatake YAMATO for (i = 0; i < builtInCount ; ++i)
1974e02be843SMasatake YAMATO linkDependenciesAtInitializeParsing (LanguageTable [i].def);
1975dc0f490fSMasatake YAMATO }
1976dc0f490fSMasatake YAMATO
freeParserResources(void)1977d4c6f1e6SMasatake YAMATO extern void freeParserResources (void)
1978d4c6f1e6SMasatake YAMATO {
1979d4c6f1e6SMasatake YAMATO unsigned int i;
1980d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
1981d4c6f1e6SMasatake YAMATO {
1982efe089d4SMasatake YAMATO parserObject* const parser = LanguageTable + i;
1983d4c6f1e6SMasatake YAMATO
1984efe089d4SMasatake YAMATO if (parser->def->finalize)
1985e61266e4SMasatake YAMATO (parser->def->finalize)((langType)i, (bool)parser->initialized);
1986b88a2810SMasatake YAMATO
1987eb480042SMasatake YAMATO uninstallTagXpathTable (i);
1988eb480042SMasatake YAMATO
1989bce55cc7SMasatake YAMATO freeLregexControlBlock (parser->lregexControlBlock);
19907bef4da4SMasatake YAMATO freeKindControlBlock (parser->kindControlBlock);
19917bef4da4SMasatake YAMATO parser->kindControlBlock = NULL;
19927bef4da4SMasatake YAMATO
1993edc12faeSMasatake YAMATO finalizeDependencies (parser->def, parser->slaveControlBlock);
1994edc12faeSMasatake YAMATO freeSlaveControlBlock (parser->slaveControlBlock);
1995edc12faeSMasatake YAMATO parser->slaveControlBlock = NULL;
1996b88a2810SMasatake YAMATO
1997efe089d4SMasatake YAMATO freeList (&parser->currentPatterns);
1998efe089d4SMasatake YAMATO freeList (&parser->currentExtensions);
1999efe089d4SMasatake YAMATO freeList (&parser->currentAliases);
2000d4c6f1e6SMasatake YAMATO
2001efe089d4SMasatake YAMATO eFree (parser->def->name);
2002efe089d4SMasatake YAMATO parser->def->name = NULL;
2003efe089d4SMasatake YAMATO eFree (parser->def);
2004efe089d4SMasatake YAMATO parser->def = NULL;
2005d4c6f1e6SMasatake YAMATO }
2006d4c6f1e6SMasatake YAMATO if (LanguageTable != NULL)
2007d4c6f1e6SMasatake YAMATO eFree (LanguageTable);
2008d4c6f1e6SMasatake YAMATO LanguageTable = NULL;
2009d4c6f1e6SMasatake YAMATO LanguageCount = 0;
2010d4c6f1e6SMasatake YAMATO }
2011d4c6f1e6SMasatake YAMATO
doNothing(void)2012d4c6f1e6SMasatake YAMATO static void doNothing (void)
2013d4c6f1e6SMasatake YAMATO {
2014d4c6f1e6SMasatake YAMATO }
2015d4c6f1e6SMasatake YAMATO
optlibRunBaseParser(void)201611fea497SMasatake YAMATO static void optlibRunBaseParser (void)
201711fea497SMasatake YAMATO {
201811fea497SMasatake YAMATO scheduleRunningBaseparser (0);
201911fea497SMasatake YAMATO }
202011fea497SMasatake YAMATO
optlibIsDedicatedSubparser(parserDefinition * def)202111fea497SMasatake YAMATO static bool optlibIsDedicatedSubparser (parserDefinition* def)
202211fea497SMasatake YAMATO {
202311fea497SMasatake YAMATO return (def->dependencies
202411fea497SMasatake YAMATO && (def->dependencies->type == DEPTYPE_SUBPARSER)
202511fea497SMasatake YAMATO && ((subparser *)def->dependencies->data)->direction & SUBPARSER_SUB_RUNS_BASE);
202611fea497SMasatake YAMATO }
202711fea497SMasatake YAMATO
lazyInitialize(langType language)20285492e375SMasatake YAMATO static void lazyInitialize (langType language)
2029d4c6f1e6SMasatake YAMATO {
203011fea497SMasatake YAMATO parserDefinition* def;
2031d4c6f1e6SMasatake YAMATO
2032d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
203311fea497SMasatake YAMATO def = LanguageTable [language].def;
2034d4c6f1e6SMasatake YAMATO
203511fea497SMasatake YAMATO def->parser = doNothing;
2036d4c6f1e6SMasatake YAMATO
203711fea497SMasatake YAMATO if (def->method & METHOD_REGEX)
203811fea497SMasatake YAMATO {
203911fea497SMasatake YAMATO if (optlibIsDedicatedSubparser (def))
204011fea497SMasatake YAMATO def->parser = optlibRunBaseParser;
204111fea497SMasatake YAMATO else
204211fea497SMasatake YAMATO def->parser = findRegexTags;
204311fea497SMasatake YAMATO }
20442fa3c9e1SMasatake YAMATO }
2045d4c6f1e6SMasatake YAMATO
enableDefaultFileKind(bool state)204664270418SMasatake YAMATO extern void enableDefaultFileKind (bool state)
204764270418SMasatake YAMATO {
204864270418SMasatake YAMATO defaultFileKind.enabled = state;
204964270418SMasatake YAMATO }
205064270418SMasatake YAMATO
2051d4c6f1e6SMasatake YAMATO /*
2052d4c6f1e6SMasatake YAMATO * Option parsing
2053d4c6f1e6SMasatake YAMATO */
205411fea497SMasatake YAMATO struct preLangDefFlagData
205511fea497SMasatake YAMATO {
205611fea497SMasatake YAMATO char *base;
205711fea497SMasatake YAMATO subparserRunDirection direction;
2058225f14f2SMasatake YAMATO bool autoFQTag;
205911fea497SMasatake YAMATO };
206011fea497SMasatake YAMATO
pre_lang_def_flag_base_long(const char * const optflag,const char * const param,void * data)2061beb5437bSMasatake YAMATO static void pre_lang_def_flag_base_long (const char* const optflag, const char* const param, void* data)
2062beb5437bSMasatake YAMATO {
206311fea497SMasatake YAMATO struct preLangDefFlagData * flag_data = data;
2064beb5437bSMasatake YAMATO langType base;
2065beb5437bSMasatake YAMATO
2066beb5437bSMasatake YAMATO if (param[0] == '\0')
2067beb5437bSMasatake YAMATO {
2068beb5437bSMasatake YAMATO error (WARNING, "No base parser specified for \"%s\" flag of --langdef option", optflag);
2069beb5437bSMasatake YAMATO return;
2070beb5437bSMasatake YAMATO }
2071beb5437bSMasatake YAMATO
2072beb5437bSMasatake YAMATO base = getNamedLanguage (param, 0);
2073beb5437bSMasatake YAMATO if (base == LANG_IGNORE)
2074beb5437bSMasatake YAMATO {
2075759d281dSK.Takata error (WARNING, "Unknown language(%s) is specified for \"%s\" flag of --langdef option",
2076beb5437bSMasatake YAMATO param, optflag);
2077beb5437bSMasatake YAMATO return;
2078beb5437bSMasatake YAMATO
2079beb5437bSMasatake YAMATO }
2080beb5437bSMasatake YAMATO
2081ee235db8SMasatake YAMATO langType cpreproc = getNamedLanguage ("CPreProcessor", 0);
2082ee235db8SMasatake YAMATO if (base == cpreproc)
2083ee235db8SMasatake YAMATO {
2084ee235db8SMasatake YAMATO error (WARNING,
2085ee235db8SMasatake YAMATO "Because of an internal limitation, Making a sub parser based on the CPreProcessor parser is not allowed: %s",
2086ee235db8SMasatake YAMATO param);
2087ee235db8SMasatake YAMATO return;
2088ee235db8SMasatake YAMATO }
2089ee235db8SMasatake YAMATO
209011fea497SMasatake YAMATO flag_data->base = eStrdup(param);
209111fea497SMasatake YAMATO }
209211fea497SMasatake YAMATO
209311fea497SMasatake YAMATO #define LANGDEF_FLAG_DEDICATED "dedicated"
209411fea497SMasatake YAMATO #define LANGDEF_FLAG_SHARED "shared"
209511fea497SMasatake YAMATO #define LANGDEF_FLAG_BIDIR "bidirectional"
pre_lang_def_flag_direction_long(const char * const optflag,const char * const param CTAGS_ATTR_UNUSED,void * data)2096e4d16241SMasatake YAMATO static void pre_lang_def_flag_direction_long (const char* const optflag, const char* const param CTAGS_ATTR_UNUSED, void* data)
209711fea497SMasatake YAMATO {
209811fea497SMasatake YAMATO struct preLangDefFlagData * flag_data = data;
209911fea497SMasatake YAMATO
210011fea497SMasatake YAMATO if (strcmp(optflag, LANGDEF_FLAG_DEDICATED) == 0)
210111fea497SMasatake YAMATO flag_data->direction = SUBPARSER_SUB_RUNS_BASE;
210211fea497SMasatake YAMATO else if (strcmp(optflag, LANGDEF_FLAG_SHARED) == 0)
210311fea497SMasatake YAMATO flag_data->direction = SUBPARSER_BASE_RUNS_SUB;
210411fea497SMasatake YAMATO else if (strcmp(optflag, LANGDEF_FLAG_BIDIR) == 0)
210511fea497SMasatake YAMATO flag_data->direction = SUBPARSER_BI_DIRECTION;
210611fea497SMasatake YAMATO else
210711fea497SMasatake YAMATO AssertNotReached ();
2108beb5437bSMasatake YAMATO }
2109beb5437bSMasatake YAMATO
pre_lang_def_flag_autoFQTag_long(const char * const optflag,const char * const param CTAGS_ATTR_UNUSED,void * data)2110225f14f2SMasatake YAMATO static void pre_lang_def_flag_autoFQTag_long (const char* const optflag,
2111225f14f2SMasatake YAMATO const char* const param CTAGS_ATTR_UNUSED,
2112225f14f2SMasatake YAMATO void* data)
2113225f14f2SMasatake YAMATO {
2114225f14f2SMasatake YAMATO struct preLangDefFlagData * flag_data = data;
2115225f14f2SMasatake YAMATO flag_data->autoFQTag = true;
2116225f14f2SMasatake YAMATO }
2117225f14f2SMasatake YAMATO
2118beb5437bSMasatake YAMATO static flagDefinition PreLangDefFlagDef [] = {
2119d8539e07SMasatake YAMATO { '\0', "base", NULL, pre_lang_def_flag_base_long,
2120d8539e07SMasatake YAMATO "BASEPARSER", "utilize as a base parser"},
2121d8539e07SMasatake YAMATO { '\0', LANGDEF_FLAG_DEDICATED, NULL,
2122d8539e07SMasatake YAMATO pre_lang_def_flag_direction_long,
2123d8539e07SMasatake YAMATO NULL, "make the base parser dedicated to this subparser"},
2124d8539e07SMasatake YAMATO { '\0', LANGDEF_FLAG_SHARED, NULL,
2125d8539e07SMasatake YAMATO pre_lang_def_flag_direction_long,
2126d8539e07SMasatake YAMATO NULL, "share the base parser with the other subparsers"
2127d8539e07SMasatake YAMATO },
2128d8539e07SMasatake YAMATO { '\0', LANGDEF_FLAG_BIDIR, NULL,
2129d8539e07SMasatake YAMATO pre_lang_def_flag_direction_long,
2130d8539e07SMasatake YAMATO NULL, "utilize the base parser both 'dedicated' and 'shared' way"
2131d8539e07SMasatake YAMATO },
2132225f14f2SMasatake YAMATO { '\0', "_autoFQTag", NULL, pre_lang_def_flag_autoFQTag_long,
2133225f14f2SMasatake YAMATO NULL, "make full qualified tags automatically based on scope information"},
2134beb5437bSMasatake YAMATO };
2135beb5437bSMasatake YAMATO
optlibFreeDep(langType lang,bool initialized CTAGS_ATTR_UNUSED)2136431f0b01SMasatake YAMATO static void optlibFreeDep (langType lang, bool initialized CTAGS_ATTR_UNUSED)
2137beb5437bSMasatake YAMATO {
2138beb5437bSMasatake YAMATO parserDefinition * pdef = LanguageTable [lang].def;
2139beb5437bSMasatake YAMATO
2140beb5437bSMasatake YAMATO if (pdef->dependencyCount == 1)
2141beb5437bSMasatake YAMATO {
2142beb5437bSMasatake YAMATO parserDependency *dep = pdef->dependencies;
2143beb5437bSMasatake YAMATO
2144beb5437bSMasatake YAMATO eFree ((char *)dep->upperParser); /* Dirty cast */
2145beb5437bSMasatake YAMATO dep->upperParser = NULL;
2146beb5437bSMasatake YAMATO eFree (dep->data);
2147beb5437bSMasatake YAMATO dep->data = NULL;
2148beb5437bSMasatake YAMATO eFree (dep);
2149beb5437bSMasatake YAMATO pdef->dependencies = NULL;
2150beb5437bSMasatake YAMATO }
2151beb5437bSMasatake YAMATO }
2152beb5437bSMasatake YAMATO
OptlibParser(const char * name,const char * base,subparserRunDirection direction)215311fea497SMasatake YAMATO static parserDefinition* OptlibParser(const char *name, const char *base,
215411fea497SMasatake YAMATO subparserRunDirection direction)
21559f303cbfSMasatake YAMATO {
21569f303cbfSMasatake YAMATO parserDefinition *def;
21579f303cbfSMasatake YAMATO
21589f303cbfSMasatake YAMATO def = parserNew (name);
21599f303cbfSMasatake YAMATO def->initialize = lazyInitialize;
21609f303cbfSMasatake YAMATO def->method = METHOD_NOT_CRAFTED;
2161beb5437bSMasatake YAMATO if (base)
2162beb5437bSMasatake YAMATO {
2163beb5437bSMasatake YAMATO subparser *sub = xCalloc (1, subparser);
2164beb5437bSMasatake YAMATO parserDependency *dep = xCalloc (1, parserDependency);
2165beb5437bSMasatake YAMATO
216611fea497SMasatake YAMATO sub->direction = direction;
2167beb5437bSMasatake YAMATO dep->type = DEPTYPE_SUBPARSER;
2168beb5437bSMasatake YAMATO dep->upperParser = eStrdup (base);
2169beb5437bSMasatake YAMATO dep->data = sub;
2170beb5437bSMasatake YAMATO def->dependencies = dep;
2171beb5437bSMasatake YAMATO def->dependencyCount = 1;
2172beb5437bSMasatake YAMATO def->finalize = optlibFreeDep;
2173beb5437bSMasatake YAMATO }
21749f303cbfSMasatake YAMATO
21759f303cbfSMasatake YAMATO return def;
21769f303cbfSMasatake YAMATO }
21779f303cbfSMasatake YAMATO
processLanguageDefineOption(const char * const option,const char * const parameter)2178d4c6f1e6SMasatake YAMATO extern void processLanguageDefineOption (
217911fea497SMasatake YAMATO const char *const option, const char *const parameter)
2180d4c6f1e6SMasatake YAMATO {
21816144f58aSMasatake YAMATO char *name;
21826144f58aSMasatake YAMATO char *flags;
21836144f58aSMasatake YAMATO parserDefinition* def;
21846144f58aSMasatake YAMATO
21856144f58aSMasatake YAMATO flags = strchr (parameter, LONG_FLAGS_OPEN);
21866144f58aSMasatake YAMATO if (flags)
21876144f58aSMasatake YAMATO name = eStrndup (parameter, flags - parameter);
21886144f58aSMasatake YAMATO else
21896144f58aSMasatake YAMATO name = eStrdup (parameter);
21906144f58aSMasatake YAMATO
21912ff65297SMasatake YAMATO /* Veirfy that the name of new language is acceptable or not. */
21920278c2a1SMasatake YAMATO char *unacceptable;
21932ff65297SMasatake YAMATO if (name [0] == '\0')
21942ff65297SMasatake YAMATO {
21952ff65297SMasatake YAMATO eFree (name);
21962ff65297SMasatake YAMATO error (FATAL, "No language specified for \"%s\" option", option);
21972ff65297SMasatake YAMATO }
21982ff65297SMasatake YAMATO else if (getNamedLanguage (name, 0) != LANG_IGNORE)
21992ce906a2SMasatake YAMATO {
22002ce906a2SMasatake YAMATO /* name cannot be freed because it is used in the FATAL message. */
22012ce906a2SMasatake YAMATO error (FATAL, "Language \"%s\" already defined", name);
22022ce906a2SMasatake YAMATO }
22032ff65297SMasatake YAMATO else if (strcmp(name, RSV_LANG_ALL) == 0)
22042ff65297SMasatake YAMATO {
22052ff65297SMasatake YAMATO eFree (name);
22062ff65297SMasatake YAMATO error (FATAL, "\"all\" is reserved; don't use it as the name for defining a new language");
22072ff65297SMasatake YAMATO }
22080278c2a1SMasatake YAMATO else if ((unacceptable = strpbrk (name, "!\"$%&'()*,-./:;<=>?@[\\]^`|~")))
22090278c2a1SMasatake YAMATO {
22100278c2a1SMasatake YAMATO char c = *unacceptable;
22110278c2a1SMasatake YAMATO
22120278c2a1SMasatake YAMATO /* name cannot be freed because it is used in the FATAL message. */
22130278c2a1SMasatake YAMATO /* We accept '_'.
22140278c2a1SMasatake YAMATO * We accept # and + because they are already used in C# parser and C++ parser.
22150278c2a1SMasatake YAMATO * {... is already trimmed at the beginning of this function. */
22160278c2a1SMasatake YAMATO if ((c == '`') || (c == '\''))
22170278c2a1SMasatake YAMATO error (FATAL, "don't use \"%c\" in a language name (%s)", c, name);
22180278c2a1SMasatake YAMATO else
22190278c2a1SMasatake YAMATO error (FATAL, "don't use `%c' in a language name (%s)", c, name);
22200278c2a1SMasatake YAMATO }
22212ff65297SMasatake YAMATO
22229f303cbfSMasatake YAMATO LanguageTable = xRealloc (LanguageTable, LanguageCount + 1, parserObject);
22239f303cbfSMasatake YAMATO memset (LanguageTable + LanguageCount, 0, sizeof(parserObject));
22249f303cbfSMasatake YAMATO
222511fea497SMasatake YAMATO struct preLangDefFlagData data = {
222611fea497SMasatake YAMATO .base = NULL,
222711fea497SMasatake YAMATO .direction = SUBPARSER_UNKNOWN_DIRECTION,
2228225f14f2SMasatake YAMATO .autoFQTag = false,
222911fea497SMasatake YAMATO };
223011fea497SMasatake YAMATO flagsEval (flags, PreLangDefFlagDef, ARRAY_SIZE (PreLangDefFlagDef), &data);
2231beb5437bSMasatake YAMATO
223211fea497SMasatake YAMATO if (data.base == NULL && data.direction != SUBPARSER_UNKNOWN_DIRECTION)
223311fea497SMasatake YAMATO error (WARNING, "Ignore the direction of subparser because \"{base=}\" is not given");
223411fea497SMasatake YAMATO
223511fea497SMasatake YAMATO if (data.base && data.direction == SUBPARSER_UNKNOWN_DIRECTION)
223611fea497SMasatake YAMATO data.direction = SUBPARSER_BASE_RUNS_SUB;
223711fea497SMasatake YAMATO
223811fea497SMasatake YAMATO def = OptlibParser (name, data.base, data.direction);
223911fea497SMasatake YAMATO if (data.base)
224011fea497SMasatake YAMATO eFree (data.base);
2241beb5437bSMasatake YAMATO
2242225f14f2SMasatake YAMATO def->requestAutomaticFQTag = data.autoFQTag;
2243225f14f2SMasatake YAMATO
22449f303cbfSMasatake YAMATO initializeParsingCommon (def, false);
2245beb5437bSMasatake YAMATO linkDependenciesAtInitializeParsing (def);
22469f303cbfSMasatake YAMATO
22479f303cbfSMasatake YAMATO LanguageTable [def->id].currentPatterns = stringListNew ();
22489f303cbfSMasatake YAMATO LanguageTable [def->id].currentExtensions = stringListNew ();
2249f02166dcSMasatake YAMATO LanguageTable [def->id].pretendingAsLanguage = LANG_IGNORE;
2250f02166dcSMasatake YAMATO LanguageTable [def->id].pretendedAsLanguage = LANG_IGNORE;
22516144f58aSMasatake YAMATO
22526144f58aSMasatake YAMATO eFree (name);
2253d4c6f1e6SMasatake YAMATO }
2254d4c6f1e6SMasatake YAMATO
isLanguageKindEnabled(const langType language,int kindIndex)22555c56d939SMasatake YAMATO extern bool isLanguageKindEnabled (const langType language, int kindIndex)
2256ebd6043dSMasatake YAMATO {
22575a475eaeSMasatake YAMATO kindDefinition * kdef = getLanguageKind (language, kindIndex);
225853485acaSMasatake YAMATO return kdef->enabled;
225953485acaSMasatake YAMATO }
2260ebd6043dSMasatake YAMATO
isLanguageRoleEnabled(const langType language,int kindIndex,int roleIndex)2261320b1e8bSMasatake YAMATO extern bool isLanguageRoleEnabled (const langType language, int kindIndex, int roleIndex)
2262320b1e8bSMasatake YAMATO {
2263320b1e8bSMasatake YAMATO return isRoleEnabled(LanguageTable [language].kindControlBlock,
2264320b1e8bSMasatake YAMATO kindIndex, roleIndex);
2265320b1e8bSMasatake YAMATO }
2266320b1e8bSMasatake YAMATO
isLanguageKindRefOnly(const langType language,int kindIndex)22679261585aSMasatake YAMATO extern bool isLanguageKindRefOnly (const langType language, int kindIndex)
22689261585aSMasatake YAMATO {
22699261585aSMasatake YAMATO kindDefinition * def = getLanguageKind(language, kindIndex);
22709261585aSMasatake YAMATO return def->referenceOnly;
22719261585aSMasatake YAMATO }
22729261585aSMasatake YAMATO
resetLanguageKinds(const langType language,const bool mode)2273ce990805SThomas Braun static void resetLanguageKinds (const langType language, const bool mode)
2274d4c6f1e6SMasatake YAMATO {
22757f1bb89cSMasatake YAMATO const parserObject* parser;
22767f1bb89cSMasatake YAMATO
2277d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
22787f1bb89cSMasatake YAMATO parser = LanguageTable + language;
2279d4c6f1e6SMasatake YAMATO
2280d4c6f1e6SMasatake YAMATO {
2281d4c6f1e6SMasatake YAMATO unsigned int i;
22827f1bb89cSMasatake YAMATO struct kindControlBlock *kcb = parser->kindControlBlock;
22837f1bb89cSMasatake YAMATO
22847f1bb89cSMasatake YAMATO for (i = 0 ; i < countKinds (kcb) ; ++i)
22857f1bb89cSMasatake YAMATO {
22867f1bb89cSMasatake YAMATO kindDefinition *kdef = getKind (kcb, i);
22877f1bb89cSMasatake YAMATO enableKind (kdef, mode);
22887f1bb89cSMasatake YAMATO }
2289d4c6f1e6SMasatake YAMATO }
2290d4c6f1e6SMasatake YAMATO }
2291d4c6f1e6SMasatake YAMATO
enableLanguageKindForLetter(const langType language,const int kind,const bool mode)22924177f5aaSMasatake YAMATO static bool enableLanguageKindForLetter (
2293ce990805SThomas Braun const langType language, const int kind, const bool mode)
2294d4c6f1e6SMasatake YAMATO {
2295ce990805SThomas Braun bool result = false;
22964177f5aaSMasatake YAMATO kindDefinition* const def = getLanguageKindForLetter (language, kind);
229720aac2eeSMasatake YAMATO if (def != NULL)
2298d4c6f1e6SMasatake YAMATO {
229920aac2eeSMasatake YAMATO enableKind (def, mode);
2300ce990805SThomas Braun result = true;
2301d4c6f1e6SMasatake YAMATO }
2302d4c6f1e6SMasatake YAMATO return result;
2303d4c6f1e6SMasatake YAMATO }
2304d4c6f1e6SMasatake YAMATO
enableLanguageKindForName(const langType language,const char * const name,const bool mode)2305c9dd5111SMasatake YAMATO static bool enableLanguageKindForName (
2306c9dd5111SMasatake YAMATO const langType language, const char * const name, const bool mode)
2307b77a0405SMasatake YAMATO {
2308ce990805SThomas Braun bool result = false;
2309c9dd5111SMasatake YAMATO kindDefinition* const def = getLanguageKindForName (language, name);
231020aac2eeSMasatake YAMATO if (def != NULL)
2311b77a0405SMasatake YAMATO {
231220aac2eeSMasatake YAMATO enableKind (def, mode);
2313ce990805SThomas Braun result = true;
2314b77a0405SMasatake YAMATO }
2315b77a0405SMasatake YAMATO return result;
2316b77a0405SMasatake YAMATO }
2317b77a0405SMasatake YAMATO
processLangKindDefinition(const langType language,const char * const option,const char * const parameter)2318e112e8abSMasatake YAMATO static void processLangKindDefinition (
2319d4c6f1e6SMasatake YAMATO const langType language, const char *const option,
2320d4c6f1e6SMasatake YAMATO const char *const parameter)
2321d4c6f1e6SMasatake YAMATO {
2322d4c6f1e6SMasatake YAMATO const char *p = parameter;
2323ce990805SThomas Braun bool mode = true;
2324d4c6f1e6SMasatake YAMATO int c;
2325b77a0405SMasatake YAMATO static vString *longName;
2326ce990805SThomas Braun bool inLongName = false;
2327b77a0405SMasatake YAMATO const char *k;
2328ce990805SThomas Braun bool r;
2329d4c6f1e6SMasatake YAMATO
2330d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
2331d4c6f1e6SMasatake YAMATO
2332078b9679SMasatake YAMATO initializeParser (language);
2333d4c6f1e6SMasatake YAMATO if (*p == '*')
2334d4c6f1e6SMasatake YAMATO {
2335ce990805SThomas Braun resetLanguageKinds (language, true);
2336d4c6f1e6SMasatake YAMATO p++;
2337d4c6f1e6SMasatake YAMATO }
2338d4c6f1e6SMasatake YAMATO else if (*p != '+' && *p != '-')
2339ce990805SThomas Braun resetLanguageKinds (language, false);
2340d4c6f1e6SMasatake YAMATO
234156065e52SMasatake YAMATO longName = vStringNewOrClearWithAutoRelease (longName);
2342b77a0405SMasatake YAMATO
2343b77a0405SMasatake YAMATO while ((c = *p++) != '\0')
2344d4c6f1e6SMasatake YAMATO {
2345b77a0405SMasatake YAMATO switch (c)
2346b77a0405SMasatake YAMATO {
2347b77a0405SMasatake YAMATO case '+':
2348b77a0405SMasatake YAMATO if (inLongName)
2349b77a0405SMasatake YAMATO vStringPut (longName, c);
2350b77a0405SMasatake YAMATO else
2351ce990805SThomas Braun mode = true;
2352b77a0405SMasatake YAMATO break;
2353b77a0405SMasatake YAMATO case '-':
2354b77a0405SMasatake YAMATO if (inLongName)
2355b77a0405SMasatake YAMATO vStringPut (longName, c);
2356b77a0405SMasatake YAMATO else
2357ce990805SThomas Braun mode = false;
2358b77a0405SMasatake YAMATO break;
2359b77a0405SMasatake YAMATO case '{':
2360b77a0405SMasatake YAMATO if (inLongName)
2361b77a0405SMasatake YAMATO error(FATAL,
2362b77a0405SMasatake YAMATO "unexpected character in kind specification: \'%c\'",
2363b77a0405SMasatake YAMATO c);
2364ce990805SThomas Braun inLongName = true;
2365b77a0405SMasatake YAMATO break;
2366b77a0405SMasatake YAMATO case '}':
2367b77a0405SMasatake YAMATO if (!inLongName)
2368b77a0405SMasatake YAMATO error(FATAL,
2369b77a0405SMasatake YAMATO "unexpected character in kind specification: \'%c\'",
2370b77a0405SMasatake YAMATO c);
2371b77a0405SMasatake YAMATO k = vStringValue (longName);
2372c9dd5111SMasatake YAMATO r = enableLanguageKindForName (language, k, mode);
2373b77a0405SMasatake YAMATO if (! r)
2374b77a0405SMasatake YAMATO error (WARNING, "Unsupported kind: '%s' for --%s option",
2375b77a0405SMasatake YAMATO k, option);
2376b77a0405SMasatake YAMATO
2377ce990805SThomas Braun inLongName = false;
2378b77a0405SMasatake YAMATO vStringClear (longName);
2379b77a0405SMasatake YAMATO break;
2380d4c6f1e6SMasatake YAMATO default:
2381b77a0405SMasatake YAMATO if (inLongName)
2382b77a0405SMasatake YAMATO vStringPut (longName, c);
2383b77a0405SMasatake YAMATO else
2384b77a0405SMasatake YAMATO {
23854177f5aaSMasatake YAMATO r = enableLanguageKindForLetter (language, c, mode);
2386b77a0405SMasatake YAMATO if (! r)
23871c4543c1SMasatake YAMATO error (WARNING, "Unsupported kind: '%c' for --%s option",
2388d4c6f1e6SMasatake YAMATO c, option);
2389b77a0405SMasatake YAMATO }
2390d4c6f1e6SMasatake YAMATO break;
2391d4c6f1e6SMasatake YAMATO }
2392d4c6f1e6SMasatake YAMATO }
2393b77a0405SMasatake YAMATO }
2394d4c6f1e6SMasatake YAMATO
freeKdef(kindDefinition * kdef)23953b7988cfSMasatake YAMATO static void freeKdef (kindDefinition *kdef)
23963b7988cfSMasatake YAMATO {
23973b7988cfSMasatake YAMATO eFree (kdef->name);
23983b7988cfSMasatake YAMATO eFree (kdef->description);
23993b7988cfSMasatake YAMATO eFree (kdef);
24003b7988cfSMasatake YAMATO }
24013b7988cfSMasatake YAMATO
extractDescriptionAndFlags(const char * input,const char ** flags)2402f741fddfSMasatake YAMATO static char *extractDescriptionAndFlags(const char *input, const char **flags)
2403f741fddfSMasatake YAMATO {
2404f741fddfSMasatake YAMATO vString *vdesc = vStringNew();
2405f741fddfSMasatake YAMATO bool escaped = false;
2406f741fddfSMasatake YAMATO
2407f741fddfSMasatake YAMATO if (flags)
2408f741fddfSMasatake YAMATO *flags = NULL;
2409f741fddfSMasatake YAMATO
2410f741fddfSMasatake YAMATO while (*input != '\0')
2411f741fddfSMasatake YAMATO {
2412f741fddfSMasatake YAMATO if (escaped)
2413f741fddfSMasatake YAMATO {
2414f741fddfSMasatake YAMATO vStringPut (vdesc, *input);
2415f741fddfSMasatake YAMATO escaped = false;
2416f741fddfSMasatake YAMATO
2417f741fddfSMasatake YAMATO }
2418f741fddfSMasatake YAMATO else if (*input == '\\')
2419f741fddfSMasatake YAMATO escaped = true;
2420f741fddfSMasatake YAMATO else if (*input == LONG_FLAGS_OPEN)
2421f741fddfSMasatake YAMATO {
2422f741fddfSMasatake YAMATO if (flags)
2423f741fddfSMasatake YAMATO *flags = input;
2424f741fddfSMasatake YAMATO break;
2425f741fddfSMasatake YAMATO }
2426f741fddfSMasatake YAMATO else
2427f741fddfSMasatake YAMATO vStringPut (vdesc, *input);
2428f741fddfSMasatake YAMATO input++;
2429f741fddfSMasatake YAMATO }
2430f741fddfSMasatake YAMATO return vStringDeleteUnwrap(vdesc);
2431f741fddfSMasatake YAMATO }
2432f741fddfSMasatake YAMATO
pre_kind_def_flag_refonly_long(const char * const optflag,const char * const param,void * data)2433ba1453a4SMasatake YAMATO static void pre_kind_def_flag_refonly_long (const char* const optflag,
2434ba1453a4SMasatake YAMATO const char* const param, void* data)
2435ba1453a4SMasatake YAMATO {
2436ba1453a4SMasatake YAMATO kindDefinition *kdef = data;
2437ba1453a4SMasatake YAMATO kdef->referenceOnly = true;
2438ba1453a4SMasatake YAMATO }
2439ba1453a4SMasatake YAMATO
2440ba1453a4SMasatake YAMATO static flagDefinition PreKindDefFlagDef [] = {
2441ba1453a4SMasatake YAMATO { '\0', "_refonly", NULL, pre_kind_def_flag_refonly_long,
2442ba1453a4SMasatake YAMATO NULL, "use this kind reference tags only"},
2443ba1453a4SMasatake YAMATO };
2444ba1453a4SMasatake YAMATO
processLangDefineKind(const langType language,const char * const option,const char * const parameter)24453b7988cfSMasatake YAMATO static bool processLangDefineKind(const langType language,
24463b7988cfSMasatake YAMATO const char *const option,
24473a6dd371SMasatake YAMATO const char *const parameter)
24483b7988cfSMasatake YAMATO {
24493b7988cfSMasatake YAMATO parserObject *parser;
24503b7988cfSMasatake YAMATO
24513b7988cfSMasatake YAMATO kindDefinition *kdef;
2452751c4167SMasatake YAMATO char letter;
24533a6dd371SMasatake YAMATO const char * p = parameter;
24543b7988cfSMasatake YAMATO char *name;
24553b7988cfSMasatake YAMATO char *description;
24562854ad6dSMasatake YAMATO const char *name_start;
24572854ad6dSMasatake YAMATO const char *marker_end;
24582854ad6dSMasatake YAMATO size_t name_len;
2459f741fddfSMasatake YAMATO const char *flags;
24603b7988cfSMasatake YAMATO
24613b7988cfSMasatake YAMATO
24623b7988cfSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
24633b7988cfSMasatake YAMATO parser = LanguageTable + language;
24643b7988cfSMasatake YAMATO
24653b7988cfSMasatake YAMATO Assert (p);
24663b7988cfSMasatake YAMATO
24673b7988cfSMasatake YAMATO if (p[0] == '\0')
24683b7988cfSMasatake YAMATO error (FATAL, "no kind definition specified in \"--%s\" option", option);
24693b7988cfSMasatake YAMATO
2470751c4167SMasatake YAMATO letter = p[0];
24713b7988cfSMasatake YAMATO if (letter == ',')
24723b7988cfSMasatake YAMATO error (FATAL, "no kind letter specified in \"--%s\" option", option);
2473751c4167SMasatake YAMATO if (/* See #1697. isalnum expects 0~255 as the range of characters. */
2474751c4167SMasatake YAMATO !isalpha ((unsigned char)letter)
2475751c4167SMasatake YAMATO )
2476e0b5213bSMasatake YAMATO error (FATAL, "the kind letter given in \"--%s\" option is not an alphabet", option);
24777e1bd430SMasatake YAMATO else if (letter == KIND_FILE_DEFAULT_LETTER)
247847df83bdSMasatake YAMATO error (FATAL, "the kind letter `%c' in \"--%s\" option is reserved for \"%s\" kind",
247947df83bdSMasatake YAMATO KIND_FILE_DEFAULT_LETTER, option, KIND_FILE_DEFAULT_NAME);
24803b7988cfSMasatake YAMATO else if (getKindForLetter (parser->kindControlBlock, letter))
24813b7988cfSMasatake YAMATO {
24823b7988cfSMasatake YAMATO error (WARNING, "the kind for letter `%c' specified in \"--%s\" option is already defined.",
24833b7988cfSMasatake YAMATO letter, option);
24843b7988cfSMasatake YAMATO return true;
24853b7988cfSMasatake YAMATO }
24863b7988cfSMasatake YAMATO
24873b7988cfSMasatake YAMATO if (p[1] != ',')
24883b7988cfSMasatake YAMATO error (FATAL, "wrong kind definition in \"--%s\" option: no comma after letter", option);
24893b7988cfSMasatake YAMATO
24903b7988cfSMasatake YAMATO p += 2;
24913b7988cfSMasatake YAMATO if (p[0] == '\0')
24923b7988cfSMasatake YAMATO error (FATAL, "no kind name specified in \"--%s\" option", option);
24932854ad6dSMasatake YAMATO marker_end = strchr (p, ',');
24942854ad6dSMasatake YAMATO if (!marker_end)
24953b7988cfSMasatake YAMATO error (FATAL, "no kind description specified in \"--%s\" option", option);
24963b7988cfSMasatake YAMATO
24972854ad6dSMasatake YAMATO name_start = p;
24982854ad6dSMasatake YAMATO while (p != marker_end)
24992854ad6dSMasatake YAMATO {
25002854ad6dSMasatake YAMATO if (p == name_start)
25012854ad6dSMasatake YAMATO {
25022854ad6dSMasatake YAMATO if (!isalpha(*p))
25032854ad6dSMasatake YAMATO {
25042854ad6dSMasatake YAMATO char *name_in_msg = eStrndup (name_start, marker_end - name_start);
25052854ad6dSMasatake YAMATO error (FATAL,
25062854ad6dSMasatake YAMATO "a kind name doesn't start with an alphabetical character: "
25072854ad6dSMasatake YAMATO "'%s' in \"--%s\" option",
25082854ad6dSMasatake YAMATO name_in_msg, option);
25092854ad6dSMasatake YAMATO }
25102854ad6dSMasatake YAMATO }
25112854ad6dSMasatake YAMATO else
25123b7988cfSMasatake YAMATO {
2513a2bda196SMasatake YAMATO if (!isalnum (*p))
25142854ad6dSMasatake YAMATO {
25152854ad6dSMasatake YAMATO char *name_in_msg = eStrndup (name_start, marker_end - name_start);
25162854ad6dSMasatake YAMATO error (FATAL,
25172854ad6dSMasatake YAMATO "non-alphanumeric char is used as part of kind name: "
25182854ad6dSMasatake YAMATO "'%s' in \"--%s\" option",
25192854ad6dSMasatake YAMATO name_in_msg, option);
25202854ad6dSMasatake YAMATO }
25212854ad6dSMasatake YAMATO }
25223b7988cfSMasatake YAMATO p++;
25233b7988cfSMasatake YAMATO }
25243b7988cfSMasatake YAMATO
25252854ad6dSMasatake YAMATO if (marker_end == name_start)
25263b7988cfSMasatake YAMATO error (FATAL, "the kind name in \"--%s\" option is empty", option);
25273b7988cfSMasatake YAMATO
25282854ad6dSMasatake YAMATO name_len = marker_end - name_start;
25292854ad6dSMasatake YAMATO if (strncmp (name_start, KIND_FILE_DEFAULT_NAME, name_len) == 0)
25300f8ba855SMasatake YAMATO error (FATAL,
25317e1bd430SMasatake YAMATO "the kind name " KIND_FILE_DEFAULT_NAME " in \"--%s\" option is reserved",
25320f8ba855SMasatake YAMATO option);
25330f8ba855SMasatake YAMATO
25342854ad6dSMasatake YAMATO name = eStrndup (name_start, name_len);
25353b7988cfSMasatake YAMATO if (getKindForName (parser->kindControlBlock, name))
25363b7988cfSMasatake YAMATO {
25373b7988cfSMasatake YAMATO error (WARNING, "the kind for name `%s' specified in \"--%s\" option is already defined.",
25383b7988cfSMasatake YAMATO name, option);
25393b7988cfSMasatake YAMATO eFree (name);
25403b7988cfSMasatake YAMATO return true;
25413b7988cfSMasatake YAMATO }
25423b7988cfSMasatake YAMATO
25433b7988cfSMasatake YAMATO p++;
254496b4483eSMasatake YAMATO if (p [0] == '\0' || p [0] == LONG_FLAGS_OPEN)
25453b7988cfSMasatake YAMATO error (FATAL, "found an empty kind description in \"--%s\" option", option);
254696b4483eSMasatake YAMATO
2547f741fddfSMasatake YAMATO description = extractDescriptionAndFlags (p, &flags);
25483b7988cfSMasatake YAMATO
25493b7988cfSMasatake YAMATO kdef = xCalloc (1, kindDefinition);
25503b7988cfSMasatake YAMATO kdef->enabled = true;
25513b7988cfSMasatake YAMATO kdef->letter = letter;
25523b7988cfSMasatake YAMATO kdef->name = name;
25533b7988cfSMasatake YAMATO kdef->description = description;
255496b4483eSMasatake YAMATO if (flags)
2555ba1453a4SMasatake YAMATO flagsEval (flags, PreKindDefFlagDef, ARRAY_SIZE (PreKindDefFlagDef), kdef);
25563b7988cfSMasatake YAMATO
25573b7988cfSMasatake YAMATO defineKind (parser->kindControlBlock, kdef, freeKdef);
25583b7988cfSMasatake YAMATO return true;
25593b7988cfSMasatake YAMATO }
25603b7988cfSMasatake YAMATO
freeRdef(roleDefinition * rdef)25617adc9db2SMasatake YAMATO static void freeRdef (roleDefinition *rdef)
25627adc9db2SMasatake YAMATO {
25637adc9db2SMasatake YAMATO eFree (rdef->name);
25647adc9db2SMasatake YAMATO eFree (rdef->description);
25657adc9db2SMasatake YAMATO eFree (rdef);
25667adc9db2SMasatake YAMATO }
25677adc9db2SMasatake YAMATO
processLangDefineRole(const langType language,const char * const kindSpec,const char * const option,const char * const parameter)25687adc9db2SMasatake YAMATO static bool processLangDefineRole(const langType language,
256997d2a121SMasatake YAMATO const char *const kindSpec,
25707adc9db2SMasatake YAMATO const char *const option,
25713a6dd371SMasatake YAMATO const char *const parameter)
25727adc9db2SMasatake YAMATO {
25737adc9db2SMasatake YAMATO parserObject *parser;
25747adc9db2SMasatake YAMATO
25757adc9db2SMasatake YAMATO kindDefinition *kdef;
25767adc9db2SMasatake YAMATO roleDefinition *rdef;
25777adc9db2SMasatake YAMATO char *name;
25787adc9db2SMasatake YAMATO char *description;
25797adc9db2SMasatake YAMATO
25807adc9db2SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
258197d2a121SMasatake YAMATO Assert (parameter);
258297d2a121SMasatake YAMATO
25837adc9db2SMasatake YAMATO parser = LanguageTable + language;
25847adc9db2SMasatake YAMATO
258597d2a121SMasatake YAMATO if (*kindSpec == '{')
258697d2a121SMasatake YAMATO {
258797d2a121SMasatake YAMATO const char *end = strchr (kindSpec, '}');
258897d2a121SMasatake YAMATO if (end == NULL)
258997d2a121SMasatake YAMATO error (FATAL, "no '}' representing the end of kind name in --%s option: %s",
259097d2a121SMasatake YAMATO option, kindSpec);
259197d2a121SMasatake YAMATO if (*(end + 1) != '\0')
259297d2a121SMasatake YAMATO error (FATAL, "garbage after the kind specification %s in --%s option",
259397d2a121SMasatake YAMATO kindSpec, option);
259497d2a121SMasatake YAMATO char *kindName = eStrndup (kindSpec + 1, end - (kindSpec + 1));
259597d2a121SMasatake YAMATO if (strcmp (kindName, KIND_FILE_DEFAULT_NAME) == 0)
259697d2a121SMasatake YAMATO error (FATAL, "don't define a role for %c/%s kind; it has no role: --%s",
259797d2a121SMasatake YAMATO KIND_FILE_DEFAULT_LETTER, KIND_FILE_DEFAULT_NAME,
259897d2a121SMasatake YAMATO option);
259997d2a121SMasatake YAMATO kdef = getKindForName (parser->kindControlBlock, kindName);
260097d2a121SMasatake YAMATO if (kdef == NULL)
260197d2a121SMasatake YAMATO error (FATAL, "the kind for name `%s' specified in \"--%s\" option is not defined.",
260297d2a121SMasatake YAMATO kindName, option);
260397d2a121SMasatake YAMATO eFree (kindName);
260497d2a121SMasatake YAMATO }
260597d2a121SMasatake YAMATO else
260697d2a121SMasatake YAMATO {
260797d2a121SMasatake YAMATO char kletter = *kindSpec;
2608751c4167SMasatake YAMATO if (!isalnum ((unsigned char)kletter))
2609bb61d62dSMasatake YAMATO error (FATAL, "the kind letter given in \"--%s\" option is not an alphabet or a number", option);
26107e1bd430SMasatake YAMATO else if (kletter == KIND_FILE_DEFAULT_LETTER)
261197d2a121SMasatake YAMATO error (FATAL, "the kind letter `%c' in \"--%s\" option is reserved for \"%s\" kind, and no role can be attached to it",
261297d2a121SMasatake YAMATO KIND_FILE_DEFAULT_LETTER, option, KIND_FILE_DEFAULT_NAME);
261397d2a121SMasatake YAMATO else if (*(kindSpec + 1) != '\0')
261497d2a121SMasatake YAMATO error (FATAL, "more than one letters are specified as a kind spec in \"--%s\" option: use `{' and `}' for specifying a kind name",
261597d2a121SMasatake YAMATO option);
26167adc9db2SMasatake YAMATO
26177adc9db2SMasatake YAMATO kdef = getKindForLetter (parser->kindControlBlock, kletter);
26187adc9db2SMasatake YAMATO if (kdef == NULL)
26197adc9db2SMasatake YAMATO {
262097d2a121SMasatake YAMATO error (FATAL, "the kind for letter `%c' specified in \"--%s\" option is not defined.",
262197d2a121SMasatake YAMATO *kindSpec, option);
26227adc9db2SMasatake YAMATO return true;
26237adc9db2SMasatake YAMATO }
262497d2a121SMasatake YAMATO }
26257adc9db2SMasatake YAMATO
262697d2a121SMasatake YAMATO const char * p = parameter;
262797d2a121SMasatake YAMATO const char *tmp_end = strchr (p, ',');
26287adc9db2SMasatake YAMATO if (!tmp_end)
26297adc9db2SMasatake YAMATO error (FATAL, "no role description specified in \"--%s\" option", option);
26307adc9db2SMasatake YAMATO
263197d2a121SMasatake YAMATO const char * tmp_start = p;
26327adc9db2SMasatake YAMATO while (p != tmp_end)
26337adc9db2SMasatake YAMATO {
26347adc9db2SMasatake YAMATO if (!isalnum (*p))
2635af6edb60SMasatake YAMATO error (FATAL, "unacceptable char as part of role name in \"--%s\" option: %c",
2636af6edb60SMasatake YAMATO option, *p);
26377adc9db2SMasatake YAMATO p++;
26387adc9db2SMasatake YAMATO }
26397adc9db2SMasatake YAMATO
26407adc9db2SMasatake YAMATO if (tmp_end == tmp_start)
26417adc9db2SMasatake YAMATO error (FATAL, "the role name in \"--%s\" option is empty", option);
26427adc9db2SMasatake YAMATO
26437adc9db2SMasatake YAMATO name = eStrndup (tmp_start, tmp_end - tmp_start);
26447adc9db2SMasatake YAMATO if (getRoleForName (parser->kindControlBlock, kdef->id, name))
26457adc9db2SMasatake YAMATO {
26467adc9db2SMasatake YAMATO error (WARNING, "the role for name `%s' specified in \"--%s\" option is already defined.",
26477adc9db2SMasatake YAMATO name, option);
26487adc9db2SMasatake YAMATO eFree (name);
26497adc9db2SMasatake YAMATO return true;
26507adc9db2SMasatake YAMATO }
26517adc9db2SMasatake YAMATO
26527adc9db2SMasatake YAMATO p++;
26537adc9db2SMasatake YAMATO if (p [0] == '\0' || p [0] == LONG_FLAGS_OPEN)
26547adc9db2SMasatake YAMATO error (FATAL, "found an empty role description in \"--%s\" option", option);
26557adc9db2SMasatake YAMATO
265697d2a121SMasatake YAMATO const char *flags;
26577adc9db2SMasatake YAMATO description = extractDescriptionAndFlags (p, &flags);
26587adc9db2SMasatake YAMATO
26597adc9db2SMasatake YAMATO rdef = xCalloc (1, roleDefinition);
26607adc9db2SMasatake YAMATO rdef->enabled = true;
26617adc9db2SMasatake YAMATO rdef->name = name;
26627adc9db2SMasatake YAMATO rdef->description = description;
26637adc9db2SMasatake YAMATO
26647adc9db2SMasatake YAMATO if (flags)
26657adc9db2SMasatake YAMATO flagsEval (flags, NULL, 0, rdef);
26667adc9db2SMasatake YAMATO
26677adc9db2SMasatake YAMATO defineRole (parser->kindControlBlock, kdef->id, rdef, freeRdef);
26687adc9db2SMasatake YAMATO
26697adc9db2SMasatake YAMATO return true;
26707adc9db2SMasatake YAMATO }
26717adc9db2SMasatake YAMATO
processKinddefOption(const char * const option,const char * const parameter)267218dab48bSMasatake YAMATO extern bool processKinddefOption (const char *const option, const char * const parameter)
26733b7988cfSMasatake YAMATO {
26743b7988cfSMasatake YAMATO langType language;
26753b7988cfSMasatake YAMATO
26763b7988cfSMasatake YAMATO language = getLanguageComponentInOption (option, "kinddef-");
26773b7988cfSMasatake YAMATO if (language == LANG_IGNORE)
26783b7988cfSMasatake YAMATO return false;
26793b7988cfSMasatake YAMATO
26803b7988cfSMasatake YAMATO return processLangDefineKind (language, option, parameter);
26813b7988cfSMasatake YAMATO }
26823b7988cfSMasatake YAMATO
processRoledefOption(const char * const option,const char * const parameter)26837adc9db2SMasatake YAMATO extern bool processRoledefOption (const char *const option, const char * const parameter)
26847adc9db2SMasatake YAMATO {
268597d2a121SMasatake YAMATO #define PREFIX "_roledef-"
268697d2a121SMasatake YAMATO #define PREFIX_LEN strlen(PREFIX)
26877adc9db2SMasatake YAMATO
268897d2a121SMasatake YAMATO langType language = getLanguageComponentInOption (option, PREFIX);
26897adc9db2SMasatake YAMATO if (language == LANG_IGNORE)
26907adc9db2SMasatake YAMATO return false;
26917adc9db2SMasatake YAMATO
269297d2a121SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
269397d2a121SMasatake YAMATO const char* kindSpec = option + PREFIX_LEN + strlen (getLanguageName (language));
269497d2a121SMasatake YAMATO if (*kindSpec == '\0')
269597d2a121SMasatake YAMATO error (FATAL, "no kind is specifined in \"--%s=%s\"", option, parameter);
269697d2a121SMasatake YAMATO if (*kindSpec != '.')
269797d2a121SMasatake YAMATO error (FATAL, "no delimiter (.) where a kindspec starts is found in \"--%s\": %c",
269897d2a121SMasatake YAMATO option, *kindSpec);
269997d2a121SMasatake YAMATO kindSpec++;
270097d2a121SMasatake YAMATO
270197d2a121SMasatake YAMATO return processLangDefineRole (language, kindSpec, option, parameter);
270297d2a121SMasatake YAMATO #undef PREFIX
270397d2a121SMasatake YAMATO #undef PREFIX_LEN
27047adc9db2SMasatake YAMATO }
27057adc9db2SMasatake YAMATO
2706e112e8abSMasatake YAMATO struct langKindDefinitionStruct {
2707d4c6f1e6SMasatake YAMATO const char *const option;
2708d4c6f1e6SMasatake YAMATO const char *const parameter;
2709d4c6f1e6SMasatake YAMATO };
processLangKindDefinitionEach(langType lang,void * user_data)2710e112e8abSMasatake YAMATO static void processLangKindDefinitionEach(
2711d4c6f1e6SMasatake YAMATO langType lang, void* user_data)
2712d4c6f1e6SMasatake YAMATO {
2713e112e8abSMasatake YAMATO struct langKindDefinitionStruct *arg = user_data;
2714e112e8abSMasatake YAMATO processLangKindDefinition (lang, arg->option, arg->parameter);
2715d4c6f1e6SMasatake YAMATO }
2716d4c6f1e6SMasatake YAMATO
parameterEnablingAllOrFileKind(const char * const option,const char * const parameter,bool following_plus_or_minus_op)27177edb8484SMasatake YAMATO static bool parameterEnablingAllOrFileKind (const char *const option,
27187edb8484SMasatake YAMATO const char *const parameter,
27197edb8484SMasatake YAMATO bool following_plus_or_minus_op)
27207edb8484SMasatake YAMATO {
27217edb8484SMasatake YAMATO size_t file_long_flag_len = strlen(KIND_FILE_DEFAULT_NAME);
27227edb8484SMasatake YAMATO
27237edb8484SMasatake YAMATO switch (parameter[0])
27247edb8484SMasatake YAMATO {
27257edb8484SMasatake YAMATO /* Though only '*' is documented as an acceptable kind spec for
27267edb8484SMasatake YAMATO * --kinds-all option in our man page, we accept '\0' here because
27277edb8484SMasatake YAMATO * it will be useful for testing purpose. */
27287edb8484SMasatake YAMATO case '\0':
27297edb8484SMasatake YAMATO if (following_plus_or_minus_op)
27307edb8484SMasatake YAMATO error(FATAL, "no kind specification after + (or -) in --%s option",
27317edb8484SMasatake YAMATO option);
27327edb8484SMasatake YAMATO else
27337edb8484SMasatake YAMATO return true;
27347edb8484SMasatake YAMATO case '+':
27357edb8484SMasatake YAMATO case '-':
27367edb8484SMasatake YAMATO if (following_plus_or_minus_op)
27377edb8484SMasatake YAMATO error(FATAL, "don't repeat + (nor -) in --%s option",
27387edb8484SMasatake YAMATO option);
27397edb8484SMasatake YAMATO else
27407edb8484SMasatake YAMATO return parameterEnablingAllOrFileKind (option, parameter + 1, true);
27417edb8484SMasatake YAMATO case KIND_WILDCARD_LETTER:
27427edb8484SMasatake YAMATO if (following_plus_or_minus_op)
27437edb8484SMasatake YAMATO error(FATAL, "don't use '*' after + (nor -) in --%s option",
27447edb8484SMasatake YAMATO option);
27457edb8484SMasatake YAMATO else
27467edb8484SMasatake YAMATO return parameterEnablingAllOrFileKind (option, parameter + 1, false);
27477edb8484SMasatake YAMATO case KIND_FILE_DEFAULT_LETTER:
27487edb8484SMasatake YAMATO return parameterEnablingAllOrFileKind (option, parameter + 1, false);
27497edb8484SMasatake YAMATO case '{':
27507edb8484SMasatake YAMATO if (strncmp (parameter + 1, KIND_FILE_DEFAULT_NAME, file_long_flag_len) == 0
27517edb8484SMasatake YAMATO && parameter [1 + file_long_flag_len] == '}')
27527edb8484SMasatake YAMATO return parameterEnablingAllOrFileKind (option,
27537edb8484SMasatake YAMATO parameter + 1 + file_long_flag_len + 1,
27547edb8484SMasatake YAMATO false);
27557edb8484SMasatake YAMATO break;
27567edb8484SMasatake YAMATO }
27577edb8484SMasatake YAMATO return false;
27587edb8484SMasatake YAMATO }
27597edb8484SMasatake YAMATO
processKindsOption(const char * const option,const char * const parameter)276018dab48bSMasatake YAMATO extern bool processKindsOption (
2761d4c6f1e6SMasatake YAMATO const char *const option, const char *const parameter)
2762d4c6f1e6SMasatake YAMATO {
276343586520SMasatake YAMATO #define PREFIX "kinds-"
276443586520SMasatake YAMATO #define PREFIX_LEN strlen(PREFIX)
2765d4c6f1e6SMasatake YAMATO
2766ce990805SThomas Braun bool handled = false;
2767e112e8abSMasatake YAMATO struct langKindDefinitionStruct arg = {
2768d4c6f1e6SMasatake YAMATO .option = option,
2769d4c6f1e6SMasatake YAMATO .parameter = parameter,
2770d4c6f1e6SMasatake YAMATO };
277143586520SMasatake YAMATO langType language;
2772d4c6f1e6SMasatake YAMATO
277343586520SMasatake YAMATO const char* const dash = strchr (option, '-');
277443586520SMasatake YAMATO if (dash != NULL &&
277543586520SMasatake YAMATO (strcmp (dash + 1, "kinds") == 0 || strcmp (dash + 1, "types") == 0))
277643586520SMasatake YAMATO {
277743586520SMasatake YAMATO size_t len = dash - option;
2778a7c5f3b5SMasatake YAMATO char *langName = eStrndup (option, len);
277943586520SMasatake YAMATO
2780a7c5f3b5SMasatake YAMATO if ((len == 3) && (strcmp (langName, RSV_LANG_ALL) == 0))
27811295de21SMasatake YAMATO {
2782a7c5f3b5SMasatake YAMATO error (WARNING,
2783a7c5f3b5SMasatake YAMATO "\"--%s\" option is obsolete; use \"--kinds-%s\" instead",
2784a7c5f3b5SMasatake YAMATO option, langName);
27857edb8484SMasatake YAMATO if (!parameterEnablingAllOrFileKind (option, parameter, false))
27867edb8484SMasatake YAMATO error (FATAL, "only '*', 'F', \"{file}\" or their combination is acceptable as kind letter for --%s", option);
2787e112e8abSMasatake YAMATO foreachLanguage(processLangKindDefinitionEach, &arg);
27881295de21SMasatake YAMATO }
2789d4c6f1e6SMasatake YAMATO else
2790d4c6f1e6SMasatake YAMATO {
2791a7c5f3b5SMasatake YAMATO language = getNamedLanguage (langName, 0);
2792d4c6f1e6SMasatake YAMATO if (language == LANG_IGNORE)
27937d35e3d4SMasatake YAMATO error (WARNING, "Unknown language \"%s\" in \"%s\" option", langName, option);
2794d4c6f1e6SMasatake YAMATO else
2795e112e8abSMasatake YAMATO processLangKindDefinition (language, option, parameter);
2796d4c6f1e6SMasatake YAMATO }
2797a7c5f3b5SMasatake YAMATO eFree (langName);
2798ce990805SThomas Braun handled = true;
2799d4c6f1e6SMasatake YAMATO }
280043586520SMasatake YAMATO else if ( strncmp (option, PREFIX, PREFIX_LEN) == 0 )
280143586520SMasatake YAMATO {
280243586520SMasatake YAMATO const char* lang;
280343586520SMasatake YAMATO
280443586520SMasatake YAMATO lang = option + PREFIX_LEN;
2805a1f18f64SMasatake YAMATO if (lang[0] == '\0')
280643586520SMasatake YAMATO error (WARNING, "No language given in \"%s\" option", option);
2807a1f18f64SMasatake YAMATO else if (strcmp (lang, RSV_LANG_ALL) == 0)
28081295de21SMasatake YAMATO {
28097edb8484SMasatake YAMATO if (!parameterEnablingAllOrFileKind (option, parameter, false))
28107edb8484SMasatake YAMATO error (FATAL, "only '*', 'F', \"{file}\" or their combination is acceptable as kind letter for --%s", option);
2811e112e8abSMasatake YAMATO foreachLanguage(processLangKindDefinitionEach, &arg);
28121295de21SMasatake YAMATO }
281343586520SMasatake YAMATO else
281443586520SMasatake YAMATO {
28155a55f03bSMasatake YAMATO language = getNamedLanguage (lang, 0);
281643586520SMasatake YAMATO if (language == LANG_IGNORE)
281743586520SMasatake YAMATO error (WARNING, "Unknown language \"%s\" in \"%s\" option", lang, option);
281843586520SMasatake YAMATO else
2819e112e8abSMasatake YAMATO processLangKindDefinition (language, option, parameter);
28201d4e02b7SMasatake YAMATO }
2821ce990805SThomas Braun handled = true;
282243586520SMasatake YAMATO }
2823d4c6f1e6SMasatake YAMATO return handled;
282443586520SMasatake YAMATO #undef PREFIX
282543586520SMasatake YAMATO #undef PREFIX_LEN
2826d4c6f1e6SMasatake YAMATO }
2827d4c6f1e6SMasatake YAMATO
2828d2842001SMasatake YAMATO /*
2829d2842001SMasatake YAMATO * The argument specification for --roles-<LANG>:<KIND>= option
2830d2842001SMasatake YAMATO * =====================================================================
2831d2842001SMasatake YAMATO *
2832d2842001SMasatake YAMATO * --roles-all.*=
2833d2842001SMasatake YAMATO * --roles-all=
2834d2842001SMasatake YAMATO * => Disable all roles of all kinds in all languages.
2835d2842001SMasatake YAMATO *
2836d2842001SMasatake YAMATO * --roles-all.*='*'
2837d2842001SMasatake YAMATO * --roles-all='*'
2838d2842001SMasatake YAMATO * => Enable all roles of all kinds in all languages.
2839d2842001SMasatake YAMATO *
2840d2842001SMasatake YAMATO * --roles-<LANG>.*=
2841d2842001SMasatake YAMATO * --roles-<LANG>=
2842d2842001SMasatake YAMATO * => Disable all roles of all kinds.
2843d2842001SMasatake YAMATO *
2844d2842001SMasatake YAMATO * --roles-<LANG>.*=*
2845d2842001SMasatake YAMATO * --roles-<LANG>=*
2846d2842001SMasatake YAMATO * => Enable all roles of all kinds.
2847d2842001SMasatake YAMATO *
2848d2842001SMasatake YAMATO * --roles-<LANG>.{kind}=
2849d2842001SMasatake YAMATO * --roles-<LANG>.k=
2850d2842001SMasatake YAMATO * => Disable all roles of the kind specified with a letter.
2851d2842001SMasatake YAMATO *
2852d2842001SMasatake YAMATO * --roles-<LANG>.{kind}=*
2853d2842001SMasatake YAMATO * --roles-<LANG>.k=*
2854d2842001SMasatake YAMATO * => Enable all roles of the kind specified with a letter.
2855d2842001SMasatake YAMATO *
2856d2842001SMasatake YAMATO * --roles-<LANG>.{kind}=[+|-]{role}
2857d2842001SMasatake YAMATO * --roles-<LANG>.k=[+|-]{role}
2858d2842001SMasatake YAMATO * => Enable/disable the role of the kind specified with a letter.
2859d2842001SMasatake YAMATO *
2860d2842001SMasatake YAMATO *
2861d2842001SMasatake YAMATO * Examples of combination
2862d2842001SMasatake YAMATO * ---------------------------------------------------------------------
2863d2842001SMasatake YAMATO *
2864d2842001SMasatake YAMATO * --roles-<LANG>.k0=+{role0}-{role1}{role2}
2865d2842001SMasatake YAMATO * --roles-<LANG>.{kind1}=+{role0}-{role1}{role2}
2866d2842001SMasatake YAMATO *
2867d2842001SMasatake YAMATO *
286857a18729SMasatake YAMATO * How --roledef should be change to align --roles-<LANG> notation
2869d2842001SMasatake YAMATO * ---------------------------------------------------------------------
2870d2842001SMasatake YAMATO *
2871d2842001SMasatake YAMATO * --_roledef-<LANG>.k=role,description
2872d2842001SMasatake YAMATO * --_roledef-<LANG>.{kind}=role,description
2873d2842001SMasatake YAMATO *
2874d2842001SMasatake YAMATO * The notation was
2875d2842001SMasatake YAMATO * --_roledef-<LANG>=k.role,description
2876d2842001SMasatake YAMATO *
2877d2842001SMasatake YAMATO *
287857a18729SMasatake YAMATO * How --param should be change to align --roles-<LANG> notation
2879d2842001SMasatake YAMATO * ---------------------------------------------------------------------
2880d2842001SMasatake YAMATO *
28818114f7b3SMasatake YAMATO * --param-<LANG>.name=argument
2882d2842001SMasatake YAMATO *
28834c5decb0SMasatake YAMATO * The notation was
28848114f7b3SMasatake YAMATO * --param-<LANG>:name=argument
2885d2842001SMasatake YAMATO *
2886d2842001SMasatake YAMATO *
288757a18729SMasatake YAMATO * How --paramdef should be to align --roles-<LANG> notation
2888d2842001SMasatake YAMATO * ---------------------------------------------------------------------
2889d2842001SMasatake YAMATO *
2890d2842001SMasatake YAMATO * --_paramdef-<LANG>.name=[ default (desription) ]
2891d2842001SMasatake YAMATO *
2892d2842001SMasatake YAMATO *
2893d2842001SMasatake YAMATO * Discussion: which shoule we use . or : ?
2894d2842001SMasatake YAMATO * ---------------------------------------------------------------------
2895d2842001SMasatake YAMATO *
2896d2842001SMasatake YAMATO * `.' is better because `:' implies fields.
2897d2842001SMasatake YAMATO *
2898d2842001SMasatake YAMATO */
2899d2842001SMasatake YAMATO struct langKindRoleDefinitionStruct {
2900d2842001SMasatake YAMATO int kindIndex;
2901d2842001SMasatake YAMATO const char *const option;
2902d2842001SMasatake YAMATO const char *const parameter;
2903d2842001SMasatake YAMATO };
2904d2842001SMasatake YAMATO
2905d2842001SMasatake YAMATO typedef void (*kindCallback) (langType language, int kindIndex, void* user_data);
foreachKind(langType language,kindCallback callback,void * user_data)2906d2842001SMasatake YAMATO static void foreachKind(langType language, kindCallback callback, void *user_data)
2907d2842001SMasatake YAMATO {
2908d2842001SMasatake YAMATO unsigned int c = countLanguageKinds (language);
2909d2842001SMasatake YAMATO for (unsigned int i = 0; i < c; i++)
2910d2842001SMasatake YAMATO callback (language, (int)i, user_data);
2911d2842001SMasatake YAMATO }
2912d2842001SMasatake YAMATO
resetKindRoles(const langType language,int kindIndex,const bool mode)2913d2842001SMasatake YAMATO static void resetKindRoles (const langType language, int kindIndex, const bool mode)
2914d2842001SMasatake YAMATO {
2915d2842001SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
2916d2842001SMasatake YAMATO unsigned int c = countLanguageRoles (language, kindIndex);
2917d2842001SMasatake YAMATO
2918d2842001SMasatake YAMATO for (unsigned int i = 0; i < c; i++)
2919d2842001SMasatake YAMATO {
2920d2842001SMasatake YAMATO roleDefinition* rdef = getLanguageRole (language, kindIndex, (int)i);
2921d2842001SMasatake YAMATO enableRole (rdef, mode);
2922d2842001SMasatake YAMATO }
2923d2842001SMasatake YAMATO }
2924d2842001SMasatake YAMATO
resetKindRolesAsCallback(const langType language,int kindIndex,void * user_data)2925d2842001SMasatake YAMATO static void resetKindRolesAsCallback (const langType language, int kindIndex, void *user_data)
2926d2842001SMasatake YAMATO {
2927d2842001SMasatake YAMATO bool mode = (bool)user_data;
2928d2842001SMasatake YAMATO resetKindRoles (language, kindIndex, mode);
2929d2842001SMasatake YAMATO }
2930d2842001SMasatake YAMATO
processLangKindRoleDefinition(const langType language,const int kindIndex,const char * const option,const char * const parameter)2931d2842001SMasatake YAMATO static void processLangKindRoleDefinition (
2932d2842001SMasatake YAMATO const langType language, const int kindIndex, const char *const option,
2933d2842001SMasatake YAMATO const char *const parameter)
2934d2842001SMasatake YAMATO {
2935d2842001SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
2936d2842001SMasatake YAMATO Assert (kindIndex != KIND_GHOST_INDEX);
2937d2842001SMasatake YAMATO initializeParser (language);
2938d2842001SMasatake YAMATO
2939d2842001SMasatake YAMATO const char *p = parameter;
2940d2842001SMasatake YAMATO bool mode = true;
2941d2842001SMasatake YAMATO
2942d2842001SMasatake YAMATO if (*p == '\0')
2943d2842001SMasatake YAMATO {
2944d2842001SMasatake YAMATO resetKindRoles (language, kindIndex, false);
2945d2842001SMasatake YAMATO return;
2946d2842001SMasatake YAMATO }
2947d2842001SMasatake YAMATO else if (*p != '+' && *p != '-' )
2948d2842001SMasatake YAMATO resetKindRoles (language, kindIndex, false);
2949d2842001SMasatake YAMATO
2950d2842001SMasatake YAMATO while (*p != '\0')
2951d2842001SMasatake YAMATO {
2952d2842001SMasatake YAMATO if (*p == '+')
2953d2842001SMasatake YAMATO {
2954d2842001SMasatake YAMATO mode = true;
2955d2842001SMasatake YAMATO p++;
2956d2842001SMasatake YAMATO }
2957d2842001SMasatake YAMATO else if (*p == '-')
2958d2842001SMasatake YAMATO {
2959d2842001SMasatake YAMATO mode = false;
2960d2842001SMasatake YAMATO p++;
2961d2842001SMasatake YAMATO }
2962d2842001SMasatake YAMATO else if (*p == '{')
2963d2842001SMasatake YAMATO {
2964d2842001SMasatake YAMATO p++;
2965d2842001SMasatake YAMATO char *q = strchr (p, '}');
2966d2842001SMasatake YAMATO if (!q)
2967d2842001SMasatake YAMATO
2968d2842001SMasatake YAMATO error (FATAL, "no '}' representing the end of role name in --%s option: %s",
2969d2842001SMasatake YAMATO option, p);
2970d2842001SMasatake YAMATO if (p == q)
2971d2842001SMasatake YAMATO error (FATAL, "empty role for the kind letter: %c",
2972d2842001SMasatake YAMATO getLanguageKind (language, kindIndex)->letter);
2973d2842001SMasatake YAMATO
2974d2842001SMasatake YAMATO char *rname = eStrndup (p, q - p);
2975d2842001SMasatake YAMATO roleDefinition *rdef = getLanguageRoleForName (language, kindIndex, rname);
2976d2842001SMasatake YAMATO if (!rdef)
2977d2842001SMasatake YAMATO error (WARNING, "no such role: %s of %c kind in language %s",
2978d2842001SMasatake YAMATO rname, getLanguageKind (language, kindIndex)->letter,
2979d2842001SMasatake YAMATO getLanguageName (language));
2980d2842001SMasatake YAMATO else
2981d2842001SMasatake YAMATO enableRole (rdef, mode);
2982d2842001SMasatake YAMATO eFree (rname);
2983d2842001SMasatake YAMATO p = q + 1;
2984d2842001SMasatake YAMATO }
2985d2842001SMasatake YAMATO else if (*p == '*')
2986d2842001SMasatake YAMATO {
2987d2842001SMasatake YAMATO resetKindRoles (language, kindIndex, true);
2988d2842001SMasatake YAMATO p++;
2989d2842001SMasatake YAMATO }
2990d2842001SMasatake YAMATO else
2991d2842001SMasatake YAMATO error (FATAL, "unexpected character %c in --%s=%s option",
2992d2842001SMasatake YAMATO *p, option, parameter);
2993d2842001SMasatake YAMATO }
2994d2842001SMasatake YAMATO }
2995d2842001SMasatake YAMATO
processLangKindRoleDefinitionEach(langType language,void * user_data)2996d2842001SMasatake YAMATO static void processLangKindRoleDefinitionEach (langType language, void* user_data)
2997d2842001SMasatake YAMATO {
2998d2842001SMasatake YAMATO struct langKindRoleDefinitionStruct *arg = user_data;
2999d2842001SMasatake YAMATO
3000d2842001SMasatake YAMATO if (arg->kindIndex == KIND_GHOST_INDEX)
3001d2842001SMasatake YAMATO {
3002d2842001SMasatake YAMATO initializeParser (language);
3003d2842001SMasatake YAMATO foreachKind (language, resetKindRolesAsCallback,
3004d2842001SMasatake YAMATO ((*(arg->parameter) == '*')? (void *)true: (void *)false));
3005d2842001SMasatake YAMATO }
3006d2842001SMasatake YAMATO else
3007d2842001SMasatake YAMATO processLangKindRoleDefinition (language, arg->kindIndex,
3008d2842001SMasatake YAMATO arg->option, arg->parameter);
3009d2842001SMasatake YAMATO }
3010d2842001SMasatake YAMATO
processRolesOption(const char * const option,const char * const parameter)3011d2842001SMasatake YAMATO extern bool processRolesOption (const char *const option, const char *const parameter)
3012d2842001SMasatake YAMATO {
3013d2842001SMasatake YAMATO #define PREFIX "roles-"
3014d2842001SMasatake YAMATO #define PREFIX_LEN strlen(PREFIX)
3015d2842001SMasatake YAMATO
3016d2842001SMasatake YAMATO if ( strncmp (option, PREFIX, PREFIX_LEN) != 0 )
3017d2842001SMasatake YAMATO return false;
3018d2842001SMasatake YAMATO
3019d2842001SMasatake YAMATO const char* lang = option + PREFIX_LEN;
3020d2842001SMasatake YAMATO if (lang[0] == '\0')
3021d2842001SMasatake YAMATO {
3022d2842001SMasatake YAMATO error (WARNING, "no language given in \"%s\" option", option);
3023d2842001SMasatake YAMATO return true;
3024d2842001SMasatake YAMATO }
3025d2842001SMasatake YAMATO
3026d2842001SMasatake YAMATO /*
3027d2842001SMasatake YAMATO * --roles-all.*=
3028d2842001SMasatake YAMATO * --roles-all=
3029d2842001SMasatake YAMATO * => Disable all roles of all kinds in all languages.
3030d2842001SMasatake YAMATO *
3031d2842001SMasatake YAMATO * --roles-all.*='*'
3032d2842001SMasatake YAMATO * --roles-all='*'
3033d2842001SMasatake YAMATO * => Enable all roles of all kinds in all languages.
3034d2842001SMasatake YAMATO */
3035d2842001SMasatake YAMATO if (strncmp (lang, RSV_LANG_ALL, strlen(RSV_LANG_ALL)) == 0)
3036d2842001SMasatake YAMATO {
3037d2842001SMasatake YAMATO if (lang [strlen (RSV_LANG_ALL)] == '\0'
3038d2842001SMasatake YAMATO || (strcmp (lang + strlen (RSV_LANG_ALL), ".*") == 0))
3039d2842001SMasatake YAMATO {
3040d2842001SMasatake YAMATO if (*parameter == '\0'
3041d2842001SMasatake YAMATO || strcmp(parameter, "*") == 0)
3042d2842001SMasatake YAMATO {
3043d2842001SMasatake YAMATO struct langKindRoleDefinitionStruct arg = {
3044d2842001SMasatake YAMATO .kindIndex = KIND_GHOST_INDEX,
3045d2842001SMasatake YAMATO .option = option,
3046d2842001SMasatake YAMATO .parameter = parameter,
3047d2842001SMasatake YAMATO };
3048d2842001SMasatake YAMATO foreachLanguage (processLangKindRoleDefinitionEach, &arg);
3049d2842001SMasatake YAMATO return true;
3050d2842001SMasatake YAMATO }
3051d2842001SMasatake YAMATO else
3052d2842001SMasatake YAMATO error (FATAL, "only '*' or '' (empty string) is acceptable as an argument for --%s: %s",
3053d2842001SMasatake YAMATO option,
3054d2842001SMasatake YAMATO parameter);
3055d2842001SMasatake YAMATO }
3056d2842001SMasatake YAMATO else if (lang [strlen(RSV_LANG_ALL)] == '.')
3057d2842001SMasatake YAMATO error (FATAL, "only '*' or '' (empty string) is acceptable as a kind spec for --%sall: --%s",
3058d2842001SMasatake YAMATO PREFIX,
3059d2842001SMasatake YAMATO option);
3060d2842001SMasatake YAMATO }
3061d2842001SMasatake YAMATO
3062d2842001SMasatake YAMATO /* Decide the language. */
3063d2842001SMasatake YAMATO langType language;
3064d2842001SMasatake YAMATO const char *dot = strchr (lang, '.');
3065d2842001SMasatake YAMATO if (dot)
3066d2842001SMasatake YAMATO language = getNamedLanguage (lang, dot - lang);
3067d2842001SMasatake YAMATO else
3068d2842001SMasatake YAMATO language = getNamedLanguage (lang, 0);
3069d2842001SMasatake YAMATO
3070d2842001SMasatake YAMATO if (language == LANG_IGNORE)
3071d2842001SMasatake YAMATO {
3072d2842001SMasatake YAMATO char *lang0 = dot? eStrndup (lang, dot - lang): NULL;
3073d2842001SMasatake YAMATO error (WARNING, "unknown language \"%s\" in --%s option",
3074d2842001SMasatake YAMATO (lang0? lang0: lang), option);
3075d2842001SMasatake YAMATO if (lang0)
3076d2842001SMasatake YAMATO eFree (lang0);
3077d2842001SMasatake YAMATO return true;
3078d2842001SMasatake YAMATO }
3079d2842001SMasatake YAMATO
3080d2842001SMasatake YAMATO /*
3081d2842001SMasatake YAMATO * --roles-<LANG>.*=
3082d2842001SMasatake YAMATO * --roles-<LANG>=
3083d2842001SMasatake YAMATO * => Disable all roles of all kinds.
3084d2842001SMasatake YAMATO *
3085d2842001SMasatake YAMATO * --roles-<LANG>.*=*
3086d2842001SMasatake YAMATO * --roles-<LANG>=*
3087d2842001SMasatake YAMATO * => Enable all roles of all kinds.
3088d2842001SMasatake YAMATO */
3089d2842001SMasatake YAMATO if (dot == NULL || (strcmp (dot, ".*") == 0))
3090d2842001SMasatake YAMATO {
3091d2842001SMasatake YAMATO if (*parameter == '\0'
3092d2842001SMasatake YAMATO || strcmp(parameter, "*") == 0)
3093d2842001SMasatake YAMATO {
3094d2842001SMasatake YAMATO foreachKind (language, resetKindRolesAsCallback,
3095d2842001SMasatake YAMATO ((*parameter == '*')? (void*)true: (void*)false));
3096d2842001SMasatake YAMATO return true;
3097d2842001SMasatake YAMATO }
3098d2842001SMasatake YAMATO else
3099d2842001SMasatake YAMATO error (FATAL, "only '*' or '' (empty string) is acceptable as an argument for --%s: %s",
3100d2842001SMasatake YAMATO option,
3101d2842001SMasatake YAMATO parameter);
3102d2842001SMasatake YAMATO }
3103d2842001SMasatake YAMATO
3104d2842001SMasatake YAMATO /* Decide the kind of the language. */
3105d2842001SMasatake YAMATO parserObject *parser = LanguageTable + language;
3106d2842001SMasatake YAMATO int kindIndex = KIND_GHOST_INDEX;
3107d2842001SMasatake YAMATO const char *kind = dot + 1;
3108d2842001SMasatake YAMATO if (*kind == '{')
3109d2842001SMasatake YAMATO {
3110d2842001SMasatake YAMATO const char *name_end = strchr (kind, '}');
3111d2842001SMasatake YAMATO if (name_end == NULL)
3112d2842001SMasatake YAMATO error (FATAL, "no '}' representing the end of kind name in --%s option: %s",
3113d2842001SMasatake YAMATO option, kind);
3114d2842001SMasatake YAMATO char *kindName = eStrndup (kind + 1, name_end - (kind + 1));
3115d2842001SMasatake YAMATO if (strcmp (kindName, KIND_FILE_DEFAULT_NAME) == 0)
3116d2842001SMasatake YAMATO {
311747df83bdSMasatake YAMATO error (WARNING, "don't enable/disable a role in %c/%s kind; it has no role: --%s",
311847df83bdSMasatake YAMATO KIND_FILE_DEFAULT_LETTER, KIND_FILE_DEFAULT_NAME,
3119d2842001SMasatake YAMATO option);
3120d2842001SMasatake YAMATO return true;
3121d2842001SMasatake YAMATO }
3122d2842001SMasatake YAMATO kindIndex = getKindIndexForName (parser->kindControlBlock, kindName);
3123d2842001SMasatake YAMATO if (kindIndex == KIND_GHOST_INDEX)
3124d2842001SMasatake YAMATO {
3125d2842001SMasatake YAMATO eFree (kindName);
3126d2842001SMasatake YAMATO error (WARNING, "no such kind name as specified in --%s option", option);
3127d2842001SMasatake YAMATO return true;
3128d2842001SMasatake YAMATO }
3129d2842001SMasatake YAMATO if (*(name_end + 1) != '\0')
3130d2842001SMasatake YAMATO error (FATAL, "garbage after the kind specification {%s} in --%s option",
3131d2842001SMasatake YAMATO kindName, option);
3132d2842001SMasatake YAMATO eFree (kindName);
3133d2842001SMasatake YAMATO }
3134d2842001SMasatake YAMATO else if (isalpha ((unsigned char)*kind))
3135d2842001SMasatake YAMATO {
3136d2842001SMasatake YAMATO if (*kind == KIND_FILE_DEFAULT_LETTER)
3137d2842001SMasatake YAMATO {
313847df83bdSMasatake YAMATO error (WARNING, "don't enable/disable a role in %c/%s kind; it has no role: --%s",
313947df83bdSMasatake YAMATO KIND_FILE_DEFAULT_LETTER, KIND_FILE_DEFAULT_NAME,
3140d2842001SMasatake YAMATO option);
3141d2842001SMasatake YAMATO return true;
3142d2842001SMasatake YAMATO }
3143d2842001SMasatake YAMATO kindIndex = getKindIndexForLetter (parser->kindControlBlock, *kind);
3144d2842001SMasatake YAMATO if (kindIndex == KIND_GHOST_INDEX)
3145d2842001SMasatake YAMATO {
3146d2842001SMasatake YAMATO error (WARNING, "no such kind letter as specified in --%s option", option);
3147d2842001SMasatake YAMATO return true;
3148d2842001SMasatake YAMATO }
3149d2842001SMasatake YAMATO if (*(kind + 1) != '\0')
3150d2842001SMasatake YAMATO error (FATAL, "garbage after the kind specification '%c' in --%s option",
3151d2842001SMasatake YAMATO *kind, option);
3152d2842001SMasatake YAMATO }
3153d2842001SMasatake YAMATO else
3154d2842001SMasatake YAMATO error (FATAL, "'%c', unexpected character in --%s", *kind, option);
3155d2842001SMasatake YAMATO
3156d2842001SMasatake YAMATO
3157d2842001SMasatake YAMATO /*
3158d2842001SMasatake YAMATO * --roles-<LANG>.{kind}=
3159d2842001SMasatake YAMATO * --roles-<LANG>.k=
3160d2842001SMasatake YAMATO * => Disable all roles of the kind specified with a letter.
3161d2842001SMasatake YAMATO *
3162d2842001SMasatake YAMATO * --roles-<LANG>.{kind}=*
3163d2842001SMasatake YAMATO * --roles-<LANG>.k=*
3164d2842001SMasatake YAMATO * => Enable all roles of the kind specified with a letter.
3165d2842001SMasatake YAMATO *
3166d2842001SMasatake YAMATO * --roles-<LANG>.{kind}=[+|-|]{role}
3167d2842001SMasatake YAMATO * --roles-<LANG>.k=[+|-|]{role}
3168d2842001SMasatake YAMATO * => Enable/disable the role of the kind specified with a letter.
3169d2842001SMasatake YAMATO */
3170d2842001SMasatake YAMATO processLangKindRoleDefinition (language, kindIndex, option, parameter);
3171d2842001SMasatake YAMATO
3172d2842001SMasatake YAMATO return true;
3173d2842001SMasatake YAMATO #undef PREFIX
3174d2842001SMasatake YAMATO #undef PREFIX_LEN
3175d2842001SMasatake YAMATO }
3176d2842001SMasatake YAMATO
printLanguageRoles(const langType language,const char * kindspecs,bool withListHeader,bool machinable,FILE * fp)31776348dd8fSMasatake YAMATO extern void printLanguageRoles (const langType language, const char* kindspecs,
3178489f37b8SMasatake YAMATO bool withListHeader, bool machinable, FILE *fp)
3179575c9c6cSMasatake YAMATO {
3180489f37b8SMasatake YAMATO struct colprintTable *table = roleColprintTableNew();
3181489f37b8SMasatake YAMATO parserObject *parser;
3182575c9c6cSMasatake YAMATO
3183489f37b8SMasatake YAMATO initializeParser (language);
3184471cbca7SMasatake YAMATO
3185575c9c6cSMasatake YAMATO if (language == LANG_AUTO)
3186575c9c6cSMasatake YAMATO {
3187489f37b8SMasatake YAMATO for (unsigned int i = 0 ; i < LanguageCount ; ++i)
3188489f37b8SMasatake YAMATO {
3189489f37b8SMasatake YAMATO if (!isLanguageVisible (i))
3190489f37b8SMasatake YAMATO continue;
3191489f37b8SMasatake YAMATO
3192489f37b8SMasatake YAMATO parser = LanguageTable + i;
31936348dd8fSMasatake YAMATO roleColprintAddRoles (table, parser->kindControlBlock, kindspecs);
3194489f37b8SMasatake YAMATO }
3195575c9c6cSMasatake YAMATO }
3196575c9c6cSMasatake YAMATO else
3197489f37b8SMasatake YAMATO {
3198489f37b8SMasatake YAMATO parser = LanguageTable + language;
31996348dd8fSMasatake YAMATO roleColprintAddRoles (table, parser->kindControlBlock, kindspecs);
3200489f37b8SMasatake YAMATO }
3201575c9c6cSMasatake YAMATO
3202489f37b8SMasatake YAMATO roleColprintTablePrint (table, (language != LANG_AUTO),
3203489f37b8SMasatake YAMATO withListHeader, machinable, fp);
3204489f37b8SMasatake YAMATO colprintTableDelete (table);
3205575c9c6cSMasatake YAMATO }
3206575c9c6cSMasatake YAMATO
printKinds(langType language,bool indent,struct colprintTable * table)32079601d44cSMasatake YAMATO static void printKinds (langType language, bool indent,
32089601d44cSMasatake YAMATO struct colprintTable * table)
3209d4c6f1e6SMasatake YAMATO {
3210384186fcSMasatake YAMATO const parserObject *parser;
3211384186fcSMasatake YAMATO struct kindControlBlock *kcb;
3212d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3213078b9679SMasatake YAMATO
3214078b9679SMasatake YAMATO initializeParser (language);
3215384186fcSMasatake YAMATO parser = LanguageTable + language;
3216384186fcSMasatake YAMATO kcb = parser->kindControlBlock;
3217384186fcSMasatake YAMATO
32189601d44cSMasatake YAMATO if (table)
32199601d44cSMasatake YAMATO kindColprintAddLanguageLines (table, kcb);
32209601d44cSMasatake YAMATO else
322121d6a459SMasatake YAMATO {
32229601d44cSMasatake YAMATO for (unsigned int i = 0 ; i < countKinds(kcb) ; ++i)
32239601d44cSMasatake YAMATO printKind (getKind(kcb, i), indent);
322421d6a459SMasatake YAMATO }
3225d4c6f1e6SMasatake YAMATO }
3226d4c6f1e6SMasatake YAMATO
printLanguageKinds(const langType language,bool allKindFields,bool withListHeader,bool machinable,FILE * fp)3227a2dce47aSMasatake YAMATO extern void printLanguageKinds (const langType language, bool allKindFields,
3228a2dce47aSMasatake YAMATO bool withListHeader, bool machinable, FILE *fp)
3229d4c6f1e6SMasatake YAMATO {
32309601d44cSMasatake YAMATO struct colprintTable * table = NULL;
32319601d44cSMasatake YAMATO
32329601d44cSMasatake YAMATO if (allKindFields)
32339601d44cSMasatake YAMATO table = kindColprintTableNew ();
32349601d44cSMasatake YAMATO
3235d4c6f1e6SMasatake YAMATO if (language == LANG_AUTO)
3236d4c6f1e6SMasatake YAMATO {
32379601d44cSMasatake YAMATO for (unsigned int i = 0 ; i < LanguageCount ; ++i)
3238d4c6f1e6SMasatake YAMATO {
3239e02be843SMasatake YAMATO const parserDefinition* const lang = LanguageTable [i].def;
324021d6a459SMasatake YAMATO
3241632163c2SMasatake YAMATO if (lang->invisible)
3242632163c2SMasatake YAMATO continue;
3243632163c2SMasatake YAMATO
32449601d44cSMasatake YAMATO if (!table)
3245362fa008SMasatake YAMATO printf ("%s%s\n", lang->name, isLanguageEnabled (i) ? "" : " [disabled]");
32469601d44cSMasatake YAMATO printKinds (i, true, table);
3247d4c6f1e6SMasatake YAMATO }
3248d4c6f1e6SMasatake YAMATO }
3249d4c6f1e6SMasatake YAMATO else
32509601d44cSMasatake YAMATO printKinds (language, false, table);
3251908570b8SMasatake YAMATO
32529601d44cSMasatake YAMATO if (allKindFields)
32539601d44cSMasatake YAMATO {
32549601d44cSMasatake YAMATO kindColprintTablePrint(table, (language == LANG_AUTO)? 0: 1,
3255a2dce47aSMasatake YAMATO withListHeader, machinable, fp);
32569601d44cSMasatake YAMATO colprintTableDelete (table);
3257d4c6f1e6SMasatake YAMATO }
3258908570b8SMasatake YAMATO }
3259d4c6f1e6SMasatake YAMATO
printParameters(struct colprintTable * table,langType language)3260813a10c0SMasatake YAMATO static void printParameters (struct colprintTable *table, langType language)
32613671b1d2SMasatake YAMATO {
32623671b1d2SMasatake YAMATO const parserDefinition* lang;
32633671b1d2SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
32643671b1d2SMasatake YAMATO
32653671b1d2SMasatake YAMATO initializeParser (language);
3266e02be843SMasatake YAMATO lang = LanguageTable [language].def;
32673671b1d2SMasatake YAMATO if (lang->parameterHandlerTable != NULL)
32683671b1d2SMasatake YAMATO {
3269813a10c0SMasatake YAMATO for (unsigned int i = 0; i < lang->parameterHandlerCount; ++i)
3270813a10c0SMasatake YAMATO paramColprintAddParameter(table, language, lang->parameterHandlerTable + i);
3271813a10c0SMasatake YAMATO }
32723671b1d2SMasatake YAMATO
3273813a10c0SMasatake YAMATO }
3274813a10c0SMasatake YAMATO
printLanguageParameters(const langType language,bool withListHeader,bool machinable,FILE * fp)3275813a10c0SMasatake YAMATO extern void printLanguageParameters (const langType language,
3276813a10c0SMasatake YAMATO bool withListHeader, bool machinable, FILE *fp)
32773671b1d2SMasatake YAMATO {
3278813a10c0SMasatake YAMATO struct colprintTable *table = paramColprintTableNew();
32793671b1d2SMasatake YAMATO
32803671b1d2SMasatake YAMATO if (language == LANG_AUTO)
32813671b1d2SMasatake YAMATO {
3282813a10c0SMasatake YAMATO for (unsigned int i = 0; i < LanguageCount ; ++i)
32833671b1d2SMasatake YAMATO {
3284e02be843SMasatake YAMATO const parserDefinition* const lang = LanguageTable [i].def;
32853671b1d2SMasatake YAMATO
32863671b1d2SMasatake YAMATO if (lang->invisible)
32873671b1d2SMasatake YAMATO continue;
3288813a10c0SMasatake YAMATO
3289813a10c0SMasatake YAMATO printParameters (table, i);
32903671b1d2SMasatake YAMATO }
32913671b1d2SMasatake YAMATO }
32923671b1d2SMasatake YAMATO else
3293813a10c0SMasatake YAMATO printParameters (table, language);
32943671b1d2SMasatake YAMATO
3295813a10c0SMasatake YAMATO paramColprintTablePrint (table, (language != LANG_AUTO),
3296813a10c0SMasatake YAMATO withListHeader, machinable, fp);
3297813a10c0SMasatake YAMATO colprintTableDelete (table);
32983671b1d2SMasatake YAMATO }
32993671b1d2SMasatake YAMATO
processLangAliasOption(const langType language,const char * const parameter)3300322bc4faSMasatake YAMATO static void processLangAliasOption (const langType language,
3301d4c6f1e6SMasatake YAMATO const char *const parameter)
3302d4c6f1e6SMasatake YAMATO {
3303d4c6f1e6SMasatake YAMATO const char* alias;
3304efe089d4SMasatake YAMATO const parserObject * parser;
3305d4c6f1e6SMasatake YAMATO
3306d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3307efe089d4SMasatake YAMATO parser = LanguageTable + language;
3308d4c6f1e6SMasatake YAMATO
3309f3f2d137SMasatake YAMATO if (parameter[0] == '\0')
3310f3f2d137SMasatake YAMATO {
3311f3f2d137SMasatake YAMATO clearLanguageAliases (language);
3312aed717c1SMasatake YAMATO verbose ("clear aliases for %s\n", parser->def->name);
3313aed717c1SMasatake YAMATO }
3314aed717c1SMasatake YAMATO else if (strcmp (parameter, RSV_LANGMAP_DEFAULT) == 0)
3315aed717c1SMasatake YAMATO {
3316aed717c1SMasatake YAMATO installLanguageAliasesDefault (language);
3317aed717c1SMasatake YAMATO verbose ("reset aliases for %s\n", parser->def->name);
3318f3f2d137SMasatake YAMATO }
3319f3f2d137SMasatake YAMATO else if (parameter[0] == '+')
3320d4c6f1e6SMasatake YAMATO {
3321d4c6f1e6SMasatake YAMATO alias = parameter + 1;
3322d4c6f1e6SMasatake YAMATO addLanguageAlias(language, alias);
3323aed717c1SMasatake YAMATO verbose ("add an alias %s to %s\n", alias, parser->def->name);
3324d4c6f1e6SMasatake YAMATO }
3325d4c6f1e6SMasatake YAMATO else if (parameter[0] == '-')
3326d4c6f1e6SMasatake YAMATO {
3327efe089d4SMasatake YAMATO if (parser->currentAliases)
3328d4c6f1e6SMasatake YAMATO {
3329d4c6f1e6SMasatake YAMATO alias = parameter + 1;
3330efe089d4SMasatake YAMATO if (stringListDeleteItemExtension (parser->currentAliases, alias))
3331d4c6f1e6SMasatake YAMATO {
3332aed717c1SMasatake YAMATO verbose ("remove an alias %s from %s\n", alias, parser->def->name);
3333d4c6f1e6SMasatake YAMATO }
3334d4c6f1e6SMasatake YAMATO }
3335d4c6f1e6SMasatake YAMATO }
3336d4c6f1e6SMasatake YAMATO else
3337d4c6f1e6SMasatake YAMATO {
3338d4c6f1e6SMasatake YAMATO alias = parameter;
3339d4c6f1e6SMasatake YAMATO clearLanguageAliases (language);
3340d4c6f1e6SMasatake YAMATO addLanguageAlias(language, alias);
3341efe089d4SMasatake YAMATO verbose ("set alias %s to %s\n", alias, parser->def->name);
3342d4c6f1e6SMasatake YAMATO }
3343d4c6f1e6SMasatake YAMATO
3344d4c6f1e6SMasatake YAMATO }
3345d4c6f1e6SMasatake YAMATO
processAliasOption(const char * const option,const char * const parameter)3346ce990805SThomas Braun extern bool processAliasOption (
3347d4c6f1e6SMasatake YAMATO const char *const option, const char *const parameter)
3348d4c6f1e6SMasatake YAMATO {
3349d4c6f1e6SMasatake YAMATO langType language;
3350d4c6f1e6SMasatake YAMATO
3351a18efdb7SMasatake YAMATO Assert (parameter);
3352a18efdb7SMasatake YAMATO
3353a18efdb7SMasatake YAMATO #define PREFIX "alias-"
3354a18efdb7SMasatake YAMATO if (strcmp (option, "alias-" RSV_LANG_ALL) == 0)
3355a18efdb7SMasatake YAMATO {
3356a18efdb7SMasatake YAMATO if ((parameter[0] == '\0')
3357a18efdb7SMasatake YAMATO || (strcmp (parameter, RSV_LANGMAP_DEFAULT) == 0))
3358a18efdb7SMasatake YAMATO {
3359a18efdb7SMasatake YAMATO for (unsigned int i = 0; i < LanguageCount; i++)
3360a18efdb7SMasatake YAMATO {
3361a18efdb7SMasatake YAMATO clearLanguageAliases (i);
3362a18efdb7SMasatake YAMATO verbose ("clear aliases for %s\n", getLanguageName(i));
3363a18efdb7SMasatake YAMATO }
3364a18efdb7SMasatake YAMATO
3365a18efdb7SMasatake YAMATO if (parameter[0] != '\0')
3366a18efdb7SMasatake YAMATO {
3367a18efdb7SMasatake YAMATO verbose (" Installing default language aliases:\n");
3368a18efdb7SMasatake YAMATO installLanguageAliasesDefaults ();
3369a18efdb7SMasatake YAMATO }
3370a18efdb7SMasatake YAMATO }
3371a18efdb7SMasatake YAMATO else
3372a18efdb7SMasatake YAMATO {
3373a18efdb7SMasatake YAMATO error (WARNING, "Use \"%s\" option for reset (\"default\") or clearing (\"\")", option);
3374a18efdb7SMasatake YAMATO return false;
3375a18efdb7SMasatake YAMATO }
3376a18efdb7SMasatake YAMATO return true;
3377a18efdb7SMasatake YAMATO }
3378a18efdb7SMasatake YAMATO
3379d4ee22f1SMasatake YAMATO language = getLanguageComponentInOption (option, "alias-");
3380d4c6f1e6SMasatake YAMATO if (language == LANG_IGNORE)
3381ce990805SThomas Braun return false;
3382a18efdb7SMasatake YAMATO #undef PREFIX
3383d4c6f1e6SMasatake YAMATO
3384322bc4faSMasatake YAMATO processLangAliasOption (language, parameter);
3385ce990805SThomas Braun return true;
3386d4c6f1e6SMasatake YAMATO }
3387d4c6f1e6SMasatake YAMATO
printMaps(const langType language,langmapType type)338859204b36SMasatake YAMATO static void printMaps (const langType language, langmapType type)
3389d4c6f1e6SMasatake YAMATO {
3390efe089d4SMasatake YAMATO const parserObject* parser;
3391d4c6f1e6SMasatake YAMATO unsigned int i;
3392e57a5ca2SMasatake YAMATO
3393efe089d4SMasatake YAMATO parser = LanguageTable + language;
3394efe089d4SMasatake YAMATO printf ("%-8s", parser->def->name);
3395efe089d4SMasatake YAMATO if (parser->currentPatterns != NULL && (type & LMAP_PATTERN))
3396efe089d4SMasatake YAMATO for (i = 0 ; i < stringListCount (parser->currentPatterns) ; ++i)
3397d4c6f1e6SMasatake YAMATO printf (" %s", vStringValue (
3398efe089d4SMasatake YAMATO stringListItem (parser->currentPatterns, i)));
3399922d4048SMasatake YAMATO if (parser->currentExtensions != NULL && (type & LMAP_EXTENSION))
3400922d4048SMasatake YAMATO for (i = 0 ; i < stringListCount (parser->currentExtensions) ; ++i)
3401922d4048SMasatake YAMATO printf (" *.%s", vStringValue (
3402922d4048SMasatake YAMATO stringListItem (parser->currentExtensions, i)));
3403d4c6f1e6SMasatake YAMATO putchar ('\n');
3404d4c6f1e6SMasatake YAMATO }
3405d4c6f1e6SMasatake YAMATO
mapColprintTableNew(langmapType type)3406e57a5ca2SMasatake YAMATO static struct colprintTable *mapColprintTableNew (langmapType type)
3407d4c6f1e6SMasatake YAMATO {
3408e57a5ca2SMasatake YAMATO if ((type & LMAP_ALL) == LMAP_ALL)
3409e57a5ca2SMasatake YAMATO return colprintTableNew ("L:LANGUAGE", "L:TYPE", "L:MAP", NULL);
3410e57a5ca2SMasatake YAMATO else if (type & LMAP_PATTERN)
3411e57a5ca2SMasatake YAMATO return colprintTableNew ("L:LANGUAGE", "L:PATTERN", NULL);
3412e57a5ca2SMasatake YAMATO else if (type & LMAP_EXTENSION)
3413e57a5ca2SMasatake YAMATO return colprintTableNew ("L:LANGUAGE", "L:EXTENSION", NULL);
3414e57a5ca2SMasatake YAMATO else
3415e57a5ca2SMasatake YAMATO {
3416e57a5ca2SMasatake YAMATO AssertNotReached ();
3417e57a5ca2SMasatake YAMATO return NULL;
3418e57a5ca2SMasatake YAMATO }
3419d4c6f1e6SMasatake YAMATO }
3420d4c6f1e6SMasatake YAMATO
mapColprintAddLanguage(struct colprintTable * table,langmapType type,const parserObject * parser)3421e57a5ca2SMasatake YAMATO static void mapColprintAddLanguage (struct colprintTable * table,
3422e57a5ca2SMasatake YAMATO langmapType type,
3423e57a5ca2SMasatake YAMATO const parserObject* parser)
3424d4c6f1e6SMasatake YAMATO {
3425e57a5ca2SMasatake YAMATO struct colprintLine * line;
3426e57a5ca2SMasatake YAMATO unsigned int count;
3427e57a5ca2SMasatake YAMATO unsigned int i;
3428e57a5ca2SMasatake YAMATO
3429e57a5ca2SMasatake YAMATO if ((type & LMAP_PATTERN) && (0 < (count = stringListCount (parser->currentPatterns))))
3430e57a5ca2SMasatake YAMATO {
3431e57a5ca2SMasatake YAMATO for (i = 0; i < count; i++)
3432e57a5ca2SMasatake YAMATO {
3433e57a5ca2SMasatake YAMATO line = colprintTableGetNewLine (table);
3434e57a5ca2SMasatake YAMATO vString *pattern = stringListItem (parser->currentPatterns, i);
3435e57a5ca2SMasatake YAMATO
3436e57a5ca2SMasatake YAMATO colprintLineAppendColumnCString (line, parser->def->name);
3437e57a5ca2SMasatake YAMATO if (type & LMAP_EXTENSION)
3438e57a5ca2SMasatake YAMATO colprintLineAppendColumnCString (line, "pattern");
3439e57a5ca2SMasatake YAMATO colprintLineAppendColumnVString (line, pattern);
3440e57a5ca2SMasatake YAMATO }
3441e57a5ca2SMasatake YAMATO }
3442e57a5ca2SMasatake YAMATO
3443e57a5ca2SMasatake YAMATO if ((type & LMAP_EXTENSION) && (0 < (count = stringListCount (parser->currentExtensions))))
3444e57a5ca2SMasatake YAMATO {
3445e57a5ca2SMasatake YAMATO for (i = 0; i < count; i++)
3446e57a5ca2SMasatake YAMATO {
3447e57a5ca2SMasatake YAMATO line = colprintTableGetNewLine (table);
3448e57a5ca2SMasatake YAMATO vString *extension = stringListItem (parser->currentExtensions, i);
3449e57a5ca2SMasatake YAMATO
3450e57a5ca2SMasatake YAMATO colprintLineAppendColumnCString (line, parser->def->name);
3451e57a5ca2SMasatake YAMATO if (type & LMAP_PATTERN)
3452e57a5ca2SMasatake YAMATO colprintLineAppendColumnCString (line, "extension");
3453e57a5ca2SMasatake YAMATO colprintLineAppendColumnVString (line, extension);
3454e57a5ca2SMasatake YAMATO }
3455e57a5ca2SMasatake YAMATO }
3456e57a5ca2SMasatake YAMATO }
3457e57a5ca2SMasatake YAMATO
printLanguageMaps(const langType language,langmapType type,bool withListHeader,bool machinable,FILE * fp)3458e57a5ca2SMasatake YAMATO extern void printLanguageMaps (const langType language, langmapType type,
3459e57a5ca2SMasatake YAMATO bool withListHeader, bool machinable, FILE *fp)
3460e57a5ca2SMasatake YAMATO {
3461e57a5ca2SMasatake YAMATO /* DON'T SORT THE LIST
3462e57a5ca2SMasatake YAMATO
3463e57a5ca2SMasatake YAMATO The order of listing should be equal to the order of matching
3464e57a5ca2SMasatake YAMATO for the parser selection. */
3465e57a5ca2SMasatake YAMATO
3466e57a5ca2SMasatake YAMATO struct colprintTable * table = NULL;
3467e57a5ca2SMasatake YAMATO if (type & LMAP_TABLE_OUTPUT)
3468e57a5ca2SMasatake YAMATO table = mapColprintTableNew(type);
3469e57a5ca2SMasatake YAMATO
3470d4c6f1e6SMasatake YAMATO if (language == LANG_AUTO)
3471d4c6f1e6SMasatake YAMATO {
3472e57a5ca2SMasatake YAMATO for (unsigned int i = 0 ; i < LanguageCount ; ++i)
3473e57a5ca2SMasatake YAMATO {
3474e57a5ca2SMasatake YAMATO if (!isLanguageVisible (i))
3475e57a5ca2SMasatake YAMATO continue;
3476e57a5ca2SMasatake YAMATO
3477e57a5ca2SMasatake YAMATO if (type & LMAP_TABLE_OUTPUT)
3478e57a5ca2SMasatake YAMATO {
3479e57a5ca2SMasatake YAMATO const parserObject* parser = LanguageTable + i;
3480e57a5ca2SMasatake YAMATO
3481e57a5ca2SMasatake YAMATO mapColprintAddLanguage (table, type, parser);
3482e57a5ca2SMasatake YAMATO }
3483e57a5ca2SMasatake YAMATO else
348459204b36SMasatake YAMATO printMaps (i, type);
3485d4c6f1e6SMasatake YAMATO }
3486e57a5ca2SMasatake YAMATO }
3487e57a5ca2SMasatake YAMATO else
3488e57a5ca2SMasatake YAMATO {
3489e57a5ca2SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3490e57a5ca2SMasatake YAMATO
3491e57a5ca2SMasatake YAMATO if (type & LMAP_TABLE_OUTPUT)
3492e57a5ca2SMasatake YAMATO {
3493e57a5ca2SMasatake YAMATO const parserObject* parser = LanguageTable + language;
3494e57a5ca2SMasatake YAMATO
3495e57a5ca2SMasatake YAMATO mapColprintAddLanguage (table, type, parser);
3496e57a5ca2SMasatake YAMATO }
3497d4c6f1e6SMasatake YAMATO else
349859204b36SMasatake YAMATO printMaps (language, type);
3499d4c6f1e6SMasatake YAMATO }
3500d4c6f1e6SMasatake YAMATO
3501e57a5ca2SMasatake YAMATO
3502e57a5ca2SMasatake YAMATO if (type & LMAP_TABLE_OUTPUT)
3503d4c6f1e6SMasatake YAMATO {
3504e57a5ca2SMasatake YAMATO colprintTablePrint (table, (language == LANG_AUTO)? 0: 1,
3505e57a5ca2SMasatake YAMATO withListHeader, machinable, fp);
3506e57a5ca2SMasatake YAMATO colprintTableDelete (table);
3507e57a5ca2SMasatake YAMATO }
3508e57a5ca2SMasatake YAMATO }
3509e57a5ca2SMasatake YAMATO
aliasColprintTableNew(void)351045425726SMasatake YAMATO static struct colprintTable *aliasColprintTableNew (void)
3511d4c6f1e6SMasatake YAMATO {
351245425726SMasatake YAMATO return colprintTableNew ("L:LANGUAGE", "L:ALIAS", NULL);
351345425726SMasatake YAMATO }
351445425726SMasatake YAMATO
aliasColprintAddLanguage(struct colprintTable * table,const parserObject * parser)351545425726SMasatake YAMATO static void aliasColprintAddLanguage (struct colprintTable * table,
351645425726SMasatake YAMATO const parserObject* parser)
351745425726SMasatake YAMATO {
351845425726SMasatake YAMATO unsigned int count;
351945425726SMasatake YAMATO
352045425726SMasatake YAMATO if (parser->currentAliases && (0 < (count = stringListCount (parser->currentAliases))))
352145425726SMasatake YAMATO {
352245425726SMasatake YAMATO for (unsigned int i = 0; i < count; i++)
352345425726SMasatake YAMATO {
352445425726SMasatake YAMATO struct colprintLine * line = colprintTableGetNewLine (table);
352545425726SMasatake YAMATO vString *alias = stringListItem (parser->currentAliases, i);;
352645425726SMasatake YAMATO
352745425726SMasatake YAMATO colprintLineAppendColumnCString (line, parser->def->name);
352845425726SMasatake YAMATO colprintLineAppendColumnVString (line, alias);
352945425726SMasatake YAMATO }
353045425726SMasatake YAMATO }
353145425726SMasatake YAMATO }
353245425726SMasatake YAMATO
printLanguageAliases(const langType language,bool withListHeader,bool machinable,FILE * fp)353345425726SMasatake YAMATO extern void printLanguageAliases (const langType language,
353445425726SMasatake YAMATO bool withListHeader, bool machinable, FILE *fp)
353545425726SMasatake YAMATO {
353645425726SMasatake YAMATO /* DON'T SORT THE LIST
353745425726SMasatake YAMATO
353845425726SMasatake YAMATO The order of listing should be equal to the order of matching
353945425726SMasatake YAMATO for the parser selection. */
354045425726SMasatake YAMATO
354145425726SMasatake YAMATO struct colprintTable * table = aliasColprintTableNew();
354245425726SMasatake YAMATO const parserObject* parser;
354345425726SMasatake YAMATO
3544d4c6f1e6SMasatake YAMATO if (language == LANG_AUTO)
3545d4c6f1e6SMasatake YAMATO {
354645425726SMasatake YAMATO for (unsigned int i = 0; i < LanguageCount; ++i)
354745425726SMasatake YAMATO {
354845425726SMasatake YAMATO parser = LanguageTable + i;
354945425726SMasatake YAMATO if (parser->def->invisible)
355045425726SMasatake YAMATO continue;
355145425726SMasatake YAMATO
355245425726SMasatake YAMATO aliasColprintAddLanguage (table, parser);
355345425726SMasatake YAMATO }
3554d4c6f1e6SMasatake YAMATO }
3555d4c6f1e6SMasatake YAMATO else
3556d4c6f1e6SMasatake YAMATO {
3557d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
355845425726SMasatake YAMATO parser = LanguageTable + language;
355945425726SMasatake YAMATO aliasColprintAddLanguage (table, parser);
3560d4c6f1e6SMasatake YAMATO }
356145425726SMasatake YAMATO
356245425726SMasatake YAMATO colprintTablePrint (table, (language == LANG_AUTO)? 0: 1,
356345425726SMasatake YAMATO withListHeader, machinable, fp);
356445425726SMasatake YAMATO colprintTableDelete (table);
3565d4c6f1e6SMasatake YAMATO }
3566d4c6f1e6SMasatake YAMATO
printLanguage(const langType language,parserDefinition ** ltable)3567f10da43aSMasatake YAMATO static void printLanguage (const langType language, parserDefinition** ltable)
3568d4c6f1e6SMasatake YAMATO {
3569d4c6f1e6SMasatake YAMATO const parserDefinition* lang;
3570d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3571f10da43aSMasatake YAMATO lang = ltable [language];
3572a7fc12e5SMasatake YAMATO
3573a7fc12e5SMasatake YAMATO if (lang->invisible)
3574a7fc12e5SMasatake YAMATO return;
3575a7fc12e5SMasatake YAMATO
3576f10da43aSMasatake YAMATO printf ("%s%s\n", lang->name, isLanguageEnabled (lang->id) ? "" : " [disabled]");
3577f10da43aSMasatake YAMATO }
3578f10da43aSMasatake YAMATO
printLanguageList(void)3579d4c6f1e6SMasatake YAMATO extern void printLanguageList (void)
3580d4c6f1e6SMasatake YAMATO {
3581d4c6f1e6SMasatake YAMATO unsigned int i;
3582f10da43aSMasatake YAMATO parserDefinition **ltable;
3583f10da43aSMasatake YAMATO
3584f10da43aSMasatake YAMATO ltable = xMalloc (LanguageCount, parserDefinition*);
3585e02be843SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
3586e02be843SMasatake YAMATO ltable[i] = LanguageTable[i].def;
3587f10da43aSMasatake YAMATO qsort (ltable, LanguageCount, sizeof (parserDefinition*), compareParsersByName);
3588f10da43aSMasatake YAMATO
3589d4c6f1e6SMasatake YAMATO for (i = 0 ; i < LanguageCount ; ++i)
3590f10da43aSMasatake YAMATO printLanguage (i, ltable);
3591f10da43aSMasatake YAMATO
3592f10da43aSMasatake YAMATO eFree (ltable);
3593d4c6f1e6SMasatake YAMATO }
3594d4c6f1e6SMasatake YAMATO
xtagDefinitionDestroy(xtagDefinition * xdef)3595ac99a095SMasatake YAMATO static void xtagDefinitionDestroy (xtagDefinition *xdef)
3596ac99a095SMasatake YAMATO {
3597ac99a095SMasatake YAMATO eFree ((void *)xdef->name);
3598ac99a095SMasatake YAMATO eFree ((void *)xdef->description);
3599ac99a095SMasatake YAMATO eFree (xdef);
3600ac99a095SMasatake YAMATO }
3601ac99a095SMasatake YAMATO
processLangDefineExtra(const langType language,const char * const option,const char * const parameter)3602f687ebcfSMasatake YAMATO static bool processLangDefineExtra (const langType language,
3603f687ebcfSMasatake YAMATO const char *const option,
36043a6dd371SMasatake YAMATO const char *const parameter)
3605f687ebcfSMasatake YAMATO {
3606f687ebcfSMasatake YAMATO xtagDefinition *xdef;
36073a6dd371SMasatake YAMATO const char * p = parameter;
360876d85274SMasatake YAMATO const char *name_end;
3609f687ebcfSMasatake YAMATO const char *desc;
361076d85274SMasatake YAMATO const char *flags;
3611f687ebcfSMasatake YAMATO
3612f687ebcfSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3613f687ebcfSMasatake YAMATO Assert (p);
3614f687ebcfSMasatake YAMATO
3615f687ebcfSMasatake YAMATO if (p[0] == '\0')
3616f687ebcfSMasatake YAMATO error (FATAL, "no extra definition specified in \"--%s\" option", option);
3617f687ebcfSMasatake YAMATO
361876d85274SMasatake YAMATO name_end = strchr (p, ',');
361976d85274SMasatake YAMATO if (!name_end)
3620f687ebcfSMasatake YAMATO error (FATAL, "no extra description specified in \"--%s\" option", option);
362176d85274SMasatake YAMATO else if (name_end == p)
3622f687ebcfSMasatake YAMATO error (FATAL, "the extra name in \"--%s\" option is empty", option);
3623f687ebcfSMasatake YAMATO
362476d85274SMasatake YAMATO for (; p < name_end; p++)
3625f687ebcfSMasatake YAMATO {
3626f687ebcfSMasatake YAMATO if (!isalnum (*p))
3627f687ebcfSMasatake YAMATO error (FATAL, "unacceptable char as part of extra name in \"--%s\" option",
3628f687ebcfSMasatake YAMATO option);
3629f687ebcfSMasatake YAMATO }
3630f687ebcfSMasatake YAMATO
363176d85274SMasatake YAMATO p++;
363276d85274SMasatake YAMATO if (p [0] == '\0' || p [0] == LONG_FLAGS_OPEN)
363376d85274SMasatake YAMATO error (FATAL, "extra description in \"--%s\" option is empty", option);
363476d85274SMasatake YAMATO
363576d85274SMasatake YAMATO desc = extractDescriptionAndFlags (p, &flags);
363676d85274SMasatake YAMATO
3637f687ebcfSMasatake YAMATO xdef = xCalloc (1, xtagDefinition);
3638f687ebcfSMasatake YAMATO xdef->enabled = false;
3639f687ebcfSMasatake YAMATO xdef->letter = NUL_XTAG_LETTER;
36403a6dd371SMasatake YAMATO xdef->name = eStrndup (parameter, name_end - parameter);
364176d85274SMasatake YAMATO xdef->description = desc;
3642f687ebcfSMasatake YAMATO xdef->isEnabled = NULL;
3643ac99a095SMasatake YAMATO DEFAULT_TRASH_BOX(xdef, xtagDefinitionDestroy);
3644f687ebcfSMasatake YAMATO
364576d85274SMasatake YAMATO if (flags)
364676d85274SMasatake YAMATO flagsEval (flags, NULL, 0, xdef);
364776d85274SMasatake YAMATO
3648f687ebcfSMasatake YAMATO defineXtag (xdef, language);
3649f687ebcfSMasatake YAMATO
3650f687ebcfSMasatake YAMATO return true;
3651f687ebcfSMasatake YAMATO }
3652f687ebcfSMasatake YAMATO
processExtradefOption(const char * const option,const char * const parameter)3653f687ebcfSMasatake YAMATO extern bool processExtradefOption (const char *const option, const char *const parameter)
3654f687ebcfSMasatake YAMATO {
3655f687ebcfSMasatake YAMATO langType language;
3656f687ebcfSMasatake YAMATO
36572d422213SMasatake YAMATO language = getLanguageComponentInOption (option, "_" "extradef-");
3658f687ebcfSMasatake YAMATO if (language == LANG_IGNORE)
3659f687ebcfSMasatake YAMATO return false;
3660f687ebcfSMasatake YAMATO
3661f687ebcfSMasatake YAMATO return processLangDefineExtra (language, option, parameter);
3662f687ebcfSMasatake YAMATO }
3663f687ebcfSMasatake YAMATO
fieldDefinitionDestroy(fieldDefinition * fdef)36645fd045b3SMasatake YAMATO static void fieldDefinitionDestroy (fieldDefinition *fdef)
36655fd045b3SMasatake YAMATO {
36665fd045b3SMasatake YAMATO eFree ((void *)fdef->description);
36675fd045b3SMasatake YAMATO eFree ((void *)fdef->name);
36685fd045b3SMasatake YAMATO eFree (fdef);
36695fd045b3SMasatake YAMATO }
36705fd045b3SMasatake YAMATO
processLangDefineField(const langType language,const char * const option,const char * const parameter)36715fd045b3SMasatake YAMATO static bool processLangDefineField (const langType language,
36725fd045b3SMasatake YAMATO const char *const option,
36735fd045b3SMasatake YAMATO const char *const parameter)
36745fd045b3SMasatake YAMATO {
36755fd045b3SMasatake YAMATO fieldDefinition *fdef;
36765fd045b3SMasatake YAMATO const char * p = parameter;
36773c7e951eSMasatake YAMATO const char *name_end;
36785fd045b3SMasatake YAMATO const char *desc;
36793c7e951eSMasatake YAMATO const char *flags;
36805fd045b3SMasatake YAMATO
36815fd045b3SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
36825fd045b3SMasatake YAMATO Assert (p);
36835fd045b3SMasatake YAMATO
36845fd045b3SMasatake YAMATO if (p[0] == '\0')
36855fd045b3SMasatake YAMATO error (FATAL, "no field definition specified in \"--%s\" option", option);
36865fd045b3SMasatake YAMATO
36873c7e951eSMasatake YAMATO name_end = strchr (p, ',');
36883c7e951eSMasatake YAMATO if (!name_end)
36895fd045b3SMasatake YAMATO error (FATAL, "no field description specified in \"--%s\" option", option);
36903c7e951eSMasatake YAMATO else if (name_end == p)
36915fd045b3SMasatake YAMATO error (FATAL, "the field name in \"--%s\" option is empty", option);
36925fd045b3SMasatake YAMATO
36933c7e951eSMasatake YAMATO for (; p < name_end; p++)
36945fd045b3SMasatake YAMATO {
3695ae599e0fSMasatake YAMATO if (!isalpha (*p))
36965fd045b3SMasatake YAMATO error (FATAL, "unacceptable char as part of field name in \"--%s\" option",
36975fd045b3SMasatake YAMATO option);
36985fd045b3SMasatake YAMATO }
36995fd045b3SMasatake YAMATO
37003c7e951eSMasatake YAMATO p++;
37013c7e951eSMasatake YAMATO if (p [0] == '\0' || p [0] == LONG_FLAGS_OPEN)
37025fd045b3SMasatake YAMATO error (FATAL, "field description in \"--%s\" option is empty", option);
37035fd045b3SMasatake YAMATO
37043c7e951eSMasatake YAMATO desc = extractDescriptionAndFlags (p, &flags);
37053c7e951eSMasatake YAMATO
37065fd045b3SMasatake YAMATO fdef = xCalloc (1, fieldDefinition);
37075fd045b3SMasatake YAMATO fdef->enabled = false;
37085fd045b3SMasatake YAMATO fdef->letter = NUL_FIELD_LETTER;
37093c7e951eSMasatake YAMATO fdef->name = eStrndup(parameter, name_end - parameter);
37103c7e951eSMasatake YAMATO fdef->description = desc;
37115fd045b3SMasatake YAMATO fdef->isValueAvailable = NULL;
3712fba3677cSMasatake YAMATO fdef->getValueObject = NULL;
3713fba3677cSMasatake YAMATO fdef->getterValueType = NULL;
3714fba3677cSMasatake YAMATO fdef->setValueObject = NULL;
3715fba3677cSMasatake YAMATO fdef->setterValueType = NULL;
3716fba3677cSMasatake YAMATO fdef->checkValueForSetter = NULL;
37175fd045b3SMasatake YAMATO fdef->dataType = FIELDTYPE_STRING; /* TODO */
37185fd045b3SMasatake YAMATO fdef->ftype = FIELD_UNKNOWN;
37195fd045b3SMasatake YAMATO DEFAULT_TRASH_BOX(fdef, fieldDefinitionDestroy);
37205fd045b3SMasatake YAMATO
37213c7e951eSMasatake YAMATO if (flags)
37223c7e951eSMasatake YAMATO flagsEval (flags, NULL, 0, fdef);
37233c7e951eSMasatake YAMATO
37245fd045b3SMasatake YAMATO defineField (fdef, language);
37255fd045b3SMasatake YAMATO
37265fd045b3SMasatake YAMATO return true;
37275fd045b3SMasatake YAMATO }
37285fd045b3SMasatake YAMATO
processFielddefOption(const char * const option,const char * const parameter)37295fd045b3SMasatake YAMATO extern bool processFielddefOption (const char *const option, const char *const parameter)
37305fd045b3SMasatake YAMATO {
37315fd045b3SMasatake YAMATO langType language;
37325fd045b3SMasatake YAMATO
37335fd045b3SMasatake YAMATO language = getLanguageComponentInOption (option, "_fielddef-");
37345fd045b3SMasatake YAMATO if (language == LANG_IGNORE)
37355fd045b3SMasatake YAMATO return false;
37365fd045b3SMasatake YAMATO
37375fd045b3SMasatake YAMATO return processLangDefineField (language, option, parameter);
37385fd045b3SMasatake YAMATO }
3739f687ebcfSMasatake YAMATO
3740d4c6f1e6SMasatake YAMATO /*
3741d4c6f1e6SMasatake YAMATO * File parsing
3742d4c6f1e6SMasatake YAMATO */
3743d4c6f1e6SMasatake YAMATO
createTagsForFile(const langType language,const unsigned int passCount)3744e5b7a250SMasatake YAMATO static rescanReason createTagsForFile (const langType language,
3745bc1a5e1bSMasatake YAMATO const unsigned int passCount)
3746d4c6f1e6SMasatake YAMATO {
3747e02be843SMasatake YAMATO parserDefinition *const lang = LanguageTable [language].def;
3748bc1a5e1bSMasatake YAMATO rescanReason rescan = RESCAN_NONE;
3749bc1a5e1bSMasatake YAMATO
3750bc1a5e1bSMasatake YAMATO resetInputFile (language);
37518d8d8e3bSMasatake YAMATO
37528d8d8e3bSMasatake YAMATO Assert (lang->parser || lang->parser2);
3753d4c6f1e6SMasatake YAMATO
3754a53e10d8SMasatake YAMATO notifyInputStart ();
3755a53e10d8SMasatake YAMATO
3756d4c6f1e6SMasatake YAMATO if (lang->parser != NULL)
3757d4c6f1e6SMasatake YAMATO lang->parser ();
3758d4c6f1e6SMasatake YAMATO else if (lang->parser2 != NULL)
3759d4c6f1e6SMasatake YAMATO rescan = lang->parser2 (passCount);
3760d4c6f1e6SMasatake YAMATO
3761a53e10d8SMasatake YAMATO notifyInputEnd ();
3762a53e10d8SMasatake YAMATO
3763d4c6f1e6SMasatake YAMATO return rescan;
3764d4c6f1e6SMasatake YAMATO }
3765d4c6f1e6SMasatake YAMATO
notifyLanguageRegexInputStart(langType language)37662db4cedcSMasatake YAMATO extern void notifyLanguageRegexInputStart (langType language)
37672db4cedcSMasatake YAMATO {
3768d86d3772SMasatake YAMATO parserObject *pobj = LanguageTable + language;
3769d86d3772SMasatake YAMATO parserDefinition *pdef = pobj->def;
3770d86d3772SMasatake YAMATO
3771d86d3772SMasatake YAMATO notifyRegexInputStart(pobj->lregexControlBlock);
3772d86d3772SMasatake YAMATO for (unsigned int i = 0; i < pdef->dependencyCount; i++)
3773d86d3772SMasatake YAMATO {
3774d86d3772SMasatake YAMATO parserDependency *d = pdef->dependencies + i;
3775d86d3772SMasatake YAMATO if (d->type != DEPTYPE_FOREIGNER)
3776d86d3772SMasatake YAMATO continue;
3777d86d3772SMasatake YAMATO langType foreigner = getNamedLanguage (d->upperParser, 0);
3778d86d3772SMasatake YAMATO if (foreigner == LANG_IGNORE)
3779d86d3772SMasatake YAMATO continue;
3780d86d3772SMasatake YAMATO
3781d86d3772SMasatake YAMATO notifyLanguageRegexInputStart (foreigner);
3782d86d3772SMasatake YAMATO }
37832db4cedcSMasatake YAMATO }
37842db4cedcSMasatake YAMATO
notifyLanguageRegexInputEnd(langType language)37852db4cedcSMasatake YAMATO extern void notifyLanguageRegexInputEnd (langType language)
37862db4cedcSMasatake YAMATO {
3787d86d3772SMasatake YAMATO parserObject *pobj = LanguageTable + language;
3788d86d3772SMasatake YAMATO parserDefinition *pdef = pobj->def;
3789d86d3772SMasatake YAMATO
3790d86d3772SMasatake YAMATO for (unsigned int i = 0; i < pdef->dependencyCount; i++)
3791d86d3772SMasatake YAMATO {
3792d86d3772SMasatake YAMATO parserDependency *d = pdef->dependencies + i;
3793d86d3772SMasatake YAMATO if (d->type != DEPTYPE_FOREIGNER)
3794d86d3772SMasatake YAMATO continue;
3795d86d3772SMasatake YAMATO langType foreigner = getNamedLanguage (d->upperParser, 0);
3796d86d3772SMasatake YAMATO if (foreigner == LANG_IGNORE)
3797d86d3772SMasatake YAMATO continue;
3798d86d3772SMasatake YAMATO
3799d86d3772SMasatake YAMATO notifyLanguageRegexInputEnd (foreigner);
3800d86d3772SMasatake YAMATO }
38012db4cedcSMasatake YAMATO notifyRegexInputEnd((LanguageTable + language)->lregexControlBlock);
38022db4cedcSMasatake YAMATO }
38032db4cedcSMasatake YAMATO
parserCorkFlags(parserDefinition * parser)38046b1a862eSMasatake YAMATO static unsigned int parserCorkFlags (parserDefinition *parser)
3805bbd7ded8SMasatake YAMATO {
3806bbd7ded8SMasatake YAMATO subparser *tmp;
38076b1a862eSMasatake YAMATO unsigned int r = 0;
3808bbd7ded8SMasatake YAMATO
38096b1a862eSMasatake YAMATO r |= parser->useCork;
3810bbd7ded8SMasatake YAMATO
3811c25346c2SMasatake YAMATO if (doesLanguageExpectCorkInRegex (parser->id)
3812298e3c61SMasatake YAMATO || parser->requestAutomaticFQTag)
38136b1a862eSMasatake YAMATO r |= CORK_QUEUE;
3814298e3c61SMasatake YAMATO
3815bbd7ded8SMasatake YAMATO pushLanguage (parser->id);
381611358a9dSMasatake YAMATO foreachSubparser(tmp, true)
3817bbd7ded8SMasatake YAMATO {
3818edc12faeSMasatake YAMATO langType t = getSubparserLanguage (tmp);
38196b1a862eSMasatake YAMATO r |= parserCorkFlags (LanguageTable[t].def);
3820bbd7ded8SMasatake YAMATO }
3821bbd7ded8SMasatake YAMATO popLanguage ();
3822bbd7ded8SMasatake YAMATO return r;
3823bbd7ded8SMasatake YAMATO }
3824bbd7ded8SMasatake YAMATO
setupLanguageSubparsersInUse(const langType language)38256a8f21eaSMasatake YAMATO static void setupLanguageSubparsersInUse (const langType language)
38266a8f21eaSMasatake YAMATO {
38276a8f21eaSMasatake YAMATO subparser *tmp;
38286a8f21eaSMasatake YAMATO
38296a8f21eaSMasatake YAMATO setupSubparsersInUse ((LanguageTable + language)->slaveControlBlock);
383011358a9dSMasatake YAMATO foreachSubparser(tmp, true)
38316a8f21eaSMasatake YAMATO {
38326a8f21eaSMasatake YAMATO langType t = getSubparserLanguage (tmp);
38336a8f21eaSMasatake YAMATO enterSubparser (tmp);
38346a8f21eaSMasatake YAMATO setupLanguageSubparsersInUse(t);
38356a8f21eaSMasatake YAMATO leaveSubparser ();
38366a8f21eaSMasatake YAMATO }
38376a8f21eaSMasatake YAMATO }
38386a8f21eaSMasatake YAMATO
teardownLanguageSubparsersInUse(const langType language)38396a8f21eaSMasatake YAMATO static subparser* teardownLanguageSubparsersInUse (const langType language)
38406a8f21eaSMasatake YAMATO {
38416a8f21eaSMasatake YAMATO subparser *tmp;
38426a8f21eaSMasatake YAMATO
384311358a9dSMasatake YAMATO foreachSubparser(tmp, true)
38446a8f21eaSMasatake YAMATO {
38456a8f21eaSMasatake YAMATO langType t = getSubparserLanguage (tmp);
38466a8f21eaSMasatake YAMATO enterSubparser (tmp);
38476a8f21eaSMasatake YAMATO teardownLanguageSubparsersInUse(t);
38486a8f21eaSMasatake YAMATO leaveSubparser ();
38496a8f21eaSMasatake YAMATO }
38506a8f21eaSMasatake YAMATO return teardownSubparsersInUse ((LanguageTable + language)->slaveControlBlock);
38516a8f21eaSMasatake YAMATO }
38526a8f21eaSMasatake YAMATO
initializeParserStats(parserObject * parser)3853a9c91f4dSMasatake YAMATO static void initializeParserStats (parserObject *parser)
3854a9c91f4dSMasatake YAMATO {
3855a9c91f4dSMasatake YAMATO if (Option.printTotals > 1 && parser->used == 0 && parser->def->initStats)
3856a9c91f4dSMasatake YAMATO parser->def->initStats (parser->def->id);
3857a9c91f4dSMasatake YAMATO parser->used = 1;
3858a9c91f4dSMasatake YAMATO }
3859a9c91f4dSMasatake YAMATO
printParserStatisticsIfUsed(langType language)3860a9c91f4dSMasatake YAMATO extern void printParserStatisticsIfUsed (langType language)
3861a9c91f4dSMasatake YAMATO {
3862a9c91f4dSMasatake YAMATO parserObject *parser = &(LanguageTable [language]);
3863a9c91f4dSMasatake YAMATO
3864d4318624SMasatake YAMATO if (parser->used)
3865d4318624SMasatake YAMATO {
3866d4318624SMasatake YAMATO if (parser->def->printStats)
3867a9c91f4dSMasatake YAMATO {
3868a9c91f4dSMasatake YAMATO fprintf(stderr, "\nSTATISTICS of %s\n", getLanguageName (language));
3869a9c91f4dSMasatake YAMATO fputs("==============================================\n", stderr);
3870a9c91f4dSMasatake YAMATO parser->def->printStats (language);
3871a9c91f4dSMasatake YAMATO }
3872d4318624SMasatake YAMATO printLanguageMultitableStatistics (language);
3873d4318624SMasatake YAMATO }
3874a9c91f4dSMasatake YAMATO }
3875a9c91f4dSMasatake YAMATO
createTagsWithFallback1(const langType language,langType * exclusive_subparser)387609b4041bSMasatake YAMATO static bool createTagsWithFallback1 (const langType language,
387709b4041bSMasatake YAMATO langType *exclusive_subparser)
3878d4c6f1e6SMasatake YAMATO {
3879ce990805SThomas Braun bool tagFileResized = false;
3880c1f939f9SMasatake YAMATO unsigned long numTags = numTagsAdded ();
3881509a47dbSJiří Techet MIOPos tagfpos;
38824fa68e36SMasatake YAMATO int lastPromise = getLastPromise ();
3883d4c6f1e6SMasatake YAMATO unsigned int passCount = 0;
3884d4c6f1e6SMasatake YAMATO rescanReason whyRescan;
388597a77b13SMasatake YAMATO parserObject *parser;
38866b1a862eSMasatake YAMATO unsigned int corkFlags;
38876b1a862eSMasatake YAMATO bool useCork = false;
3888d4c6f1e6SMasatake YAMATO
3889bc1a5e1bSMasatake YAMATO initializeParser (language);
389097a77b13SMasatake YAMATO parser = &(LanguageTable [language]);
3891a53e10d8SMasatake YAMATO
38926a8f21eaSMasatake YAMATO setupLanguageSubparsersInUse (language);
3893a53e10d8SMasatake YAMATO
38946b1a862eSMasatake YAMATO corkFlags = parserCorkFlags (parser->def);
38956b1a862eSMasatake YAMATO useCork = corkFlags & CORK_QUEUE;
3896bbd7ded8SMasatake YAMATO if (useCork)
38976b1a862eSMasatake YAMATO corkTagFile(corkFlags);
3898e5b7a250SMasatake YAMATO
38995d526d9eSMasatake YAMATO if (isXtagEnabled (XTAG_PSEUDO_TAGS))
3900bc1a5e1bSMasatake YAMATO addParserPseudoTags (language);
3901a9c91f4dSMasatake YAMATO initializeParserStats (parser);
3902c1f939f9SMasatake YAMATO tagFilePosition (&tagfpos);
3903bc1a5e1bSMasatake YAMATO
3904b90904baSMasatake YAMATO anonResetMaybe (parser);
39053c91b1eaSMasatake YAMATO
3906d4c6f1e6SMasatake YAMATO while ( ( whyRescan =
3907e5b7a250SMasatake YAMATO createTagsForFile (language, ++passCount) )
3908d4c6f1e6SMasatake YAMATO != RESCAN_NONE)
3909d4c6f1e6SMasatake YAMATO {
3910bbd7ded8SMasatake YAMATO if (useCork)
3911e5b7a250SMasatake YAMATO {
3912e5b7a250SMasatake YAMATO uncorkTagFile();
39136b1a862eSMasatake YAMATO corkTagFile(corkFlags);
3914e5b7a250SMasatake YAMATO }
3915e5b7a250SMasatake YAMATO
3916e5b7a250SMasatake YAMATO
3917d4c6f1e6SMasatake YAMATO if (whyRescan == RESCAN_FAILED)
3918d4c6f1e6SMasatake YAMATO {
3919d4c6f1e6SMasatake YAMATO /* Restore prior state of tag file.
3920d4c6f1e6SMasatake YAMATO */
39214a3ba775SMasatake YAMATO setTagFilePosition (&tagfpos, true);
3922c1f939f9SMasatake YAMATO setNumTagsAdded (numTags);
392367d1f12fSJiří Techet writerRescanFailed (numTags);
3924ce990805SThomas Braun tagFileResized = true;
39254fa68e36SMasatake YAMATO breakPromisesAfter(lastPromise);
3926d4c6f1e6SMasatake YAMATO }
3927d4c6f1e6SMasatake YAMATO else if (whyRescan == RESCAN_APPEND)
3928d4c6f1e6SMasatake YAMATO {
3929c1f939f9SMasatake YAMATO tagFilePosition (&tagfpos);
3930c1f939f9SMasatake YAMATO numTags = numTagsAdded ();
39314fa68e36SMasatake YAMATO lastPromise = getLastPromise ();
3932d4c6f1e6SMasatake YAMATO }
3933d4c6f1e6SMasatake YAMATO }
3934bc1a5e1bSMasatake YAMATO
39354e0c6ed6SMasatake YAMATO /* Force filling allLines buffer and kick the multiline regex parser */
3936b177b3faSMasatake YAMATO if (hasLanguageMultilineRegexPatterns (language))
39374e0c6ed6SMasatake YAMATO while (readLineFromInputFile () != NULL)
39384e0c6ed6SMasatake YAMATO ; /* Do nothing */
39394e0c6ed6SMasatake YAMATO
3940bbd7ded8SMasatake YAMATO if (useCork)
3941e5b7a250SMasatake YAMATO uncorkTagFile();
3942e5b7a250SMasatake YAMATO
394309b4041bSMasatake YAMATO {
39446a8f21eaSMasatake YAMATO subparser *s = teardownLanguageSubparsersInUse (language);
394509b4041bSMasatake YAMATO if (exclusive_subparser && s)
394609b4041bSMasatake YAMATO *exclusive_subparser = getSubparserLanguage (s);
394709b4041bSMasatake YAMATO }
3948a53e10d8SMasatake YAMATO
3949e5b7a250SMasatake YAMATO return tagFileResized;
3950e5b7a250SMasatake YAMATO }
3951e5b7a250SMasatake YAMATO
runParserInNarrowedInputStream(const langType language,unsigned long startLine,long startCharOffset,unsigned long endLine,long endCharOffset,unsigned long sourceLineOffset,int promise)3952ce990805SThomas Braun extern bool runParserInNarrowedInputStream (const langType language,
3953ef722b09SMasatake YAMATO unsigned long startLine, long startCharOffset,
3954ef722b09SMasatake YAMATO unsigned long endLine, long endCharOffset,
395511e58e48SMasatake YAMATO unsigned long sourceLineOffset,
395611e58e48SMasatake YAMATO int promise)
39574fa68e36SMasatake YAMATO {
3958ce990805SThomas Braun bool tagFileResized;
3959af389e57SMasatake YAMATO
3960af389e57SMasatake YAMATO verbose ("runParserInNarrowedInputStream: %s; "
3961af389e57SMasatake YAMATO "file: %s, "
3962c3f1785fSMasatake YAMATO "start(line: %lu, offset: %ld, srcline: %lu)"
3963af389e57SMasatake YAMATO " - "
3964c3f1785fSMasatake YAMATO "end(line: %lu, offset: %ld)\n",
3965af389e57SMasatake YAMATO getLanguageName (language),
3966af389e57SMasatake YAMATO getInputFileName (),
3967af389e57SMasatake YAMATO startLine, startCharOffset, sourceLineOffset,
3968af389e57SMasatake YAMATO endLine, endCharOffset);
3969af389e57SMasatake YAMATO
39704d1713c7SMasatake YAMATO pushNarrowedInputStream (
39719128cdbaSMasatake YAMATO doesParserRequireMemoryStream (language),
39724fa68e36SMasatake YAMATO startLine, startCharOffset,
39734fa68e36SMasatake YAMATO endLine, endCharOffset,
397411e58e48SMasatake YAMATO sourceLineOffset,
397511e58e48SMasatake YAMATO promise);
397609b4041bSMasatake YAMATO tagFileResized = createTagsWithFallback1 (language, NULL);
39774fa68e36SMasatake YAMATO popNarrowedInputStream ();
39784fa68e36SMasatake YAMATO return tagFileResized;
39794fa68e36SMasatake YAMATO
39804fa68e36SMasatake YAMATO }
39814fa68e36SMasatake YAMATO
createTagsWithFallback(const char * const fileName,const langType language,MIO * mio,time_t mtime,bool * failureInOpenning)3982ce990805SThomas Braun static bool createTagsWithFallback (
3983e5b7a250SMasatake YAMATO const char *const fileName, const langType language,
3984ce1f2415SMasatake YAMATO MIO *mio, time_t mtime, bool *failureInOpenning)
3985e5b7a250SMasatake YAMATO {
398609b4041bSMasatake YAMATO langType exclusive_subparser = LANG_IGNORE;
3987ce990805SThomas Braun bool tagFileResized = false;
3988e5b7a250SMasatake YAMATO
3989e5b7a250SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
3990e5b7a250SMasatake YAMATO
3991ce1f2415SMasatake YAMATO if (!openInputFile (fileName, language, mio, mtime))
39928ae1a1ffSMasatake YAMATO {
39938ae1a1ffSMasatake YAMATO *failureInOpenning = true;
3994ce990805SThomas Braun return false;
39958ae1a1ffSMasatake YAMATO }
39968ae1a1ffSMasatake YAMATO *failureInOpenning = false;
3997e5b7a250SMasatake YAMATO
399809b4041bSMasatake YAMATO tagFileResized = createTagsWithFallback1 (language,
399909b4041bSMasatake YAMATO &exclusive_subparser);
4000ce990805SThomas Braun tagFileResized = forcePromises()? true: tagFileResized;
4001e5b7a250SMasatake YAMATO
400209b4041bSMasatake YAMATO pushLanguage ((exclusive_subparser == LANG_IGNORE)
400309b4041bSMasatake YAMATO ? language
400409b4041bSMasatake YAMATO : exclusive_subparser);
4005e5b7a250SMasatake YAMATO makeFileTag (fileName);
40064dfa41deSMasatake YAMATO popLanguage ();
4007bc1a5e1bSMasatake YAMATO closeInputFile ();
4008bc1a5e1bSMasatake YAMATO
4009d4c6f1e6SMasatake YAMATO return tagFileResized;
4010d4c6f1e6SMasatake YAMATO }
4011d4c6f1e6SMasatake YAMATO
printGuessedParser(const char * const fileName,langType language)4012d4c6f1e6SMasatake YAMATO static void printGuessedParser (const char* const fileName, langType language)
4013d4c6f1e6SMasatake YAMATO {
4014d4c6f1e6SMasatake YAMATO const char *parserName;
4015d4c6f1e6SMasatake YAMATO
4016d4c6f1e6SMasatake YAMATO if (language == LANG_IGNORE)
4017d4c6f1e6SMasatake YAMATO {
4018ce990805SThomas Braun Option.printLanguage = ((int)true) + 1;
4019db2bf481SMasatake YAMATO parserName = RSV_NONE;
4020d4c6f1e6SMasatake YAMATO }
4021d4c6f1e6SMasatake YAMATO else
4022f02166dcSMasatake YAMATO {
4023f02166dcSMasatake YAMATO parserName = getLanguageName (language);
4024f02166dcSMasatake YAMATO }
4025d4c6f1e6SMasatake YAMATO
4026d4c6f1e6SMasatake YAMATO printf("%s: %s\n", fileName, parserName);
4027d4c6f1e6SMasatake YAMATO }
4028d4c6f1e6SMasatake YAMATO
40292acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
40302acdcfa1SYasuhiro Matsumoto static char **EncodingMap;
40312acdcfa1SYasuhiro Matsumoto static unsigned int EncodingMapMax;
40322acdcfa1SYasuhiro Matsumoto
addLanguageEncoding(const langType language,const char * const encoding)40332acdcfa1SYasuhiro Matsumoto static void addLanguageEncoding (const langType language,
40342acdcfa1SYasuhiro Matsumoto const char *const encoding)
40352acdcfa1SYasuhiro Matsumoto {
40362acdcfa1SYasuhiro Matsumoto if (language > EncodingMapMax || EncodingMapMax == 0)
40372acdcfa1SYasuhiro Matsumoto {
40382acdcfa1SYasuhiro Matsumoto int i;
40392acdcfa1SYasuhiro Matsumoto int istart = (EncodingMapMax == 0)? 0: EncodingMapMax + 1;
40402acdcfa1SYasuhiro Matsumoto EncodingMap = xRealloc (EncodingMap, (language + 1), char*);
40412acdcfa1SYasuhiro Matsumoto for (i = istart; i <= language ; ++i)
40422acdcfa1SYasuhiro Matsumoto {
40432acdcfa1SYasuhiro Matsumoto EncodingMap [i] = NULL;
40442acdcfa1SYasuhiro Matsumoto }
40452acdcfa1SYasuhiro Matsumoto EncodingMapMax = language;
40462acdcfa1SYasuhiro Matsumoto }
40472acdcfa1SYasuhiro Matsumoto if (EncodingMap [language])
40482acdcfa1SYasuhiro Matsumoto eFree (EncodingMap [language]);
40492acdcfa1SYasuhiro Matsumoto EncodingMap [language] = eStrdup(encoding);
40502acdcfa1SYasuhiro Matsumoto if (!Option.outputEncoding)
40512acdcfa1SYasuhiro Matsumoto Option.outputEncoding = eStrdup("UTF-8");
40522acdcfa1SYasuhiro Matsumoto }
40532acdcfa1SYasuhiro Matsumoto
processLanguageEncodingOption(const char * const option,const char * const parameter)4054ce990805SThomas Braun extern bool processLanguageEncodingOption (const char *const option, const char *const parameter)
40552acdcfa1SYasuhiro Matsumoto {
40562acdcfa1SYasuhiro Matsumoto langType language;
40572acdcfa1SYasuhiro Matsumoto
40582acdcfa1SYasuhiro Matsumoto language = getLanguageComponentInOption (option, "input-encoding-");
40592acdcfa1SYasuhiro Matsumoto if (language == LANG_IGNORE)
4060ce990805SThomas Braun return false;
40612acdcfa1SYasuhiro Matsumoto
40622acdcfa1SYasuhiro Matsumoto addLanguageEncoding (language, parameter);
4063ce990805SThomas Braun return true;
40642acdcfa1SYasuhiro Matsumoto }
40652acdcfa1SYasuhiro Matsumoto
freeEncodingResources(void)40662acdcfa1SYasuhiro Matsumoto extern void freeEncodingResources (void)
40672acdcfa1SYasuhiro Matsumoto {
40682acdcfa1SYasuhiro Matsumoto if (EncodingMap)
40692acdcfa1SYasuhiro Matsumoto {
407046ab94ccSMasatake YAMATO unsigned int i;
40712acdcfa1SYasuhiro Matsumoto for (i = 0 ; i <= EncodingMapMax ; ++i)
40722acdcfa1SYasuhiro Matsumoto {
40732acdcfa1SYasuhiro Matsumoto if (EncodingMap [i])
40742acdcfa1SYasuhiro Matsumoto eFree (EncodingMap [i]);
40752acdcfa1SYasuhiro Matsumoto }
4076a32a50f1SMasatake YAMATO eFree (EncodingMap);
40772acdcfa1SYasuhiro Matsumoto }
40782acdcfa1SYasuhiro Matsumoto if (Option.inputEncoding)
40792acdcfa1SYasuhiro Matsumoto eFree (Option.inputEncoding);
40802acdcfa1SYasuhiro Matsumoto if (Option.outputEncoding)
40812acdcfa1SYasuhiro Matsumoto eFree (Option.outputEncoding);
40822acdcfa1SYasuhiro Matsumoto }
4083bde9f60aSColomban Wendling
getLanguageEncoding(const langType language)4084bde9f60aSColomban Wendling extern const char *getLanguageEncoding (const langType language)
4085bde9f60aSColomban Wendling {
4086bde9f60aSColomban Wendling if (EncodingMap && language <= EncodingMapMax && EncodingMap [language])
4087bde9f60aSColomban Wendling return EncodingMap[language];
4088bde9f60aSColomban Wendling else
4089bde9f60aSColomban Wendling return Option.inputEncoding;
4090bde9f60aSColomban Wendling }
40912acdcfa1SYasuhiro Matsumoto #endif
40922acdcfa1SYasuhiro Matsumoto
addParserPseudoTags(langType language)4093ce8d2e8fSMasatake YAMATO static void addParserPseudoTags (langType language)
4094ce8d2e8fSMasatake YAMATO {
40958df191b2SMasatake YAMATO parserObject *parser = LanguageTable + language;
40968df191b2SMasatake YAMATO if (!parser->pseudoTagPrinted)
4097ce8d2e8fSMasatake YAMATO {
4098ef573be0SMasatake YAMATO for (int i = 0; i < PTAG_COUNT; i++)
4099ef573be0SMasatake YAMATO {
4100ef573be0SMasatake YAMATO if (isPtagParserSpecific (i))
4101ef573be0SMasatake YAMATO makePtagIfEnabled (i, language, parser);
4102ef573be0SMasatake YAMATO }
41038df191b2SMasatake YAMATO parser->pseudoTagPrinted = 1;
4104ce8d2e8fSMasatake YAMATO }
4105ce8d2e8fSMasatake YAMATO }
4106ce8d2e8fSMasatake YAMATO
doesParserRequireMemoryStream(const langType language)4107ce990805SThomas Braun extern bool doesParserRequireMemoryStream (const langType language)
410831cb4225SMasatake YAMATO {
410931cb4225SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4110e02be843SMasatake YAMATO parserDefinition *const lang = LanguageTable [language].def;
411146ab94ccSMasatake YAMATO unsigned int i;
411231cb4225SMasatake YAMATO
4113b19a98c8SMasatake YAMATO if (lang->tagXpathTableCount > 0
4114e535639cSMasatake YAMATO || lang->useMemoryStreamInput)
4115b19a98c8SMasatake YAMATO {
4116b19a98c8SMasatake YAMATO verbose ("%s requires a memory stream for input\n", lang->name);
4117288cd67dSMasatake YAMATO return true;
4118b19a98c8SMasatake YAMATO }
4119288cd67dSMasatake YAMATO
41207d7040f4SMasatake YAMATO for (i = 0; i < lang->dependencyCount; i++)
41217d7040f4SMasatake YAMATO {
41227d7040f4SMasatake YAMATO parserDependency *d = lang->dependencies + i;
41237d7040f4SMasatake YAMATO if (d->type == DEPTYPE_SUBPARSER &&
41247d7040f4SMasatake YAMATO ((subparser *)(d->data))->direction & SUBPARSER_SUB_RUNS_BASE)
41257d7040f4SMasatake YAMATO {
41267d7040f4SMasatake YAMATO langType baseParser;
41277d7040f4SMasatake YAMATO baseParser = getNamedLanguage (d->upperParser, 0);
41287d7040f4SMasatake YAMATO if (doesParserRequireMemoryStream(baseParser))
41297d7040f4SMasatake YAMATO {
41307d7040f4SMasatake YAMATO verbose ("%s/%s requires a memory stream for input\n", lang->name,
41317d7040f4SMasatake YAMATO LanguageTable[baseParser].def->name);
41327d7040f4SMasatake YAMATO return true;
41337d7040f4SMasatake YAMATO }
41347d7040f4SMasatake YAMATO }
41357d7040f4SMasatake YAMATO }
41367d7040f4SMasatake YAMATO
4137288cd67dSMasatake YAMATO return false;
413831cb4225SMasatake YAMATO }
413931cb4225SMasatake YAMATO
parseFile(const char * const fileName)4140ce990805SThomas Braun extern bool parseFile (const char *const fileName)
4141d4c6f1e6SMasatake YAMATO {
4142d33423e3SSzymon Tomasz Stefanek TRACE_ENTER_TEXT("Parsing file %s",fileName);
4143eda0f17cSMasatake YAMATO bool bRet = parseFileWithMio (fileName, NULL, NULL);
4144d33423e3SSzymon Tomasz Stefanek TRACE_LEAVE();
4145d33423e3SSzymon Tomasz Stefanek return bRet;
4146f9f37517SAman Gupta }
4147f9f37517SAman Gupta
parseMio(const char * const fileName,langType language,MIO * mio,time_t mtime,bool useSourceFileTagPath,void * clientData)4148ce1f2415SMasatake YAMATO static bool parseMio (const char *const fileName, langType language, MIO* mio, time_t mtime, bool useSourceFileTagPath,
4149eda0f17cSMasatake YAMATO void *clientData)
4150eda0f17cSMasatake YAMATO {
4151eda0f17cSMasatake YAMATO bool tagFileResized = false;
41528ae1a1ffSMasatake YAMATO bool failureInOpenning = false;
4153eda0f17cSMasatake YAMATO
4154eda0f17cSMasatake YAMATO setupWriter (clientData);
4155eda0f17cSMasatake YAMATO
4156eda0f17cSMasatake YAMATO setupAnon ();
4157eda0f17cSMasatake YAMATO
4158eda0f17cSMasatake YAMATO initParserTrashBox ();
4159eda0f17cSMasatake YAMATO
4160ce1f2415SMasatake YAMATO tagFileResized = createTagsWithFallback (fileName, language, mio, mtime, &failureInOpenning);
4161eda0f17cSMasatake YAMATO
4162eda0f17cSMasatake YAMATO finiParserTrashBox ();
4163eda0f17cSMasatake YAMATO
4164eda0f17cSMasatake YAMATO teardownAnon ();
4165eda0f17cSMasatake YAMATO
41668ae1a1ffSMasatake YAMATO if (useSourceFileTagPath && (!failureInOpenning))
4167eda0f17cSMasatake YAMATO return teardownWriter (getSourceFileTagPath())? true: tagFileResized;
4168eda0f17cSMasatake YAMATO else
4169eda0f17cSMasatake YAMATO return teardownWriter(fileName);
4170eda0f17cSMasatake YAMATO }
4171eda0f17cSMasatake YAMATO
parseFileWithMio(const char * const fileName,MIO * mio,void * clientData)4172eda0f17cSMasatake YAMATO extern bool parseFileWithMio (const char *const fileName, MIO *mio,
4173eda0f17cSMasatake YAMATO void *clientData)
4174f9f37517SAman Gupta {
4175ce990805SThomas Braun bool tagFileResized = false;
417642b60e7aSMasatake YAMATO langType language;
4177cfac930dSMasatake YAMATO struct GetLanguageRequest req = {
4178cfac930dSMasatake YAMATO .type = mio? GLR_REUSE: GLR_OPEN,
4179cfac930dSMasatake YAMATO .fileName = fileName,
4180cfac930dSMasatake YAMATO .mio = mio,
4181cfac930dSMasatake YAMATO };
4182ce1f2415SMasatake YAMATO memset (&req.mtime, 0, sizeof (req.mtime));
418342b60e7aSMasatake YAMATO
4184cfac930dSMasatake YAMATO language = getFileLanguageForRequest (&req);
4185d4c6f1e6SMasatake YAMATO Assert (language != LANG_AUTO);
4186d4c6f1e6SMasatake YAMATO
4187d4c6f1e6SMasatake YAMATO if (Option.printLanguage)
4188d4c6f1e6SMasatake YAMATO {
4189d4c6f1e6SMasatake YAMATO printGuessedParser (fileName, language);
4190d4c6f1e6SMasatake YAMATO return tagFileResized;
4191d4c6f1e6SMasatake YAMATO }
4192d4c6f1e6SMasatake YAMATO
4193d4c6f1e6SMasatake YAMATO if (language == LANG_IGNORE)
4194f8bd0fa2SMasatake YAMATO verbose ("ignoring %s (unknown language/language disabled)\n",
4195f8bd0fa2SMasatake YAMATO fileName);
4196d4c6f1e6SMasatake YAMATO else
4197d4c6f1e6SMasatake YAMATO {
41983e7e9e07SMasatake YAMATO Assert(isLanguageEnabled (language));
41993e7e9e07SMasatake YAMATO
42002050d074SAman Gupta if (Option.filter && ! Option.interactive)
4201d4c6f1e6SMasatake YAMATO openTagFile ();
42022acdcfa1SYasuhiro Matsumoto
42032acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
42047d6be565SMasatake YAMATO /* TODO: checkUTF8BOM can be used to update the encodings. */
4205bde9f60aSColomban Wendling openConverter (getLanguageEncoding (language), Option.outputEncoding);
42062acdcfa1SYasuhiro Matsumoto #endif
4207ce1f2415SMasatake YAMATO tagFileResized = parseMio (fileName, language, req.mio, req.mtime, true, clientData);
42082050d074SAman Gupta if (Option.filter && ! Option.interactive)
4209d4c6f1e6SMasatake YAMATO closeTagFile (tagFileResized);
4210d4c6f1e6SMasatake YAMATO addTotals (1, 0L, 0L);
4211d4c6f1e6SMasatake YAMATO
42122acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
42132acdcfa1SYasuhiro Matsumoto closeConverter ();
42142acdcfa1SYasuhiro Matsumoto #endif
4215d4c6f1e6SMasatake YAMATO }
4216e9d4c72cSMasatake YAMATO
4217cfac930dSMasatake YAMATO if (req.type == GLR_OPEN && req.mio)
4218b978efd6SMasatake YAMATO mio_unref (req.mio);
4219d33423e3SSzymon Tomasz Stefanek
4220d4c6f1e6SMasatake YAMATO return tagFileResized;
4221d4c6f1e6SMasatake YAMATO }
4222d4c6f1e6SMasatake YAMATO
parseRawBuffer(const char * fileName,unsigned char * buffer,size_t bufferSize,const langType language,void * clientData)4223eda0f17cSMasatake YAMATO extern bool parseRawBuffer(const char *fileName, unsigned char *buffer,
4224eda0f17cSMasatake YAMATO size_t bufferSize, const langType language, void *clientData)
4225eda0f17cSMasatake YAMATO {
4226eda0f17cSMasatake YAMATO MIO *mio = NULL;
4227eda0f17cSMasatake YAMATO bool r;
4228eda0f17cSMasatake YAMATO
4229eda0f17cSMasatake YAMATO if (buffer)
4230eda0f17cSMasatake YAMATO mio = mio_new_memory (buffer, bufferSize, NULL, NULL);
4231eda0f17cSMasatake YAMATO
4232ce1f2415SMasatake YAMATO r = parseMio (fileName, language, mio, (time_t)0, false, clientData);
4233eda0f17cSMasatake YAMATO
4234eda0f17cSMasatake YAMATO if (buffer)
4235eda0f17cSMasatake YAMATO mio_unref (mio);
4236eda0f17cSMasatake YAMATO
4237eda0f17cSMasatake YAMATO return r;
4238eda0f17cSMasatake YAMATO }
4239eda0f17cSMasatake YAMATO
matchLanguageMultilineRegexCommon(const langType language,bool (* func)(struct lregexControlBlock *,const vString * const),const vString * const allLines)424041e0b4f8SMasatake YAMATO static void matchLanguageMultilineRegexCommon (const langType language,
424141e0b4f8SMasatake YAMATO bool (* func) (struct lregexControlBlock *, const vString* const),
424241e0b4f8SMasatake YAMATO const vString* const allLines)
424353dda59eSMasatake YAMATO {
4244b177b3faSMasatake YAMATO subparser *tmp;
4245b177b3faSMasatake YAMATO
424641e0b4f8SMasatake YAMATO func ((LanguageTable + language)->lregexControlBlock, allLines);
424711358a9dSMasatake YAMATO foreachSubparser(tmp, true)
4248b177b3faSMasatake YAMATO {
4249b177b3faSMasatake YAMATO langType t = getSubparserLanguage (tmp);
4250b177b3faSMasatake YAMATO enterSubparser (tmp);
425141e0b4f8SMasatake YAMATO matchLanguageMultilineRegexCommon (t, func, allLines);
4252b177b3faSMasatake YAMATO leaveSubparser ();
4253b177b3faSMasatake YAMATO }
4254b177b3faSMasatake YAMATO }
4255b177b3faSMasatake YAMATO
matchLanguageMultilineRegex(const langType language,const vString * const allLines)425641e0b4f8SMasatake YAMATO extern void matchLanguageMultilineRegex (const langType language,
425741e0b4f8SMasatake YAMATO const vString* const allLines)
425841e0b4f8SMasatake YAMATO {
425941e0b4f8SMasatake YAMATO matchLanguageMultilineRegexCommon(language, matchMultilineRegex, allLines);
426041e0b4f8SMasatake YAMATO }
426141e0b4f8SMasatake YAMATO
matchLanguageMultitableRegex(const langType language,const vString * const allLines)426241e0b4f8SMasatake YAMATO extern void matchLanguageMultitableRegex (const langType language,
426341e0b4f8SMasatake YAMATO const vString* const allLines)
426441e0b4f8SMasatake YAMATO {
426541e0b4f8SMasatake YAMATO matchLanguageMultilineRegexCommon(language, matchMultitableRegex, allLines);
426641e0b4f8SMasatake YAMATO }
426741e0b4f8SMasatake YAMATO
processLanguageMultitableExtendingOption(langType language,const char * const parameter)4268bf809d1aSMasatake YAMATO extern void processLanguageMultitableExtendingOption (langType language, const char *const parameter)
4269bf809d1aSMasatake YAMATO {
4270bf809d1aSMasatake YAMATO const char* src;
4271bf809d1aSMasatake YAMATO char* dist;
4272bf809d1aSMasatake YAMATO const char *tmp;
4273bf809d1aSMasatake YAMATO
4274bf809d1aSMasatake YAMATO tmp = strchr(parameter, '+');
4275bf809d1aSMasatake YAMATO
4276bf809d1aSMasatake YAMATO if (!tmp)
4277bf809d1aSMasatake YAMATO error (FATAL, "no separator(+) found: %s", parameter);
4278bf809d1aSMasatake YAMATO
4279bf809d1aSMasatake YAMATO if (tmp == parameter)
4280bf809d1aSMasatake YAMATO error (FATAL, "the name of source table is empty in table extending: %s", parameter);
4281bf809d1aSMasatake YAMATO
4282bf809d1aSMasatake YAMATO src = tmp + 1;
4283bf809d1aSMasatake YAMATO if (!*src)
4284bf809d1aSMasatake YAMATO error (FATAL, "the name of dist table is empty in table extending: %s", parameter);
4285bf809d1aSMasatake YAMATO
4286bf809d1aSMasatake YAMATO dist = eStrndup(parameter, tmp - parameter);
4287bf809d1aSMasatake YAMATO extendRegexTable(((LanguageTable + language)->lregexControlBlock), src, dist);
4288bf809d1aSMasatake YAMATO eFree (dist);
4289bf809d1aSMasatake YAMATO }
4290bf809d1aSMasatake YAMATO
lregexQueryParserAndSubparsers(const langType language,bool (* predicate)(struct lregexControlBlock *))4291018165e6Sjannick0 static bool lregexQueryParserAndSubparsers (const langType language, bool (* predicate) (struct lregexControlBlock *))
4292b177b3faSMasatake YAMATO {
4293b177b3faSMasatake YAMATO bool r;
4294b177b3faSMasatake YAMATO subparser *tmp;
4295b177b3faSMasatake YAMATO
4296b177b3faSMasatake YAMATO r = predicate ((LanguageTable + language)->lregexControlBlock);
4297b177b3faSMasatake YAMATO if (!r)
4298b177b3faSMasatake YAMATO {
429911358a9dSMasatake YAMATO foreachSubparser(tmp, true)
4300b177b3faSMasatake YAMATO {
4301b177b3faSMasatake YAMATO langType t = getSubparserLanguage (tmp);
4302b177b3faSMasatake YAMATO enterSubparser (tmp);
4303018165e6Sjannick0 r = lregexQueryParserAndSubparsers (t, predicate);
4304b177b3faSMasatake YAMATO leaveSubparser ();
4305b177b3faSMasatake YAMATO
4306b177b3faSMasatake YAMATO if (r)
4307b177b3faSMasatake YAMATO break;
4308b177b3faSMasatake YAMATO }
4309b177b3faSMasatake YAMATO }
4310b177b3faSMasatake YAMATO
4311b177b3faSMasatake YAMATO return r;
431253dda59eSMasatake YAMATO }
431353dda59eSMasatake YAMATO
hasLanguageMultilineRegexPatterns(const langType language)431453dda59eSMasatake YAMATO extern bool hasLanguageMultilineRegexPatterns (const langType language)
431553dda59eSMasatake YAMATO {
4316018165e6Sjannick0 return lregexQueryParserAndSubparsers (language, regexNeedsMultilineBuffer);
431753dda59eSMasatake YAMATO }
431853dda59eSMasatake YAMATO
4319b177b3faSMasatake YAMATO
addLanguageCallbackRegex(const langType language,const char * const regex,const char * const flags,const regexCallback callback,bool * disabled,void * userData)432053dda59eSMasatake YAMATO extern void addLanguageCallbackRegex (const langType language, const char *const regex, const char *const flags,
432153dda59eSMasatake YAMATO const regexCallback callback, bool *disabled, void *userData)
432253dda59eSMasatake YAMATO {
432353dda59eSMasatake YAMATO addCallbackRegex ((LanguageTable +language)->lregexControlBlock, regex, flags, callback, disabled, userData);
432453dda59eSMasatake YAMATO }
432553dda59eSMasatake YAMATO
doesLanguageExpectCorkInRegex(const langType language)4326c25346c2SMasatake YAMATO extern bool doesLanguageExpectCorkInRegex (const langType language)
432753dda59eSMasatake YAMATO {
4328cb4dd5c3SMasatake YAMATO bool hasScopeAction;
4329cb4dd5c3SMasatake YAMATO
4330cb4dd5c3SMasatake YAMATO pushLanguage (language);
4331c25346c2SMasatake YAMATO hasScopeAction = lregexQueryParserAndSubparsers (language, doesExpectCorkInRegex);
4332cb4dd5c3SMasatake YAMATO popLanguage ();
4333cb4dd5c3SMasatake YAMATO
4334cb4dd5c3SMasatake YAMATO return hasScopeAction;
433553dda59eSMasatake YAMATO }
433653dda59eSMasatake YAMATO
matchLanguageRegex(const langType language,const vString * const line)433730edf066SMasatake YAMATO extern void matchLanguageRegex (const langType language, const vString* const line)
433853dda59eSMasatake YAMATO {
433918193ebfSMasatake YAMATO subparser *tmp;
434018193ebfSMasatake YAMATO
434130edf066SMasatake YAMATO matchRegex ((LanguageTable + language)->lregexControlBlock, line);
434211358a9dSMasatake YAMATO foreachSubparser(tmp, true)
434318193ebfSMasatake YAMATO {
434418193ebfSMasatake YAMATO langType t = getSubparserLanguage (tmp);
434518193ebfSMasatake YAMATO enterSubparser (tmp);
434618193ebfSMasatake YAMATO matchLanguageRegex (t, line);
434718193ebfSMasatake YAMATO leaveSubparser ();
434818193ebfSMasatake YAMATO }
434953dda59eSMasatake YAMATO }
435053dda59eSMasatake YAMATO
processLanguageRegexOption(langType language,enum regexParserType regptype,const char * const parameter)4351056b32e1SMasatake YAMATO extern bool processLanguageRegexOption (langType language,
43521b9c3aecSMasatake YAMATO enum regexParserType regptype,
4353056b32e1SMasatake YAMATO const char *const parameter)
4354056b32e1SMasatake YAMATO {
4355641e337aSMasatake YAMATO processTagRegexOption ((LanguageTable +language)->lregexControlBlock,
43561b9c3aecSMasatake YAMATO regptype, parameter);
4357056b32e1SMasatake YAMATO
4358056b32e1SMasatake YAMATO return true;
4359056b32e1SMasatake YAMATO }
4360056b32e1SMasatake YAMATO
processTabledefOption(const char * const option,const char * const parameter)4361e0e33135SMasatake YAMATO extern bool processTabledefOption (const char *const option, const char *const parameter)
4362e0e33135SMasatake YAMATO {
4363e0e33135SMasatake YAMATO langType language;
4364e0e33135SMasatake YAMATO
4365e0e33135SMasatake YAMATO language = getLanguageComponentInOption (option, "_tabledef-");
4366e0e33135SMasatake YAMATO if (language == LANG_IGNORE)
4367e0e33135SMasatake YAMATO return false;
4368e0e33135SMasatake YAMATO
4369e0e33135SMasatake YAMATO if (parameter == NULL || parameter[0] == '\0')
4370e0e33135SMasatake YAMATO error (FATAL, "A parameter is needed after \"%s\" option", option);
4371e0e33135SMasatake YAMATO
4372e0e33135SMasatake YAMATO addRegexTable((LanguageTable +language)->lregexControlBlock, parameter);
4373e0e33135SMasatake YAMATO return true;
4374e0e33135SMasatake YAMATO }
4375e0e33135SMasatake YAMATO
useRegexMethod(const langType language)4376d4c6f1e6SMasatake YAMATO extern void useRegexMethod (const langType language)
4377d4c6f1e6SMasatake YAMATO {
4378d4c6f1e6SMasatake YAMATO parserDefinition* lang;
4379d4c6f1e6SMasatake YAMATO
4380d4c6f1e6SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4381e02be843SMasatake YAMATO lang = LanguageTable [language].def;
4382d4c6f1e6SMasatake YAMATO lang->method |= METHOD_REGEX;
4383d4c6f1e6SMasatake YAMATO }
4384d4c6f1e6SMasatake YAMATO
useXpathMethod(const langType language)43852082dbbfSColomban Wendling static void useXpathMethod (const langType language)
4386a086aff1SMasatake YAMATO {
4387a086aff1SMasatake YAMATO parserDefinition* lang;
4388a086aff1SMasatake YAMATO
4389a086aff1SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4390e02be843SMasatake YAMATO lang = LanguageTable [language].def;
4391a086aff1SMasatake YAMATO lang->method |= METHOD_XPATH;
4392a086aff1SMasatake YAMATO }
4393a086aff1SMasatake YAMATO
installTagRegexTable(const langType language)4394d453869fSMasatake YAMATO static void installTagRegexTable (const langType language)
4395dc0f490fSMasatake YAMATO {
4396056b32e1SMasatake YAMATO parserObject* parser;
4397dc0f490fSMasatake YAMATO parserDefinition* lang;
4398dc0f490fSMasatake YAMATO unsigned int i;
4399dc0f490fSMasatake YAMATO
4400dc0f490fSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4401056b32e1SMasatake YAMATO parser = LanguageTable + language;
4402056b32e1SMasatake YAMATO lang = parser->def;
4403dc0f490fSMasatake YAMATO
4404dc0f490fSMasatake YAMATO
4405d453869fSMasatake YAMATO if (lang->tagRegexTable != NULL)
44066578b12dSMasatake YAMATO {
4407965b7025SMasatake YAMATO /* ctags_cli_main() calls initRegexOptscript ().
4408965b7025SMasatake YAMATO * However, mini-geany deasn't call ctags_cli_main().
4409965b7025SMasatake YAMATO * So we call initRegexOptscript () here.
4410965b7025SMasatake YAMATO */
4411965b7025SMasatake YAMATO initRegexOptscript ();
4412965b7025SMasatake YAMATO
4413dc0f490fSMasatake YAMATO for (i = 0; i < lang->tagRegexCount; ++i)
4414641e337aSMasatake YAMATO {
4415641e337aSMasatake YAMATO if (lang->tagRegexTable [i].mline)
4416641e337aSMasatake YAMATO addTagMultiLineRegex (parser->lregexControlBlock,
4417641e337aSMasatake YAMATO lang->tagRegexTable [i].regex,
4418641e337aSMasatake YAMATO lang->tagRegexTable [i].name,
4419641e337aSMasatake YAMATO lang->tagRegexTable [i].kinds,
4420641e337aSMasatake YAMATO lang->tagRegexTable [i].flags,
4421641e337aSMasatake YAMATO (lang->tagRegexTable [i].disabled));
4422641e337aSMasatake YAMATO else
4423056b32e1SMasatake YAMATO addTagRegex (parser->lregexControlBlock,
4424dc0f490fSMasatake YAMATO lang->tagRegexTable [i].regex,
4425dc0f490fSMasatake YAMATO lang->tagRegexTable [i].name,
4426dc0f490fSMasatake YAMATO lang->tagRegexTable [i].kinds,
44272a738f47SMasatake YAMATO lang->tagRegexTable [i].flags,
44282a738f47SMasatake YAMATO (lang->tagRegexTable [i].disabled));
44296578b12dSMasatake YAMATO }
4430dc0f490fSMasatake YAMATO }
4431641e337aSMasatake YAMATO }
4432dc0f490fSMasatake YAMATO
installKeywordTable(const langType language)4433d453869fSMasatake YAMATO static void installKeywordTable (const langType language)
4434c379c5d2SMasatake YAMATO {
4435c379c5d2SMasatake YAMATO parserDefinition* lang;
4436c379c5d2SMasatake YAMATO unsigned int i;
4437c379c5d2SMasatake YAMATO
4438c379c5d2SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4439e02be843SMasatake YAMATO lang = LanguageTable [language].def;
4440c379c5d2SMasatake YAMATO
4441d453869fSMasatake YAMATO if (lang->keywordTable != NULL)
444273ba730fSMasatake YAMATO {
4443c379c5d2SMasatake YAMATO for (i = 0; i < lang->keywordCount; ++i)
4444c379c5d2SMasatake YAMATO addKeyword (lang->keywordTable [i].name,
4445c379c5d2SMasatake YAMATO language,
4446c379c5d2SMasatake YAMATO lang->keywordTable [i].id);
444773ba730fSMasatake YAMATO }
4448c379c5d2SMasatake YAMATO }
4449e7283d01SMasatake YAMATO
installTagXpathTable(const langType language)4450d453869fSMasatake YAMATO static void installTagXpathTable (const langType language)
4451a086aff1SMasatake YAMATO {
4452a086aff1SMasatake YAMATO parserDefinition* lang;
4453a086aff1SMasatake YAMATO unsigned int i, j;
4454a086aff1SMasatake YAMATO
4455a086aff1SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4456e02be843SMasatake YAMATO lang = LanguageTable [language].def;
4457a086aff1SMasatake YAMATO
4458d453869fSMasatake YAMATO if (lang->tagXpathTableTable != NULL)
4459a086aff1SMasatake YAMATO {
4460a086aff1SMasatake YAMATO for (i = 0; i < lang->tagXpathTableCount; ++i)
4461a086aff1SMasatake YAMATO for (j = 0; j < lang->tagXpathTableTable[i].count; ++j)
4462a086aff1SMasatake YAMATO addTagXpath (language, lang->tagXpathTableTable[i].table + j);
4463fe9cf7d1SMasatake YAMATO useXpathMethod (language);
4464a086aff1SMasatake YAMATO }
4465a086aff1SMasatake YAMATO }
4466a086aff1SMasatake YAMATO
uninstallTagXpathTable(const langType language)4467eb480042SMasatake YAMATO static void uninstallTagXpathTable (const langType language)
4468eb480042SMasatake YAMATO {
4469eb480042SMasatake YAMATO parserDefinition* lang;
4470eb480042SMasatake YAMATO unsigned int i, j;
4471eb480042SMasatake YAMATO
4472eb480042SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4473eb480042SMasatake YAMATO lang = LanguageTable [language].def;
4474eb480042SMasatake YAMATO
4475eb480042SMasatake YAMATO if (lang->tagXpathTableTable != NULL)
4476eb480042SMasatake YAMATO {
4477eb480042SMasatake YAMATO for (i = 0; i < lang->tagXpathTableCount; ++i)
4478eb480042SMasatake YAMATO for (j = 0; j < lang->tagXpathTableTable[i].count; ++j)
4479eb480042SMasatake YAMATO removeTagXpath (language, lang->tagXpathTableTable[i].table + j);
4480eb480042SMasatake YAMATO }
4481eb480042SMasatake YAMATO }
4482eb480042SMasatake YAMATO
getXpathTableTable(const langType language,unsigned int nth)44830fde73e0SMasatake YAMATO const tagXpathTableTable *getXpathTableTable (const langType language, unsigned int nth)
44840fde73e0SMasatake YAMATO {
44850fde73e0SMasatake YAMATO parserDefinition* lang;
44860fde73e0SMasatake YAMATO
44870fde73e0SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
44880fde73e0SMasatake YAMATO lang = LanguageTable [language].def;
44890fde73e0SMasatake YAMATO
44900fde73e0SMasatake YAMATO Assert (nth < lang->tagXpathTableCount);
44910fde73e0SMasatake YAMATO return lang->tagXpathTableTable + nth;
44920fde73e0SMasatake YAMATO }
44930fde73e0SMasatake YAMATO
getXpathFileSpecCount(const langType language)4494d5e6de9cSMasatake YAMATO extern unsigned int getXpathFileSpecCount (const langType language)
4495d5e6de9cSMasatake YAMATO {
4496d5e6de9cSMasatake YAMATO parserDefinition* lang;
4497d5e6de9cSMasatake YAMATO
4498d5e6de9cSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4499e02be843SMasatake YAMATO lang = LanguageTable [language].def;
4500d5e6de9cSMasatake YAMATO
4501d5e6de9cSMasatake YAMATO return lang->xpathFileSpecCount;
4502d5e6de9cSMasatake YAMATO }
4503d5e6de9cSMasatake YAMATO
getXpathFileSpec(const langType language,unsigned int nth)4504d5e6de9cSMasatake YAMATO extern xpathFileSpec* getXpathFileSpec (const langType language, unsigned int nth)
4505d5e6de9cSMasatake YAMATO {
4506d5e6de9cSMasatake YAMATO parserDefinition* lang;
4507d5e6de9cSMasatake YAMATO
4508d5e6de9cSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4509e02be843SMasatake YAMATO lang = LanguageTable [language].def;
4510d5e6de9cSMasatake YAMATO
4511d5e6de9cSMasatake YAMATO Assert (nth < lang->xpathFileSpecCount);
4512d5e6de9cSMasatake YAMATO return lang->xpathFileSpecs + nth;
4513d5e6de9cSMasatake YAMATO }
4514d5e6de9cSMasatake YAMATO
makeKindSeparatorsPseudoTags(const langType language,const ptagDesc * pdesc)4515ce990805SThomas Braun extern bool makeKindSeparatorsPseudoTags (const langType language,
4516c645eb4cSMasatake YAMATO const ptagDesc *pdesc)
4517ce8d2e8fSMasatake YAMATO {
45185510af75SMasatake YAMATO parserObject* parser;
4519ce8d2e8fSMasatake YAMATO parserDefinition* lang;
45205510af75SMasatake YAMATO struct kindControlBlock *kcb;
45215510af75SMasatake YAMATO kindDefinition *kind;
4522ce8d2e8fSMasatake YAMATO unsigned int kindCount;
4523e5f9cc19SMasatake YAMATO unsigned int i, j;
4524ce8d2e8fSMasatake YAMATO
4525ce990805SThomas Braun bool r = false;
4526ab9fd29dSMasatake YAMATO
4527ce8d2e8fSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
45285510af75SMasatake YAMATO parser = LanguageTable + language;
45295510af75SMasatake YAMATO lang = parser->def;
45305510af75SMasatake YAMATO kcb = parser->kindControlBlock;
45315510af75SMasatake YAMATO kindCount = countKinds(kcb);
4532ce8d2e8fSMasatake YAMATO
45335510af75SMasatake YAMATO if (kindCount == 0)
4534ab9fd29dSMasatake YAMATO return r;
4535ce8d2e8fSMasatake YAMATO
453602cadfe0SMasatake YAMATO vString *sepval = vStringNew();
4537ce8d2e8fSMasatake YAMATO for (i = 0; i < kindCount; ++i)
4538ce8d2e8fSMasatake YAMATO {
45395510af75SMasatake YAMATO kind = getKind (kcb, i);
45405510af75SMasatake YAMATO for (j = 0; j < kind->separatorCount; ++j)
4541ce8d2e8fSMasatake YAMATO {
45422ea43882SMasatake YAMATO char name[3] = {[1] = '\0', [2] = '\0'};
4543e112e8abSMasatake YAMATO const kindDefinition *upperKind;
4544ce8d2e8fSMasatake YAMATO const scopeSeparator *sep;
4545ce8d2e8fSMasatake YAMATO
45465510af75SMasatake YAMATO sep = kind->separators + j;
4547ce8d2e8fSMasatake YAMATO
4548f92e6bf2SMasatake YAMATO if (sep->parentKindIndex == KIND_WILDCARD_INDEX)
4549e9e86f51SMasatake YAMATO {
45502ea43882SMasatake YAMATO name[0] = KIND_WILDCARD_LETTER;
45512ea43882SMasatake YAMATO name[1] = kind->letter;
4552e9e86f51SMasatake YAMATO }
4553f92e6bf2SMasatake YAMATO else if (sep->parentKindIndex == KIND_GHOST_INDEX)
4554e9e86f51SMasatake YAMATO {
4555e9e86f51SMasatake YAMATO /* This is root separator: no upper item is here. */
45562ea43882SMasatake YAMATO name[0] = kind->letter;
4557e9e86f51SMasatake YAMATO }
4558ce8d2e8fSMasatake YAMATO else
4559ce8d2e8fSMasatake YAMATO {
4560f92e6bf2SMasatake YAMATO upperKind = getLanguageKind (language,
4561f92e6bf2SMasatake YAMATO sep->parentKindIndex);
4562ce8d2e8fSMasatake YAMATO if (!upperKind)
4563ce8d2e8fSMasatake YAMATO continue;
4564ce8d2e8fSMasatake YAMATO
45652ea43882SMasatake YAMATO name[0] = upperKind->letter;
45662ea43882SMasatake YAMATO name[1] = kind->letter;
4567e9e86f51SMasatake YAMATO }
4568e9e86f51SMasatake YAMATO
4569ce8d2e8fSMasatake YAMATO
4570ce8d2e8fSMasatake YAMATO vStringClear (sepval);
4571ce8d2e8fSMasatake YAMATO vStringCatSWithEscaping (sepval, sep->separator);
4572ce8d2e8fSMasatake YAMATO
4573ab9fd29dSMasatake YAMATO r = writePseudoTag (pdesc, vStringValue (sepval),
4574ab9fd29dSMasatake YAMATO name, lang->name) || r;
4575ce8d2e8fSMasatake YAMATO }
4576ce8d2e8fSMasatake YAMATO }
457702cadfe0SMasatake YAMATO vStringDelete (sepval);
4578ab9fd29dSMasatake YAMATO
4579ab9fd29dSMasatake YAMATO return r;
4580ce8d2e8fSMasatake YAMATO }
4581ce8d2e8fSMasatake YAMATO
4582e362e918SMasatake YAMATO struct makeKindDescriptionPseudoTagData {
4583e362e918SMasatake YAMATO const char* langName;
4584c645eb4cSMasatake YAMATO const ptagDesc *pdesc;
4585ce990805SThomas Braun bool written;
4586e362e918SMasatake YAMATO };
4587e362e918SMasatake YAMATO
makeKindDescriptionPseudoTag(kindDefinition * kind,void * user_data)4588e112e8abSMasatake YAMATO static bool makeKindDescriptionPseudoTag (kindDefinition *kind,
4589e362e918SMasatake YAMATO void *user_data)
4590e362e918SMasatake YAMATO {
4591e362e918SMasatake YAMATO struct makeKindDescriptionPseudoTagData *data = user_data;
4592e362e918SMasatake YAMATO vString *letter_and_name;
4593e362e918SMasatake YAMATO vString *description;
45942b2809eaSMasatake YAMATO const char *d;
4595e362e918SMasatake YAMATO
4596e362e918SMasatake YAMATO letter_and_name = vStringNew ();
4597e362e918SMasatake YAMATO description = vStringNew ();
4598e362e918SMasatake YAMATO
4599e362e918SMasatake YAMATO vStringPut (letter_and_name, kind -> letter);
4600e362e918SMasatake YAMATO vStringPut (letter_and_name, ',');
4601e362e918SMasatake YAMATO vStringCatS (letter_and_name, kind -> name);
4602e362e918SMasatake YAMATO
46032b2809eaSMasatake YAMATO d = kind->description? kind->description: kind->name;
46042b2809eaSMasatake YAMATO vStringCatSWithEscapingAsPattern (description, d);
4605ab9fd29dSMasatake YAMATO data->written |= writePseudoTag (data->pdesc, vStringValue (letter_and_name),
4606e362e918SMasatake YAMATO vStringValue (description),
4607e362e918SMasatake YAMATO data->langName);
4608e362e918SMasatake YAMATO
4609e362e918SMasatake YAMATO vStringDelete (description);
4610e362e918SMasatake YAMATO vStringDelete (letter_and_name);
4611e362e918SMasatake YAMATO
4612ce990805SThomas Braun return false;
4613e362e918SMasatake YAMATO }
4614e362e918SMasatake YAMATO
makeRoleDescriptionPseudoTag(kindDefinition * kind,roleDefinition * role,void * user_data)4615cea85fadSMasatake YAMATO static bool makeRoleDescriptionPseudoTag (kindDefinition *kind,
4616cea85fadSMasatake YAMATO roleDefinition *role,
4617cea85fadSMasatake YAMATO void *user_data)
4618cea85fadSMasatake YAMATO {
4619cea85fadSMasatake YAMATO struct makeKindDescriptionPseudoTagData *data = user_data;
4620cea85fadSMasatake YAMATO
4621cea85fadSMasatake YAMATO vString *parser_and_kind_name = vStringNewInit (data->langName);
4622cea85fadSMasatake YAMATO vStringCatS (parser_and_kind_name, PSEUDO_TAG_SEPARATOR);
4623cea85fadSMasatake YAMATO vStringCatS (parser_and_kind_name, kind->name);
4624cea85fadSMasatake YAMATO
4625cea85fadSMasatake YAMATO vString *description = vStringNew ();
4626cea85fadSMasatake YAMATO const char *d = role->description? role->description: role->name;
4627cea85fadSMasatake YAMATO vStringCatSWithEscapingAsPattern (description, d);
4628cea85fadSMasatake YAMATO
4629cea85fadSMasatake YAMATO data->written |= writePseudoTag (data->pdesc, role->name,
4630cea85fadSMasatake YAMATO vStringValue (description),
4631cea85fadSMasatake YAMATO vStringValue (parser_and_kind_name));
4632cea85fadSMasatake YAMATO
4633cea85fadSMasatake YAMATO vStringDelete (description);
4634cea85fadSMasatake YAMATO vStringDelete (parser_and_kind_name);
4635cea85fadSMasatake YAMATO
4636cea85fadSMasatake YAMATO return false;
4637cea85fadSMasatake YAMATO }
4638cea85fadSMasatake YAMATO
makeKindDescriptionsPseudoTags(const langType language,const ptagDesc * pdesc)4639ce990805SThomas Braun extern bool makeKindDescriptionsPseudoTags (const langType language,
4640c645eb4cSMasatake YAMATO const ptagDesc *pdesc)
4641e362e918SMasatake YAMATO {
46427b543634SMasatake YAMATO parserObject *parser;
46437b543634SMasatake YAMATO struct kindControlBlock *kcb;
4644e362e918SMasatake YAMATO parserDefinition* lang;
46457b543634SMasatake YAMATO kindDefinition *kind;
4646e362e918SMasatake YAMATO unsigned int kindCount, i;
4647e362e918SMasatake YAMATO struct makeKindDescriptionPseudoTagData data;
4648e362e918SMasatake YAMATO
4649e362e918SMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
46507b543634SMasatake YAMATO parser = LanguageTable + language;
46517b543634SMasatake YAMATO kcb = parser->kindControlBlock;
46527b543634SMasatake YAMATO lang = parser->def;
46537b543634SMasatake YAMATO
46547b543634SMasatake YAMATO kindCount = countKinds(kcb);
4655e362e918SMasatake YAMATO
4656e362e918SMasatake YAMATO data.langName = lang->name;
4657e362e918SMasatake YAMATO data.pdesc = pdesc;
4658ce990805SThomas Braun data.written = false;
4659e362e918SMasatake YAMATO
4660e362e918SMasatake YAMATO for (i = 0; i < kindCount; ++i)
46617b543634SMasatake YAMATO {
4662fd0af0cfSMasatake YAMATO if (!isLanguageKindEnabled (language, i))
4663fd0af0cfSMasatake YAMATO continue;
4664fd0af0cfSMasatake YAMATO
46657b543634SMasatake YAMATO kind = getKind (kcb, i);
46667b543634SMasatake YAMATO makeKindDescriptionPseudoTag (kind, &data);
46677b543634SMasatake YAMATO }
4668e362e918SMasatake YAMATO
4669ab9fd29dSMasatake YAMATO return data.written;
4670e362e918SMasatake YAMATO }
4671e362e918SMasatake YAMATO
makeFieldDescriptionPseudoTag(const langType language,fieldType f,const ptagDesc * pdesc)46729ab0e076SMasatake YAMATO static bool makeFieldDescriptionPseudoTag (const langType language,
46739ab0e076SMasatake YAMATO fieldType f,
46749ab0e076SMasatake YAMATO const ptagDesc *pdesc)
46759ab0e076SMasatake YAMATO {
46769ab0e076SMasatake YAMATO vString *description;
46779ab0e076SMasatake YAMATO const char *name = getFieldName (f);
46789ab0e076SMasatake YAMATO
46799ab0e076SMasatake YAMATO if (name == NULL || name [0] == '\0')
46809ab0e076SMasatake YAMATO return false;
46819ab0e076SMasatake YAMATO
46829ab0e076SMasatake YAMATO description = vStringNew ();
46839ab0e076SMasatake YAMATO vStringCatSWithEscapingAsPattern (description,
46849ab0e076SMasatake YAMATO getFieldDescription (f));
46859ab0e076SMasatake YAMATO
46869ab0e076SMasatake YAMATO bool r = writePseudoTag (pdesc, name,
46879ab0e076SMasatake YAMATO vStringValue (description),
46889ab0e076SMasatake YAMATO language == LANG_IGNORE? NULL: getLanguageName (language));
46899ab0e076SMasatake YAMATO
46909ab0e076SMasatake YAMATO vStringDelete (description);
46919ab0e076SMasatake YAMATO return r;
46929ab0e076SMasatake YAMATO }
46939ab0e076SMasatake YAMATO
makeFieldDescriptionsPseudoTags(const langType language,const ptagDesc * pdesc)46949ab0e076SMasatake YAMATO extern bool makeFieldDescriptionsPseudoTags (const langType language,
46959ab0e076SMasatake YAMATO const ptagDesc *pdesc)
46969ab0e076SMasatake YAMATO {
46979ab0e076SMasatake YAMATO bool written = false;
46989ab0e076SMasatake YAMATO for (int i = 0; i < countFields (); i++)
46999ab0e076SMasatake YAMATO {
47009ab0e076SMasatake YAMATO if (getFieldOwner (i) == language
47019ab0e076SMasatake YAMATO && isFieldEnabled (i))
47029ab0e076SMasatake YAMATO {
47039ab0e076SMasatake YAMATO if (makeFieldDescriptionPseudoTag (language, i, pdesc))
47049ab0e076SMasatake YAMATO written = true;
47059ab0e076SMasatake YAMATO }
47069ab0e076SMasatake YAMATO }
47079ab0e076SMasatake YAMATO return written;
47089ab0e076SMasatake YAMATO }
47099ab0e076SMasatake YAMATO
makeExtraDescriptionPseudoTag(const langType language,xtagType x,const ptagDesc * pdesc)4710726cac0cSMasatake YAMATO static bool makeExtraDescriptionPseudoTag (const langType language,
4711726cac0cSMasatake YAMATO xtagType x,
4712726cac0cSMasatake YAMATO const ptagDesc *pdesc)
4713726cac0cSMasatake YAMATO {
4714726cac0cSMasatake YAMATO vString *description;
4715726cac0cSMasatake YAMATO const char *name = getXtagName (x);
4716726cac0cSMasatake YAMATO
4717726cac0cSMasatake YAMATO if (name == NULL || name [0] == '\0')
4718726cac0cSMasatake YAMATO return false;
4719726cac0cSMasatake YAMATO
4720726cac0cSMasatake YAMATO description = vStringNew ();
4721726cac0cSMasatake YAMATO vStringCatSWithEscapingAsPattern (description,
4722726cac0cSMasatake YAMATO getXtagDescription (x));
4723726cac0cSMasatake YAMATO
4724726cac0cSMasatake YAMATO bool r = writePseudoTag (pdesc, name,
4725726cac0cSMasatake YAMATO vStringValue (description),
4726726cac0cSMasatake YAMATO language == LANG_IGNORE? NULL: getLanguageName (language));
4727726cac0cSMasatake YAMATO
4728726cac0cSMasatake YAMATO vStringDelete (description);
4729726cac0cSMasatake YAMATO return r;
4730726cac0cSMasatake YAMATO }
4731726cac0cSMasatake YAMATO
makeExtraDescriptionsPseudoTags(const langType language,const ptagDesc * pdesc)4732726cac0cSMasatake YAMATO extern bool makeExtraDescriptionsPseudoTags (const langType language,
4733726cac0cSMasatake YAMATO const ptagDesc *pdesc)
4734726cac0cSMasatake YAMATO {
4735726cac0cSMasatake YAMATO bool written = false;
4736726cac0cSMasatake YAMATO for (int i = 0; i < countXtags (); i++)
4737726cac0cSMasatake YAMATO {
4738726cac0cSMasatake YAMATO if (getXtagOwner (i) == language
4739726cac0cSMasatake YAMATO && isXtagEnabled (i))
4740726cac0cSMasatake YAMATO {
4741726cac0cSMasatake YAMATO if (makeExtraDescriptionPseudoTag (language, i, pdesc))
4742726cac0cSMasatake YAMATO written = true;
4743726cac0cSMasatake YAMATO }
4744726cac0cSMasatake YAMATO }
4745726cac0cSMasatake YAMATO return written;
4746726cac0cSMasatake YAMATO }
4747726cac0cSMasatake YAMATO
makeRoleDescriptionsPseudoTags(const langType language,const ptagDesc * pdesc)4748cea85fadSMasatake YAMATO extern bool makeRoleDescriptionsPseudoTags (const langType language,
4749cea85fadSMasatake YAMATO const ptagDesc *pdesc)
4750cea85fadSMasatake YAMATO {
4751cea85fadSMasatake YAMATO parserObject *parser;
4752cea85fadSMasatake YAMATO struct kindControlBlock *kcb;
4753cea85fadSMasatake YAMATO parserDefinition* lang;
4754cea85fadSMasatake YAMATO kindDefinition *kind;
4755cea85fadSMasatake YAMATO struct makeKindDescriptionPseudoTagData data;
4756cea85fadSMasatake YAMATO
4757cea85fadSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
4758cea85fadSMasatake YAMATO parser = LanguageTable + language;
4759cea85fadSMasatake YAMATO kcb = parser->kindControlBlock;
4760cea85fadSMasatake YAMATO lang = parser->def;
4761cea85fadSMasatake YAMATO
4762cea85fadSMasatake YAMATO unsigned int kindCount = countKinds(kcb);
4763cea85fadSMasatake YAMATO
4764cea85fadSMasatake YAMATO data.langName = lang->name;
4765cea85fadSMasatake YAMATO data.pdesc = pdesc;
4766cea85fadSMasatake YAMATO data.written = false;
4767cea85fadSMasatake YAMATO
4768cea85fadSMasatake YAMATO for (unsigned int i = 0; i < kindCount; ++i)
4769cea85fadSMasatake YAMATO {
4770cea85fadSMasatake YAMATO if (!isLanguageKindEnabled (language, i))
4771cea85fadSMasatake YAMATO continue;
4772cea85fadSMasatake YAMATO
4773cea85fadSMasatake YAMATO kind = getKind (kcb, i);
4774cea85fadSMasatake YAMATO
4775cea85fadSMasatake YAMATO unsigned int roleCount = countRoles (kcb, i);
4776cea85fadSMasatake YAMATO for (unsigned int j = 0; j < roleCount; ++j)
4777cea85fadSMasatake YAMATO {
4778cea85fadSMasatake YAMATO if (isRoleEnabled (kcb, i, j))
4779cea85fadSMasatake YAMATO {
4780cea85fadSMasatake YAMATO roleDefinition *role = getRole (kcb, i, j);
4781cea85fadSMasatake YAMATO makeRoleDescriptionPseudoTag (kind, role, &data);
4782cea85fadSMasatake YAMATO }
4783cea85fadSMasatake YAMATO }
4784cea85fadSMasatake YAMATO }
4785cea85fadSMasatake YAMATO
4786cea85fadSMasatake YAMATO return data.written;
4787cea85fadSMasatake YAMATO }
4788cea85fadSMasatake YAMATO
4789e7283d01SMasatake YAMATO /*
4790d1437c58SMasatake YAMATO * Copyright (c) 2016, Szymon Tomasz Stefanek
4791d1437c58SMasatake YAMATO *
4792d1437c58SMasatake YAMATO * This source code is released for free distribution under the terms of the
4793d1437c58SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
4794d1437c58SMasatake YAMATO *
4795d1437c58SMasatake YAMATO * Anonymous name generator
4796d1437c58SMasatake YAMATO */
479787b7bfceSMasatake YAMATO static ptrArray *parsersUsedInCurrentInput;
4798d1437c58SMasatake YAMATO
setupAnon(void)479987b7bfceSMasatake YAMATO static void setupAnon (void)
4800d1437c58SMasatake YAMATO {
48013c91b1eaSMasatake YAMATO parsersUsedInCurrentInput = ptrArrayNew (NULL);
48023c91b1eaSMasatake YAMATO }
48033c91b1eaSMasatake YAMATO
teardownAnon(void)480487b7bfceSMasatake YAMATO static void teardownAnon (void)
480587b7bfceSMasatake YAMATO {
480687b7bfceSMasatake YAMATO ptrArrayDelete (parsersUsedInCurrentInput);
480787b7bfceSMasatake YAMATO }
480887b7bfceSMasatake YAMATO
anonResetMaybe(parserObject * parser)480997a77b13SMasatake YAMATO static void anonResetMaybe (parserObject *parser)
48103c91b1eaSMasatake YAMATO {
481197a77b13SMasatake YAMATO if (ptrArrayHas (parsersUsedInCurrentInput, parser))
48123c91b1eaSMasatake YAMATO return;
48133c91b1eaSMasatake YAMATO
481497a77b13SMasatake YAMATO parser -> anonymousIdentiferId = 0;
481597a77b13SMasatake YAMATO ptrArrayAdd (parsersUsedInCurrentInput, parser);
4816d1437c58SMasatake YAMATO }
4817d1437c58SMasatake YAMATO
anonHash(const unsigned char * str)4818d1437c58SMasatake YAMATO static unsigned int anonHash(const unsigned char *str)
4819d1437c58SMasatake YAMATO {
4820d1437c58SMasatake YAMATO unsigned int hash = 5381;
4821d1437c58SMasatake YAMATO int c;
4822d1437c58SMasatake YAMATO
4823d1437c58SMasatake YAMATO while((c = *str++))
4824d1437c58SMasatake YAMATO hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
4825d1437c58SMasatake YAMATO
4826d1437c58SMasatake YAMATO return hash ;
4827d1437c58SMasatake YAMATO }
4828d1437c58SMasatake YAMATO
anonHashString(const char * filename,char buf[9])48292b15528aSMasatake YAMATO extern void anonHashString (const char *filename, char buf[9])
48302b15528aSMasatake YAMATO {
48312b15528aSMasatake YAMATO sprintf(buf, "%08x", anonHash((const unsigned char *)filename));
48322b15528aSMasatake YAMATO }
48332b15528aSMasatake YAMATO
48342b15528aSMasatake YAMATO
anonConcat(vString * buffer,int kind)4835a13d8d73SMasatake YAMATO extern void anonConcat (vString *buffer, int kind)
4836a13d8d73SMasatake YAMATO {
4837a13d8d73SMasatake YAMATO anonGenerate (buffer, NULL, kind);
4838a13d8d73SMasatake YAMATO }
4839a13d8d73SMasatake YAMATO
anonGenerate(vString * buffer,const char * prefix,int kind)4840d1437c58SMasatake YAMATO extern void anonGenerate (vString *buffer, const char *prefix, int kind)
4841d1437c58SMasatake YAMATO {
484297a77b13SMasatake YAMATO parserObject* parser = LanguageTable + getInputLanguage ();
484397a77b13SMasatake YAMATO parser -> anonymousIdentiferId ++;
4844d1437c58SMasatake YAMATO
4845d1437c58SMasatake YAMATO char szNum[32];
48462b15528aSMasatake YAMATO char buf [9];
4847d1437c58SMasatake YAMATO
4848a13d8d73SMasatake YAMATO if (prefix)
4849d1437c58SMasatake YAMATO vStringCopyS(buffer, prefix);
4850d1437c58SMasatake YAMATO
48512b15528aSMasatake YAMATO anonHashString (getInputFileName(), buf);
48522b15528aSMasatake YAMATO sprintf(szNum,"%s%02x%02x",buf,parser -> anonymousIdentiferId, kind);
4853d1437c58SMasatake YAMATO vStringCatS(buffer,szNum);
4854d1437c58SMasatake YAMATO }
4855d1437c58SMasatake YAMATO
anonGenerateNew(const char * prefix,int kind)485622f2e7c1SMasatake YAMATO extern vString *anonGenerateNew (const char *prefix, int kind)
485722f2e7c1SMasatake YAMATO {
485822f2e7c1SMasatake YAMATO vString *buffer = vStringNew ();
485922f2e7c1SMasatake YAMATO
486022f2e7c1SMasatake YAMATO anonGenerate (buffer, prefix, kind);
486122f2e7c1SMasatake YAMATO return buffer;
486222f2e7c1SMasatake YAMATO }
486322f2e7c1SMasatake YAMATO
48644d6cdcecSMasatake YAMATO
applyParameter(const langType language,const char * name,const char * args)48654d6cdcecSMasatake YAMATO extern void applyParameter (const langType language, const char *name, const char *args)
48664d6cdcecSMasatake YAMATO {
48674d6cdcecSMasatake YAMATO parserDefinition* parser;
48684d6cdcecSMasatake YAMATO
48694d6cdcecSMasatake YAMATO
48704d6cdcecSMasatake YAMATO Assert (0 <= language && language < (int) LanguageCount);
48714d6cdcecSMasatake YAMATO
48724d6cdcecSMasatake YAMATO initializeParserOne (language);
4873e02be843SMasatake YAMATO parser = LanguageTable [language].def;
48744d6cdcecSMasatake YAMATO
48754d6cdcecSMasatake YAMATO if (parser->parameterHandlerTable)
48764d6cdcecSMasatake YAMATO {
48774d6cdcecSMasatake YAMATO unsigned int i;
48784d6cdcecSMasatake YAMATO
48794d6cdcecSMasatake YAMATO for (i = 0; i < parser->parameterHandlerCount; i++)
48804d6cdcecSMasatake YAMATO {
48814d6cdcecSMasatake YAMATO if (strcmp (parser->parameterHandlerTable [i].name, name) == 0)
48824d6cdcecSMasatake YAMATO {
48834d6cdcecSMasatake YAMATO parser->parameterHandlerTable [i].handleParameter (language, name, args);
48844d6cdcecSMasatake YAMATO return;
48854d6cdcecSMasatake YAMATO }
48864d6cdcecSMasatake YAMATO }
48874d6cdcecSMasatake YAMATO }
48884d6cdcecSMasatake YAMATO
48894d6cdcecSMasatake YAMATO error (FATAL, "no such parameter in %s: %s", parser->name, name);
48904d6cdcecSMasatake YAMATO }
48914d6cdcecSMasatake YAMATO
getNextSubparser(subparser * last,bool includingNoneCraftedParser)489211358a9dSMasatake YAMATO extern subparser *getNextSubparser(subparser *last,
489311358a9dSMasatake YAMATO bool includingNoneCraftedParser)
4894a53e10d8SMasatake YAMATO {
4895a53e10d8SMasatake YAMATO langType lang = getInputLanguage ();
4896faa60990SMasatake YAMATO parserObject *parser = LanguageTable + lang;
489791ee7ae2SMasatake YAMATO subparser *r;
489891ee7ae2SMasatake YAMATO langType t;
4899a53e10d8SMasatake YAMATO
4900a53e10d8SMasatake YAMATO if (last == NULL)
4901edc12faeSMasatake YAMATO r = getFirstSubparser(parser->slaveControlBlock);
4902a53e10d8SMasatake YAMATO else
490391ee7ae2SMasatake YAMATO r = last->next;
490491ee7ae2SMasatake YAMATO
490591ee7ae2SMasatake YAMATO if (r == NULL)
490691ee7ae2SMasatake YAMATO return r;
490791ee7ae2SMasatake YAMATO
490891ee7ae2SMasatake YAMATO t = getSubparserLanguage(r);
490911358a9dSMasatake YAMATO if (isLanguageEnabled (t) &&
491011358a9dSMasatake YAMATO (includingNoneCraftedParser
49111593689dSMasatake YAMATO || ((((LanguageTable + t)->def->method) & METHOD_NOT_CRAFTED) == 0)))
491291ee7ae2SMasatake YAMATO return r;
491391ee7ae2SMasatake YAMATO else
491411358a9dSMasatake YAMATO return getNextSubparser (r, includingNoneCraftedParser);
4915a53e10d8SMasatake YAMATO }
4916a53e10d8SMasatake YAMATO
getNextSlaveParser(slaveParser * last)4917c9ab038cSMasatake YAMATO extern slaveParser *getNextSlaveParser(slaveParser *last)
4918c9ab038cSMasatake YAMATO {
4919c9ab038cSMasatake YAMATO langType lang = getInputLanguage ();
4920c9ab038cSMasatake YAMATO parserObject *parser = LanguageTable + lang;
4921c9ab038cSMasatake YAMATO slaveParser *r;
4922c9ab038cSMasatake YAMATO
4923c9ab038cSMasatake YAMATO if (last == NULL)
4924c9ab038cSMasatake YAMATO r = getFirstSlaveParser(parser->slaveControlBlock);
4925c9ab038cSMasatake YAMATO else
4926c9ab038cSMasatake YAMATO r = last->next;
4927c9ab038cSMasatake YAMATO
4928c9ab038cSMasatake YAMATO return r;
4929c9ab038cSMasatake YAMATO }
4930c9ab038cSMasatake YAMATO
scheduleRunningBaseparser(int dependencyIndex)4931a53e10d8SMasatake YAMATO extern void scheduleRunningBaseparser (int dependencyIndex)
4932a53e10d8SMasatake YAMATO {
4933a53e10d8SMasatake YAMATO langType current = getInputLanguage ();
4934e02be843SMasatake YAMATO parserDefinition *current_parser = LanguageTable [current].def;
4935a53e10d8SMasatake YAMATO parserDependency *dep = NULL;
4936a53e10d8SMasatake YAMATO
4937a53e10d8SMasatake YAMATO if (dependencyIndex == RUN_DEFAULT_SUBPARSERS)
4938a53e10d8SMasatake YAMATO {
493946ab94ccSMasatake YAMATO for (unsigned int i = 0; i < current_parser->dependencyCount; ++i)
4940a53e10d8SMasatake YAMATO if (current_parser->dependencies[i].type == DEPTYPE_SUBPARSER)
4941a53e10d8SMasatake YAMATO {
4942a53e10d8SMasatake YAMATO dep = current_parser->dependencies + i;
4943a53e10d8SMasatake YAMATO break;
4944a53e10d8SMasatake YAMATO }
4945a53e10d8SMasatake YAMATO }
4946a53e10d8SMasatake YAMATO else
4947a53e10d8SMasatake YAMATO dep = current_parser->dependencies + dependencyIndex;
4948a53e10d8SMasatake YAMATO
4949a53e10d8SMasatake YAMATO if (dep == NULL)
4950a53e10d8SMasatake YAMATO return;
4951a53e10d8SMasatake YAMATO
4952a53e10d8SMasatake YAMATO const char *base_name = dep->upperParser;
4953a53e10d8SMasatake YAMATO langType base = getNamedLanguage (base_name, 0);
4954a5489f2eSMasatake YAMATO parserObject *base_parser = LanguageTable + base;
4955a53e10d8SMasatake YAMATO
4956a53e10d8SMasatake YAMATO if (dependencyIndex == RUN_DEFAULT_SUBPARSERS)
4957edc12faeSMasatake YAMATO useDefaultSubparsers(base_parser->slaveControlBlock);
4958a53e10d8SMasatake YAMATO else
4959edc12faeSMasatake YAMATO useSpecifiedSubparser (base_parser->slaveControlBlock,
4960edc12faeSMasatake YAMATO dep->data);
4961a53e10d8SMasatake YAMATO
4962f91acbe7SMasatake YAMATO if (!isLanguageEnabled (base))
4963f91acbe7SMasatake YAMATO {
4964f91acbe7SMasatake YAMATO enableLanguage (base, true);
4965f91acbe7SMasatake YAMATO base_parser->dontEmit = true;
4966a5489f2eSMasatake YAMATO verbose ("force enable \"%s\" as base parser\n", base_parser->def->name);
4967f91acbe7SMasatake YAMATO }
4968f91acbe7SMasatake YAMATO
4969a53e10d8SMasatake YAMATO {
4970a53e10d8SMasatake YAMATO subparser *tmp;
4971a53e10d8SMasatake YAMATO
4972a53e10d8SMasatake YAMATO verbose ("scheduleRunningBaseparser %s with subparsers: ", base_name);
4973a53e10d8SMasatake YAMATO pushLanguage (base);
497411358a9dSMasatake YAMATO foreachSubparser(tmp, true)
4975b2ee2118SMasatake YAMATO {
4976b2ee2118SMasatake YAMATO langType t = getSubparserLanguage (tmp);
4977b2ee2118SMasatake YAMATO verbose ("%s ", getLanguageName (t));
4978b2ee2118SMasatake YAMATO }
4979a53e10d8SMasatake YAMATO popLanguage ();
4980a53e10d8SMasatake YAMATO verbose ("\n");
4981a53e10d8SMasatake YAMATO }
4982a53e10d8SMasatake YAMATO
4983a53e10d8SMasatake YAMATO
4984a53e10d8SMasatake YAMATO makePromise(base_name, THIN_STREAM_SPEC);
4985a53e10d8SMasatake YAMATO }
4986a53e10d8SMasatake YAMATO
isParserMarkedNoEmission(void)4987f91acbe7SMasatake YAMATO extern bool isParserMarkedNoEmission (void)
4988f91acbe7SMasatake YAMATO {
4989f91acbe7SMasatake YAMATO langType lang = getInputLanguage();
4990a5489f2eSMasatake YAMATO parserObject *parser = LanguageTable + lang;
4991f91acbe7SMasatake YAMATO
4992f91acbe7SMasatake YAMATO return parser->dontEmit;
4993f91acbe7SMasatake YAMATO }
4994f91acbe7SMasatake YAMATO
4995a53e10d8SMasatake YAMATO
getSubparserRunningBaseparser(void)4996a53e10d8SMasatake YAMATO extern subparser* getSubparserRunningBaseparser (void)
4997a53e10d8SMasatake YAMATO {
4998a53e10d8SMasatake YAMATO langType current = getInputLanguage ();
4999faa60990SMasatake YAMATO parserObject *current_parser = LanguageTable + current;
5000edc12faeSMasatake YAMATO subparser *s = getFirstSubparser (current_parser->slaveControlBlock);
5001a53e10d8SMasatake YAMATO
5002a53e10d8SMasatake YAMATO if (s && s->schedulingBaseparserExplicitly)
5003a53e10d8SMasatake YAMATO return s;
5004a53e10d8SMasatake YAMATO else
5005a53e10d8SMasatake YAMATO return NULL;
5006a53e10d8SMasatake YAMATO }
5007a53e10d8SMasatake YAMATO
printLanguageSubparsers(const langType language,bool withListHeader,bool machinable,FILE * fp)5008406a9384SMasatake YAMATO extern void printLanguageSubparsers (const langType language,
5009406a9384SMasatake YAMATO bool withListHeader, bool machinable, FILE *fp)
5010410a34d6SMasatake YAMATO {
5011410a34d6SMasatake YAMATO for (int i = 0; i < (int) LanguageCount; i++)
5012410a34d6SMasatake YAMATO initializeParserOne (i);
5013410a34d6SMasatake YAMATO
5014406a9384SMasatake YAMATO struct colprintTable * table = subparserColprintTableNew();
5015406a9384SMasatake YAMATO parserObject *parser;
5016410a34d6SMasatake YAMATO
5017410a34d6SMasatake YAMATO if (language == LANG_AUTO)
5018410a34d6SMasatake YAMATO {
5019410a34d6SMasatake YAMATO for (int i = 0; i < (int) LanguageCount; i++)
5020406a9384SMasatake YAMATO {
5021406a9384SMasatake YAMATO parser = LanguageTable + i;
5022406a9384SMasatake YAMATO if (parser->def->invisible)
5023406a9384SMasatake YAMATO continue;
5024406a9384SMasatake YAMATO
5025406a9384SMasatake YAMATO subparserColprintAddSubparsers (table,
5026406a9384SMasatake YAMATO parser->slaveControlBlock);
5027406a9384SMasatake YAMATO }
5028410a34d6SMasatake YAMATO }
5029410a34d6SMasatake YAMATO else
5030406a9384SMasatake YAMATO {
5031406a9384SMasatake YAMATO parser = (LanguageTable + language);
5032406a9384SMasatake YAMATO subparserColprintAddSubparsers (table,
5033406a9384SMasatake YAMATO parser->slaveControlBlock);
5034406a9384SMasatake YAMATO }
5035406a9384SMasatake YAMATO
5036406a9384SMasatake YAMATO subparserColprintTablePrint (table,
5037406a9384SMasatake YAMATO withListHeader, machinable,
5038406a9384SMasatake YAMATO fp);
5039406a9384SMasatake YAMATO colprintTableDelete (table);
5040410a34d6SMasatake YAMATO }
5041410a34d6SMasatake YAMATO
printLangdefFlags(bool withListHeader,bool machinable,FILE * fp)5042d8539e07SMasatake YAMATO extern void printLangdefFlags (bool withListHeader, bool machinable, FILE *fp)
5043d8539e07SMasatake YAMATO {
5044d8539e07SMasatake YAMATO struct colprintTable * table;
5045d8539e07SMasatake YAMATO
5046d8539e07SMasatake YAMATO table = flagsColprintTableNew ();
5047d8539e07SMasatake YAMATO
5048d8539e07SMasatake YAMATO flagsColprintAddDefinitions (table, PreLangDefFlagDef, ARRAY_SIZE (PreLangDefFlagDef));
5049d8539e07SMasatake YAMATO
5050d8539e07SMasatake YAMATO flagsColprintTablePrint (table, withListHeader, machinable, fp);
5051d8539e07SMasatake YAMATO colprintTableDelete(table);
5052d8539e07SMasatake YAMATO }
5053d8539e07SMasatake YAMATO
printKinddefFlags(bool withListHeader,bool machinable,FILE * fp)5054e5d40a50SMasatake YAMATO extern void printKinddefFlags (bool withListHeader, bool machinable, FILE *fp)
5055e5d40a50SMasatake YAMATO {
5056e5d40a50SMasatake YAMATO struct colprintTable * table;
5057e5d40a50SMasatake YAMATO
5058e5d40a50SMasatake YAMATO table = flagsColprintTableNew ();
5059e5d40a50SMasatake YAMATO
5060e5d40a50SMasatake YAMATO flagsColprintAddDefinitions (table, PreKindDefFlagDef, ARRAY_SIZE (PreKindDefFlagDef));
5061e5d40a50SMasatake YAMATO
5062e5d40a50SMasatake YAMATO flagsColprintTablePrint (table, withListHeader, machinable, fp);
5063e5d40a50SMasatake YAMATO colprintTableDelete(table);
5064e5d40a50SMasatake YAMATO }
5065e5d40a50SMasatake YAMATO
printLanguageMultitableStatistics(langType language)5066d4318624SMasatake YAMATO extern void printLanguageMultitableStatistics (langType language)
50671e923193SMasatake YAMATO {
50681e923193SMasatake YAMATO parserObject* const parser = LanguageTable + language;
5069d4318624SMasatake YAMATO printMultitableStatistics (parser->lregexControlBlock);
50701e923193SMasatake YAMATO }
50711e923193SMasatake YAMATO
addLanguageRegexTable(const langType language,const char * name)507289c588f7SMasatake YAMATO extern void addLanguageRegexTable (const langType language, const char *name)
507389c588f7SMasatake YAMATO {
507489c588f7SMasatake YAMATO parserObject* const parser = LanguageTable + language;
507589c588f7SMasatake YAMATO addRegexTable (parser->lregexControlBlock, name);
507689c588f7SMasatake YAMATO }
507789c588f7SMasatake YAMATO
addLanguageTagMultiTableRegex(const langType language,const char * const table_name,const char * const regex,const char * const name,const char * const kinds,const char * const flags,bool * disabled)507889c588f7SMasatake YAMATO extern void addLanguageTagMultiTableRegex(const langType language,
507989c588f7SMasatake YAMATO const char* const table_name,
508089c588f7SMasatake YAMATO const char* const regex,
508189c588f7SMasatake YAMATO const char* const name, const char* const kinds, const char* const flags,
508289c588f7SMasatake YAMATO bool *disabled)
508389c588f7SMasatake YAMATO {
508489c588f7SMasatake YAMATO parserObject* const parser = LanguageTable + language;
508589c588f7SMasatake YAMATO addTagMultiTableRegex (parser->lregexControlBlock, table_name, regex,
508689c588f7SMasatake YAMATO name, kinds, flags, disabled);
508789c588f7SMasatake YAMATO }
508889c588f7SMasatake YAMATO
addLanguageOptscriptToHook(langType language,enum scriptHook hook,const char * const src)5089b6124a60SMasatake YAMATO extern void addLanguageOptscriptToHook (langType language, enum scriptHook hook, const char *const src)
50905c872341SMasatake YAMATO {
5091b6124a60SMasatake YAMATO addOptscriptToHook (LanguageTable [language].lregexControlBlock, hook, src);
50921409a195SMasatake YAMATO }
50931409a195SMasatake YAMATO
processHookOption(const char * const option,const char * const parameter,const char * prefix,enum scriptHook hook)50941409a195SMasatake YAMATO static bool processHookOption (const char *const option, const char *const parameter, const char *prefix,
5095b6124a60SMasatake YAMATO enum scriptHook hook)
50961409a195SMasatake YAMATO {
50971409a195SMasatake YAMATO langType language = getLanguageComponentInOption (option, prefix);
50985c872341SMasatake YAMATO if (language == LANG_IGNORE)
50995c872341SMasatake YAMATO return false;
51005c872341SMasatake YAMATO
51015c872341SMasatake YAMATO if (parameter == NULL || parameter[0] == '\0')
51025c872341SMasatake YAMATO error (FATAL, "A parameter is needed after \"%s\" option", option);
51035c872341SMasatake YAMATO
51045c872341SMasatake YAMATO const char * code = flagsEval (parameter, NULL, 0, NULL);
51055c872341SMasatake YAMATO if (code == NULL)
51065c872341SMasatake YAMATO error (FATAL, "Cannot recognized a code block surrounded by `{{' and `}}' after \"%s\" option", option);
5107b6124a60SMasatake YAMATO addLanguageOptscriptToHook (language, hook, code);
51085c872341SMasatake YAMATO
51095c872341SMasatake YAMATO return true;
51105c872341SMasatake YAMATO }
51115c872341SMasatake YAMATO
processPreludeOption(const char * const option,const char * const parameter)51121409a195SMasatake YAMATO extern bool processPreludeOption (const char *const option, const char *const parameter)
51131409a195SMasatake YAMATO {
5114b6124a60SMasatake YAMATO return processHookOption (option, parameter, "_prelude-", SCRIPT_HOOK_PRELUDE);
51151409a195SMasatake YAMATO }
51161409a195SMasatake YAMATO
processSequelOption(const char * const option,const char * const parameter)51171409a195SMasatake YAMATO extern bool processSequelOption (const char *const option, const char *const parameter)
51181409a195SMasatake YAMATO {
5119b6124a60SMasatake YAMATO return processHookOption (option, parameter, "_sequel-", SCRIPT_HOOK_SEQUEL);
51201409a195SMasatake YAMATO }
51211409a195SMasatake YAMATO
processPretendOption(const char * const option,const char * const parameter)5122f02166dcSMasatake YAMATO extern bool processPretendOption (const char *const option, const char *const parameter)
5123f02166dcSMasatake YAMATO {
5124f02166dcSMasatake YAMATO langType new_language, old_language;
5125f02166dcSMasatake YAMATO
5126f02166dcSMasatake YAMATO #define pretendOptionPrefix "_pretend-"
5127f02166dcSMasatake YAMATO new_language = getLanguageComponentInOptionFull (option, pretendOptionPrefix, true);
5128f02166dcSMasatake YAMATO if (new_language == LANG_IGNORE)
5129f02166dcSMasatake YAMATO return false;
5130f02166dcSMasatake YAMATO
5131f02166dcSMasatake YAMATO if (parameter == NULL || parameter[0] == '\0')
5132f02166dcSMasatake YAMATO error (FATAL, "A parameter is needed after \"%s\" option", option);
5133f02166dcSMasatake YAMATO
51349a391711SMasatake YAMATO old_language = getNamedLanguageFull (parameter, 0, true, false);
5135f02166dcSMasatake YAMATO if (old_language == LANG_IGNORE)
5136f02166dcSMasatake YAMATO error (FATAL, "Unknown language \"%s\" in option \"--%s=%s\"",
5137f02166dcSMasatake YAMATO parameter, option, parameter);
5138f02166dcSMasatake YAMATO
5139f02166dcSMasatake YAMATO if (LanguageTable [new_language].pretendingAsLanguage != LANG_IGNORE)
5140f02166dcSMasatake YAMATO {
5141f02166dcSMasatake YAMATO error (FATAL, "%s parser pretends as %s already\n",
5142f02166dcSMasatake YAMATO getLanguageNameFull (new_language, true),
5143f02166dcSMasatake YAMATO getLanguageNameFull (LanguageTable [new_language].pretendingAsLanguage, true));
5144f02166dcSMasatake YAMATO }
5145f02166dcSMasatake YAMATO if (LanguageTable [old_language].pretendedAsLanguage != LANG_IGNORE)
5146f02166dcSMasatake YAMATO {
5147f02166dcSMasatake YAMATO error (FATAL, "%s parser is pretended as %s already\n",
5148f02166dcSMasatake YAMATO getLanguageNameFull (old_language, true),
5149f02166dcSMasatake YAMATO getLanguageNameFull (LanguageTable [old_language].pretendedAsLanguage, true));
5150f02166dcSMasatake YAMATO }
5151f02166dcSMasatake YAMATO
5152f02166dcSMasatake YAMATO verbose ("%s pretends %s\n",
5153f02166dcSMasatake YAMATO getLanguageNameFull (new_language, true),
5154f02166dcSMasatake YAMATO getLanguageNameFull (old_language, true));
5155f02166dcSMasatake YAMATO
5156f02166dcSMasatake YAMATO LanguageTable [new_language].pretendingAsLanguage = old_language;
5157f02166dcSMasatake YAMATO LanguageTable [old_language].pretendedAsLanguage = new_language;
5158f02166dcSMasatake YAMATO
5159f02166dcSMasatake YAMATO verbose ("force enabling %s\n",
5160f02166dcSMasatake YAMATO getLanguageNameFull (new_language, true));
5161f02166dcSMasatake YAMATO enableLanguage (new_language, true);
5162f02166dcSMasatake YAMATO
5163351239a8SMasanari Iida verbose ("force disabling %s\n",
5164f02166dcSMasatake YAMATO getLanguageNameFull (old_language, true));
5165f02166dcSMasatake YAMATO enableLanguage (old_language, false);
5166f02166dcSMasatake YAMATO
5167f02166dcSMasatake YAMATO return true;
5168f02166dcSMasatake YAMATO }
5169f02166dcSMasatake YAMATO
getLanguageCorkUsage(langType lang)5170a64816f9SMasatake YAMATO extern unsigned int getLanguageCorkUsage (langType lang)
5171a64816f9SMasatake YAMATO {
5172a64816f9SMasatake YAMATO parserObject* const parser = LanguageTable + lang;
5173a64816f9SMasatake YAMATO return parserCorkFlags (parser->def);
5174a64816f9SMasatake YAMATO }
5175a64816f9SMasatake YAMATO
5176d1437c58SMasatake YAMATO /*
517782791c20SMasatake YAMATO * The universal fallback parser.
517882791c20SMasatake YAMATO * If any parser doesn't handle the input, this parser is
517982791c20SMasatake YAMATO * used for the input when --languages=+Unknown is given.
518082791c20SMasatake YAMATO * writer-etags enables this parser implicitly.
518182791c20SMasatake YAMATO */
FallbackParser(void)518282791c20SMasatake YAMATO static parserDefinition *FallbackParser (void)
518382791c20SMasatake YAMATO {
518482791c20SMasatake YAMATO parserDefinition *const def = parserNew ("Unknown");
518582791c20SMasatake YAMATO def->extensions = NULL;
518682791c20SMasatake YAMATO def->kindTable = NULL;
518782791c20SMasatake YAMATO def->kindCount = 0;
518882791c20SMasatake YAMATO
518982791c20SMasatake YAMATO /* A user can extend this parser with --regex-Unknown=...
519082791c20SMasatake YAMATO * or --langdef=MyParser{base=Unknown}.
519182791c20SMasatake YAMATO *
519282791c20SMasatake YAMATO * TODO: if following conditions are met, dontFindTags()
519382791c20SMasatake YAMATO * defined below can be used.
519482791c20SMasatake YAMATO * - any regex pattern is not defined,
519582791c20SMasatake YAMATO * - any sub parser is not defined, and
519682791c20SMasatake YAMATO * - end: field is not enabled.
519782791c20SMasatake YAMATO */
519882791c20SMasatake YAMATO def->parser = findRegexTags;
519982791c20SMasatake YAMATO def->enabled = 0;
520082791c20SMasatake YAMATO def->method = METHOD_REGEX;
520182791c20SMasatake YAMATO return def;
520282791c20SMasatake YAMATO }
520382791c20SMasatake YAMATO
520482791c20SMasatake YAMATO /*
5205b9636b4dSMasatake YAMATO * A dummy parser for printing pseudo tags in xref output
5206b9636b4dSMasatake YAMATO */
dontFindTags(void)5207b9636b4dSMasatake YAMATO static void dontFindTags (void)
5208b9636b4dSMasatake YAMATO {
5209b9636b4dSMasatake YAMATO }
5210b9636b4dSMasatake YAMATO
5211b9636b4dSMasatake YAMATO static kindDefinition CtagsKinds[] = {
5212b9636b4dSMasatake YAMATO {true, 'p', "ptag", "pseudo tags"},
5213b9636b4dSMasatake YAMATO };
5214b9636b4dSMasatake YAMATO
CTagsParser(void)5215b9636b4dSMasatake YAMATO static parserDefinition *CTagsParser (void)
5216b9636b4dSMasatake YAMATO {
5217b9636b4dSMasatake YAMATO parserDefinition *const def = parserNew ("UniversalCtags");
5218b9636b4dSMasatake YAMATO def->extensions = NULL;
5219b9636b4dSMasatake YAMATO def->kindTable = CtagsKinds;
5220b9636b4dSMasatake YAMATO def->kindCount = ARRAY_SIZE(CtagsKinds);
5221b9636b4dSMasatake YAMATO def->parser = dontFindTags;
5222b9636b4dSMasatake YAMATO def->invisible = true;
5223b9636b4dSMasatake YAMATO return def;
5224b9636b4dSMasatake YAMATO }
5225b9636b4dSMasatake YAMATO
5226b9636b4dSMasatake YAMATO /*
5227e7283d01SMasatake YAMATO * A parser for CTagsSelfTest (CTST)
5228e7283d01SMasatake YAMATO */
5229d3ee68cdSMasatake YAMATO #define SELF_TEST_PARSER "CTagsSelfTest"
523034826b73SMasatake YAMATO #if defined(DEBUG) && defined(HAVE_SECCOMP)
5231539991e1SMasatake YAMATO extern void getppid(void);
5232539991e1SMasatake YAMATO #endif
5233d3ee68cdSMasatake YAMATO
5234a9c91f4dSMasatake YAMATO static bool CTST_GatherStats;
5235a9c91f4dSMasatake YAMATO static int CTST_num_handled_char;
5236a9c91f4dSMasatake YAMATO
5237e7283d01SMasatake YAMATO typedef enum {
5238e7283d01SMasatake YAMATO K_BROKEN,
52397aeeb638SMasatake YAMATO K_NO_LETTER,
52407aeeb638SMasatake YAMATO K_NO_LONG_NAME,
5241d3ee68cdSMasatake YAMATO K_NOTHING_SPECIAL,
5242d3ee68cdSMasatake YAMATO K_GUEST_BEGINNING,
5243d3ee68cdSMasatake YAMATO K_GUEST_END,
524434826b73SMasatake YAMATO #if defined(DEBUG) && defined(HAVE_SECCOMP)
5245539991e1SMasatake YAMATO K_CALL_GETPPID,
5246539991e1SMasatake YAMATO #endif
5247bac26e10SMasatake YAMATO K_DISABLED,
5248bac26e10SMasatake YAMATO K_ENABLED,
5249f7ce3343SMasatake YAMATO K_ROLES,
5250f7ce3343SMasatake YAMATO K_ROLES_DISABLED,
52517b08b440SMasatake YAMATO K_FIELD_TESTING,
525256175ec1SMasatake YAMATO K_TRIGGER_NOTICE,
5253e7283d01SMasatake YAMATO KIND_COUNT
5254e7283d01SMasatake YAMATO } CTST_Kind;
5255e7283d01SMasatake YAMATO
5256a31f61c4SMasatake YAMATO typedef enum {
5257a31f61c4SMasatake YAMATO R_BROKEN_REF,
5258a31f61c4SMasatake YAMATO } CTST_BrokenRole;
5259a31f61c4SMasatake YAMATO
526013457258SMasatake YAMATO static roleDefinition CTST_BrokenRoles [] = {
5261ce990805SThomas Braun {true, "broken", "broken" },
5262a31f61c4SMasatake YAMATO };
5263a31f61c4SMasatake YAMATO
5264bac26e10SMasatake YAMATO typedef enum {
5265bac26e10SMasatake YAMATO R_DISABLED_KIND_DISABLED_ROLE,
5266bac26e10SMasatake YAMATO R_DISABLED_KIND_ENABLED_ROLE,
5267bac26e10SMasatake YAMATO } CTST_DisabledKindRole;
5268bac26e10SMasatake YAMATO
526913457258SMasatake YAMATO static roleDefinition CTST_DisabledKindRoles [] = {
5270351239a8SMasanari Iida { false, "disabled", "disabled role attached to disabled kind" },
5271bac26e10SMasatake YAMATO { true, "enabled", "enabled role attached to disabled kind" },
5272bac26e10SMasatake YAMATO };
5273bac26e10SMasatake YAMATO
5274bac26e10SMasatake YAMATO typedef enum {
5275bac26e10SMasatake YAMATO R_ENABLED_KIND_DISABLED_ROLE,
5276bac26e10SMasatake YAMATO R_ENABLED_KIND_ENABLED_ROLE,
5277bac26e10SMasatake YAMATO } CTST_EnabledKindRole;
5278bac26e10SMasatake YAMATO
527913457258SMasatake YAMATO static roleDefinition CTST_EnabledKindRoles [] = {
5280351239a8SMasanari Iida { false, "disabled", "disabled role attached to enabled kind" },
5281bac26e10SMasatake YAMATO { true, "enabled", "enabled role attached to enabled kind" },
5282bac26e10SMasatake YAMATO };
5283bac26e10SMasatake YAMATO
5284f7ce3343SMasatake YAMATO typedef enum {
5285f7ce3343SMasatake YAMATO R_ROLES_KIND_A_ROLE,
5286f7ce3343SMasatake YAMATO R_ROLES_KIND_B_ROLE,
5287f7ce3343SMasatake YAMATO R_ROLES_KIND_C_ROLE,
5288f7ce3343SMasatake YAMATO R_ROLES_KIND_D_ROLE,
5289f7ce3343SMasatake YAMATO } CTST_RolesKindRole;
5290f7ce3343SMasatake YAMATO
529113457258SMasatake YAMATO static roleDefinition CTST_RolesKindRoles [] = {
5292f7ce3343SMasatake YAMATO { true, "a", "A role" },
5293f7ce3343SMasatake YAMATO { true, "b", "B role" },
5294f7ce3343SMasatake YAMATO { false, "c", "C role" },
5295f7ce3343SMasatake YAMATO { true, "d", "D role" },
5296f7ce3343SMasatake YAMATO };
5297f7ce3343SMasatake YAMATO
5298f7ce3343SMasatake YAMATO typedef enum {
5299f7ce3343SMasatake YAMATO R_ROLES_DISABLED_KIND_A_ROLE,
5300f7ce3343SMasatake YAMATO R_ROLES_DISABLED_KIND_B_ROLE,
5301f7ce3343SMasatake YAMATO } CTST_RolesDisableKindRole;
5302f7ce3343SMasatake YAMATO
5303f7ce3343SMasatake YAMATO
530413457258SMasatake YAMATO static roleDefinition CTST_RolesDisabledKindRoles [] = {
5305f7ce3343SMasatake YAMATO { true, "A", "A role" },
5306f7ce3343SMasatake YAMATO { true, "B", "B role" },
5307f7ce3343SMasatake YAMATO };
5308f7ce3343SMasatake YAMATO
5309e112e8abSMasatake YAMATO static kindDefinition CTST_Kinds[KIND_COUNT] = {
53108c4e6d88SMasatake YAMATO /* `a' is reserved for kinddef testing */
5311ce990805SThomas Braun {true, 'b', "broken tag", "name with unwanted characters",
5312ce990805SThomas Braun .referenceOnly = false, ATTACH_ROLES (CTST_BrokenRoles) },
53137e1bd430SMasatake YAMATO {true, KIND_NULL_LETTER, "no letter", "kind with no letter"
53147aeeb638SMasatake YAMATO /* use '@' when testing. */
53157aeeb638SMasatake YAMATO },
53167aeeb638SMasatake YAMATO {true, 'L', NULL, "kind with no long name" },
5317d3ee68cdSMasatake YAMATO {true, 'N', "nothingSpecial", "emit a normal tag" },
5318d3ee68cdSMasatake YAMATO {true, 'B', NULL, "beginning of an area for a guest" },
5319d3ee68cdSMasatake YAMATO {true, 'E', NULL, "end of an area for a guest" },
532034826b73SMasatake YAMATO #if defined(DEBUG) && defined(HAVE_SECCOMP)
5321539991e1SMasatake YAMATO {true, 'P', "callGetPPid", "trigger calling getppid(2) that seccomp sandbox disallows"},
5322539991e1SMasatake YAMATO #endif
5323bac26e10SMasatake YAMATO {false,'d', "disabled", "a kind disabled by default",
5324bac26e10SMasatake YAMATO .referenceOnly = false, ATTACH_ROLES (CTST_DisabledKindRoles)},
5325bac26e10SMasatake YAMATO {true, 'e', "enabled", "a kind enabled by default",
5326bac26e10SMasatake YAMATO .referenceOnly = false, ATTACH_ROLES (CTST_EnabledKindRoles)},
5327f7ce3343SMasatake YAMATO {true, 'r', "roles", "emit a tag with multi roles",
5328f7ce3343SMasatake YAMATO .referenceOnly = true, ATTACH_ROLES (CTST_RolesKindRoles)},
5329f7ce3343SMasatake YAMATO {false, 'R', "rolesDisabled", "emit a tag with multi roles(disabled by default)",
5330f7ce3343SMasatake YAMATO .referenceOnly = true, ATTACH_ROLES (CTST_RolesDisabledKindRoles)},
53317b08b440SMasatake YAMATO {true, 'f', "fieldMaker", "tag for testing field:" },
533256175ec1SMasatake YAMATO {true, 'n', "triggerNotice", "trigger notice output"},
53337b08b440SMasatake YAMATO };
53347b08b440SMasatake YAMATO
53357b08b440SMasatake YAMATO typedef enum {
53367b08b440SMasatake YAMATO F_BOOLEAN_FIELD,
53377b08b440SMasatake YAMATO F_BOOLEAN_AND_STRING_FIELD,
53387b08b440SMasatake YAMATO COUNT_FIELD
53397b08b440SMasatake YAMATO } CTSTField;
53407b08b440SMasatake YAMATO
53417b08b440SMasatake YAMATO static fieldDefinition CTSTFields[COUNT_FIELD] = {
53427b08b440SMasatake YAMATO { .name = "bField",
53437b08b440SMasatake YAMATO .description = "field for testing boolean type",
53447b08b440SMasatake YAMATO .dataType = FIELDTYPE_BOOL,
53457b08b440SMasatake YAMATO .enabled = true,
53467b08b440SMasatake YAMATO },
53477b08b440SMasatake YAMATO { .name = "sbField",
53487b08b440SMasatake YAMATO .description = "field for testing string|boolean type",
53497b08b440SMasatake YAMATO .dataType = FIELDTYPE_STRING|FIELDTYPE_BOOL,
53507b08b440SMasatake YAMATO .enabled = true,
53517b08b440SMasatake YAMATO },
5352e7283d01SMasatake YAMATO };
5353e7283d01SMasatake YAMATO
createCTSTTags(void)5354e7283d01SMasatake YAMATO static void createCTSTTags (void)
5355e7283d01SMasatake YAMATO {
5356e7283d01SMasatake YAMATO int i;
5357e7283d01SMasatake YAMATO const unsigned char *line;
5358e7283d01SMasatake YAMATO tagEntryInfo e;
5359e7283d01SMasatake YAMATO
5360d3ee68cdSMasatake YAMATO unsigned long lb = 0;
5361d3ee68cdSMasatake YAMATO unsigned long le = 0;
5362d3ee68cdSMasatake YAMATO
5363bac26e10SMasatake YAMATO int found_enabled_disabled[2] = {0, 0};
5364bac26e10SMasatake YAMATO
5365e97e7d4aSMasatake YAMATO TRACE_ENTER_TEXT("Parsing starts");
5366e97e7d4aSMasatake YAMATO
53671b312fe7SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
5368e7283d01SMasatake YAMATO {
5369e7283d01SMasatake YAMATO int c = line[0];
5370e7283d01SMasatake YAMATO
5371e7283d01SMasatake YAMATO for (i = 0; i < KIND_COUNT; i++)
53727aeeb638SMasatake YAMATO if ((c == CTST_Kinds[i].letter && i != K_NO_LETTER)
53737aeeb638SMasatake YAMATO || (c == '@' && i == K_NO_LETTER))
5374e7283d01SMasatake YAMATO {
5375a9c91f4dSMasatake YAMATO if (CTST_GatherStats)
5376a9c91f4dSMasatake YAMATO CTST_num_handled_char++;
5377a9c91f4dSMasatake YAMATO
5378e7283d01SMasatake YAMATO switch (i)
5379e7283d01SMasatake YAMATO {
5380e7283d01SMasatake YAMATO case K_BROKEN:
538116a2541cSMasatake YAMATO initTagEntry (&e, "one\nof\rbroken\tname", i);
5382f92e6bf2SMasatake YAMATO e.extensionFields.scopeKindIndex = K_BROKEN;
5383f63d8d2cSMasatake YAMATO e.extensionFields.scopeName = "\\Broken\tContext";
5384e7283d01SMasatake YAMATO makeTagEntry (&e);
53850647c2a9SMasatake YAMATO initTagEntry (&e, "only\nnewline", i);
53860647c2a9SMasatake YAMATO makeTagEntry (&e);
53870647c2a9SMasatake YAMATO initTagEntry (&e, "only\ttab", i);
53880647c2a9SMasatake YAMATO makeTagEntry (&e);
53890647c2a9SMasatake YAMATO initTagEntry (&e, "newline-in-scope", i);
53900647c2a9SMasatake YAMATO e.extensionFields.scopeKindIndex = K_BROKEN;
53910647c2a9SMasatake YAMATO e.extensionFields.scopeName = "parent\nscope";
53920647c2a9SMasatake YAMATO makeTagEntry (&e);
53930647c2a9SMasatake YAMATO initTagEntry (&e, "tab-in-scope", i);
53940647c2a9SMasatake YAMATO e.extensionFields.scopeKindIndex = K_BROKEN;
53950647c2a9SMasatake YAMATO e.extensionFields.scopeName = "parent\tscope";
53960647c2a9SMasatake YAMATO makeTagEntry (&e);
5397e7283d01SMasatake YAMATO break;
53987aeeb638SMasatake YAMATO case K_NO_LETTER:
539916a2541cSMasatake YAMATO initTagEntry (&e, "abnormal kindDefinition testing (no letter)", i);
54007aeeb638SMasatake YAMATO makeTagEntry (&e);
54017aeeb638SMasatake YAMATO break;
54027aeeb638SMasatake YAMATO case K_NO_LONG_NAME:
540316a2541cSMasatake YAMATO initTagEntry (&e, "abnormal kindDefinition testing (no long name)", i);
54047aeeb638SMasatake YAMATO makeTagEntry (&e);
54057aeeb638SMasatake YAMATO break;
5406d3ee68cdSMasatake YAMATO case K_NOTHING_SPECIAL:
5407d3ee68cdSMasatake YAMATO if (!lb)
5408d3ee68cdSMasatake YAMATO {
540916a2541cSMasatake YAMATO initTagEntry (&e, "NOTHING_SPECIAL", i);
5410d3ee68cdSMasatake YAMATO makeTagEntry (&e);
5411d3ee68cdSMasatake YAMATO }
5412d3ee68cdSMasatake YAMATO break;
5413d3ee68cdSMasatake YAMATO case K_GUEST_BEGINNING:
5414d3ee68cdSMasatake YAMATO lb = getInputLineNumber ();
5415d3ee68cdSMasatake YAMATO break;
5416d3ee68cdSMasatake YAMATO case K_GUEST_END:
5417d3ee68cdSMasatake YAMATO le = getInputLineNumber ();
5418d3ee68cdSMasatake YAMATO makePromise (SELF_TEST_PARSER, lb + 1, 0, le, 0, lb + 1);
5419d3ee68cdSMasatake YAMATO break;
542034826b73SMasatake YAMATO #if defined(DEBUG) && defined(HAVE_SECCOMP)
5421539991e1SMasatake YAMATO case K_CALL_GETPPID:
5422539991e1SMasatake YAMATO getppid();
5423539991e1SMasatake YAMATO break;
5424539991e1SMasatake YAMATO #endif
5425bac26e10SMasatake YAMATO case K_DISABLED:
5426bac26e10SMasatake YAMATO case K_ENABLED:
5427bac26e10SMasatake YAMATO {
5428bac26e10SMasatake YAMATO int role;
5429bac26e10SMasatake YAMATO char *name;
5430bac26e10SMasatake YAMATO if (found_enabled_disabled[i == K_DISABLED]++ == 0)
5431bac26e10SMasatake YAMATO {
543224b256e3SMasatake YAMATO role = ROLE_DEFINITION_INDEX;
5433bac26e10SMasatake YAMATO name = (i == K_DISABLED)
5434bac26e10SMasatake YAMATO ? "disable-kind-no-role"
5435bac26e10SMasatake YAMATO : "enabled-kind-no-role";
5436bac26e10SMasatake YAMATO }
5437bac26e10SMasatake YAMATO else if (found_enabled_disabled[i == K_DISABLED]++ == 1)
5438bac26e10SMasatake YAMATO {
5439bac26e10SMasatake YAMATO role = (i == K_DISABLED)
5440bac26e10SMasatake YAMATO ? R_DISABLED_KIND_DISABLED_ROLE
5441bac26e10SMasatake YAMATO : R_ENABLED_KIND_DISABLED_ROLE;
5442bac26e10SMasatake YAMATO name = (i == K_DISABLED)
5443bac26e10SMasatake YAMATO ? "disable-kind-disabled-role"
5444bac26e10SMasatake YAMATO : "enabled-kind-disabled-role";
5445bac26e10SMasatake YAMATO }
5446bac26e10SMasatake YAMATO else
5447bac26e10SMasatake YAMATO {
5448bac26e10SMasatake YAMATO role = (i == K_DISABLED)
5449bac26e10SMasatake YAMATO ? R_DISABLED_KIND_ENABLED_ROLE
5450bac26e10SMasatake YAMATO : R_ENABLED_KIND_ENABLED_ROLE;
5451bac26e10SMasatake YAMATO name = (i == K_DISABLED)
5452bac26e10SMasatake YAMATO ? "disable-kind-enabled-role"
5453bac26e10SMasatake YAMATO : "enabled-kind-enabled-role";
5454bac26e10SMasatake YAMATO }
5455bac26e10SMasatake YAMATO initRefTagEntry (&e, name, i, role);
5456bac26e10SMasatake YAMATO makeTagEntry (&e);
5457bac26e10SMasatake YAMATO break;
5458bac26e10SMasatake YAMATO }
5459f7ce3343SMasatake YAMATO case K_ROLES:
5460f7ce3343SMasatake YAMATO {
5461f7ce3343SMasatake YAMATO char *name = "multiRolesTarget";
5462f7ce3343SMasatake YAMATO int qindex;
5463f7ce3343SMasatake YAMATO tagEntryInfo *qe;
5464f7ce3343SMasatake YAMATO
5465f7ce3343SMasatake YAMATO initTagEntry (&e, name, i);
5466f7ce3343SMasatake YAMATO assignRole(&e, R_ROLES_KIND_A_ROLE);
5467f7ce3343SMasatake YAMATO assignRole(&e, R_ROLES_KIND_C_ROLE);
5468f7ce3343SMasatake YAMATO assignRole(&e, R_ROLES_KIND_D_ROLE);
5469f7ce3343SMasatake YAMATO qindex = makeTagEntry (&e);
5470f7ce3343SMasatake YAMATO qe = getEntryInCorkQueue (qindex);
54713671ad72SMasatake YAMATO if (qe)
5472f7ce3343SMasatake YAMATO assignRole(qe, R_ROLES_KIND_B_ROLE);
5473f7ce3343SMasatake YAMATO break;
5474f7ce3343SMasatake YAMATO }
5475f7ce3343SMasatake YAMATO case K_ROLES_DISABLED:
5476f7ce3343SMasatake YAMATO {
5477f7ce3343SMasatake YAMATO char *name = "multiRolesDisabledTarget";
5478f7ce3343SMasatake YAMATO
5479f7ce3343SMasatake YAMATO initRefTagEntry (&e, name, i, R_ROLES_DISABLED_KIND_A_ROLE);
5480f7ce3343SMasatake YAMATO makeTagEntry (&e);
5481f7ce3343SMasatake YAMATO initRefTagEntry (&e, name, i, R_ROLES_DISABLED_KIND_B_ROLE);
5482f7ce3343SMasatake YAMATO makeTagEntry (&e);
5483f7ce3343SMasatake YAMATO break;
5484f7ce3343SMasatake YAMATO }
54857b08b440SMasatake YAMATO case K_FIELD_TESTING:
54867b08b440SMasatake YAMATO {
54877b08b440SMasatake YAMATO char c = 'a';
54887b08b440SMasatake YAMATO char name []= {'\0', 't', 'a', 'g', '\0' };
54897b08b440SMasatake YAMATO
54907b08b440SMasatake YAMATO name [0] = c++;
54917b08b440SMasatake YAMATO initTagEntry (&e, name, i);
54927b08b440SMasatake YAMATO attachParserField (&e, false,
54937b08b440SMasatake YAMATO CTSTFields[F_BOOLEAN_FIELD].ftype, "");
54947b08b440SMasatake YAMATO makeTagEntry (&e);
54957b08b440SMasatake YAMATO
54967b08b440SMasatake YAMATO name [0] = c++;
54977b08b440SMasatake YAMATO initTagEntry (&e, name, i);
54987b08b440SMasatake YAMATO makeTagEntry (&e);
54997b08b440SMasatake YAMATO
55007b08b440SMasatake YAMATO name [0] = c++;
55017b08b440SMasatake YAMATO initTagEntry (&e, name, i);
55027b08b440SMasatake YAMATO attachParserField (&e, false,
55037b08b440SMasatake YAMATO CTSTFields[F_BOOLEAN_AND_STRING_FIELD].ftype, "val");
55047b08b440SMasatake YAMATO makeTagEntry (&e);
55057b08b440SMasatake YAMATO
55067b08b440SMasatake YAMATO name [0] = c++;
55077b08b440SMasatake YAMATO initTagEntry (&e, name, i);
55087b08b440SMasatake YAMATO attachParserField (&e, false,
55097b08b440SMasatake YAMATO CTSTFields[F_BOOLEAN_AND_STRING_FIELD].ftype, "");
55107b08b440SMasatake YAMATO makeTagEntry (&e);
55117b08b440SMasatake YAMATO
55127b08b440SMasatake YAMATO break;
55137b08b440SMasatake YAMATO }
551456175ec1SMasatake YAMATO case K_TRIGGER_NOTICE:
551556175ec1SMasatake YAMATO notice ("notice output for testing: %s", CTST_Kinds [i].name);
551656175ec1SMasatake YAMATO break;
5517e7283d01SMasatake YAMATO }
5518e7283d01SMasatake YAMATO }
5519e7283d01SMasatake YAMATO }
5520e97e7d4aSMasatake YAMATO
5521e97e7d4aSMasatake YAMATO TRACE_LEAVE();
5522e7283d01SMasatake YAMATO }
5523e7283d01SMasatake YAMATO
initStatsCTST(langType lang CTAGS_ATTR_UNUSED)5524a9c91f4dSMasatake YAMATO static void initStatsCTST (langType lang CTAGS_ATTR_UNUSED)
5525a9c91f4dSMasatake YAMATO {
5526a9c91f4dSMasatake YAMATO CTST_GatherStats = true;
5527a9c91f4dSMasatake YAMATO }
5528a9c91f4dSMasatake YAMATO
printStatsCTST(langType lang CTAGS_ATTR_UNUSED)5529a9c91f4dSMasatake YAMATO static void printStatsCTST (langType lang CTAGS_ATTR_UNUSED)
5530a9c91f4dSMasatake YAMATO {
5531a9c91f4dSMasatake YAMATO fprintf (stderr, "The number of handled chars: %d\n",
5532a9c91f4dSMasatake YAMATO CTST_num_handled_char);
5533a9c91f4dSMasatake YAMATO }
5534a9c91f4dSMasatake YAMATO
CTagsSelfTestParser(void)55350435a2b5SMasatake YAMATO static parserDefinition *CTagsSelfTestParser (void)
5536e7283d01SMasatake YAMATO {
5537e7283d01SMasatake YAMATO static const char *const extensions[] = { NULL };
5538d3ee68cdSMasatake YAMATO parserDefinition *const def = parserNew (SELF_TEST_PARSER);
5539e7283d01SMasatake YAMATO def->extensions = extensions;
554009ae690fSMasatake YAMATO def->kindTable = CTST_Kinds;
5541e7283d01SMasatake YAMATO def->kindCount = KIND_COUNT;
5542e7283d01SMasatake YAMATO def->parser = createCTSTTags;
5543ce990805SThomas Braun def->invisible = true;
55446342bbd5SMasatake YAMATO def->useMemoryStreamInput = true;
55456b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
5546a9c91f4dSMasatake YAMATO def->initStats = initStatsCTST;
5547a9c91f4dSMasatake YAMATO def->printStats = printStatsCTST;
55487b08b440SMasatake YAMATO def->fieldTable = CTSTFields;
55497b08b440SMasatake YAMATO def->fieldCount = ARRAY_SIZE (CTSTFields);
55507b08b440SMasatake YAMATO
5551e7283d01SMasatake YAMATO return def;
5552e7283d01SMasatake YAMATO }
5553