11ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
21ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# flp - Module to load fl forms from fd files
31ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
41ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Jack Jansen, December 1991
51ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
6178582e2a48dab04bb0a20b92d38a8280327dd6fBrett Cannonfrom warnings import warnpy3k
7178582e2a48dab04bb0a20b92d38a8280327dd6fBrett Cannonwarnpy3k("the flp module has been removed in Python 3.0", stacklevel=2)
8178582e2a48dab04bb0a20b92d38a8280327dd6fBrett Cannondel warnpy3k
9178582e2a48dab04bb0a20b92d38a8280327dd6fBrett Cannon
101ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumimport os
111ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumimport sys
121ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumimport FL
131ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
141ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van RossumSPLITLINE = '--------------------'
151ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van RossumFORMLINE = '=============== FORM ==============='
161ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van RossumENDLINE = '=============================='
171ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
18def003845b687b785f70d655a5372906f7e042d2Fred Drakeclass error(Exception):
19def003845b687b785f70d655a5372906f7e042d2Fred Drake    pass
201ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
211ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum##################################################################
221ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#    Part 1 - The parsing routines                               #
231ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum##################################################################
241ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
251ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
261ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Externally visible function. Load form.
271ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
281ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef parse_form(filename, formname):
291ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    forms = checkcache(filename)
301ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if forms is None:
31fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        forms = parse_forms(filename)
321ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if forms.has_key(formname):
33fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return forms[formname]
341ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    else:
35fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise error, 'No such form in fd file'
361ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
371ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
381ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Externally visible function. Load all forms.
391ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
401ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef parse_forms(filename):
411ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    forms = checkcache(filename)
42132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if forms is not None: return forms
431ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp = _open_formfile(filename)
441ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    nforms = _parse_fd_header(fp)
451ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    forms = {}
461ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    for i in range(nforms):
47fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        form = _parse_fd_form(fp, None)
48fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        forms[form[0].Name] = form
491ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    writecache(filename, forms)
501ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return forms
511ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
521ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
531ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal: see if a cached version of the file exists
541ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
551ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van RossumMAGIC = '.fdc'
56fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum_internal_cache = {}                    # Used by frozen scripts only
571ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef checkcache(filename):
581ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if _internal_cache.has_key(filename):
59fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        altforms = _internal_cache[filename]
60fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return _unpack_cache(altforms)
611ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    import marshal
621ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp, filename = _open_formfile2(filename)
631ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.close()
641ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    cachename = filename + 'c'
651ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    try:
66fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        fp = open(cachename, 'r')
671ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    except IOError:
68fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        #print 'flp: no cache file', cachename
69fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return None
701ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    try:
71fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        if fp.read(4) != MAGIC:
72fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            print 'flp: bad magic word in cache file', cachename
73fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            return None
74fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        cache_mtime = rdlong(fp)
75fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        file_mtime = getmtime(filename)
76fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        if cache_mtime != file_mtime:
77fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            #print 'flp: outdated cache file', cachename
78fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            return None
79fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        #print 'flp: valid cache file', cachename
80fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        altforms = marshal.load(fp)
81fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return _unpack_cache(altforms)
821ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    finally:
83fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        fp.close()
841ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
851ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _unpack_cache(altforms):
86182b5aca27d376b08a2904bed42b751496f932f3Tim Peters    forms = {}
87182b5aca27d376b08a2904bed42b751496f932f3Tim Peters    for name in altforms.keys():
88182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        altobj, altlist = altforms[name]
89182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        obj = _newobj()
90182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        obj.make(altobj)
91182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        list = []
92182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        for altobj in altlist:
93182b5aca27d376b08a2904bed42b751496f932f3Tim Peters            nobj = _newobj()
94182b5aca27d376b08a2904bed42b751496f932f3Tim Peters            nobj.make(altobj)
95182b5aca27d376b08a2904bed42b751496f932f3Tim Peters            list.append(nobj)
96182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        forms[name] = obj, list
97182b5aca27d376b08a2904bed42b751496f932f3Tim Peters    return forms
981ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
991ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef rdlong(fp):
1001ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    s = fp.read(4)
1011ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if len(s) != 4: return None
1021ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    a, b, c, d = s[0], s[1], s[2], s[3]
1031ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return ord(a)<<24 | ord(b)<<16 | ord(c)<<8 | ord(d)
1041ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1051ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef wrlong(fp, x):
1061ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    a, b, c, d = (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff
1071ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.write(chr(a) + chr(b) + chr(c) + chr(d))
1081ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1091ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef getmtime(filename):
1101ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    import os
1111ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    from stat import ST_MTIME
1121ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    try:
113fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return os.stat(filename)[ST_MTIME]
1141ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    except os.error:
115fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return None
1161ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1171ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1181ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal: write cached version of the form (parsing is too slow!)
1191ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1201ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef writecache(filename, forms):
1211ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    import marshal
1221ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp, filename = _open_formfile2(filename)
1231ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.close()
1241ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    cachename = filename + 'c'
1251ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    try:
126fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        fp = open(cachename, 'w')
1271ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    except IOError:
128fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print 'flp: can\'t create cache file', cachename
129fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return # Never mind
1301ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.write('\0\0\0\0') # Seek back and write MAGIC when done
1311ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    wrlong(fp, getmtime(filename))
1321ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    altforms = _pack_cache(forms)
1331ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    marshal.dump(altforms, fp)
1341ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.seek(0)
1351ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.write(MAGIC)
1361ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    fp.close()
1371ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    #print 'flp: wrote cache file', cachename
1381ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1391ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1401ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# External: print some statements that set up the internal cache.
1411ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# This is for use with the "freeze" script.  You should call
1421ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# flp.freeze(filename) for all forms used by the script, and collect
1431ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# the output on a file in a module file named "frozenforms.py".  Then
1441ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# in the main program of the script import frozenforms.
1451ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# (Don't forget to take this out when using the unfrozen version of
1461ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# the script!)
1471ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1481ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef freeze(filename):
1491ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    forms = parse_forms(filename)
1501ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    altforms = _pack_cache(forms)
1511ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    print 'import flp'
15270a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald    print 'flp._internal_cache[', repr(filename), '] =', altforms
1531ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1541ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1551ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal: create the data structure to be placed in the cache
1561ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1571ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _pack_cache(forms):
1581ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    altforms = {}
1591ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    for name in forms.keys():
160fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj, list = forms[name]
161fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        altobj = obj.__dict__
162fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        altlist = []
163fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        for obj in list: altlist.append(obj.__dict__)
164fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        altforms[name] = altobj, altlist
1651ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return altforms
1661ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1671ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1681ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal: Locate form file (using PYTHONPATH) and open file
1691ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1701ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _open_formfile(filename):
1711ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return _open_formfile2(filename)[0]
1721ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1731ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _open_formfile2(filename):
174132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if filename[-3:] != '.fd':
175fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        filename = filename + '.fd'
1761ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if filename[0] == '/':
177fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        try:
178fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            fp = open(filename,'r')
179fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        except IOError:
180fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            fp = None
1811ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    else:
182fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        for pc in sys.path:
183fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            pn = os.path.join(pc, filename)
184fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            try:
185fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum                fp = open(pn, 'r')
186fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum                filename = pn
187fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum                break
188fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            except IOError:
189fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum                fp = None
190132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if fp is None:
191fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise error, 'Cannot find forms file ' + filename
1921ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return fp, filename
1931ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
1941ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1951ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal: parse the fd file header, return number of forms
1961ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
1971ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_fd_header(file):
1981ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    # First read the magic header line
1991ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    datum = _parse_1_line(file)
200132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if datum != ('Magic', 12321):
201fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise error, 'Not a forms definition file'
2021ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    # Now skip until we know number of forms
2031ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    while 1:
204fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        datum = _parse_1_line(file)
205fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        if type(datum) == type(()) and datum[0] == 'Numberofforms':
206fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            break
2071ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return datum[1]
2081ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
2091ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal: parse fd form, or skip if name doesn't match.
210a05e293a219f0fbaf4301fa7a292b9578a523675Jeremy Hylton# the special value None means 'always parse it'.
2111ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
2121ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_fd_form(file, name):
2131ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    datum = _parse_1_line(file)
214132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if datum != FORMLINE:
215fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise error, 'Missing === FORM === line'
2161ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    form = _parse_object(file)
217132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if form.Name == name or name is None:
218fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        objs = []
219fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        for j in range(form.Numberofobjects):
220fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            obj = _parse_object(file)
221fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            objs.append(obj)
222fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return (form, objs)
2231ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    else:
224fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        for j in range(form.Numberofobjects):
225fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            _skip_object(file)
2261ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return None
2271ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2281ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
229a05e293a219f0fbaf4301fa7a292b9578a523675Jeremy Hylton# Internal class: a convenient place to store object info fields
2301ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
2311ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumclass _newobj:
2321ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    def add(self, name, value):
233fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        self.__dict__[name] = value
2341ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    def make(self, dict):
235fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        for name in dict.keys():
236fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            self.add(name, dict[name])
2371ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2381ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
2391ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal parsing routines.
2401ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
2411ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_string(str):
2421ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if '\\' in str:
243fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        s = '\'' + str + '\''
244fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        try:
245fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            return eval(s)
246fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        except:
247fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            pass
2481ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return str
2491ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2501ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_num(str):
2511ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return eval(str)
2521ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2531ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_numlist(str):
254b3acd3e4d338ef41d50b86e9230646c510bb5c6aEric S. Raymond    slist = str.split()
2551ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    nlist = []
2561ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    for i in slist:
257fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        nlist.append(_parse_num(i))
2581ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return nlist
2591ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2601ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# This dictionary maps item names to parsing routines.
2611ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# If no routine is given '_parse_num' is default.
2621ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum_parse_func = { \
263fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Name':         _parse_string, \
264fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Box':          _parse_numlist, \
265fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Colors':       _parse_numlist, \
266fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Label':        _parse_string, \
267fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Name':         _parse_string, \
268fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Callback':     _parse_string, \
269fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        'Argument':     _parse_string }
2701ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2711ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# This function parses a line, and returns either
2721ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# a string or a tuple (name,value)
2731ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2749694fcab5332f27dc28b195ba1391e5491d2eaefGuido van Rossumimport re
2759694fcab5332f27dc28b195ba1391e5491d2eaefGuido van Rossumprog = re.compile('^([^:]*): *(.*)')
2761ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2771ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_line(line):
2789694fcab5332f27dc28b195ba1391e5491d2eaefGuido van Rossum    match = prog.match(line)
2799694fcab5332f27dc28b195ba1391e5491d2eaefGuido van Rossum    if not match:
280fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        return line
2819694fcab5332f27dc28b195ba1391e5491d2eaefGuido van Rossum    name, value = match.group(1, 2)
2821ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if name[0] == 'N':
283182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        name = ''.join(name.split())
284182b5aca27d376b08a2904bed42b751496f932f3Tim Peters        name = name.lower()
285b3acd3e4d338ef41d50b86e9230646c510bb5c6aEric S. Raymond    name = name.capitalize()
2861ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    try:
287fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        pf = _parse_func[name]
2881ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    except KeyError:
289fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        pf = _parse_num
2901ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    value = pf(value)
2911ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return (name, value)
2921ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
2931ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _readline(file):
2941ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    line = file.readline()
2951ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if not line:
296fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise EOFError
2971ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return line[:-1]
298182b5aca27d376b08a2904bed42b751496f932f3Tim Peters
2991ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_1_line(file):
3001ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    line = _readline(file)
3011ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    while line == '':
302fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        line = _readline(file)
3031ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return _parse_line(line)
3041ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3051ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _skip_object(file):
3061ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    line = ''
3071ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    while not line in (SPLITLINE, FORMLINE, ENDLINE):
308fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        pos = file.tell()
309fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        line = _readline(file)
3101ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if line == FORMLINE:
311fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        file.seek(pos)
3121ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3131ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _parse_object(file):
3141ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    obj = _newobj()
3151ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    while 1:
316fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        pos = file.tell()
317fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        datum = _parse_1_line(file)
318fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        if datum in (SPLITLINE, FORMLINE, ENDLINE):
319fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            if datum == FORMLINE:
320fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum                file.seek(pos)
321fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            return obj
322132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake        if type(datum) is not type(()) or len(datum) != 2:
323fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            raise error, 'Parse error, illegal line in object: '+datum
324fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.add(datum[0], datum[1])
3251ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3261ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#################################################################
3271ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#   Part 2 - High-level object/form creation routines            #
3281ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#################################################################
3291ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3301ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3319a118f1dc3f23ead28f31fdc5144ad5ce01e5b7fSerhiy Storchaka# External - Create a form and link to an instance variable.
3321ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3331ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef create_full_form(inst, (fdata, odatalist)):
3341ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    form = create_form(fdata)
3351ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    exec 'inst.'+fdata.Name+' = form\n'
3361ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    for odata in odatalist:
337fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        create_object_instance(inst, form, odata)
3381ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3391ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3401ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# External - Merge a form into an existing form in an instance
3411ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# variable.
3421ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3431ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef merge_full_form(inst, form, (fdata, odatalist)):
3441ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    exec 'inst.'+fdata.Name+' = form\n'
345132dce22469f476f399d1bbc6d1cc2f7ba0110ccFred Drake    if odatalist[0].Class != FL.BOX:
346fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise error, 'merge_full_form() expects FL.BOX as first obj'
3471ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    for odata in odatalist[1:]:
348fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        create_object_instance(inst, form, odata)
3491ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3501ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3511ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#################################################################
3521ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#   Part 3 - Low-level object/form creation routines            #
3531ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#################################################################
3541ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3551ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3561ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# External Create_form - Create form from parameters
3571ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3581ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef create_form(fdata):
3591ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    import fl
3601ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return fl.make_form(FL.NO_BOX, fdata.Width, fdata.Height)
3611ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
3621ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3631ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# External create_object - Create an object. Make sure there are
3641ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# no callbacks. Returns the object created.
3651ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3661ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef create_object(form, odata):
3671ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    obj = _create_object(form, odata)
3681ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if odata.Callback:
369fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        raise error, 'Creating free object with callback'
3701ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return obj
3711ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3721ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# External create_object_instance - Create object in an instance.
3731ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3741ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef create_object_instance(inst, form, odata):
3751ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    obj = _create_object(form, odata)
3761ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if odata.Callback:
377fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        cbfunc = eval('inst.'+odata.Callback)
378fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.set_call_back(cbfunc, odata.Argument)
3791ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if odata.Name:
380fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        exec 'inst.' + odata.Name + ' = obj\n'
3811ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3821ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal _create_object: Create the object and fill options
3831ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3841ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _create_object(form, odata):
3851ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    crfunc = _select_crfunc(form, odata.Class)
3861ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    obj = crfunc(odata.Type, odata.Box[0], odata.Box[1], odata.Box[2], \
387fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            odata.Box[3], odata.Label)
3881ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if not odata.Class in (FL.BEGIN_GROUP, FL.END_GROUP):
389fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.boxtype = odata.Boxtype
390fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.col1 = odata.Colors[0]
391fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.col2 = odata.Colors[1]
392fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.align = odata.Alignment
393fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.lstyle = odata.Style
394fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.lsize = odata.Size
395fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        obj.lcol = odata.Lcol
3961ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    return obj
3971ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
3981ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum# Internal crfunc: helper function that returns correct create function
3991ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum#
4001ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _select_crfunc(fm, cl):
4011ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if cl == FL.BEGIN_GROUP: return fm.bgn_group
4021ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.END_GROUP: return fm.end_group
4031ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.BITMAP: return fm.add_bitmap
4041ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.BOX: return fm.add_box
4051ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.BROWSER: return fm.add_browser
4061ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.BUTTON: return fm.add_button
4071ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.CHART: return fm.add_chart
4081ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.CHOICE: return fm.add_choice
4091ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.CLOCK: return fm.add_clock
4101ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.COUNTER: return fm.add_counter
4111ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.DIAL: return fm.add_dial
4121ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.FREE: return fm.add_free
4131ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.INPUT: return fm.add_input
4141ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.LIGHTBUTTON: return fm.add_lightbutton
4151ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.MENU: return fm.add_menu
4161ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.POSITIONER: return fm.add_positioner
4171ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.ROUNDBUTTON: return fm.add_roundbutton
4181ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.SLIDER: return fm.add_slider
4191ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.VALSLIDER: return fm.add_valslider
4201ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.TEXT: return fm.add_text
4211ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif cl == FL.TIMER: return fm.add_timer
4221ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    else:
42370a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald        raise error, 'Unknown object type: %r' % (cl,)
4241ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
4251ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
4261ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef test():
4271ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    import time
4281ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    t0 = time.time()
4291ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    if len(sys.argv) == 2:
430fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        forms = parse_forms(sys.argv[1])
431fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        t1 = time.time()
432fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print 'parse time:', 0.001*(t1-t0), 'sec.'
433fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        keys = forms.keys()
434fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        keys.sort()
435fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        for i in keys:
436fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum            _printform(forms[i])
4371ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    elif len(sys.argv) == 3:
438fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        form = parse_form(sys.argv[1], sys.argv[2])
439fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        t1 = time.time()
440fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print 'parse time:', round(t1-t0, 3), 'sec.'
441fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        _printform(form)
4421ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    else:
443fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print 'Usage: test fdfile [form]'
4441ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum
4451ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossumdef _printform(form):
4461ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    f = form[0]
4471ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    objs = form[1]
4481ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    print 'Form ', f.Name, ', size: ', f.Width, f.Height, ' Nobj ', f.Numberofobjects
4491ce7c6fde8a8879ec64242dc0d01b660b934633aGuido van Rossum    for i in objs:
450fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print '  Obj ', i.Name, ' type ', i.Class, i.Type
451fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print '    Box ', i.Box, ' btype ', i.Boxtype
452fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print '    Label ', i.Label, ' size/style/col/align ', i.Size,i.Style, i.Lcol, i.Alignment
453fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print '    cols ', i.Colors
454fa6e254b34b7a0f85cb34a9fd99b5a6400714940Guido van Rossum        print '    cback ', i.Callback, i.Argument
455