From ea1018a0cbeebd622c7a556f10ea7363aed58dd1 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 1 Sep 2009 02:08:45 +0000 Subject: Split into spec translation and generation. --- jsongen.py | 131 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 49 deletions(-) (limited to 'jsongen.py') diff --git a/jsongen.py b/jsongen.py index d684b6fb..ff736e0e 100755 --- a/jsongen.py +++ b/jsongen.py @@ -11,41 +11,75 @@ import sys, getopt # Make shared field names to data types typemap = { - # AIS fields "raim":"boolean", "accuracy":"boolean", "timestamp":"string", } -# Map C and Python-type format letters to JSON parser datatypes -fmtmap = { - "d": "integer", - "u": "uinteger", - "f": "real", - "a": "string", - } - - ais_specs = ( - ("json_ais4", "\tAIS_HEADER,", "ais->type4", - "\"timestamp\":\"%4u:%02u:%02uT%02u:%02u:%02uZ\","\ - "\"accuracy\":%s,\"lon\":%d,\"lat\":%d,"\ - "\"epfd\":%u,\"raim\":%s,\"radio\":%d}\r\n" - ), - ) + { + "initname" : "json_ais4", + "header": "\tAIS_HEADER,", + "structname": "ais->type4", + "fieldmap":( + # fieldname type default + ('timestamp', 'string', None), + ('accuracy', 'boolean', "true"), + ('lon', 'integer', "AIS_LON_NOT_AVAILABLE"), + ('lat', 'integer', "AIS_LAT_NOT_AVAILABLE"), + ('epfd', 'uinteger', "0"), + ('raim', 'boolean', "false"), + ('radio', 'integer', "0"), + ), + "stringbuffered":("timestamp",), + }, +) -def generate(initname, header, structname, specifier): - specifier = specifier.strip() - if specifier[-1] == "}": - specifier = specifier[:-1] +def generate(spec): + print " const struct json_attr_t %s[] = {" % spec["initname"] + if spec["header"]: + print spec["header"] + for (attr, itype, default) in spec["fieldmap"]: + structname = spec["structname"] + if itype == "string": + deref = "" + else: + deref = "&" + if attr in spec["stringbuffered"]: + target = attr + else: + target = structname + "." + attr + print '\t{"%s",%s%s,%s.addr.%s = %s%s,' % \ + (attr, " "*(12-len(attr)),itype, " "*(12-len(itype)), itype, deref, target) + leader = " " * 37 + if itype == "string": + print leader + ".maxlen = sizeof(%s)}," % target + else: + print leader + ".dflt.%s = %s}," % (itype, default) + + print """\ + {NULL}, + }; + +""" + +def string_to_specifier(strspec): + "Compile a Python-style format string to an attribute-type fieldmap." + # Map C and Python-type format letters to JSON parser datatypes + fmtmap = { + "d": "integer", + "u": "uinteger", + "f": "real", + "a": "string", + } + strspec = strspec.strip() + if strspec[-1] == "}": + strspec = strspec[:-1] else: print "Missing terminating }" sys.exit(1) - - print " const struct json_attr_t %s[] = {" % initname - if header: - print header - for item in specifier.split(","): + print '"fieldmap":(' + for item in strspec.split(","): if "timestamp" in item: (attr, itype) = ("timestamp", "string") else: @@ -59,31 +93,30 @@ def generate(initname, header, structname, specifier): itype = typemap[attr] if fmt[-1] in fmtmap: itype = fmtmap[fmt[-1]] - if itype == "string": - deref = "" - else: - deref = "&" - print '\t{"%s",%s%s,%s.addr.%s = %s%s.%s,' % \ - (attr, " "*(12-len(attr)),itype, " "*(12-len(itype)), itype, deref, structname, attr) - leader = " " * 37 - if itype == "string": - print leader + ".maxlen = sizeof(%s.%s)}," % (structname, attr) - elif itype == "boolean": - print leader + ".dflt.boolean = false}," - elif itype == "real": - print leader + ".dflt.real = 0.0}," - else: - print leader + ".dflt.%s = 0}," % itype + print " " + `(attr, itype)` + "," + print " )" - print """\ - {NULL}, - }; -""" +# Edit into this global the string spec you need to convert +stringspec = \ +"\"timestamp\":\"%4u:%02u:%02uT%02u:%02u:%02uZ\","\ + "\"accuracy\":%s,\"lon\":%d,\"lat\":%d,"\ + "\"epfd\":%u,\"raim\":%s,\"radio\":%d}\r\n" if __name__ == '__main__': - for description in ais_specs: - generate(initname=description[0], - header=description[1], - structname=description[2], - specifier=description[3]) + try: + (options, arguments) = getopt.getopt(sys.argv[1:], "g") + except getopt.GetoptError, msg: + print "jsongen.py: " + str(msg) + raise SystemExit, 1 + + specify = False + for (switch, val) in options: + if (switch == '-g'): + specify = True + + if specify: + string_to_specifier(stringspec) + else: + for description in ais_specs: + generate(description) -- cgit v1.2.1