Fix a bug in ifndef.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 20 Feb 2009 17:27:33 -0500
changeset 150 d3574d51916d
parent 149 729f4f785446
child 152 a1d75c7a23fb
child 153 6b366de3a54b
child 154 c8132cbf96e4
push id86
push userbsmedberg@mozilla.com
push date2009-02-21 00:25 +0000
Fix a bug in ifndef.
mkparse.py
pymake/parserdata.py
tests/ifdefs.mk
new file mode 100755
--- /dev/null
+++ b/mkparse.py
@@ -0,0 +1,8 @@
+import sys
+import pymake.parser
+
+for f in sys.argv[1:]:
+    print "Parsing %s" % f
+    fd = open(f)
+    stmts = pymake.parser.parsestream(fd, f)
+    print stmts
--- a/pymake/parserdata.py
+++ b/pymake/parserdata.py
@@ -91,18 +91,22 @@ class Statement(object):
 
 class Override(Statement):
     def __init__(self, s):
         self.s = s
 
     def execute(self, makefile, context):
         makefile.overrides.append(self.s)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "Override: %r" % (self.s,)
+
 class DummyRule(object):
     def addcommand(self, r):
+        _log.debug("Discarding rule at %s" % (r.loc,))
         pass
 
 class Rule(Statement):
     def __init__(self, targetexp, depexp, doublecolon):
         assert isinstance(targetexp, data.Expansion)
         assert isinstance(depexp, data.Expansion)
         
         self.targetexp = targetexp
@@ -129,16 +133,19 @@ class Rule(Statement):
         else:
             rule = data.Rule(deps, self.doublecolon, loc=self.targetexp.loc)
             for t in targets:
                 makefile.gettarget(t.gettarget()).addrule(rule)
             makefile.foundtarget(targets[0].gettarget())
 
         context.currule = rule
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "Rule %s: %s" % (self.targetexp, self.depexp)
+
 class StaticPatternRule(Statement):
     def __init__(self, targetexp, patternexp, depexp, doublecolon):
         assert isinstance(targetexp, data.Expansion)
         assert isinstance(patternexp, data.Expansion)
         assert isinstance(depexp, data.Expansion)
 
         self.targetexp = targetexp
         self.patternexp = patternexp
@@ -167,25 +174,31 @@ class StaticPatternRule(Statement):
             stem = pattern.match(t)
             if stem is None:
                 raise data.DataError("Target '%s' does not match the static pattern '%s'" % (t, pattern), self.targetexp.loc)
             makefile.gettarget(t).addrule(data.PatternRuleInstance(rule, '', stem, pattern.ismatchany()))
 
         makefile.foundtarget(targets[0])
         context.currule = rule
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "StaticPatternRule %r: %r: %r" % (self.targetexp, self.patternexp, self.depexp)
+
 class Command(Statement):
     def __init__(self, exp):
         assert isinstance(exp, data.Expansion)
         self.exp = exp
 
     def execute(self, makefile, context):
         assert context.currule is not None
         context.currule.addcommand(self.exp)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "Command %r" % (self.exp,)
+
 class SetVariable(Statement):
     def __init__(self, vnameexp, token, value, valueloc, targetexp, source=None):
         assert isinstance(vnameexp, data.Expansion)
         assert isinstance(value, str)
         assert targetexp is None or isinstance(targetexp, data.Expansion)
 
         if source is None:
             source = data.Variables.SOURCE_MAKEFILE
@@ -233,16 +246,19 @@ class SetVariable(Statement):
 
                 flavor = data.Variables.FLAVOR_SIMPLE
                 d = parser.Data.fromstring(self.value, self.valueloc)
                 e, t, o = parser.parsemakesyntax(d, 0, (), parser.iterdata)
                 value = e.resolve(makefile, makefile.variables)
 
             v.set(vname, flavor, self.source, value)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "SetVariable %r value=%r" % (self.vnameexp, self.value)
+
 class Condition(object):
     """
     An abstract "condition", either ifeq or ifdef, perhaps negated. Subclasses must implement:
 
     def evaluate(self, makefile)
     """
 
 class EqCondition(Condition):
@@ -255,36 +271,47 @@ class EqCondition(Condition):
         self.exp1 = exp1
         self.exp2 = exp2
 
     def evaluate(self, makefile):
         r1 = self.exp1.resolve(makefile, makefile.variables)
         r2 = self.exp2.resolve(makefile, makefile.variables)
         return (r1 == r2) == self.expected
 
+    def __str__(self):
+        return "ifeq (expected=%s) %r %r" % (self.expected, self.exp1, self.exp2)
+
 class IfdefCondition(Condition):
     expected = True
 
     def __init__(self, exp):
         assert isinstance(exp, data.Expansion)
         self.exp = exp
 
     def evaluate(self, makefile):
         vname = self.exp.resolve(makefile, makefile.variables)
         flavor, source, value = makefile.variables.get(vname, expand=False)
 
