]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[freestanding] Improve macro resolution to handle #if X
authorNick Terrell <terrelln@fb.com>
Thu, 24 Sep 2020 23:25:58 +0000 (16:25 -0700)
committerNick Terrell <terrelln@fb.com>
Fri, 25 Sep 2020 02:42:04 +0000 (19:42 -0700)
contrib/freestanding_lib/freestanding.py
lib/compress/zstd_compress.c

index f96543f0462aae302acc664354d66a324b1aeb12..9e91a489a737df49a287e0a58188855dc2bfd55b 100755 (executable)
@@ -78,7 +78,7 @@ class PartialPreprocessor(object):
             fr"\s*#\s*{ELIF_GROUP}if\s+(?P<not>!)?\s*defined\s*\(\s*{MACRO_GROUP}\s*\)\s*{OP_GROUP}"
         )
         self._if_defined_value = re.compile(
-            fr"\s*#\s*if\s+defined\s*\(\s*{MACRO_GROUP}\s*\)\s*"
+            fr"\s*#\s*{ELIF_GROUP}if\s+defined\s*\(\s*{MACRO_GROUP}\s*\)\s*"
             fr"(?P<op>&&)\s*"
             fr"(?P<openp>\()?\s*"
             fr"(?P<macro2>[a-zA-Z_][a-zA-Z_0-9]*)\s*"
@@ -86,6 +86,9 @@ class PartialPreprocessor(object):
             fr"(?P<value>[0-9]*)\s*"
             fr"(?P<closep>\))?\s*"
         )
+        self._if_true = re.compile(
+            fr"\s*#\s*{ELIF_GROUP}if\s+{MACRO_GROUP}\s*{OP_GROUP}"
+        )
 
         self._c_comment = re.compile(r"/\*.*?\*/")
         self._cpp_comment = re.compile(r"//")
@@ -262,10 +265,14 @@ class PartialPreprocessor(object):
             line = self._inlines[idx]
             sline = self._strip_comments(line)
             m = self._ifdef.fullmatch(sline)
+            if_true = False
             if m is None:
                 m = self._if_defined_value.fullmatch(sline)
             if m is None:
                 m = self._if_defined.match(sline)
+            if m is None:
+                m = self._if_true.match(sline)
+                if_true = (m is not None)
             if m is None:
                 outlines.append(line)
                 idx += 1
@@ -273,84 +280,116 @@ class PartialPreprocessor(object):
 
             groups = m.groupdict()
             macro = groups['macro']
-            ifdef = groups.get('not') is None
-            elseif = groups.get('elif') is not None
             op = groups.get('op')
 
-            macro2 = groups.get('macro2')
-            cmp = groups.get('cmp')
-            value = groups.get('value')
-            openp = groups.get('openp')
-            closep = groups.get('closep')
-
             if not (macro in self._defs or macro in self._undefs):
                 outlines.append(line)
                 idx += 1
                 continue
 
             defined = macro in self._defs
-            is_true = (ifdef == defined)
-            resolved = True
-            if op is not None:
-                if op == '&&':
-                    resolved = not is_true
-                else:
-                    assert op == '||'
-                    resolved = is_true
-
-            if macro2 is not None and not resolved:
-                assert ifdef and defined and op == '&&' and cmp is not None
-                # If the statment is true, but we have a single value check, then
-                # check the value.
+
+            # Needed variables set:
+            # resolved: Is the statement fully resolved?
+            # is_true: If resolved, is the statement true?
+            ifdef = False
+            if if_true:
+                if not defined:
+                    outlines.append(line)
+                    idx += 1
+                    continue
+
                 defined_value = self._defs[macro]
-                are_ints = True
+                is_int = True
                 try:
                     defined_value = int(defined_value)
-                    value = int(value)
                 except TypeError:
-                    are_ints = False
+                    is_int = False
                 except ValueError:
