]> thyrsus.com Git - mad.git/commitdiff
Break type ceduction out of format conversion.
authorEric S. Raymond <esr@thyrsus,com>
Tue, 24 Feb 2004 10:17:04 +0000 (10:17 +0000)
committerEric S. Raymond <esr@thyrsus,com>
Tue, 24 Feb 2004 10:17:04 +0000 (10:17 +0000)
mad

diff --git a/mad b/mad
index 64874eb5652874209014dc5841b06ec3aef31289..8b54b14f5ac21e4514089192487c39fe119db62b 100755 (executable)
--- a/mad
+++ b/mad
@@ -620,7 +620,7 @@ def analyze():
                 if statement[1] not in format:
                     nonfatal("uninitialized format string" +`statement[1]`)
                 else:
-                    (fmt, types) = fmt_convert(format[statement[1]])
+                    types = deduce_types(fmt_convert(format[statement[1]]))
                     for (vtype, var) in zip(types, statement[2:]):
                         if type(var) == type(()) and var[0] == 'range':
                             typedict[var[1]] = vtype
@@ -816,7 +816,6 @@ def fmt_convert(str):
     #print "->fmt_convert(%s)" % str
     fmt = str
     res = ''
-    types = []
     while True:
         if str[0] == '*':
             break
@@ -847,29 +846,23 @@ def fmt_convert(str):
         # Now process the actual format item
         if str[0] == '(':
             i = str.find(')')
-            (innerfmt, innertypes) = fmt_convert(str[1:i]+"*")
-            res += innerfmt * count
+            res += fmt_convert(str[1:i]+"*") * count
             str = str[i+1:]
-            for i in range(count):
-                types += innertypes * count
         elif str[0] == 'C':
             i = 1
             while str[i] in '0123456789':
                 i += 1
             res += "%" + `count * int(str[1:i])` + "s"
             str = str[i:]
-            types += ['char']
         elif str[0] == 'F':
             i = 1
             while str[i] in '0123456789.':
                 i += 1
             res += ('%' + str[1:i] + 'g') * count
             str = str[i:]
-            types += ['double'] * count
         elif str[0] == 'H':
             res += str[1:count+1]
             str = str[count+1:]
-            types += ['char']
         elif str[0] == 'I':
             i = 1
             while str[i] in '0123456789':
@@ -879,14 +872,34 @@ def fmt_convert(str):
                 lenprefix = ''
             res += ('%' + lenprefix + 'd') * count
             str = str[i:]
-            types += ['int'] * count
         else:
             nonfatal('invalid field code %s at %d in format string %s!\n' % (`str[0]`, len(fmt)-len(str), `fmt`))
     #print "<-fmt_convert() = %s" % res
-    return (res, types)
+    return res
+
+def deduce_types(str):
+    "Deduce types from C format string converted from MAD format."
+    types = []
+    state = 0
+    # Simplified by the fact that MAD strings can't contain %.
+    for i in range(len(str)):
+        if str[i] == "%":
+            state = 1
+        elif state == 1:
+            if str[i].isdigit() or str[i] in ('.', '-', '+'):
+                continue
+            if str[i] == 's':
+                types.append("char")
+            elif str[i] == 'g':
+                types.append("double")
+            elif str[i] == 'd':
+                types.append("int")
+            else:
+                state = 0
+    return types
 
 def lptcodes(res):
-    "Interpret format character"
+    "Interpret line-printer control character at start of format string."
     if res[0] == ' ':          # Single space
         res = res[1:]
     elif res[0] == '0':                # Double space
@@ -984,14 +997,14 @@ def print_C_statement(statement):
     elif statement[0] == 'pause':
         return('printf("%o", ' + print_C_expr(statement[1]) + '); getchar();')
     elif statement[0] == 'print':
-        (fmt, types) = fmt_convert(format[statement[1]])
-        fmt = lptcodes(fmt)
+        fmt = lptcodes(fmt_convert(format[statement[1]]))
         if len(statement) < 3:
             return 'printf("' + fmt + '");'
         else:
             return 'printf("' + fmt + '", ' + ', '.join(map(print_C_expr, statement[2:])) + ');'
     elif statement[0] == 'read':
-        (fmt, types) = fmt_convert(format[statement[1]])
+        fmt = fmt_convert(format[statement[1]])
+        types = deduce_types(fmt)
         inlist = []
         for (ispec, itype) in zip(statement[2:], types):
             if type(ispec) == type(""):