Skip to content

Commit 2d05991

Browse files
author
Laurent Pinson
committed
solved issue #31
1 parent 40d0192 commit 2d05991

File tree

3 files changed

+42
-40
lines changed

3 files changed

+42
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ set the options of the preprocessor:
190190
* resume: Return after a file is preprocessed and can preprocess a next file if true. Default is false
191191
* save: Save preprocessed code if true. Default is true
192192
* overload: Any defines added to the preprocessor will overload existing defines. Default is false
193-
* quiet: no warning about ununderstood directives or missing #indef
193+
* quiet: no warning about not understood directives or missing #indef
194194

195195
```python
196196
pypreprocessor.input = 'inputFile.py'

pypreprocessor/__init__.py

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
__author__ = 'Evan Plaice'
55
__coauthor__ = 'Hendi O L, Epikem, Laurent Pinson'
6-
__version__ = '0.8'
6+
__version__ = '1.0'
77

88
import sys
99
import os
@@ -20,17 +20,19 @@ def append(self, var):
2020

2121

2222
class preprocessor:
23+
__overloaded = []
24+
defines = customDict()
25+
2326
def __init__(self, inFile=sys.argv[0], outFile='', defines={}, removeMeta=False,
2427
escapeChar=None, mode=None, escape='#', run=True, resume=False,
2528
save=True, overload=True, quiet=False):
2629
# public variables
27-
self.defines = customDict()
28-
#support for <=0.7.7
30+
# support for <=0.7.7
2931
if isinstance(defines, collections.Sequence):
3032
for x in defines:
31-
self.define(x)
33+
self.define(*x.split(':'))
3234
else:
33-
for x,y in defines:
35+
for x,y in defines.items():
3436
self.define(x,y)
3537
self.input = inFile
3638
self.output = outFile
@@ -89,12 +91,16 @@ def deprecation(message):
8991
def __reset_internal(self):
9092
self.__linenum = 0
9193
self.__excludeblock = False
92-
self.__ifblocks = [] # contains the evaluated if conditions
93-
self.__ifconditions = [] # contains the if conditions
94+
# contains the evaluated if conditions
95+
# due to the introduction of #elif, elements of __ifblocks are duos of boolean
96+
# the 1st is the evaluation of the current #if or #elif or #else
97+
# the 2nd indicates if at least one #if or #elif was True in the whole #if/#endif block
98+
self.__ifblocks = []
99+
# contains the if conditions
100+
self.__ifconditions = []
94101
self.__outputBuffer = ''
95102
self.__overloaded = list(self.defines.keys()) if self.overload else []
96103

97-
98104
def define(self, name, val=True):
99105
"""
100106
Adds variable definition to the store as expected from a #define directive.
@@ -164,7 +170,7 @@ def __validate_ifs(self):
164170
165171
"""
166172
# no ifs mean we pass else check all ifs are True
167-
return not self.__ifblocks or all(self.__ifblocks)
173+
return not self.__ifblocks or all(x[0] for x in self.__ifblocks)
168174

169175
def __is_directive(self, line, directive, *size):
170176
"""
@@ -243,41 +249,43 @@ def lexer(self, line):
243249
elif self.__is_directive(line, 'ifdefnot', 2) or \
244250
self.__is_directive(line, 'ifnotdef', 2) or \
245251
self.__is_directive(line, 'ifndef', 2):
246-
self.__ifblocks.append(not self.__is_defined(line.split()[1]))
252+
_check = not self.__is_defined(line.split()[1])
253+
self.__ifblocks.append([ _check, _check])
247254
self.__ifconditions.append(line.split()[1])
248255

249256
elif self.__is_directive(line, 'ifdef', 2):
250-
self.__ifblocks.append(self.__is_defined(line.split()[1]))
257+
_check = self.__is_defined(line.split()[1])
258+
self.__ifblocks.append([ _check, _check])
251259
self.__ifconditions.append(line.split()[1])
252260

253261
elif self.__is_directive(line, 'if'):
254-
self.__ifblocks.append(self.__evaluate_if(' '.join(line.split()[1:])))
262+
_check = self.__evaluate_if(' '.join(line.split()[1:]))
263+
self.__ifblocks.append([ _check, _check])
255264
self.__ifconditions.append(' '.join(line.split()[1:]))
256265

257266
# since in version <=0.7.7, it didn't handle #if it should be #elseifdef instead.
258267
# kept elseif with 2 elements for retro-compatibility (equivalent to #elseifdef).
259268
elif self.__is_directive(line, 'elseif') or \
260269
self.__is_directive(line, 'elif'):
261-
# do else
262-
self.__ifblocks[-1] = not self.__ifblocks[-1]
263-
# do if
270+
_cur, _whole = self.__ifblocks[-1]
264271
if len(line.split()) == 2:
265272
#old behaviour
266-
self.__ifblocks[-1] = self.__is_defined(line.split()[1])
273+
_check = self.__is_defined(line.split()[1])
267274
else:
268275
#new behaviour
269-
self.__ifblocks[-1] = self.__evaluate_if(' '.join(line.split()[1:]))
270-
self.__ifconditions.append(' '.join(line.split()[1:]))
276+
_check = self.__evaluate_if(' '.join(line.split()[1:]))
277+
self.__ifblocks[-1]=[ not _whole and _check, _whole or _check ]
278+
self.__ifconditions[-1]=' '.join(line.split()[1:])
271279

272280
elif self.__is_directive(line, 'elseifdef', 2):
273-
# do else
274-
self.__ifblocks[-1] = not self.__ifblocks[-1]
275-
# do if
276-
self.__ifblocks[-1]=self.__is_defined(line.split()[1])
277-
self.__ifconditions.append(' '.join(line.split()[1:]))
281+
_cur, _whole = self.__ifblocks[-1]
282+
_check = self.__is_defined(line.split()[1])
283+
self.__ifblocks[-1]=[ not _whole and _check, _whole or _check ]
284+
self.__ifconditions[-1]=' '.join(line.split()[1:])
278285

279286
elif self.__is_directive(line, 'else', 1):
280-
self.__ifblocks[-1] = not self.__ifblocks[-1] #opposite of last if
287+
_cur, _whole = self.__ifblocks[-1]
288+
self.__ifblocks[-1] = [not _whole, not _whole] #opposite of the whole if/elif block
281289

282290
elif self.__is_directive(line, 'endififdef', 2):
283291
# do endif
@@ -299,19 +307,17 @@ def lexer(self, line):
299307
except ValueError as VE:
300308
number = 1
301309

302-
if len(self.__ifconditions) >= number:
303-
for i in range(0, number):
310+
try:
311+
while number:
304312
self.__ifblocks.pop(-1)
305313
self.__ifconditions.pop(-1)
306-
else:
314+
number-=1
315+
except:
307316
if not self.quiet:
308317
print('Warning trying to remove more blocks than present',
309318
self.input, self.__linenum)
310-
self.__ifblocks = []
311-
self.__ifconditions = []
312319

313320
else:
314-
# unknown directive or comment
315321
# escapechar + space ==> comment
316322
# starts with #!/ ==> shebang
317323
# else print warning

pypreprocessor/__main__.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,26 @@
88
python -m """+__package__+""" table.json --escape #@ -d NUM:4 ID:1
99
""",
1010
formatter_class=argparse.RawDescriptionHelpFormatter,
11-
usage=' python -m '+__package__+' input [output] [-h] [-r] [-m] [-e ESCAPE] [-d [DEFINE ...]]',
11+
usage=' python -m '+__package__+' input [output] [-h] [-r] [-m] [-e ESCAPE] [-o] [-q] [-d [DEFINE ...]]',
1212
)
13-
parser.add_argument("-r", "--run", help="Run on the fly",
13+
parser.add_argument("-r", "--run", help="run on the fly",
1414
action='store_true', default=False)
1515
parser.add_argument("-m", "--removeMeta", help="remove meta lines from the output",
1616
action='store_true', default=False)
1717
parser.add_argument("-e", "--escape", help="define the escape sequence to use. Default is #")
18-
parser.add_argument("-d", "--define", help="list of variable to define", nargs='*')
18+
parser.add_argument("-d", "--define", help="list of constants to define", nargs='*', default=[])
1919
parser.add_argument("-o", "--overload", help="overload variable definition in the file by those \
2020
provided by --define", action='store_true', default=False)
21-
parser.add_argument("-q", "--quiet", help="No warning on ununderstable directives and missign ending",
21+
parser.add_argument("-q", "--quiet", help="No warning on not understood directives and missign ending",
2222
action='store_true', default=False)
2323
parser.add_argument("input", help="input file.")
2424
parser.add_argument("output", nargs='?', help="output file. Default is <input_basename>_out.<input_extension>")
2525
args = parser.parse_args()
2626

27-
p=preprocessor(inFile=args.input, mode=None, removeMeta=args.removeMeta, escapeChar=None,
27+
p=preprocessor(inFile=args.input, defines=args.define, mode=None, removeMeta=args.removeMeta, escapeChar=None,
2828
run=args.run, resume=False, save=True, overload=args.overload, quiet=args.quiet)
2929
if args.output:
3030
p.define = args.output
31-
if args.define:
32-
for elem in args.define:
33-
p.define(*elem.split(':'))
34-
self.__reset_internal() # not very pythonic
3531
if args.escape:
3632
p.escape = args.escape
3733

0 commit comments

Comments
 (0)