-                    are_ints = False
-                if (
-                        macro == macro2 and
-                        ((openp is None) == (closep is None)) and
-                        are_ints
-                ):
-                    resolved = True
-                    if cmp == '<':
-                        is_true = defined_value < value
-                    elif cmp == '<=':
-                        is_true = defined_value <= value
-                    elif cmp == '==':
-                        is_true = defined_value == value
-                    elif cmp == '!=':
-                        is_true = defined_value != value
-                    elif cmp == '>=':
-                        is_true = defined_value >= value
-                    elif cmp == '>':
-                        is_true = defined_value > value
+                    is_int = False
+
+                resolved = is_int
+                is_true = (defined_value != 0)
+
+                if resolved and op is not None:
+                    if op == '&&':
+                        resolved = not is_true
                     else:
-                        resolved = False
-
-            if op is not None and not resolved:
-                # Remove the first op in the line + spaces
-                if op == '&&':
-                    opre = op
-                else:
-                    assert op == '||'
-                    opre = r'\|\|'
-                needle = re.compile(fr"(?P<if>\s*#\s*(el)?if\s+).*?(?P<op>{opre}\s*)")
-                match = needle.match(line)
-                assert match is not None
-                newline = line[:match.end('if')] + line[match.end('op'):]
-
-                self._log(f"\tHardwiring partially resolved {macro}")
-                self._log(f"\t\t- {line[:-1]}")
-                self._log(f"\t\t+ {newline[:-1]}")
-
-                outlines.append(newline)
-                idx += 1
-                continue
+                        assert op == '||'
+                        resolved = is_true
+
+            else:
+                ifdef = groups.get('not') is None
+                elseif = groups.get('elif') is not None
+
+                macro2 = groups.get('macro2')
+                cmp = groups.get('cmp')
+                value = groups.get('value')
+                openp = groups.get('openp')
+                closep = groups.get('closep')
+
+                is_true = (ifdef == defined)
+                resolved = True
+                if op is not None:
+                    if op == '&&':
+                        resolved = not is_true
+                    else:
+                        assert op == '||'
+                        resolved = is_true
+
+                if macro2 is not None and not resolved:
+                    assert ifdef and defined and op == '&&' and cmp is not None
+                    # If the statment is true, but we have a single value check, then
+                    # check the value.
+                    defined_value = self._defs[macro]
+                    are_ints = True
+                    try:
+                        defined_value = int(defined_value)
+                        value = int(value)
+                    except TypeError:
+                        are_ints = False
+                    except ValueError:
+                        are_ints = False
+                    if (
+                            macro == macro2 and
+                            ((openp is None) == (closep is None)) and
+                            are_ints
+                    ):
+                        resolved = True
+                        if cmp == '<':
+                            is_true = defined_value < value
+                        elif cmp == '<=':
+                            is_true = defined_value <= value
+                        elif cmp == '==':
+                            is_true = defined_value == value
+                        elif cmp == '!=':
+                            is_true = defined_value != value
+                        elif cmp == '>=':
+                            is_true = defined_value >= value
+                        elif cmp == '>':
+                            is_true = defined_value > value
+                        else:
+                            resolved = False
+
+                if op is not None and not resolved:
+                    # Remove the first op in the line + spaces
+                    if op == '&&':
+                        opre = op
+                    else:
+                        assert op == '||'
+                        opre = r'\|\|'
+                    needle = re.compile(fr"(?P<if>\s*#\s*(el)?if\s+).*?(?P<op>{opre}\s*)")
+                    match = needle.match(line)
+                    assert match is not None
+                    newline = line[:match.end('if')] + line[match.end('op'):]
+
+                    self._log(f"\tHardwiring partially resolved {macro}")
+                    self._log(f"\t\t- {line[:-1]}")
+                    self._log(f"\t\t+ {newline[:-1]}")
+
+                    outlines.append(newline)
+                    idx += 1
+                    continue
 
             # Skip any statements we cannot fully compute
             if not resolved:
index dc6964f33464facfc0a99c80c3799f43dcc8e786..7fe539c3de32ec6585dda7cf150104f39b6c8f1d 100644 (file)
@@ -1902,7 +1902,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
     assert((size & (ZSTD_ROWSIZE-1)) == 0);  /* multiple of ZSTD_ROWSIZE */
     assert(size < (1U<<31));   /* can be casted to int */
 
-#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
+#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
     /* To validate that the table re-use logic is sound, and that we don't
      * access table space that we haven't cleaned, we re-"poison" the table
      * space every time we mark it dirty.