Improve escaping in configuration files
Replace pairs of backslashes before '@' or '\@' with singles (allows escaping the escape character). Do not consume next '@' after '\@'.
This commit is contained in:
parent
325b2c25b6
commit
91a0126590
|
@ -428,19 +428,28 @@ def do_replacement(regex, line, confdata):
|
|||
missing_variables = set()
|
||||
|
||||
def variable_replace(match):
|
||||
varname = match.group(1)
|
||||
if varname in confdata:
|
||||
(var, desc) = confdata.get(varname)
|
||||
if isinstance(var, str):
|
||||
pass
|
||||
elif isinstance(var, int):
|
||||
var = str(var)
|
||||
else:
|
||||
raise RuntimeError('Tried to replace a variable with something other than a string or int.')
|
||||
# Pairs of escape characters before '@' or '\@'
|
||||
if match.group(0).endswith('\\'):
|
||||
num_escapes = match.end(0) - match.start(0)
|
||||
return '\\' * (num_escapes // 2)
|
||||
# Single escape character and '@'
|
||||
elif match.group(0) == '\\@':
|
||||
return '@'
|
||||
# Template variable to be replaced
|
||||
else:
|
||||
missing_variables.add(varname)
|
||||
var = ''
|
||||
return var
|
||||
varname = match.group(1)
|
||||
if varname in confdata:
|
||||
(var, desc) = confdata.get(varname)
|
||||
if isinstance(var, str):
|
||||
pass
|
||||
elif isinstance(var, int):
|
||||
var = str(var)
|
||||
else:
|
||||
raise RuntimeError('Tried to replace a variable with something other than a string or int.')
|
||||
else:
|
||||
missing_variables.add(varname)
|
||||
var = ''
|
||||
return var
|
||||
return re.sub(regex, variable_replace, line), missing_variables
|
||||
|
||||
def do_mesondefine(line, confdata):
|
||||
|
@ -473,7 +482,7 @@ def do_conf_file(src, dst, confdata):
|
|||
raise MesonException('Could not read input file %s: %s' % (src, str(e)))
|
||||
# Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define
|
||||
# Also allow escaping '@' with '\@'
|
||||
regex = re.compile(r'(?<!\\)@([-a-zA-Z0-9_]+)@')
|
||||
regex = re.compile(r'(?:\\\\)+(?=\\?@)|\\@|@([-a-zA-Z0-9_]+)@')
|
||||
result = []
|
||||
missing_variables = set()
|
||||
for line in data:
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* No escape */
|
||||
#define MESSAGE1 "@var1@"
|
||||
|
||||
/* Single escape means no replace */
|
||||
#define MESSAGE2 "\@var1@"
|
||||
|
||||
/* Replace pairs of escapes before '@' or '\@' with escape characters
|
||||
* (note we have to double number of pairs due to C string escaping)
|
||||
*/
|
||||
#define MESSAGE3 "\\\\@var1@"
|
||||
|
||||
/* Pairs of escapes and then single escape to avoid replace */
|
||||
#define MESSAGE4 "\\\\\@var1@"
|
||||
|
||||
/* Check escaped variable does not overlap following variable */
|
||||
#define MESSAGE5 "\@var1@var2@"
|
||||
|
||||
/* Check escape character outside variables */
|
||||
#define MESSAGE6 "\\ @ \@ \\\\@ \\\\\@"
|
|
@ -120,3 +120,14 @@ configure_file(
|
|||
configuration : conf5
|
||||
)
|
||||
test('test5', executable('prog5', 'prog5.c'))
|
||||
|
||||
# Test escaping
|
||||
conf6 = configuration_data()
|
||||
conf6.set('var1', 'foo')
|
||||
conf6.set('var2', 'bar')
|
||||
configure_file(
|
||||
input : 'config6.h.in',
|
||||
output : '@BASENAME@',
|
||||
configuration : conf6
|
||||
)
|
||||
test('test6', executable('prog6', 'prog6.c'))
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#include <string.h>
|
||||
#include <config6.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return strcmp(MESSAGE1, "foo")
|
||||
|| strcmp(MESSAGE2, "@var1@")
|
||||
|| strcmp(MESSAGE3, "\\foo")
|
||||
|| strcmp(MESSAGE4, "\\@var1@")
|
||||
|| strcmp(MESSAGE5, "@var1bar")
|
||||
|| strcmp(MESSAGE6, "\\ @ @ \\@ \\@");
|
||||
}
|
Loading…
Reference in New Issue