1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
# -*- coding: utf-8 -*-
# preprocessor.py - simple preprocessor for plugin template files
# This file is part of pluma
#
# Copyright (C) 2006 - Steve Frécinaux
# Copyright (C) 2012-2021 MATE Developers
#
# pluma is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# pluma is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pluma; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA
import sys
import re
import io
class DeepnessException(Exception):
def __init__(self):
Exception.__init__(self)
statements = [re.compile("^##\s*%s\s*$" % pattern) for pattern in
['(?P<stmt>ifdef|ifndef)\s+(?P<key>[^\s]+)',
'(?P<stmt>elif|if)\s+(?P<expr>.+)',
'(?P<stmt>else|endif)',
'(?P<stmt>define)\s+(?P<key>[^\s]+)(\s+(?P<val>.+))?',
'(?P<stmt>undef)\s+(?P<key>[^\s]+)']]
variable = re.compile("##\((?P<name>[a-zA-Z_][a-zA-Z0-9_]*)(?P<mods>(\.[a-z]+)+)?\)")
def _eval(expr, macros):
return eval(expr,
{'defined': lambda x: macros.has_key(x)},
macros)
def _subvar(match, macros):
name = match.group('name')
if name in macros:
val = str(macros[name])
if val is None:
return ''
else:
return ''
mods = match.group('mods')
if mods is not None:
for mod in mods[1:].split('.'):
if mod == 'lower':
val = val.lower()
elif mod == 'upper':
val = val.upper()
elif mod == 'camel':
val = ''.join(i.capitalize()
for i in val.split('_'))
return val
def process(infile = sys.stdin, outfile = sys.stdout, macros = {}):
if not isinstance(infile, io.IOBase):
infile = open(infile, mode = 'r')
close_infile = True
else:
close_infile = False
if not isinstance(outfile, io.IOBase):
outfile = open(outfile, mode = 'w')
close_outfile = True
else:
close_outfile = False
deepness = 0
writing_disabled = None
for line in infile:
# Skip comments
if line[0:3].lower() == '##c':
continue
# Check whether current line is a preprocessor directive
for statement in statements:
match = statement.match(line)
if match: break
if match is not None:
stmt = match.group('stmt')
if stmt == "define":
if writing_disabled is None:
key = match.group('key')
val = match.group('val')
macros[key] = val
elif stmt == "undef":
if writing_disabled is None:
key = match.group('key')
if key in macros:
del macros[key]
elif stmt == "ifdef":
deepness += 1
if writing_disabled is None and \
match.group('key') not in macros:
writing_disabled = deepness
elif stmt == "ifndef":
deepness += 1
if writing_disabled is None and \
match.group('key') in macros:
writing_disabled = deepness
elif stmt == "if":
deepness += 1
if writing_disabled is None and \
not _eval(match.group('expr'), macros):
writing_disabled = deepness
elif stmt == "elif":
if deepness == 0:
raise DeepnessException()
if writing_disabled is None and \
not _eval(match.group('expr'), macros):
writing_disabled = deepness
elif writing_disabled == deepness:
writing_disabled = None
elif stmt == "else":
if deepness == 0:
raise DeepnessException()
if writing_disabled is None:
writing_disabled = deepness
elif writing_disabled == deepness:
writing_disabled = None
elif stmt == "endif":
if deepness == 0:
raise DeepnessException()
if writing_disabled is not None and \
writing_disabled == deepness:
writing_disabled = None
deepness -= 1
# Do variable substitution in the remaining lines
elif writing_disabled is None:
outfile.write(re.sub(variable,
lambda m: _subvar(m, macros),
line))
if deepness != 0:
raise DeepnessException()
if close_infile: infile.close()
if close_outfile: outfile.close()
# ex:ts=4:et:
|