xpcom/idl-parser/header.py

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 #!/usr/bin/env python
michael@0 2 # header.py - Generate C++ header files from IDL.
michael@0 3 #
michael@0 4 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 7
michael@0 8 """Print a C++ header file for the IDL files specified on the command line"""
michael@0 9
michael@0 10 import sys, os.path, re, xpidl, itertools, glob
michael@0 11
michael@0 12 printdoccomments = False
michael@0 13
michael@0 14 if printdoccomments:
michael@0 15 def printComments(fd, clist, indent):
michael@0 16 for c in clist:
michael@0 17 fd.write("%s%s\n" % (indent, c))
michael@0 18 else:
michael@0 19 def printComments(fd, clist, indent):
michael@0 20 pass
michael@0 21
michael@0 22 def firstCap(str):
michael@0 23 return str[0].upper() + str[1:]
michael@0 24
michael@0 25 def attributeParamName(a):
michael@0 26 return "a" + firstCap(a.name)
michael@0 27
michael@0 28 def attributeParamNames(a):
michael@0 29 l = [attributeParamName(a)]
michael@0 30 if a.implicit_jscontext:
michael@0 31 l.insert(0, "cx")
michael@0 32 return ", ".join(l)
michael@0 33
michael@0 34 def attributeNativeName(a, getter):
michael@0 35 binaryname = a.binaryname is not None and a.binaryname or firstCap(a.name)
michael@0 36 return "%s%s" % (getter and 'Get' or 'Set', binaryname)
michael@0 37
michael@0 38 def attributeReturnType(a, macro):
michael@0 39 """macro should be NS_IMETHOD or NS_IMETHODIMP"""
michael@0 40 if (a.nostdcall):
michael@0 41 return macro == "NS_IMETHOD" and "virtual nsresult" or "nsresult"
michael@0 42 else:
michael@0 43 return macro
michael@0 44
michael@0 45 def attributeParamlist(a, getter):
michael@0 46 l = ["%s%s" % (a.realtype.nativeType(getter and 'out' or 'in'),
michael@0 47 attributeParamName(a))]
michael@0 48 if a.implicit_jscontext:
michael@0 49 l.insert(0, "JSContext* cx")
michael@0 50
michael@0 51 return ", ".join(l)
michael@0 52
michael@0 53 def attributeAsNative(a, getter):
michael@0 54 deprecated = a.deprecated and "NS_DEPRECATED " or ""
michael@0 55 params = {'deprecated': deprecated,
michael@0 56 'returntype': attributeReturnType(a, 'NS_IMETHOD'),
michael@0 57 'binaryname': attributeNativeName(a, getter),
michael@0 58 'paramlist': attributeParamlist(a, getter)}
michael@0 59 return "%(deprecated)s%(returntype)s %(binaryname)s(%(paramlist)s)" % params
michael@0 60
michael@0 61 def methodNativeName(m):
michael@0 62 return m.binaryname is not None and m.binaryname or firstCap(m.name)
michael@0 63
michael@0 64 def methodReturnType(m, macro):
michael@0 65 """macro should be NS_IMETHOD or NS_IMETHODIMP"""
michael@0 66 if m.nostdcall and m.notxpcom:
michael@0 67 return "%s%s" % (macro == "NS_IMETHOD" and "virtual " or "",
michael@0 68 m.realtype.nativeType('in').strip())
michael@0 69 elif m.nostdcall:
michael@0 70 return "%snsresult" % (macro == "NS_IMETHOD" and "virtual " or "")
michael@0 71 elif m.notxpcom:
michael@0 72 return "%s_(%s)" % (macro, m.realtype.nativeType('in').strip())
michael@0 73 else:
michael@0 74 return macro
michael@0 75
michael@0 76 def methodAsNative(m):
michael@0 77 return "%s %s(%s)" % (methodReturnType(m, 'NS_IMETHOD'),
michael@0 78 methodNativeName(m),
michael@0 79 paramlistAsNative(m))
michael@0 80
michael@0 81 def paramlistAsNative(m, empty='void'):
michael@0 82 l = [paramAsNative(p) for p in m.params]
michael@0 83
michael@0 84 if m.implicit_jscontext:
michael@0 85 l.append("JSContext* cx")
michael@0 86
michael@0 87 if m.optional_argc:
michael@0 88 l.append('uint8_t _argc')
michael@0 89
michael@0 90 if not m.notxpcom and m.realtype.name != 'void':
michael@0 91 l.append(paramAsNative(xpidl.Param(paramtype='out',
michael@0 92 type=None,
michael@0 93 name='_retval',
michael@0 94 attlist=[],
michael@0 95 location=None,
michael@0 96 realtype=m.realtype)))
michael@0 97
michael@0 98 if len(l) == 0:
michael@0 99 return empty
michael@0 100
michael@0 101 return ", ".join(l)
michael@0 102
michael@0 103 def paramAsNative(p):
michael@0 104 return "%s%s" % (p.nativeType(),
michael@0 105 p.name)
michael@0 106
michael@0 107 def paramlistNames(m):
michael@0 108 names = [p.name for p in m.params]
michael@0 109
michael@0 110 if m.implicit_jscontext:
michael@0 111 names.append('cx')
michael@0 112
michael@0 113 if m.optional_argc:
michael@0 114 names.append('_argc')
michael@0 115
michael@0 116 if not m.notxpcom and m.realtype.name != 'void':
michael@0 117 names.append('_retval')
michael@0 118
michael@0 119 if len(names) == 0:
michael@0 120 return ''
michael@0 121 return ', '.join(names)
michael@0 122
michael@0 123 header = """/*
michael@0 124 * DO NOT EDIT. THIS FILE IS GENERATED FROM %(filename)s
michael@0 125 */
michael@0 126
michael@0 127 #ifndef __gen_%(basename)s_h__
michael@0 128 #define __gen_%(basename)s_h__
michael@0 129 """
michael@0 130
michael@0 131 include = """
michael@0 132 #ifndef __gen_%(basename)s_h__
michael@0 133 #include "%(basename)s.h"
michael@0 134 #endif
michael@0 135 """
michael@0 136
michael@0 137 jsvalue_include = """
michael@0 138 #include "js/Value.h"
michael@0 139 """
michael@0 140
michael@0 141 infallible_includes = """
michael@0 142 #include "mozilla/Assertions.h"
michael@0 143 #include "mozilla/DebugOnly.h"
michael@0 144 """
michael@0 145
michael@0 146 header_end = """/* For IDL files that don't want to include root IDL files. */
michael@0 147 #ifndef NS_NO_VTABLE
michael@0 148 #define NS_NO_VTABLE
michael@0 149 #endif
michael@0 150 """
michael@0 151
michael@0 152 footer = """
michael@0 153 #endif /* __gen_%(basename)s_h__ */
michael@0 154 """
michael@0 155
michael@0 156 forward_decl = """class %(name)s; /* forward declaration */
michael@0 157
michael@0 158 """
michael@0 159
michael@0 160 def idl_basename(f):
michael@0 161 """returns the base name of a file with the last extension stripped"""
michael@0 162 return os.path.basename(f).rpartition('.')[0]
michael@0 163
michael@0 164 def print_header(idl, fd, filename):
michael@0 165 fd.write(header % {'filename': filename,
michael@0 166 'basename': idl_basename(filename)})
michael@0 167
michael@0 168 foundinc = False
michael@0 169 for inc in idl.includes():
michael@0 170 if not foundinc:
michael@0 171 foundinc = True
michael@0 172 fd.write('\n')
michael@0 173 fd.write(include % {'basename': idl_basename(inc.filename)})
michael@0 174
michael@0 175 if idl.needsJSTypes():
michael@0 176 fd.write(jsvalue_include)
michael@0 177
michael@0 178 # Include some extra files if any attributes are infallible.
michael@0 179 for iface in [p for p in idl.productions if p.kind == 'interface']:
michael@0 180 for attr in [m for m in iface.members if isinstance(m, xpidl.Attribute)]:
michael@0 181 if attr.infallible:
michael@0 182 fd.write(infallible_includes)
michael@0 183 break
michael@0 184
michael@0 185 fd.write('\n')
michael@0 186 fd.write(header_end)
michael@0 187
michael@0 188 for p in idl.productions:
michael@0 189 if p.kind == 'include': continue
michael@0 190 if p.kind == 'cdata':
michael@0 191 fd.write(p.data)
michael@0 192 continue
michael@0 193
michael@0 194 if p.kind == 'forward':
michael@0 195 fd.write(forward_decl % {'name': p.name})
michael@0 196 continue
michael@0 197 if p.kind == 'interface':
michael@0 198 write_interface(p, fd)
michael@0 199 continue
michael@0 200 if p.kind == 'typedef':
michael@0 201 printComments(fd, p.doccomments, '')
michael@0 202 fd.write("typedef %s %s;\n\n" % (p.realtype.nativeType('in'),
michael@0 203 p.name))
michael@0 204
michael@0 205 fd.write(footer % {'basename': idl_basename(filename)})
michael@0 206
michael@0 207 iface_header = r"""
michael@0 208 /* starting interface: %(name)s */
michael@0 209 #define %(defname)s_IID_STR "%(iid)s"
michael@0 210
michael@0 211 #define %(defname)s_IID \
michael@0 212 {0x%(m0)s, 0x%(m1)s, 0x%(m2)s, \
michael@0 213 { %(m3joined)s }}
michael@0 214
michael@0 215 """
michael@0 216
michael@0 217 uuid_decoder = re.compile(r"""(?P<m0>[a-f0-9]{8})-
michael@0 218 (?P<m1>[a-f0-9]{4})-
michael@0 219 (?P<m2>[a-f0-9]{4})-
michael@0 220 (?P<m3>[a-f0-9]{4})-
michael@0 221 (?P<m4>[a-f0-9]{12})$""", re.X)
michael@0 222
michael@0 223 iface_prolog = """ {
michael@0 224 public:
michael@0 225
michael@0 226 NS_DECLARE_STATIC_IID_ACCESSOR(%(defname)s_IID)
michael@0 227
michael@0 228 """
michael@0 229
michael@0 230 iface_epilog = """};
michael@0 231
michael@0 232 NS_DEFINE_STATIC_IID_ACCESSOR(%(name)s, %(defname)s_IID)
michael@0 233
michael@0 234 /* Use this macro when declaring classes that implement this interface. */
michael@0 235 #define NS_DECL_%(macroname)s """
michael@0 236
michael@0 237
michael@0 238 iface_forward = """
michael@0 239
michael@0 240 /* Use this macro to declare functions that forward the behavior of this interface to another object. */
michael@0 241 #define NS_FORWARD_%(macroname)s(_to) """
michael@0 242
michael@0 243 iface_forward_safe = """
michael@0 244
michael@0 245 /* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
michael@0 246 #define NS_FORWARD_SAFE_%(macroname)s(_to) """
michael@0 247
michael@0 248 iface_template_prolog = """
michael@0 249
michael@0 250 #if 0
michael@0 251 /* Use the code below as a template for the implementation class for this interface. */
michael@0 252
michael@0 253 /* Header file */
michael@0 254 class %(implclass)s : public %(name)s
michael@0 255 {
michael@0 256 public:
michael@0 257 NS_DECL_ISUPPORTS
michael@0 258 NS_DECL_%(macroname)s
michael@0 259
michael@0 260 %(implclass)s();
michael@0 261
michael@0 262 private:
michael@0 263 ~%(implclass)s();
michael@0 264
michael@0 265 protected:
michael@0 266 /* additional members */
michael@0 267 };
michael@0 268
michael@0 269 /* Implementation file */
michael@0 270 NS_IMPL_ISUPPORTS(%(implclass)s, %(name)s)
michael@0 271
michael@0 272 %(implclass)s::%(implclass)s()
michael@0 273 {
michael@0 274 /* member initializers and constructor code */
michael@0 275 }
michael@0 276
michael@0 277 %(implclass)s::~%(implclass)s()
michael@0 278 {
michael@0 279 /* destructor code */
michael@0 280 }
michael@0 281
michael@0 282 """
michael@0 283
michael@0 284 example_tmpl = """%(returntype)s %(implclass)s::%(nativeName)s(%(paramList)s)
michael@0 285 {
michael@0 286 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 287 }
michael@0 288 """
michael@0 289
michael@0 290 iface_template_epilog = """/* End of implementation class template. */
michael@0 291 #endif
michael@0 292
michael@0 293 """
michael@0 294
michael@0 295 attr_infallible_tmpl = """\
michael@0 296 inline %(realtype)s%(nativename)s(%(args)s)
michael@0 297 {
michael@0 298 %(realtype)sresult;
michael@0 299 mozilla::DebugOnly<nsresult> rv = %(nativename)s(%(argnames)s&result);
michael@0 300 MOZ_ASSERT(NS_SUCCEEDED(rv));
michael@0 301 return result;
michael@0 302 }
michael@0 303 """
michael@0 304
michael@0 305 def write_interface(iface, fd):
michael@0 306 if iface.namemap is None:
michael@0 307 raise Exception("Interface was not resolved.")
michael@0 308
michael@0 309 def write_const_decls(g):
michael@0 310 fd.write(" enum {\n")
michael@0 311 enums = []
michael@0 312 for c in g:
michael@0 313 printComments(fd, c.doccomments, ' ')
michael@0 314 basetype = c.basetype
michael@0 315 value = c.getValue()
michael@0 316 enums.append(" %(name)s = %(value)s%(signed)s" % {
michael@0 317 'name': c.name,
michael@0 318 'value': value,
michael@0 319 'signed': (not basetype.signed) and 'U' or ''})
michael@0 320 fd.write(",\n".join(enums))
michael@0 321 fd.write("\n };\n\n")
michael@0 322
michael@0 323 def write_method_decl(m):
michael@0 324 printComments(fd, m.doccomments, ' ')
michael@0 325
michael@0 326 fd.write(" /* %s */\n" % m.toIDL())
michael@0 327 fd.write(" %s = 0;\n\n" % methodAsNative(m))
michael@0 328
michael@0 329 def write_attr_decl(a):
michael@0 330 printComments(fd, a.doccomments, ' ')
michael@0 331
michael@0 332 fd.write(" /* %s */\n" % a.toIDL());
michael@0 333
michael@0 334 fd.write(" %s = 0;\n" % attributeAsNative(a, True))
michael@0 335 if a.infallible:
michael@0 336 fd.write(attr_infallible_tmpl %
michael@0 337 {'realtype': a.realtype.nativeType('in'),
michael@0 338 'nativename': attributeNativeName(a, getter=True),
michael@0 339 'args': '' if not a.implicit_jscontext else 'JSContext* cx',
michael@0 340 'argnames': '' if not a.implicit_jscontext else 'cx, '})
michael@0 341
michael@0 342 if not a.readonly:
michael@0 343 fd.write(" %s = 0;\n" % attributeAsNative(a, False))
michael@0 344 fd.write("\n")
michael@0 345
michael@0 346 defname = iface.name.upper()
michael@0 347 if iface.name[0:2] == 'ns':
michael@0 348 defname = 'NS_' + defname[2:]
michael@0 349
michael@0 350 names = uuid_decoder.match(iface.attributes.uuid).groupdict()
michael@0 351 m3str = names['m3'] + names['m4']
michael@0 352 names['m3joined'] = ", ".join(["0x%s" % m3str[i:i+2] for i in xrange(0, 16, 2)])
michael@0 353
michael@0 354 if iface.name[2] == 'I':
michael@0 355 implclass = iface.name[:2] + iface.name[3:]
michael@0 356 else:
michael@0 357 implclass = '_MYCLASS_'
michael@0 358
michael@0 359 names.update({'defname': defname,
michael@0 360 'macroname': iface.name.upper(),
michael@0 361 'name': iface.name,
michael@0 362 'iid': iface.attributes.uuid,
michael@0 363 'implclass': implclass})
michael@0 364
michael@0 365 fd.write(iface_header % names)
michael@0 366
michael@0 367 printComments(fd, iface.doccomments, '')
michael@0 368
michael@0 369 fd.write("class ")
michael@0 370 foundcdata = False
michael@0 371 for m in iface.members:
michael@0 372 if isinstance(m, xpidl.CDATA):
michael@0 373 foundcdata = True
michael@0 374
michael@0 375 if not foundcdata:
michael@0 376 fd.write("NS_NO_VTABLE ")
michael@0 377
michael@0 378 if iface.attributes.deprecated:
michael@0 379 fd.write("MOZ_DEPRECATED ")
michael@0 380 fd.write(iface.name)
michael@0 381 if iface.base:
michael@0 382 fd.write(" : public %s" % iface.base)
michael@0 383 fd.write(iface_prolog % names)
michael@0 384
michael@0 385 for key, group in itertools.groupby(iface.members, key=type):
michael@0 386 if key == xpidl.ConstMember:
michael@0 387 write_const_decls(group) # iterator of all the consts
michael@0 388 else:
michael@0 389 for member in group:
michael@0 390 if key == xpidl.Attribute:
michael@0 391 write_attr_decl(member)
michael@0 392 elif key == xpidl.Method:
michael@0 393 write_method_decl(member)
michael@0 394 elif key == xpidl.CDATA:
michael@0 395 fd.write(" %s" % member.data)
michael@0 396 else:
michael@0 397 raise Exception("Unexpected interface member: %s" % member)
michael@0 398
michael@0 399 fd.write(iface_epilog % names)
michael@0 400
michael@0 401 for member in iface.members:
michael@0 402 if isinstance(member, xpidl.Attribute):
michael@0 403 fd.write("\\\n %s; " % attributeAsNative(member, True))
michael@0 404 if not member.readonly:
michael@0 405 fd.write("\\\n %s; " % attributeAsNative(member, False))
michael@0 406 elif isinstance(member, xpidl.Method):
michael@0 407 fd.write("\\\n %s; " % methodAsNative(member))
michael@0 408 if len(iface.members) == 0:
michael@0 409 fd.write('\\\n /* no methods! */')
michael@0 410 elif not member.kind in ('attribute', 'method'):
michael@0 411 fd.write('\\')
michael@0 412
michael@0 413 fd.write(iface_forward % names)
michael@0 414
michael@0 415 def emitTemplate(tmpl, tmpl_notxpcom=None):
michael@0 416 if tmpl_notxpcom == None:
michael@0 417 tmpl_notxpcom = tmpl
michael@0 418 for member in iface.members:
michael@0 419 if isinstance(member, xpidl.Attribute):
michael@0 420 fd.write(tmpl % {'asNative': attributeAsNative(member, True),
michael@0 421 'nativeName': attributeNativeName(member, True),
michael@0 422 'paramList': attributeParamNames(member)})
michael@0 423 if not member.readonly:
michael@0 424 fd.write(tmpl % {'asNative': attributeAsNative(member, False),
michael@0 425 'nativeName': attributeNativeName(member, False),
michael@0 426 'paramList': attributeParamNames(member)})
michael@0 427 elif isinstance(member, xpidl.Method):
michael@0 428 if member.notxpcom:
michael@0 429 fd.write(tmpl_notxpcom % {'asNative': methodAsNative(member),
michael@0 430 'nativeName': methodNativeName(member),
michael@0 431 'paramList': paramlistNames(member)})
michael@0 432 else:
michael@0 433 fd.write(tmpl % {'asNative': methodAsNative(member),
michael@0 434 'nativeName': methodNativeName(member),
michael@0 435 'paramList': paramlistNames(member)})
michael@0 436 if len(iface.members) == 0:
michael@0 437 fd.write('\\\n /* no methods! */')
michael@0 438 elif not member.kind in ('attribute', 'method'):
michael@0 439 fd.write('\\')
michael@0 440
michael@0 441 emitTemplate("\\\n %(asNative)s { return _to %(nativeName)s(%(paramList)s); } ")
michael@0 442
michael@0 443 fd.write(iface_forward_safe % names)
michael@0 444
michael@0 445 # Don't try to safely forward notxpcom functions, because we have no
michael@0 446 # sensible default error return. Instead, the caller will have to
michael@0 447 # implement them.
michael@0 448 emitTemplate("\\\n %(asNative)s { return !_to ? NS_ERROR_NULL_POINTER : _to->%(nativeName)s(%(paramList)s); } ",
michael@0 449 "\\\n %(asNative)s; ")
michael@0 450
michael@0 451 fd.write(iface_template_prolog % names)
michael@0 452
michael@0 453 for member in iface.members:
michael@0 454 if isinstance(member, xpidl.ConstMember) or isinstance(member, xpidl.CDATA): continue
michael@0 455 fd.write("/* %s */\n" % member.toIDL())
michael@0 456 if isinstance(member, xpidl.Attribute):
michael@0 457 fd.write(example_tmpl % {'implclass': implclass,
michael@0 458 'returntype': attributeReturnType(member, 'NS_IMETHODIMP'),
michael@0 459 'nativeName': attributeNativeName(member, True),
michael@0 460 'paramList': attributeParamlist(member, True)})
michael@0 461 if not member.readonly:
michael@0 462 fd.write(example_tmpl % {'implclass': implclass,
michael@0 463 'returntype': attributeReturnType(member, 'NS_IMETHODIMP'),
michael@0 464 'nativeName': attributeNativeName(member, False),
michael@0 465 'paramList': attributeParamlist(member, False)})
michael@0 466 elif isinstance(member, xpidl.Method):
michael@0 467 fd.write(example_tmpl % {'implclass': implclass,
michael@0 468 'returntype': methodReturnType(member, 'NS_IMETHODIMP'),
michael@0 469 'nativeName': methodNativeName(member),
michael@0 470 'paramList': paramlistAsNative(member, empty='')})
michael@0 471 fd.write('\n')
michael@0 472
michael@0 473 fd.write(iface_template_epilog)
michael@0 474
michael@0 475 if __name__ == '__main__':
michael@0 476 from optparse import OptionParser
michael@0 477 o = OptionParser()
michael@0 478 o.add_option('-I', action='append', dest='incdirs', default=['.'],
michael@0 479 help="Directory to search for imported files")
michael@0 480 o.add_option('--cachedir', dest='cachedir', default=None,
michael@0 481 help="Directory in which to cache lex/parse tables.")
michael@0 482 o.add_option('-o', dest='outfile', default=None,
michael@0 483 help="Output file (default is stdout)")
michael@0 484 o.add_option('-d', dest='depfile', default=None,
michael@0 485 help="Generate a make dependency file")
michael@0 486 o.add_option('--regen', action='store_true', dest='regen', default=False,
michael@0 487 help="Regenerate IDL Parser cache")
michael@0 488 options, args = o.parse_args()
michael@0 489 file = args[0] if args else None
michael@0 490
michael@0 491 if options.cachedir is not None:
michael@0 492 if not os.path.isdir(options.cachedir):
michael@0 493 os.mkdir(options.cachedir)
michael@0 494 sys.path.append(options.cachedir)
michael@0 495
michael@0 496 # The only thing special about a regen is that there are no input files.
michael@0 497 if options.regen:
michael@0 498 if options.cachedir is None:
michael@0 499 print >>sys.stderr, "--regen useless without --cachedir"
michael@0 500 # Delete the lex/yacc files. Ply is too stupid to regenerate them
michael@0 501 # properly
michael@0 502 for fileglobs in [os.path.join(options.cachedir, f) for f in ["xpidllex.py*", "xpidlyacc.py*"]]:
michael@0 503 for filename in glob.glob(fileglobs):
michael@0 504 os.remove(filename)
michael@0 505
michael@0 506 # Instantiate the parser.
michael@0 507 p = xpidl.IDLParser(outputdir=options.cachedir)
michael@0 508
michael@0 509 if options.regen:
michael@0 510 sys.exit(0)
michael@0 511
michael@0 512 if options.depfile is not None and options.outfile is None:
michael@0 513 print >>sys.stderr, "-d requires -o"
michael@0 514 sys.exit(1)
michael@0 515
michael@0 516 if options.outfile is not None:
michael@0 517 outfd = open(options.outfile, 'w')
michael@0 518 closeoutfd = True
michael@0 519 else:
michael@0 520 outfd = sys.stdout
michael@0 521 closeoutfd = False
michael@0 522
michael@0 523 idl = p.parse(open(file).read(), filename=file)
michael@0 524 idl.resolve(options.incdirs, p)
michael@0 525 print_header(idl, outfd, file)
michael@0 526
michael@0 527 if closeoutfd:
michael@0 528 outfd.close()
michael@0 529
michael@0 530 if options.depfile is not None:
michael@0 531 dirname = os.path.dirname(options.depfile)
michael@0 532 if dirname:
michael@0 533 try:
michael@0 534 os.makedirs(dirname)
michael@0 535 except:
michael@0 536 pass
michael@0 537 depfd = open(options.depfile, 'w')
michael@0 538 deps = [dep.replace('\\', '/') for dep in idl.deps]
michael@0 539
michael@0 540 print >>depfd, "%s: %s" % (options.outfile, " ".join(deps))
michael@0 541 for dep in deps:
michael@0 542 print >>depfd, "%s:" % dep

mercurial