2 # Copyright (c) 2017-2019, The Tor Project, Inc.
3 # See LICENSE for licensing information
7 LINE_OBVIOUSNESS_LIMIT
= 4
9 class Problem(Exception):
13 s
= re
.sub(r
'//.*','',s
)
14 s
= re
.sub(r
'/\*.*','',s
)
17 def translate(f_in
, f_out
):
20 cur_level
= whole_file
24 m
= re
.match(r
'\s*#\s*(if|ifdef|ifndef|else|endif|elif)\b\s*(.*)',
29 command
,rest
= m
.groups()
30 if command
in ("if", "ifdef", "ifndef"):
31 # The #if directive pushes us one level lower on the stack.
32 if command
== 'ifdef':
33 rest
= "defined(%s)"%uncomment
(rest
)
34 elif command
== 'ifndef':
35 rest
= "!defined(%s)"%uncomment
(rest
)
36 elif rest
.endswith("\\"):
37 rest
= rest
[:-1]+"..."
39 rest
= uncomment(rest
)
41 new_level
= [ (command
, rest
, lineno
) ]
42 stack
.append(cur_level
)
45 elif command
in ("else", "elif"):
46 if len(cur_level
) == 0 or cur_level
[-1][0] == 'else':
47 raise Problem("Unexpected #%s on %d"% (command
,lineno
))
48 if (len(cur_level
) == 1 and command
== 'else' and
49 lineno
> cur_level
[0][2] + LINE_OBVIOUSNESS_LIMIT
):
50 f_out
.write("#else /* !(%s) */\n"%cur_level
[0][1])
53 cur_level
.append((command
, rest
, lineno
))
55 assert command
== 'endif'
57 raise Problem("Unmatched #%s on %s"% (command
,lineno
))
58 if lineno
<= cur_level
[0][2] + LINE_OBVIOUSNESS_LIMIT
:
60 elif len(cur_level
) == 1 or (
61 len(cur_level
) == 2 and cur_level
[1][0] == 'else'):
62 f_out
.write("#endif /* %s */\n"%cur_level
[0][1])
64 f_out
.write("#endif /* %s || ... */\n"%cur_level
[0][1])
65 cur_level
= stack
.pop()
66 if len(stack
) or cur_level
!= whole_file
:
67 raise Problem("Missing #endif")
70 for fn
in sys
.argv
[1:]:
71 with
open(fn
+"_OUT", 'w') as output_file
:
72 translate(open(fn
, 'r'), output_file
)
73 os
.rename(fn
+"_OUT", fn
)