xref: /aoo42x/main/toolkit/src2xml/source/src2xml.py (revision cdf0e10c)
1*cdf0e10cSrcweir#!/usr/bin/env python
2*cdf0e10cSrcweir
3*cdf0e10cSrcweirimport getopt
4*cdf0e10cSrcweirimport os
5*cdf0e10cSrcweirimport re
6*cdf0e10cSrcweirimport sys
7*cdf0e10cSrcweir#
8*cdf0e10cSrcweirfrom srclexer import SrcLexer
9*cdf0e10cSrcweirfrom srcparser import SrcParser
10*cdf0e10cSrcweirfrom boxer import Boxer
11*cdf0e10cSrcweir# FIXME
12*cdf0e10cSrcweirfrom globals import *
13*cdf0e10cSrcweir
14*cdf0e10cSrcweirdef option_parser ():
15*cdf0e10cSrcweir    import optparse
16*cdf0e10cSrcweir    p = optparse.OptionParser ()
17*cdf0e10cSrcweir
18*cdf0e10cSrcweir    p.usage = '''src2xml.py [OPTION]... SRC-FILE...'''
19*cdf0e10cSrcweir
20*cdf0e10cSrcweir    examples = '''
21*cdf0e10cSrcweirExamples:
22*cdf0e10cSrcweir  src2xml.py --output-dir=. --post-process --ignore-includes zoom.src
23*cdf0e10cSrcweir  src2xml.py --dry-run -I svx/inc -I svx/source/dialog zoom.src
24*cdf0e10cSrcweir'''
25*cdf0e10cSrcweir
26*cdf0e10cSrcweir    def format_examples (self):
27*cdf0e10cSrcweir        return examples
28*cdf0e10cSrcweir
29*cdf0e10cSrcweir    if 'epilog' in  p.__dict__:
30*cdf0e10cSrcweir        p.formatter.format_epilog = format_examples
31*cdf0e10cSrcweir        p.epilog = examples
32*cdf0e10cSrcweir    else:
33*cdf0e10cSrcweir        p.formatter.format_description = format_examples
34*cdf0e10cSrcweir        p.description = examples
35*cdf0e10cSrcweir
36*cdf0e10cSrcweir    p.description = '''OOo SRC To Layout XML Converter.
37*cdf0e10cSrcweir
38*cdf0e10cSrcweirConvert OO.o's existing dialog resource files into XML layout files.
39*cdf0e10cSrcweir'''
40*cdf0e10cSrcweir
41*cdf0e10cSrcweir    p.add_option ('-l', '--debug-lexer', action='store_true',
42*cdf0e10cSrcweir                  dest='debug_lexer', default=False,
43*cdf0e10cSrcweir                  help='debug lexer')
44*cdf0e10cSrcweir
45*cdf0e10cSrcweir    p.add_option ('-p', '--debug-parser', action='store_true',
46*cdf0e10cSrcweir                  dest='debug_parser', default=False,
47*cdf0e10cSrcweir                  help='debug parser')
48*cdf0e10cSrcweir
49*cdf0e10cSrcweir    p.add_option ('-m', '--debug-macro', action='store_true',
50*cdf0e10cSrcweir                  dest='debug_macro', default=False,
51*cdf0e10cSrcweir                  help='debug macro')
52*cdf0e10cSrcweir
53*cdf0e10cSrcweir    p.add_option ('-n', '--dry-run', action='store_true',
54*cdf0e10cSrcweir                  dest='dry_run', default=False,
55*cdf0e10cSrcweir                  help='dry run')
56*cdf0e10cSrcweir
57*cdf0e10cSrcweir    p.add_option ('-k', '--keep-going', action='store_true',
58*cdf0e10cSrcweir                  dest='keep_going', default=False,
59*cdf0e10cSrcweir                  help='continue after error')
60*cdf0e10cSrcweir
61*cdf0e10cSrcweir    p.add_option ('-i', '--ignore-includes', action='store_true',
62*cdf0e10cSrcweir                  dest='ignore_includes', default=False,
63*cdf0e10cSrcweir                  help='ignore #include directives')
64*cdf0e10cSrcweir
65*cdf0e10cSrcweir    p.add_option ('-I', '--include-dir', action='append',
66*cdf0e10cSrcweir                  dest='include_path',
67*cdf0e10cSrcweir                  default=[],
68*cdf0e10cSrcweir                  metavar='DIR',
69*cdf0e10cSrcweir                  help='append DIR to include path')
70*cdf0e10cSrcweir
71*cdf0e10cSrcweir    def from_file (option, opt_str, value, parser):
72*cdf0e10cSrcweir        lst = getattr (parser.values, option.dest)
73*cdf0e10cSrcweir        lst += file (value).read ().split ('\n')
74*cdf0e10cSrcweir        setattr (parser.values, option.dest, lst)
75*cdf0e10cSrcweir
76*cdf0e10cSrcweir    def from_path (option, opt_str, value, parser):
77*cdf0e10cSrcweir        lst = getattr (parser.values, option.dest)
78*cdf0e10cSrcweir        lst += value.split (':')
79*cdf0e10cSrcweir        setattr (parser.values, option.dest, lst)
80*cdf0e10cSrcweir
81*cdf0e10cSrcweir    # Junk me?
82*cdf0e10cSrcweir    p.add_option ('--includes-from-file', action='callback', callback=from_file,
83*cdf0e10cSrcweir                  dest='include_path',
84*cdf0e10cSrcweir                  default=[],
85*cdf0e10cSrcweir                  type='string',
86*cdf0e10cSrcweir                  metavar='FILE',
87*cdf0e10cSrcweir                  help='append directory list from FILE to include path')
88*cdf0e10cSrcweir
89*cdf0e10cSrcweir    p.add_option ('--include-path', action='callback', callback=from_path,
90*cdf0e10cSrcweir                  dest='include_path',
91*cdf0e10cSrcweir                  type='string',
92*cdf0e10cSrcweir                  default=[],
93*cdf0e10cSrcweir                  metavar='PATH',
94*cdf0e10cSrcweir                  help='append PATH to include path')
95*cdf0e10cSrcweir
96*cdf0e10cSrcweir    p.add_option ('--only-expand-macros', action='store_true',
97*cdf0e10cSrcweir                  dest='only_expand_macros', default=False,
98*cdf0e10cSrcweir                  help='FIXME: better to say what NOT to expand?')
99*cdf0e10cSrcweir
100*cdf0e10cSrcweir    p.add_option ('-o', '--output-dir', action='store',
101*cdf0e10cSrcweir                  dest='output_dir', default=None,
102*cdf0e10cSrcweir                  metavar='DIR',
103*cdf0e10cSrcweir                  help='Output to DIR')
104*cdf0e10cSrcweir
105*cdf0e10cSrcweir    p.add_option ('-s', '--post-process', action='store_true',
106*cdf0e10cSrcweir                  dest='post_process', default=False,
107*cdf0e10cSrcweir                  help='post process output for use in Layout')
108*cdf0e10cSrcweir
109*cdf0e10cSrcweir    p.add_option ('--stop-on-header', action='store_true',
110*cdf0e10cSrcweir                  dest='stopOnHeader', default=False,
111*cdf0e10cSrcweir                  help='FIXME: remove this?')
112*cdf0e10cSrcweir
113*cdf0e10cSrcweir    return p
114*cdf0e10cSrcweir
115*cdf0e10cSrcweir
116*cdf0e10cSrcweirdef convert (file_name, options):
117*cdf0e10cSrcweir    progress ("parsing %(file_name)s ..." % locals ())
118*cdf0e10cSrcweir    fullpath = os.path.abspath(file_name)
119*cdf0e10cSrcweir    if not os.path.isfile(fullpath):
120*cdf0e10cSrcweir        error("no such file", exit=True)
121*cdf0e10cSrcweir
122*cdf0e10cSrcweir    ##options.include_path.append (os.path.dirname (fullpath))
123*cdf0e10cSrcweir
124*cdf0e10cSrcweir    input = file (fullpath, 'r').read()
125*cdf0e10cSrcweir    lexer = SrcLexer(input, fullpath)
126*cdf0e10cSrcweir    lexer.expandHeaders = not options.ignore_includes
127*cdf0e10cSrcweir    lexer.includeDirs = options.include_path
128*cdf0e10cSrcweir    lexer.stopOnHeader = options.stopOnHeader
129*cdf0e10cSrcweir    lexer.debugMacro = options.debug_macro
130*cdf0e10cSrcweir    if options.debug_lexer:
131*cdf0e10cSrcweir        lexer.debug = True
132*cdf0e10cSrcweir        lexer.tokenize()
133*cdf0e10cSrcweir        progress ("-"*68 + "\n")
134*cdf0e10cSrcweir        progress ("** token dump\n")
135*cdf0e10cSrcweir        lexer.dumpTokens()
136*cdf0e10cSrcweir        progress ("** end of token dump\n")
137*cdf0e10cSrcweir        return
138*cdf0e10cSrcweir
139*cdf0e10cSrcweir    # Tokenize it using lexer
140*cdf0e10cSrcweir    lexer.tokenize()
141*cdf0e10cSrcweir
142*cdf0e10cSrcweir    parser = SrcParser(lexer.getTokens(), lexer.getDefines())
143*cdf0e10cSrcweir    parser.only_expand_macros = options.only_expand_macros
144*cdf0e10cSrcweir    if options.debug_parser:
145*cdf0e10cSrcweir        parser.debug = True
146*cdf0e10cSrcweir        root = parser.parse()
147*cdf0e10cSrcweir        s = root.dump()
148*cdf0e10cSrcweir        return s
149*cdf0e10cSrcweir
150*cdf0e10cSrcweir    # Parse the tokens.
151*cdf0e10cSrcweir    root = parser.parse()
152*cdf0e10cSrcweir
153*cdf0e10cSrcweir    # Box it, and return the XML tree.
154*cdf0e10cSrcweir    root = Boxer(root).layout()
155*cdf0e10cSrcweir    output = root.dump()
156*cdf0e10cSrcweir    if not options.dry_run:
157*cdf0e10cSrcweir        progress ("\n")
158*cdf0e10cSrcweir    return output
159*cdf0e10cSrcweir
160*cdf0e10cSrcweirdef dry_one_file (file_name, options):
161*cdf0e10cSrcweir    try:
162*cdf0e10cSrcweir        str = convert(file_name, options)
163*cdf0e10cSrcweir        progress ("  SUCCESS\n")
164*cdf0e10cSrcweir    except Exception, e:
165*cdf0e10cSrcweir        if options.keep_going:
166*cdf0e10cSrcweir            progress ("  FAILED\n")
167*cdf0e10cSrcweir        else:
168*cdf0e10cSrcweir            import traceback
169*cdf0e10cSrcweir            print traceback.format_exc (None)
170*cdf0e10cSrcweir            raise e
171*cdf0e10cSrcweir
172*cdf0e10cSrcweirdef post_process (s):
173*cdf0e10cSrcweir    """Make output directly usable by layout module."""
174*cdf0e10cSrcweir    s = re.sub ('(</?)([a-z]+)-([a-z]+)-([a-z]+)', r'\1\2\3\4', s)
175*cdf0e10cSrcweir    s = re.sub ('(</?)([a-z]+)-([a-z]+)', r'\1\2\3', s)
176*cdf0e10cSrcweir    s = re.sub ('(<(checkbox|(cancel|help|ignore|ok|push|more|no|radio|reset|retry|yes)button|(fixed(info|text)))[^>]*) text=', r'\1 label=', s)
177*cdf0e10cSrcweir    s = re.sub (' (height|width|x|y)="[0-9]*"', '', s)
178*cdf0e10cSrcweir    s = re.sub (' (label|text|title)="', r' _\1="', s)
179*cdf0e10cSrcweir    s = re.sub ('&([^m][^p]*[^;]*)', r'&amp;\1', s)
180*cdf0e10cSrcweir    s = re.sub (' hide="(TRUE|true|1)"', ' show="false"', s)
181*cdf0e10cSrcweir
182*cdf0e10cSrcweir    s = s.replace ('<modaldialog', '<modaldialog sizeable="true"')
183*cdf0e10cSrcweir    s = s.replace (' rid=', ' id=')
184*cdf0e10cSrcweir    s = s.replace (' border="true"', ' has_border="true"')
185*cdf0e10cSrcweir    s = s.replace (' def-button="true"', ' defbutton="true"')
186*cdf0e10cSrcweir    s = s.replace (' drop-down="', ' dropdown="')
187*cdf0e10cSrcweir    s = s.replace (' tab-stop="', ' tabstop="')
188*cdf0e10cSrcweir    return s
189*cdf0e10cSrcweir
190*cdf0e10cSrcweirXML_HEADER = '''<?xml version="1.0" encoding="UTF-8"?>
191*cdf0e10cSrcweir<!-- This is a template.  i18n translation is not performed in-place;
192*cdf0e10cSrcweir     i18n translated XML files are generated from this template by
193*cdf0e10cSrcweir     transex3/layout/tralay.  !-->
194*cdf0e10cSrcweir'''
195*cdf0e10cSrcweir
196*cdf0e10cSrcweirdef do_one_file (file_name, options):
197*cdf0e10cSrcweir    str = XML_HEADER
198*cdf0e10cSrcweir    str += convert(file_name, options)
199*cdf0e10cSrcweir    str += '\n'
200*cdf0e10cSrcweir
201*cdf0e10cSrcweir    if options.post_process:
202*cdf0e10cSrcweir        str = post_process (str)
203*cdf0e10cSrcweir    h = sys.stdout
204*cdf0e10cSrcweir    if options.output_dir:
205*cdf0e10cSrcweir        base = os.path.basename (file_name)
206*cdf0e10cSrcweir        root, ext = os.path.splitext (base)
207*cdf0e10cSrcweir        out_name = options.output_dir + '/' + root + '.xml'
208*cdf0e10cSrcweir        progress ("writing %(out_name)s ..." % locals ())
209*cdf0e10cSrcweir        h = file (out_name, 'w')
210*cdf0e10cSrcweir    h.write (str)
211*cdf0e10cSrcweir    h.flush ()
212*cdf0e10cSrcweir    progress ("\n")
213*cdf0e10cSrcweir
214*cdf0e10cSrcweirdef main ():
215*cdf0e10cSrcweir    p = option_parser ()
216*cdf0e10cSrcweir    (options, files) = option_parser ().parse_args ()
217*cdf0e10cSrcweir    if not files:
218*cdf0e10cSrcweir        p.error ("no input files")
219*cdf0e10cSrcweir
220*cdf0e10cSrcweir    for f in files:
221*cdf0e10cSrcweir        if options.dry_run:
222*cdf0e10cSrcweir            dry_one_file (f, options)
223*cdf0e10cSrcweir        else:
224*cdf0e10cSrcweir            do_one_file (f, options)
225*cdf0e10cSrcweir
226*cdf0e10cSrcweirif __name__ == '__main__':
227*cdf0e10cSrcweir    main ()
228