5959/* The following separators are permitted for list options.
6060 */
6161#define EXTENSION_SEPARATOR '.'
62+ #define REXPR_START '%'
63+ #define REXPR_STOP '%'
64+ #define REXPR_ICASE 'i'
6265#define PATTERN_START '('
6366#define PATTERN_STOP ')'
6467#define IGNORE_SEPARATORS ", \t\n"
@@ -303,10 +306,10 @@ static optionDescription LongOptionDescription [] = {
303306 {1 ,0 ," --langmap=<map>[,<map>[...]]" },
304307 {1 ,0 ," Override default mapping of language to input file extension." },
305308 {1 ,0 ," e.g. --langmap=c:.c.x,java:+.j,make:([Mm]akefile).mak" },
306- {1 ,0 ," --map-<LANG>=[+|-]<extension>|<pattern>" },
309+ {1 ,0 ," --map-<LANG>=[+|-]<extension>|<pattern>|<regex> " },
307310 {1 ,0 ," Set, add(+) or remove(-) the map for <LANG>." },
308- {1 ,0 ," Unlike --langmap, this doesn't take a list; only one file name <pattern>" },
309- {1 ,0 ," or one file <extension> can be specified at once." },
311+ {1 ,0 ," Unlike --langmap, this doesn't take a list; only one file name <pattern>, " },
312+ {1 ,0 ," one file name <regex>, or one file <extension> can be specified at once." },
310313 {1 ,0 ," Unlike --langmap the change with this option affects mapping of <LANG> only." },
311314 {1 ,0 ,"" },
312315 {1 ,0 ,"Tags File Contents Options" },
@@ -436,6 +439,8 @@ static optionDescription LongOptionDescription [] = {
436439 {1 ,0 ," Output list of language extensions in mapping." },
437440 {1 ,0 ," --list-map-patterns[=(<language>|all)]" },
438441 {1 ,0 ," Output list of language patterns in mapping." },
442+ {1 ,0 ," --list-map-regex[=(<language>|all)]" },
443+ {1 ,0 ," Output list of language regular expressions in mapping." },
439444 {1 ,0 ," --list-maps[=(<language>|all)]" },
440445 {1 ,0 ," Output list of language mappings (both extensions and patterns)." },
441446 {1 ,0 ," --list-mline-regex-flags" },
@@ -1793,6 +1798,7 @@ static char* extractMapFromParameter (const langType language,
17931798 ++ parameter ;
17941799 for (p = parameter ; * p != PATTERN_STOP && * p != '\0' ; ++ p )
17951800 {
1801+ /* ??? */
17961802 if (* p == '\\' && * (p + 1 ) == PATTERN_STOP )
17971803 ++ p ;
17981804 }
@@ -1808,6 +1814,26 @@ static char* extractMapFromParameter (const langType language,
18081814 return result ;
18091815 }
18101816
1817+ if (first == REXPR_START )
1818+ {
1819+ * mapType = LMAP_REXPR ;
1820+
1821+ ++ parameter ;
1822+ vString * rexpr = vStringNew ();
1823+ for (p = parameter ; * p != REXPR_STOP && * p != '\0' ; ++ p )
1824+ {
1825+ if (* p == '\\' && * (p + 1 ) == REXPR_STOP )
1826+ continue ;
1827+ vStringPut (rexpr , * p );
1828+ }
1829+ if (* p == '\0' )
1830+ error (FATAL , "Unterminated file name regex for %s language" ,
1831+ getLanguageName (language ));
1832+
1833+ * tail = p + 1 ;
1834+ return vStringDeleteUnwrap (rexpr );
1835+ }
1836+
18111837 return NULL ;
18121838}
18131839
@@ -1823,6 +1849,13 @@ static char* addLanguageMap (const langType language, char* map_parameter,
18231849 addLanguageExtensionMap (language , map , exclusiveInAllLanguages );
18241850 else if (map && map_type == LMAP_PATTERN )
18251851 addLanguagePatternMap (language , map , exclusiveInAllLanguages );
1852+ else if (map && map_type == LMAP_REXPR )
1853+ {
1854+ bool icase = (* p == REXPR_ICASE );
1855+ addLanguageRexprMap (language , map , icase , exclusiveInAllLanguages );
1856+ if (icase )
1857+ p ++ ;
1858+ }
18261859 else
18271860 error (FATAL , "Badly formed language map for %s language" ,
18281861 getLanguageName (language ));
@@ -1843,6 +1876,13 @@ static char* removeLanguageMap (const langType language, char* map_parameter)
18431876 removeLanguageExtensionMap (language , map );
18441877 else if (map && map_type == LMAP_PATTERN )
18451878 removeLanguagePatternMap (language , map );
1879+ else if (map && map_type == LMAP_REXPR )
1880+ {
1881+ bool icase = (* p == REXPR_ICASE );
1882+ removeLanguageRexprMap (language , map , icase );
1883+ if (icase )
1884+ p ++ ;
1885+ }
18461886 else
18471887 error (FATAL , "Badly formed language map for %s language" ,
18481888 getLanguageName (language ));
@@ -2164,6 +2204,13 @@ static void processListMapPatternsOption (const char *const option,
21642204 processListMapsOptionForType (option , parameter , LMAP_PATTERN |LMAP_TABLE_OUTPUT );
21652205}
21662206
2207+ static void processListMapRegularExpressionsOption (const char * const option ,
2208+ const char * const parameter )
2209+ {
2210+ processListMapsOptionForType (option , parameter , LMAP_REXPR |LMAP_TABLE_OUTPUT );
2211+ }
2212+
2213+
21672214static void processListMapsOption (
21682215 const char * const option CTAGS_ATTR_UNUSED ,
21692216 const char * const parameter CTAGS_ATTR_UNUSED )
@@ -2327,6 +2374,13 @@ static void processDescribeLanguage(const char *const option,
23272374 getLanguageVersionCurrent (language ),
23282375 getLanguageVersionAge (language ));
23292376
2377+ puts ("" );
2378+ puts ("Mappings/rexprs" );
2379+ puts ("-------------------------------------------------------" );
2380+ printLanguageMaps (language , LMAP_REXPR |LMAP_NO_LANG_PREFIX ,
2381+ localOption .withListHeader , localOption .machinable ,
2382+ stdout );
2383+
23302384 puts ("" );
23312385 puts ("Mappings/patterns" );
23322386 puts ("-------------------------------------------------------" );
@@ -2999,6 +3053,7 @@ static parametricOption ParametricOptions [] = {
29993053 { "list-maps" , processListMapsOption , true, STAGE_ANY },
30003054 { "list-map-extensions" , processListMapExtensionsOption , true, STAGE_ANY },
30013055 { "list-map-patterns" , processListMapPatternsOption , true, STAGE_ANY },
3056+ { "list-map-regex" , processListMapRegularExpressionsOption , true, STAGE_ANY },
30023057 { "list-mline-regex-flags" , processListMultilineRegexFlagsOption , true, STAGE_ANY },
30033058 { "list-output-formats" , processListOutputFormatsOption , true, STAGE_ANY },
30043059 { "list-params" , processListParametersOption , true, STAGE_ANY },
0 commit comments