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