+        _log.debug("ifdef at %s: vname: %r value is %r" % (self.exp.loc, vname, value))
+
         if value is None:
-            return False
+            return not self.expected
 
         return (len(value) > 0) == self.expected
 
+    def __str__(self):
+        return "ifdef (expected=%s) %r" % (self.expected, self.exp)
+
 class ElseCondition(Condition):
     def evaluate(self, makefile):
         return True
 
+    def __str__(self):
+        return "else"
+
 class ConditionBlock(Statement):
     """
     A list of conditions: each condition has an associated list of statements.
     """
     def __init__(self, loc, condition):
         self.loc = loc
         self._groups = []
         self.addcondition(loc, condition)
@@ -299,32 +326,50 @@ class ConditionBlock(Statement):
             raise parser.SyntaxError("Multiple else conditions for block starting at %s" % self.loc, loc)
 
         self._groups.append((condition, StatementList()))
 
     def append(self, statement):
         self._groups[-1][1].append(statement)
 
     def execute(self, makefile, context):
+        i = 0
         for c, statements in self._groups:
             if c.evaluate(makefile):
+                _log.debug("Condition at %s met by clause #%i" % (self.loc, i))
                 statements.execute(makefile, context)
                 return
 
+            i += 1
+
+    def dump(self, fd, indent):
+        print >>fd, indent, "ConditionBlock"
+
+        indent1 = indent + ' '
+        indent2 = indent + '  '
+        for c, statements in self._groups:
+            print >>fd, indent1, "Condition %s" % (c,)
+            for s in statements:
+                s.dump(fd, indent2)
+        print >>fd, indent, "~ConditionBlock"
+
 class Include(Statement):
     def __init__(self, exp, required):
         assert isinstance(exp, data.Expansion)
         self.exp = exp
         self.required = required
 
     def execute(self, makefile, context):
         files = data.splitwords(self.exp.resolve(makefile, makefile.variables))
         for f in files:
             makefile.include(f, self.required, loc=self.exp.loc)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "Include %r" % (self.exp,)
+
 class VPathDirective(Statement):
     def __init__(self, exp):
         assert isinstance(exp, data.Expansion)
         self.exp = exp
 
     def execute(self, makefile, context):
         words = data.splitwords(self.exp.resolve(makefile, makefile.variables))
         if len(words) == 0:
@@ -338,16 +383,19 @@ class VPathDirective(Statement):
             else:
                 dirs = []
                 for mpath in mpaths:
                     dirs.extend((dir for dir in mpath.split(':')
                                  if dir != ''))
                 if len(dirs):
                     makefile.addvpath(pattern, dirs)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "VPath %r" % (self.exp,)
+
 class ExportDirective(Statement):
     def __init__(self, exp, single):
         assert isinstance(exp, data.Expansion)
         self.exp = exp
         self.single = single
 
     def execute(self, makefile, context):
         if self.single:
@@ -355,29 +403,43 @@ class ExportDirective(Statement):
         else:
             vlist = data.splitwords(self.exp.resolve(makefile, makefile.variables))
             if not len(vlist):
                 raise data.DataError("Exporting all variables is not supported", self.exp.loc)
 
         for v in vlist:
             makefile.exportedvars.add(v)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "Export (single=%s) %r" % (self.single, self.exp)
+
 class EmptyDirective(Statement):
     def __init__(self, exp):
         assert isinstance(exp, data.Expansion)
         self.exp = exp
 
     def execute(self, makefile, context):
         v = self.exp.resolve(makefile, makefile.variables)
         if v.strip() != '':
             raise data.DataError("Line expands to non-empty value", self.exp.loc)
 
+    def dump(self, fd, indent):
+        print >>fd, indent, "EmptyDirective: %r" % self.exp
+
 class StatementList(list):
     def append(self, statement):
         assert isinstance(statement, Statement)
         list.append(self, statement)
 
     def execute(self, makefile, context=None):
         if context is None:
             context = util.makeobject('currule')
 
         for s in self:
             s.execute(makefile, context)
+
+    def __str__(self):
+        fd = StringIO()
+        print >>fd, "StatementList"
+        for s in self:
+            s.dump(fd, ' ')
+        print >>fd, "~StatementList"
+        return fd.getvalue()
--- a/tests/ifdefs.mk
+++ b/tests/ifdefs.mk
@@ -41,16 +41,21 @@ BAZ3FOUND = true
 endif
 
 ifdef RANDOM
 CONTINUATION = \
 else           \
 endif
 endif
 
+ifndef ASDFJK
+else
+$(error ASFDJK was not set)
+endif
+
 TESTSET =
 
 ifdef TESTSET
 $(error TESTSET was not set)
 endif
 
 TESTEMPTY = $(NULL)
 ifndef TESTEMPTY