Home | History | Annotate | Download | only in build_tools
      1 #!/usr/bin/env python
      2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import copy
      7 import cStringIO
      8 import optparse
      9 import os
     10 import re
     11 import sys
     12 
     13 
     14 STATEMENT_RE = "\[\[(.*?)\]\]"  # [[...]]
     15 EXPR_RE = "\{\{(.*?)\}\}"  # {{...}}
     16 
     17 def TemplateToPython(template, statement_re, expr_re):
     18   output = cStringIO.StringIO()
     19   indent_re = re.compile(r'\s*')
     20   indent_string = ''
     21   for line in template.splitlines(1):  # 1 => keep line ends
     22     m = statement_re.match(line)
     23     if m:
     24       statement = m.group(1)
     25       indent_string = indent_re.match(statement).group()
     26       if statement.rstrip()[-1:] == ':':
     27         indent_string += '  '
     28       output.write(statement + '\n')
     29     else:
     30       line_ending = ''
     31       while line and line[-1] in '\\"\n\r':
     32         line_ending = line[-1] + line_ending
     33         line = line[:-1]
     34 
     35       ms = list(expr_re.finditer(line))
     36       if ms:
     37         # Only replace % with %% outside of the expr matches.
     38         new_line = ''
     39         start = 0
     40         for m in ms:
     41           new_line += line[start:m.start()].replace('%', '%%')
     42           new_line += line[m.start():m.end()]
     43           start = m.end()
     44         new_line += line[start:].replace('%', '%%')
     45         line = new_line
     46 
     47         subst_line = r'r"""%s""" %% (%s,)' % (
     48             re.sub(expr_re, '%s', line),
     49             ', '.join(re.findall(expr_re, line)))
     50       else:
     51         subst_line = r'r"""%s"""' % line
     52 
     53       out_string = r'%s__outfile__.write(%s + %s)' % (
     54           indent_string,
     55           subst_line,
     56           repr(line_ending))
     57       output.write(out_string + '\n')
     58 
     59   return output.getvalue()
     60 
     61 
     62 def RunTemplate(srcfile, dstfile, template_dict, statement_re=None,
     63                 expr_re=None):
     64   statement_re = statement_re or re.compile(STATEMENT_RE)
     65   expr_re = expr_re or re.compile(EXPR_RE)
     66   script = TemplateToPython(srcfile.read(), statement_re, expr_re)
     67   template_dict = copy.copy(template_dict)
     68   template_dict['__outfile__'] = dstfile
     69   exec script in template_dict
     70 
     71 
     72 def RunTemplateFile(srcpath, dstpath, template_dict, statement_re=None,
     73                     expr_re=None):
     74   with open(srcpath) as srcfile:
     75     with open(dstpath, 'w') as dstfile:
     76       RunTemplate(srcfile, dstfile, template_dict, statement_re, expr_re)
     77 
     78 
     79 def RunTemplateFileIfChanged(srcpath, dstpath, replace):
     80   dststr = cStringIO.StringIO()
     81   with open(srcpath) as srcfile:
     82     RunTemplate(srcfile, dststr, replace)
     83 
     84   if os.path.exists(dstpath):
     85     with open(dstpath) as dstfile:
     86       if dstfile.read() == dststr.getvalue():
     87         return
     88 
     89   with open(dstpath, 'w') as dstfile:
     90     dstfile.write(dststr.getvalue())
     91 
     92 
     93 def RunTemplateString(src, template_dict, statement_re=None, expr_re=None):
     94   srcstr = cStringIO.StringIO(src)
     95   dststr = cStringIO.StringIO()
     96   RunTemplate(srcstr, dststr, template_dict, statement_re, expr_re)
     97   return dststr.getvalue()
     98 
     99 
    100 def main(args):
    101   parser = optparse.OptionParser()
    102   _, args = parser.parse_args(args)
    103   if not args:
    104     return
    105 
    106   with open(args[0]) as f:
    107     print TemplateToPython(
    108         f.read(), re.compile(STATEMENT_RE), re.compile(EXPR_RE))
    109 
    110 if __name__ == '__main__':
    111   sys.exit(main(sys.argv[1:]))
    112