diff options
author | David Beazley <dave@dabeaz.com> | 2019-01-19 16:14:00 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-19 16:14:00 -0600 |
commit | 07911e13e3aecd46530319a4e311dcf337742661 (patch) | |
tree | 197ac48fe5b3f50acffe27c5c034ea0587a0bb89 | |
parent | a37e0839583d683d95e70ce1445c0063c7d4bd21 (diff) | |
parent | bd76ca8ac5dd89f23353435adb704a0fcba1c49c (diff) | |
download | ply-07911e13e3aecd46530319a4e311dcf337742661.tar.gz |
Merge pull request #197 from rreilink/master
Fixes issues #195, 196
-rw-r--r-- | ply/cpp.py | 39 | ||||
-rw-r--r-- | test/test_cpp_nonascii.c | 2 | ||||
-rw-r--r-- | test/testcpp.py | 36 |
3 files changed, 73 insertions, 4 deletions
@@ -617,11 +617,21 @@ class Preprocessor(object): del tokens[i+1:j+1] i += 1 tokens = self.expand_macros(tokens) + return self.evalexpr_expanded(tokens) + + # ---------------------------------------------------------------------- + # evalexpr_expanded() + # + # Helper for evalexpr that evaluates the expression that had its macros + # and defined(...) expressions expanded by evalexpr + # ---------------------------------------------------------------------- + + def evalexpr_expanded(self, tokens): for i,t in enumerate(tokens): if t.type == self.t_ID: tokens[i] = copy.copy(t) tokens[i].type = self.t_INTEGER - tokens[i].value = self.t_INTEGER_TYPE("0L") + tokens[i].value = self.t_INTEGER_TYPE("0") elif t.type == self.t_INTEGER: tokens[i] = copy.copy(t) # Strip off any trailing suffixes @@ -629,10 +639,19 @@ class Preprocessor(object): while tokens[i].value[-1] not in "0123456789abcdefABCDEF": tokens[i].value = tokens[i].value[:-1] - expr = "".join([str(x.value) for x in tokens]) + return self.evalexpr_string("".join([str(x.value) for x in tokens])) + + # ---------------------------------------------------------------------- + # evalexpr_string() + # + # Helper for evalexpr that evaluates a string expression + # This implementation does basic C->python conversion and then uses eval() + # ---------------------------------------------------------------------- + def evalexpr_string(self, expr): expr = expr.replace("&&"," and ") expr = expr.replace("||"," or ") expr = expr.replace("!"," not ") + expr = expr.replace(" not ="," !=") try: result = eval(expr) except Exception: @@ -805,8 +824,7 @@ class Preprocessor(object): for p in path: iname = os.path.join(p,filename) try: - with open(iname) as f: - data = f.read() + data = self.read_include_file(iname) dname = os.path.dirname(iname) if dname: self.temp_path.insert(0,dname) @@ -821,6 +839,19 @@ class Preprocessor(object): print("Couldn't find '%s'" % filename) # ---------------------------------------------------------------------- + # read_include_file() + # + # Reads a source file for inclusion using #include + # Could be overridden to e.g. customize encoding, limit access to + # certain paths on the filesystem, or provide the contents of system + # include files + # ---------------------------------------------------------------------- + + def read_include_file(self, filepath): + with open(filepath, 'r', encoding='utf-8', errors='surrogateescape') as file: + return file.read() + + # ---------------------------------------------------------------------- # define() # # Define a new macro diff --git a/test/test_cpp_nonascii.c b/test/test_cpp_nonascii.c new file mode 100644 index 0000000..3e97d81 --- /dev/null +++ b/test/test_cpp_nonascii.c @@ -0,0 +1,2 @@ +/* ë */ +#define x 1
\ No newline at end of file diff --git a/test/testcpp.py b/test/testcpp.py index 45478ff..dbfb3e4 100644 --- a/test/testcpp.py +++ b/test/testcpp.py @@ -4,6 +4,7 @@ from multiprocessing import Process, Queue from six.moves.queue import Empty import sys +import locale if ".." not in sys.path: sys.path.insert(0, "..") @@ -114,4 +115,39 @@ a""" a""" ) + def test_evalexpr(self): + # #if 1 != 2 is not processed correctly; undefined values are converted + # to 0L instead of 0 (issue #195) + # + self.__test_preprocessing("""\ +#if (1!=0) && (!x || (!(1==2))) +a; +#else +b; +#endif +""" + , """\ + +a; + +""" + ) + + def test_include_nonascii(self): + # Issue #196: #included files are read using the current locale's + # getdefaultencoding. if a #included file contains non-ascii characters, + # while default encoding is e.g. US_ASCII, this causes an error + locale.setlocale(locale.LC_ALL, 'C') + self.__test_preprocessing("""\ +#include "test_cpp_nonascii.c" +x; + +""" + , """\ + + +1; +""" + ) + main() |