3939#include "interactive_p.h"
4040#include "writer_p.h"
4141#include "trace.h"
42+ #include "flags_p.h"
4243
4344#ifdef HAVE_JANSSON
4445#include <jansson.h>
5960/* The following separators are permitted for list options.
6061 */
6162#define EXTENSION_SEPARATOR '.'
63+ #define REXPR_START '%'
64+ #define REXPR_STOP '%'
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>|<rexpr> " },
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 <extension>, or one file <rexpr > 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-rexprs[=(<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" },
@@ -1808,9 +1813,45 @@ static char* extractMapFromParameter (const langType language,
18081813 return result ;
18091814 }
18101815
1816+ if (first == REXPR_START )
1817+ {
1818+ * mapType = LMAP_REXPR ;
1819+
1820+ ++ parameter ;
1821+ vString * rexpr = vStringNew ();
1822+ for (p = parameter ; * p != REXPR_STOP && * p != '\0' ; ++ p )
1823+ {
1824+ if (* p == '\\' && * (p + 1 ) == REXPR_STOP )
1825+ p ++ ;
1826+ vStringPut (rexpr , * p );
1827+ }
1828+ if (* p == '\0' )
1829+ error (FATAL , "Unterminated file name regular expression for %s language: %s" ,
1830+ getLanguageName (language ), parameter );
1831+
1832+ * tail = p + 1 ;
1833+ return vStringDeleteUnwrap (rexpr );
1834+ }
1835+
18111836 return NULL ;
18121837}
18131838
1839+ static void langmap_rexpr_icase_short (char c CTAGS_ATTR_UNUSED , void * data )
1840+ {
1841+ bool * icase = data ;
1842+ * icase = true;
1843+ }
1844+
1845+ static void langmap_rexpr_icase_long (const char * s CTAGS_ATTR_UNUSED , const char * const unused CTAGS_ATTR_UNUSED , void * data )
1846+ {
1847+ langmap_rexpr_icase_short ('i' , data );
1848+ }
1849+
1850+ static flagDefinition langmapRexprFlagDef [] = {
1851+ { 'i' , "icase" , langmap_rexpr_icase_short , langmap_rexpr_icase_long ,
1852+ NULL , "applied in a case-insensitive manner" },
1853+ };
1854+
18141855static char * addLanguageMap (const langType language , char * map_parameter ,
18151856 bool exclusiveInAllLanguages )
18161857{
@@ -1823,6 +1864,13 @@ static char* addLanguageMap (const langType language, char* map_parameter,
18231864 addLanguageExtensionMap (language , map , exclusiveInAllLanguages );
18241865 else if (map && map_type == LMAP_PATTERN )
18251866 addLanguagePatternMap (language , map , exclusiveInAllLanguages );
1867+ else if (map && map_type == LMAP_REXPR )
1868+ {
1869+ bool icase = false;
1870+
1871+ flagsEval (p , langmapRexprFlagDef , ARRAY_SIZE (langmapRexprFlagDef ), & icase );
1872+ addLanguageRexprMap (language , map , icase , exclusiveInAllLanguages );
1873+ }
18261874 else
18271875 error (FATAL , "Badly formed language map for %s language" ,
18281876 getLanguageName (language ));
@@ -1843,6 +1891,13 @@ static char* removeLanguageMap (const langType language, char* map_parameter)
18431891 removeLanguageExtensionMap (language , map );
18441892 else if (map && map_type == LMAP_PATTERN )
18451893 removeLanguagePatternMap (language , map );
1894+ else if (map && map_type == LMAP_REXPR )
1895+ {
1896+ bool icase = false;
1897+
1898+ flagsEval (p , langmapRexprFlagDef , ARRAY_SIZE (langmapRexprFlagDef ), & icase );
1899+ removeLanguageRexprMap (language , map , icase );
1900+ }
18461901 else
18471902 error (FATAL , "Badly formed language map for %s language" ,
18481903 getLanguageName (language ));
@@ -2164,6 +2219,13 @@ static void processListMapPatternsOption (const char *const option,
21642219 processListMapsOptionForType (option , parameter , LMAP_PATTERN |LMAP_TABLE_OUTPUT );
21652220}
21662221
2222+ static void processListMapRexprsOption (const char * const option ,
2223+ const char * const parameter )
2224+ {
2225+ processListMapsOptionForType (option , parameter , LMAP_REXPR |LMAP_TABLE_OUTPUT );
2226+ }
2227+
2228+
21672229static void processListMapsOption (
21682230 const char * const option CTAGS_ATTR_UNUSED ,
21692231 const char * const parameter CTAGS_ATTR_UNUSED )
@@ -2327,6 +2389,13 @@ static void processDescribeLanguage(const char *const option,
23272389 getLanguageVersionCurrent (language ),
23282390 getLanguageVersionAge (language ));
23292391
2392+ puts ("" );
2393+ puts ("Mappings/rexprs" );
2394+ puts ("-------------------------------------------------------" );
2395+ printLanguageMaps (language , LMAP_REXPR |LMAP_NO_LANG_PREFIX ,
2396+ localOption .withListHeader , localOption .machinable ,
2397+ stdout );
2398+
23302399 puts ("" );
23312400 puts ("Mappings/patterns" );
23322401 puts ("-------------------------------------------------------" );
@@ -2999,6 +3068,7 @@ static parametricOption ParametricOptions [] = {
29993068 { "list-maps" , processListMapsOption , true, STAGE_ANY },
30003069 { "list-map-extensions" , processListMapExtensionsOption , true, STAGE_ANY },
30013070 { "list-map-patterns" , processListMapPatternsOption , true, STAGE_ANY },
3071+ { "list-map-rexprs" , processListMapRexprsOption , true, STAGE_ANY },
30023072 { "list-mline-regex-flags" , processListMultilineRegexFlagsOption , true, STAGE_ANY },
30033073 { "list-output-formats" , processListOutputFormatsOption , true, STAGE_ANY },
30043074 { "list-params" , processListParametersOption , true, STAGE_ANY },
0 commit comments