From 4f714f4e695627b37fe325151a3e77f9868e2010 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 24 Feb 2004 10:17:04 +0000 Subject: [PATCH] Break type ceduction out of format conversion. --- mad | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/mad b/mad index 64874eb..8b54b14 100755 --- 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(""): -- 2.43.0