PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/scripts/pymod-process.py

https://bitbucket.org/grelminar/asss/
Python | 1955 lines | 1888 code | 49 blank | 18 comment | 43 complexity | ee2a9907b38aa32cf855e626144ce620 MD5 | raw file
Possible License(s): AGPL-1.0
  1. #!/usr/bin/env python
  2. # dist: public
  3. import sys, os, re, string, glob
  4. DEFBUFLEN = 1024
  5. # lots of precompiled regular expressions
  6. # include directives
  7. re_pyinclude = re.compile(r'\s*/\* pyinclude: (.*) \*/')
  8. # constants
  9. re_pyconst_dir = re.compile(r'\s*/\* pyconst: (.*), "(.*)" \*/')
  10. # callbacks
  11. re_pycb_cbdef = re.compile(r'#define (CB_[A-Z_0-9]*)')
  12. re_pycb_typedef = re.compile(r'typedef void \(\*([A-Za-z_0-9]*)\)')
  13. re_pycb_dir = re.compile(r'/\* pycb: (.*?)(\*/)?$')
  14. # interfaces
  15. re_pyint_intdef = re.compile(r'#define (I_[A-Z_0-9]*)')
  16. re_pyint_typedef = re.compile(r'typedef struct (I[a-z_0-9]*)')
  17. re_pyint_func = re.compile(r'([ ]{4}|\t)[A-Za-z].*?\(\*([A-Za-z_0-9]*)\)')
  18. re_pyint_dir = re.compile(r'\s*/\* pyint: (.*?)(\*/)?$')
  19. re_pyint_done = re.compile(r'^}')
  20. # advisers
  21. re_pyadv_advdef = re.compile(r'#define (A_[A-Z_0-9]*)')
  22. re_pyadv_typedef = re.compile(r'typedef struct (A[a-z_0-9]*)')
  23. re_pyadv_func = re.compile(r'([ ]{4}|\t)[A-Za-z].*?\(\*([A-Za-z_0-9]*)\)')
  24. re_pyadv_dir = re.compile(r'\s*/\* pyadv: (.*?)(\*/)?$')
  25. re_pyadv_done = re.compile(r'^}')
  26. # types
  27. re_pytype = re.compile(r'\s*/\* pytype: (.*) \*/')
  28. # utility functions for constant translation
  29. def const_int(n):
  30. const_file.write('INT(%s)\n' % n);
  31. def const_string(n):
  32. const_file.write('STRING(%s)\n' % n);
  33. def const_one(n):
  34. const_file.write('ONE(%s)\n' % n);
  35. def const_callback(n):
  36. const_file.write('PYCALLBACK(%s)\n' % n);
  37. def const_interface(n):
  38. const_file.write('PYINTERFACE(%s)\n' % n);
  39. def const_adviser(n):
  40. const_file.write('PYADVISER(%s)\n' % n);
  41. def tokenize_signature(s):
  42. out = []
  43. t = ''
  44. dash = 0
  45. for c in s:
  46. if c in string.letters or c in string.digits or c == '_':
  47. t += c
  48. else:
  49. if t:
  50. out.append(t)
  51. t = ''
  52. if dash and c == '>':
  53. out.append('->')
  54. dash = 0
  55. else:
  56. dash = 0
  57. if c in ',()':
  58. out.append(c)
  59. elif c == '-':
  60. dash = 1
  61. assert not dash
  62. if t:
  63. out.append(t)
  64. return out
  65. class Arg:
  66. def __init__(me, tp, flags):
  67. me.tp = tp
  68. me.flags = flags
  69. def __str__(me):
  70. return str(me.tp) + '[' + ', '.join(map(str, me.flags)) + ']'
  71. class Func:
  72. def __init__(me, args, out):
  73. me.args = args
  74. me.out = out
  75. def __str__(me):
  76. return '(' + ', '.join(map(str, me.args)) + ' -> ' + str(me.out) + ')'
  77. def is_func(o):
  78. return getattr(o, '__class__', None) is Func
  79. def parse_arg(tokens):
  80. flags = []
  81. if tokens[0] == '(':
  82. tokens.pop(0)
  83. tp = parse_func(tokens)
  84. assert tokens[0] == ')'
  85. tokens.pop(0)
  86. else:
  87. tp = tokens.pop(0)
  88. while tokens and tokens[0] not in [',', '->', ')']:
  89. flags.append(tokens.pop(0))
  90. return Arg(tp, flags)
  91. def parse_func(tokens):
  92. args = []
  93. while tokens[0] != '->':
  94. assert tokens[0] != ')'
  95. args.append(parse_arg(tokens))
  96. if tokens[0] == ',':
  97. tokens.pop(0)
  98. tokens.pop(0)
  99. out = parse_arg(tokens)
  100. return Func(args, out)
  101. def genid(state = [100]):
  102. state[0] += 1
  103. return 'py_genid_%d' % state[0]
  104. class type_gen:
  105. def format_char(me):
  106. raise Exception()
  107. # these two should throw exceptions unless the format char is O&
  108. def build_converter(me):
  109. raise Exception()
  110. def parse_converter(me):
  111. raise Exception()
  112. def decl(me):
  113. raise Exception()
  114. def buf_decl(me, s):
  115. return me.decl(s)
  116. def buf_decl_def(me, s):
  117. return me.buf_decl(s) + ' = %s' % me.buf_init()
  118. def parse_decl(me, s):
  119. return me.buf_decl(s)
  120. def ptr_decl(me, s):
  121. return '%s*%s' % (me.decl(''), s)
  122. def conv_to_buf(me, buf, val):
  123. return '\t*%s = %s;' % (buf, val)
  124. def buf_init(me):
  125. return '0'
  126. def buf_prefix(me):
  127. return '&'
  128. def out_prefix(me):
  129. return ''
  130. def ptr_val(me):
  131. return '*'
  132. class type_void(type_gen):
  133. def decl(me, s):
  134. return 'void ' + s
  135. def to_obj(me, s):
  136. return 'PyCObject_FromVoidPtr(ptr, NULL)'
  137. def from_obj(me, s):
  138. return '*(int *)PyCObject_AsVoidPtr(%s)' % s
  139. class type_null(type_gen):
  140. def format_char(me):
  141. return ''
  142. def decl(me, s):
  143. return 'void *%s = NULL' % s
  144. class type_zero(type_gen):
  145. def format_char(me):
  146. return ''
  147. def decl(me, s):
  148. return 'int %s = 0' % s
  149. class type_one(type_gen):
  150. def format_char(me):
  151. return ''
  152. def decl(me, s):
  153. return 'int %s = 1' % s
  154. class type_int(type_gen):
  155. def format_char(me):
  156. return 'i'
  157. def decl(me, s):
  158. return 'int ' + s
  159. def to_obj(me, s):
  160. return 'PyInt_FromLong(%s)' % s
  161. def from_obj(me, s):
  162. return 'PyInt_AsLong(%s)' % s
  163. class type_short(type_int):
  164. def format_char(me):
  165. return 'h'
  166. def decl(me, s):
  167. return 'short ' + s
  168. class type_uint(type_int):
  169. def format_char(me):
  170. return 'I'
  171. def decl(me, s):
  172. return 'unsigned int ' + s
  173. class type_ushort(type_int):
  174. def format_char(me):
  175. return 'H'
  176. def decl(me, s):
  177. return 'unsigned short ' + s
  178. class type_double(type_gen):
  179. def format_char(me):
  180. return 'd'
  181. def decl(me, s):
  182. return 'double ' + s
  183. def to_obj(me, s):
  184. return 'PyFloat_FromDouble(%s)' % s
  185. def from_obj(me, s):
  186. return 'PyFloat_AsDouble(%s)' % s
  187. class type_string(type_gen):
  188. def format_char(me):
  189. return 's'
  190. def decl(me, s):
  191. return 'const char *' + s
  192. def parse_decl(me, s):
  193. return me.decl(s)
  194. def buf_decl(me, s):
  195. return 'charbuf %s' % s
  196. def ptr_decl(me, s):
  197. return 'char *%s' % s
  198. def buf_init(me):
  199. return '{0}'
  200. def conv_to_buf(me, buf, val):
  201. return '\tastrncpy(%s, %s, buflen);' % (buf, val)
  202. def buf_prefix(me):
  203. return ''
  204. class type_zstring(type_string):
  205. def format_char(me):
  206. return 'z'
  207. class type_retstring(type_string):
  208. def format_char(me):
  209. return 's#'
  210. class type_player(type_gen):
  211. def format_char(me):
  212. return 'O&'
  213. def decl(me, s):
  214. return 'Player *' + s
  215. def build_converter(me):
  216. return 'cvt_c2p_player'
  217. def parse_converter(me):
  218. return 'cvt_p2c_player'
  219. class type_player_not_none(type_gen):
  220. def format_char(me):
  221. return 'O&'
  222. def decl(me, s):
  223. return 'Player *' + s
  224. def build_converter(me):
  225. return 'cvt_c2p_player_not_none'
  226. def parse_converter(me):
  227. return 'cvt_p2c_player_not_none'
  228. class type_arena(type_gen):
  229. def format_char(me):
  230. return 'O&'
  231. def decl(me, s):
  232. return 'Arena *' + s
  233. def build_converter(me):
  234. return 'cvt_c2p_arena'
  235. def parse_converter(me):
  236. return 'cvt_p2c_arena'
  237. class type_arena_not_none(type_gen):
  238. def format_char(me):
  239. return 'O&'
  240. def decl(me, s):
  241. return 'Arena *' + s
  242. def build_converter(me):
  243. return 'cvt_c2p_arena_not_none'
  244. def parse_converter(me):
  245. return 'cvt_p2c_arena_not_none'
  246. class type_config(type_gen):
  247. def format_char(me):
  248. return 'O&'
  249. def decl(me, s):
  250. return 'ConfigHandle ' + s
  251. def build_converter(me):
  252. return 'cvt_c2p_config'
  253. def parse_converter(me):
  254. return 'cvt_p2c_config'
  255. class type_banner(type_gen):
  256. def format_char(me):
  257. return 'O&'
  258. def decl(me, s):
  259. return 'Banner *' + s
  260. def build_converter(me):
  261. return 'cvt_c2p_banner'
  262. def parse_converter(me):
  263. return 'cvt_p2c_banner'
  264. class type_target(type_gen):
  265. def format_char(me):
  266. return 'O&'
  267. def decl(me, s):
  268. return 'Target *' + s
  269. def buf_decl(me, s):
  270. return 'Target ' + s
  271. def build_converter(me):
  272. return 'cvt_c2p_target'
  273. def parse_converter(me):
  274. return 'cvt_p2c_target'
  275. def out_prefix(me):
  276. return '&'
  277. def conv_to_buf(me, buf, val):
  278. raise Exception()
  279. class type_bufp(type_gen):
  280. def format_char(me):
  281. return 's#'
  282. def decl(me, s):
  283. raise Exception()
  284. def buf_decl(me, s):
  285. return 'const void *%s' % s
  286. def buf_init(me):
  287. return 'NULL'
  288. def conv_to_buf(me, buf, val):
  289. raise Exception()
  290. class type_playerlist(type_gen):
  291. def format_char(me):
  292. return 'O&'
  293. def decl(me, s):
  294. return 'LinkedList *%s = LLAlloc()' % s
  295. def build_converter(me):
  296. return 'cvt_c2p_playerlist'
  297. def parse_converter(me):
  298. return 'cvt_p2c_playerlist'
  299. class type_dict(type_gen):
  300. def format_char(me):
  301. return 'O&'
  302. def decl(me, s):
  303. return 'HashTable *%s = HashAlloc()' %s
  304. def build_converter(me):
  305. return 'cvt_c2p_dict'
  306. def parse_converter(me):
  307. return 'cvt_p2c_dict'
  308. def get_type(tp):
  309. try:
  310. cname = 'type_' + tp
  311. cls = globals()[cname]
  312. return cls()
  313. except:
  314. return None
  315. def create_c_to_py_func(name, func):
  316. args = func.args
  317. out = func.out
  318. informat = []
  319. outformat = []
  320. inargs = []
  321. outargs = []
  322. decls = []
  323. extras3 = []
  324. allargs = []
  325. av_arena = None
  326. av_player = None
  327. if out.tp == 'void':
  328. retorblank = ''
  329. rettype = type_void()
  330. defretval = ''
  331. elif out.tp == 'retstring':
  332. assert not out.flags
  333. typ = get_type(out.tp)
  334. argname = 'tmp'
  335. decls.append('\tconst char *tmp;')
  336. decls.append('\tint buflen;')
  337. decls.append('\tchar *ret;')
  338. outformat.append("s#")
  339. outargs.append('&tmp')
  340. outargs.append('&buflen')
  341. retorblank = 'ret'
  342. rettype = typ
  343. defretval = 'NULL'
  344. extras3.append('\tif(buflen != 0)\n\t{')
  345. extras3.append('\t\tbuflen++;')
  346. extras3.append('\t\tret = amalloc(sizeof(char) * buflen);')
  347. extras3.append('\t\tastrncpy(ret, tmp, buflen);\n\t}')
  348. else:
  349. assert not out.flags
  350. typ = get_type(out.tp)
  351. argname = 'ret'
  352. decls.append('\t%s;' % typ.decl(argname))
  353. outformat.append(typ.format_char())
  354. try:
  355. outargs.append(typ.build_converter())
  356. except:
  357. pass
  358. outargs.append('&%s' % argname)
  359. retorblank = 'ret'
  360. rettype = typ
  361. defretval = '0'
  362. idx = 0
  363. for arg in args:
  364. idx = idx + 1
  365. argname = 'arg%d' % idx
  366. opts = arg.flags
  367. typ = get_type(arg.tp)
  368. if arg.tp == 'void':
  369. continue
  370. elif arg.tp == 'clos':
  371. decls.append('\tPyObject *closobj = clos;')
  372. allargs.append('void *clos')
  373. elif 'in' in opts or not opts:
  374. # this is an incoming arg
  375. argname += '_in'
  376. informat.append(typ.format_char())
  377. try:
  378. inargs.append(typ.build_converter())
  379. except:
  380. pass
  381. inargs.append(argname)
  382. allargs.append(typ.decl(argname))
  383. # the arena value can only be an inarg
  384. if av_arena is None and (arg.tp == 'arena' or arg.tp == 'arena_not_none'):
  385. av_arena = argname
  386. elif av_player is None and (arg.tp == 'player' or arg.tp == 'player_not_none'):
  387. av_player = argname + '->arena'
  388. elif 'out' in opts:
  389. # this is an outgoing arg
  390. argname += '_out'
  391. vargname = argname + '_v'
  392. decls.append('\t%s;' % (typ.parse_decl(vargname)))
  393. outformat.append(typ.format_char())
  394. try:
  395. outargs.append(typ.parse_converter())
  396. except:
  397. pass
  398. outargs.append('&%s' % vargname)
  399. allargs.append(typ.ptr_decl(argname))
  400. extras3.append(typ.conv_to_buf(argname, vargname))
  401. elif 'inout' in opts:
  402. # this is both incoming and outgoing
  403. argname += '_inout'
  404. vargname = argname + '_v'
  405. if arg.tp == 'string':
  406. decls.append('\t%s;' % (typ.decl(vargname)))
  407. decls.append('\tint len_%s;' % vargname)
  408. outformat.append('s#')
  409. else:
  410. decls.append('\t%s;' % (typ.buf_decl(vargname)))
  411. outformat.append(typ.format_char())
  412. informat.append(typ.format_char())
  413. try:
  414. inargs.append(typ.parse_converter())
  415. except:
  416. pass
  417. if isinstance(typ, type_string):
  418. inargs.append(argname)
  419. else:
  420. inargs.append(typ.ptr_val() + argname)
  421. try:
  422. outargs.append(typ.build_converter())
  423. except:
  424. pass
  425. outargs.append('&%s' % vargname)
  426. allargs.append(typ.ptr_decl(argname))
  427. if arg.tp == 'string':
  428. outargs.append('&len_%s' % vargname)
  429. extras3.append('\tif(++len_%s < buflen) buflen = len_%s;' % (vargname, vargname))
  430. extras3.append(typ.conv_to_buf(argname, vargname))
  431. elif 'buflen' in opts:
  432. # this arg is a buffer length
  433. allargs.append('int %s' % argname)
  434. new = []
  435. for e in extras3:
  436. new.append(e.replace('buflen', argname))
  437. extras3 = new
  438. if inargs:
  439. inargs = ', ' + ', '.join(inargs)
  440. else:
  441. inargs = ''
  442. if outargs:
  443. outargs = ', ' + ', '.join(outargs)
  444. else:
  445. outargs = ''
  446. if allargs:
  447. allargs = ', '.join(allargs)
  448. else:
  449. allargs = 'void'
  450. informat = ''.join(informat)
  451. outformat = ''.join(outformat)
  452. decls = '\n'.join(decls)
  453. extras3 = '\n'.join(extras3)
  454. retdecl = rettype.decl('')
  455. if isinstance(rettype, type_playerlist):
  456. retdecl = "LinkedList *"
  457. if av_arena:
  458. arenaval = av_arena
  459. elif av_player:
  460. arenaval = av_player
  461. if name:
  462. print "warning: %s: guessing arena from player argument" % name
  463. else:
  464. arenaval = 'ALLARENAS'
  465. del av_arena
  466. del av_player
  467. del args
  468. del out
  469. del rettype
  470. return vars()
  471. def create_py_to_c_func(func):
  472. args = func.args
  473. out = func.out
  474. informat = []
  475. outformat = []
  476. inargs = []
  477. outargs = []
  478. decls = []
  479. extras1 = []
  480. extras2 = []
  481. extras3 = []
  482. extracode = []
  483. allargs = []
  484. if out.tp == 'void':
  485. asgntoret = ''
  486. else:
  487. assert not out.flags
  488. typ = get_type(out.tp)
  489. argname = 'ret'
  490. decls.append('\t%s;' % typ.decl(argname))
  491. outformat.append(typ.format_char())
  492. try:
  493. outargs.append(typ.build_converter())
  494. except:
  495. pass
  496. outargs.append(argname)
  497. asgntoret = '%s = ' % argname
  498. idx = 0
  499. for arg in args:
  500. idx = idx + 1
  501. argname = 'arg%d' % idx
  502. opts = arg.flags
  503. typ = get_type(arg.tp)
  504. if arg.tp == 'void':
  505. continue
  506. elif arg.tp == 'formatted':
  507. # these are a little weird
  508. if idx != len(args):
  509. raise Exception, "formatted arg isn't last!"
  510. typ = get_type('string')
  511. argname += '_infmt'
  512. informat.append(typ.format_char())
  513. decls.append('\t%s;' % typ.decl(argname))
  514. inargs.append('&%s' % argname)
  515. allargs.append('"%s"')
  516. allargs.append('%s' % argname)
  517. elif arg.tp == 'clos':
  518. # hardcoded value. this depends on the existence of exactly
  519. # one function argument.
  520. allargs.append('cbfunc')
  521. elif is_func(arg.tp):
  522. cbfuncname = genid()
  523. informat.append('O')
  524. decls.append('\tPyObject *cbfunc;')
  525. inargs.append('&cbfunc')
  526. allargs.append(cbfuncname)
  527. extras1.append("""
  528. if (!PyCallable_Check(cbfunc))
  529. {
  530. PyErr_SetString(PyExc_TypeError, "func isn't callable");
  531. return NULL;
  532. }
  533. """)
  534. if 'dynamic' in opts:
  535. extras1.append('\tPy_INCREF(cbfunc);')
  536. if 'failval' in opts:
  537. # provides a way to clean up the extra reference if
  538. # the return value from the function indicates that
  539. # the callback won't be called. otherwise, we expect
  540. # the callback to be called exactly once.
  541. failval = opts[opts.index('failval')+1]
  542. extras2.append(
  543. '\tif (ret == (%s)) { Py_DECREF(cbfunc); }' % failval)
  544. decref = '\tPy_DECREF(closobj);'
  545. else:
  546. decref = ''
  547. cbdict = create_c_to_py_func(None, arg.tp)
  548. cbdict['cbfuncname'] = cbfuncname
  549. cbdict['decref'] = decref
  550. cbcode = []
  551. cbcode.append("""
  552. local %(retdecl)s %(cbfuncname)s(%(allargs)s)
  553. {
  554. NEEDS_GIL;
  555. GI_LOCK();
  556. PyObject *args, *out;
  557. %(decls)s
  558. args = Py_BuildValue("(%(informat)s)"%(inargs)s);
  559. if (!args)
  560. {
  561. log_py_exception(L_ERROR, "python error building args for "
  562. "interface argument function");
  563. GI_UNLOCK();
  564. return %(defretval)s;
  565. }
  566. out = PyObject_Call(closobj, args, NULL);
  567. Py_DECREF(args);
  568. %(decref)s
  569. if (!out)
  570. {
  571. log_py_exception(L_ERROR, "python error calling "
  572. "interface argument function");
  573. GI_UNLOCK();
  574. return %(defretval)s;
  575. }
  576. """)
  577. if cbdict['outargs']:
  578. cbcode.append("""
  579. if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
  580. {
  581. Py_DECREF(out);
  582. log_py_exception(L_ERROR, "python error unpacking results of "
  583. "interface argument function");
  584. GI_UNLOCK();
  585. return %(defretval)s;
  586. }
  587. """)
  588. else:
  589. cbcode.append("""
  590. if (out != Py_None)
  591. {
  592. Py_DECREF(out);
  593. log_py_exception(L_ERROR, "interface argument function didn't return None as expected");
  594. GI_UNLOCK();
  595. return %(defretval)s;
  596. }
  597. """)
  598. cbcode.append("""
  599. %(extras3)s
  600. Py_DECREF(out);
  601. GI_UNLOCK();
  602. }
  603. """)
  604. cbcode = ''.join(cbcode) % cbdict
  605. extracode.append(cbcode)
  606. elif 'in' in opts or not opts:
  607. # this is an incoming arg
  608. argname += '_in'
  609. informat.append(typ.format_char())
  610. decls.append('\t%s;' % (typ.parse_decl(argname)))
  611. try:
  612. inargs.append(typ.parse_converter())
  613. except:
  614. pass
  615. if typ.format_char():
  616. inargs.append('&' + argname)
  617. allargs.append(typ.out_prefix() + argname)
  618. elif 'out' in opts:
  619. # this is an outgoing arg
  620. argname += '_out'
  621. if 'buflen' not in opts:
  622. outformat.append(typ.format_char())
  623. decls.append('\t%s;' % (typ.buf_decl_def(argname)))
  624. try:
  625. outargs.append(typ.build_converter())
  626. except:
  627. pass
  628. outargs.append(typ.out_prefix() + argname)
  629. allargs.append(typ.buf_prefix() + argname)
  630. elif 'inout' in opts:
  631. # this is both incoming and outgoing
  632. argname += '_inout'
  633. informat.append(typ.format_char())
  634. outformat.append(typ.format_char())
  635. decls.append('\t%s;' % (typ.buf_decl_def(argname)))
  636. if typ.format_char():
  637. try:
  638. inargs.append(typ.parse_converter())
  639. except:
  640. pass
  641. inargs.append('&' + argname)
  642. try:
  643. outargs.append(typ.build_converter())
  644. except:
  645. pass
  646. outargs.append(typ.out_prefix() + argname)
  647. allargs.append(typ.buf_prefix() + argname)
  648. elif 'buflen' in opts:
  649. # this arg is a buffer length
  650. # it must be passed in, so it's sort of like an
  651. # inarg, but it doesn't get parsed.
  652. allargs.append('%s' % DEFBUFLEN)
  653. decls = '\n'.join(decls)
  654. if inargs:
  655. inargs = ', ' + ', '.join(inargs)
  656. else:
  657. inargs = ''
  658. if outargs:
  659. outargs = ', ' + ', '.join(outargs)
  660. else:
  661. outargs = ''
  662. informat = ''.join(informat)
  663. outformat = ''.join(outformat)
  664. allargs = ', '.join(allargs)
  665. extras1 = '\n'.join(extras1)
  666. extras2 = '\n'.join(extras2)
  667. extras3 = '\n'.join(extras3)
  668. extracode = '\n'.join(extracode)
  669. del args
  670. del out
  671. del idx
  672. return vars()
  673. # functions for asss<->python callback translation
  674. pycb_cb_names = []
  675. def translate_pycb(name, ctype, line):
  676. pycb_cb_names.append((name, ctype))
  677. tokens = tokenize_signature(line + '->void')
  678. func = parse_func(tokens)
  679. funcname = 'py_cb_%s' % name
  680. cbvars = create_c_to_py_func(name, func)
  681. cbvars.update(vars())
  682. # an optimization: if we have outargs, we need to build the arg
  683. # tuple every time to get the updated values, but if we don't, we
  684. # can reuse the tuple.
  685. outargs = cbvars['outargs']
  686. buildcode = """
  687. args = Py_BuildValue("(%(informat)s)"%(inargs)s);
  688. if (!args)
  689. {
  690. log_py_exception(L_ERROR, "python error building args for "
  691. "callback %(name)s");
  692. GI_UNLOCK();
  693. return;
  694. }
  695. """
  696. decref = """
  697. Py_DECREF(args);
  698. """
  699. code = []
  700. code.append("""
  701. local %(retdecl)s %(funcname)s(%(allargs)s)
  702. {
  703. NEEDS_GIL;
  704. GI_LOCK();
  705. PyObject *args, *out;
  706. LinkedList cbs = LL_INITIALIZER;
  707. Link *l;
  708. %(decls)s
  709. mm->LookupCallback(PYCBPREFIX %(name)s, %(arenaval)s, &cbs);
  710. if (LLIsEmpty(&cbs))
  711. {
  712. GI_UNLOCK();
  713. return;
  714. }
  715. """)
  716. if not outargs:
  717. code.append(buildcode)
  718. code.append("""
  719. for (l = LLGetHead(&cbs); l; l = l->next)
  720. {
  721. """)
  722. if outargs:
  723. code.append(buildcode)
  724. code.append("""
  725. out = PyObject_Call(l->data, args, NULL);
  726. """)
  727. if outargs:
  728. code.append(decref)
  729. code.append("""
  730. if (!out)
  731. {
  732. log_py_exception(L_ERROR, "python error calling "
  733. "callback %(name)s");
  734. continue;
  735. }
  736. """)
  737. if outargs:
  738. code.append("""
  739. if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
  740. {
  741. Py_DECREF(out);
  742. log_py_exception(L_ERROR, "python error unpacking results of "
  743. "callback %(name)s");
  744. continue;
  745. }
  746. """)
  747. else:
  748. code.append("""
  749. if (out != Py_None)
  750. {
  751. Py_DECREF(out);
  752. log_py_exception(L_ERROR, "callback %(name)s didn't return None as expected");
  753. continue;
  754. }
  755. """)
  756. code.append("""
  757. Py_DECREF(out);
  758. %(extras3)s
  759. }
  760. """)
  761. if not outargs:
  762. code.append(decref)
  763. code.append("""
  764. LLEmpty(&cbs);
  765. GI_UNLOCK();
  766. }
  767. """)
  768. code = ''.join(code) % cbvars
  769. callback_file.write(code)
  770. cbvars = create_py_to_c_func(func)
  771. cbvars['name'] = name
  772. cbvars['ctype'] = ctype
  773. code = """
  774. local PyObject * py_cb_call_%(name)s(Arena *arena, PyObject *args)
  775. {
  776. PyObject *out;
  777. %(decls)s
  778. if (!PyArg_ParseTuple(args, "%(informat)s"%(inargs)s))
  779. return NULL;
  780. %(extras1)s
  781. DO_CBS(%(name)s, arena, %(ctype)s, (%(allargs)s));
  782. %(extras2)s
  783. out = Py_BuildValue("%(outformat)s"%(outargs)s);
  784. %(extras3)s
  785. return out;
  786. }
  787. """ % cbvars
  788. callback_file.write(code)
  789. def finish_pycb():
  790. callback_file.write("""
  791. typedef PyObject * (*py_cb_caller)(Arena *arena, PyObject *args);
  792. local HashTable *py_cb_callers;
  793. local void init_py_callbacks(void)
  794. {
  795. py_cb_callers = HashAlloc();
  796. """)
  797. for n, ctype in pycb_cb_names:
  798. callback_file.write(" { %s typecheck = py_cb_%s; (void)typecheck; }\n" % (ctype, n))
  799. callback_file.write(" mm->RegCallback(%s, py_cb_%s, ALLARENAS);\n" % (n, n))
  800. callback_file.write(" HashReplace(py_cb_callers, PYCBPREFIX %s, py_cb_call_%s);\n" % (n, n))
  801. callback_file.write("""\
  802. }
  803. local void deinit_py_callbacks(void)
  804. {
  805. """)
  806. for n, _ in pycb_cb_names:
  807. callback_file.write(" mm->UnregCallback(%s, py_cb_%s, ALLARENAS);\n" % (n, n))
  808. callback_file.write("""\
  809. HashFree(py_cb_callers);
  810. }
  811. """)
  812. # translating interfaces asss<->python
  813. def init_pyint():
  814. out = int_file
  815. out.write("""
  816. /* pyint declarations */
  817. local void pyint_generic_dealloc(pyint_generic_interface_object *self)
  818. {
  819. mm->ReleaseInterface(self->i);
  820. PyObject_Del(self);
  821. }
  822. """)
  823. pyint_init_code = []
  824. def translate_pyint(iid, ifstruct, dirs):
  825. _, allowed = dirs.pop(0)
  826. allowed = map(string.strip, allowed.split(','))
  827. if 'use' in allowed:
  828. objstructname = 'pyint_obj_%s' % iid
  829. methods = []
  830. methoddecls = []
  831. members = []
  832. memberdecls = []
  833. for name, thing in dirs:
  834. try:
  835. tokens = tokenize_signature(thing)
  836. func = parse_func(tokens)
  837. except:
  838. print "couldn't parse '%s'" % thing
  839. continue
  840. dict = create_py_to_c_func(func)
  841. mthdname = 'pyint_method_%s_%s' % (iid, name)
  842. dict.update(vars())
  843. mthd = """
  844. %(extracode)s
  845. local PyObject *
  846. %(mthdname)s(%(objstructname)s *me, PyObject *args)
  847. {
  848. PyObject *out;
  849. %(decls)s
  850. if (!PyArg_ParseTuple(args, "%(informat)s"%(inargs)s))
  851. return NULL;
  852. %(extras1)s
  853. %(asgntoret)sme->i->%(name)s(%(allargs)s);
  854. %(extras2)s
  855. out = Py_BuildValue("%(outformat)s"%(outargs)s);
  856. %(extras3)s
  857. return out;
  858. }
  859. """ % dict
  860. methods.append(mthd)
  861. decl = """\
  862. {"%(name)s", (PyCFunction)%(mthdname)s, METH_VARARGS, NULL },
  863. """ % vars()
  864. methoddecls.append(decl)
  865. objstructdecl = """
  866. typedef struct {
  867. PyObject_HEAD
  868. %(ifstruct)s *i;
  869. } %(objstructname)s;
  870. """ % vars()
  871. methoddeclname = 'pyint_%s_methods' % iid
  872. methoddeclstart = """
  873. local PyMethodDef %(methoddeclname)s[] = {
  874. """ % vars()
  875. methoddeclend = """\
  876. {NULL}
  877. };
  878. """ % vars()
  879. memberdeclname = 'pyint_%s_members' % iid
  880. memberdeclstart = """
  881. local PyMemberDef %(memberdeclname)s[] = {
  882. """ % vars()
  883. memberdeclend = """\
  884. {NULL}
  885. };
  886. """ % vars()
  887. typestructname = 'pyint_%s_type' % iid
  888. typedecl = """
  889. #pragma GCC diagnostic push
  890. #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  891. local PyTypeObject %(typestructname)s = {
  892. PyObject_HEAD_INIT(NULL)
  893. 0, /*ob_size*/
  894. "asss.%(ifstruct)s", /*tp_name*/
  895. sizeof(%(objstructname)s), /*tp_basicsize*/
  896. 0, /*tp_itemsize*/
  897. (destructor)pyint_generic_dealloc, /*tp_dealloc*/
  898. 0, /*tp_print*/
  899. 0, /*tp_getattr*/
  900. 0, /*tp_setattr*/
  901. 0, /*tp_compare*/
  902. 0, /*tp_repr*/
  903. 0, /*tp_as_number*/
  904. 0, /*tp_as_sequence*/
  905. 0, /*tp_as_mapping*/
  906. 0, /*tp_hash */
  907. 0, /*tp_call*/
  908. 0, /*tp_str*/
  909. 0, /*tp_getattro*/
  910. 0, /*tp_setattro*/
  911. 0, /*tp_as_buffer*/
  912. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  913. 0, /*tp_doc */
  914. 0, /*tp_traverse */
  915. 0, /*tp_clear */
  916. 0, /*tp_richcompare*/
  917. 0, /*tp_weaklistoffset*/
  918. 0, /*tp_iter*/
  919. 0, /*tp_iternext*/
  920. %(methoddeclname)s, /*tp_methods*/
  921. %(memberdeclname)s, /*tp_members*/
  922. /* rest are null */
  923. };
  924. #pragma GCC diagnostic pop
  925. """ % vars()
  926. doinit = """\
  927. if (PyType_Ready(&%(typestructname)s) < 0) return;
  928. HashReplace(pyint_ints, %(iid)s, &%(typestructname)s);
  929. """ % vars()
  930. pyint_init_code.append(doinit)
  931. int_file.write('\n/* using interface %(iid)s from python {{{ */\n' % vars())
  932. int_file.write(objstructdecl)
  933. for m in methods:
  934. int_file.write(m)
  935. int_file.write(methoddeclstart)
  936. for m in methoddecls:
  937. int_file.write(m)
  938. int_file.write(methoddeclend)
  939. for m in members:
  940. int_file.write(m)
  941. int_file.write(memberdeclstart)
  942. for m in memberdecls:
  943. int_file.write(m)
  944. int_file.write(memberdeclend)
  945. int_file.write(typedecl)
  946. int_file.write('\n/* }}} */\n')
  947. if 'impl' in allowed:
  948. ifacename = 'pyint_int_%s' % iid
  949. funcs = []
  950. funcnames = []
  951. lastout = None
  952. for name, thing in dirs:
  953. try:
  954. tokens = tokenize_signature(thing)
  955. func = parse_func(tokens)
  956. except:
  957. print "bad declaration '%s'" % thing
  958. continue
  959. funcname = 'pyint_func_%s_%s' % (iid, name)
  960. funcdict = create_c_to_py_func('%s::%s' % (iid, name), func)
  961. funcdict.update(vars())
  962. code = []
  963. code.append("""
  964. local %(retdecl)s %(funcname)s(%(allargs)s)
  965. {
  966. NEEDS_GIL;
  967. GI_LOCK();
  968. PyObject *args, *out;
  969. %(decls)s
  970. args = Py_BuildValue("(%(informat)s)"%(inargs)s);
  971. if (!args)
  972. {
  973. log_py_exception(L_ERROR, "python error building args for "
  974. "function %(name)s in interface %(iid)s");
  975. GI_UNLOCK();
  976. return %(defretval)s;
  977. }
  978. out = call_gen_py_interface(PYINTPREFIX %(iid)s, "%(name)s", args, %(arenaval)s);
  979. if (!out)
  980. {
  981. log_py_exception(L_ERROR, "python error calling "
  982. "function %(name)s in interface %(iid)s");
  983. GI_UNLOCK();
  984. return %(defretval)s;
  985. }
  986. """)
  987. if funcdict['outargs']:
  988. code.append("""
  989. if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
  990. {
  991. Py_DECREF(out);
  992. log_py_exception(L_ERROR, "python error unpacking results of "
  993. "function %(name)s in interface %(iid)s");
  994. GI_UNLOCK();
  995. return %(defretval)s;
  996. }
  997. """)
  998. else:
  999. code.append("""
  1000. if (out != Py_None)
  1001. {
  1002. Py_DECREF(out);
  1003. log_py_exception(L_ERROR, "interface func %(name)s didn't return None as expected");
  1004. GI_UNLOCK();
  1005. return %(defretval)s;
  1006. }
  1007. """)
  1008. code.append("""
  1009. %(extras3)s
  1010. Py_DECREF(out);
  1011. GI_UNLOCK();
  1012. return %(retorblank)s;
  1013. }
  1014. """)
  1015. code = ''.join(code) % funcdict
  1016. funcs.append(code)
  1017. funcnames.append(funcname)
  1018. funcnames = ',\n\t'.join(funcnames)
  1019. ifstructdecl = """
  1020. local struct %(ifstruct)s %(ifacename)s = {
  1021. INTERFACE_HEAD_INIT(%(iid)s, "pyint-%(iid)s")
  1022. %(funcnames)s
  1023. };
  1024. """ % vars()
  1025. init = "\tHashReplace(pyint_impl_ints, PYINTPREFIX %(iid)s, &%(ifacename)s);\n" % vars()
  1026. pyint_init_code.append(init)
  1027. int_file.write('\n/* implementing interface %(iid)s in python {{{ */\n' % vars())
  1028. for func in funcs:
  1029. int_file.write(func)
  1030. int_file.write(ifstructdecl)
  1031. int_file.write('\n/* }}} */\n')
  1032. def finish_pyint():
  1033. out = int_file
  1034. out.write("""
  1035. local HashTable *pyint_ints;
  1036. local HashTable *pyint_impl_ints;
  1037. local void init_py_interfaces(void)
  1038. {
  1039. pyint_ints = HashAlloc();
  1040. pyint_impl_ints = HashAlloc();
  1041. """)
  1042. for line in pyint_init_code:
  1043. out.write(line)
  1044. out.write("""\
  1045. }
  1046. local void deinit_py_interfaces(void)
  1047. {
  1048. """)
  1049. out.write("""\
  1050. HashFree(pyint_ints);
  1051. HashFree(pyint_impl_ints);
  1052. }
  1053. """)
  1054. # translating advisers asss<->python
  1055. def init_pyadv():
  1056. out = adv_file
  1057. out.write("""
  1058. /* pyadv declarations */
  1059. local void pyadv_generic_dealloc(pyint_generic_adviser_object *self)
  1060. {
  1061. mm->UnregAdviser(self->adv);/*TODO i -> adv*/
  1062. PyObject_Del(self);
  1063. }
  1064. """)
  1065. pyadv_init_code = []
  1066. def translate_pyadv(aid, ifstruct, dirs):
  1067. _, allowed = dirs.pop(0)
  1068. allowed = map(string.strip, allowed.split(','))
  1069. if 'use' in allowed:
  1070. objstructname = 'pyadv_obj_%s' % aid
  1071. methods = []
  1072. methoddecls = []
  1073. members = []
  1074. memberdecls = []
  1075. for name, thing in dirs:
  1076. try:
  1077. tokens = tokenize_signature(thing)
  1078. func = parse_func(tokens)
  1079. except:
  1080. print "couldn't parse '%s'" % thing
  1081. continue
  1082. dict = create_py_to_c_func(func)
  1083. mthdname = 'pyadv_method_%s_%s' % (aid, name)
  1084. dict.update(vars())
  1085. mthd = """
  1086. %(extracode)s
  1087. local PyObject *
  1088. %(mthdname)s(%(objstructname)s *me, PyObject *args)
  1089. {
  1090. PyObject *out;
  1091. %(decls)s
  1092. if (!PyArg_ParseTuple(args, "%(informat)s"%(inargs)s))
  1093. return NULL;
  1094. %(extras1)s
  1095. %(asgntoret)sme->i->%(name)s(%(allargs)s);
  1096. %(extras2)s
  1097. out = Py_BuildValue("%(outformat)s"%(outargs)s);
  1098. %(extras3)s
  1099. return out;
  1100. }
  1101. """ % dict
  1102. methods.append(mthd)
  1103. decl = """\
  1104. {"%(name)s", (PyCFunction)%(mthdname)s, METH_VARARGS, NULL },
  1105. """ % vars()
  1106. methoddecls.append(decl)
  1107. objstructdecl = """
  1108. typedef struct {
  1109. PyObject_HEAD
  1110. %(ifstruct)s *i;
  1111. } %(objstructname)s;
  1112. """ % vars()
  1113. methoddeclname = 'pyadv_%s_methods' % aid
  1114. methoddeclstart = """
  1115. local PyMethodDef %(methoddeclname)s[] = {
  1116. """ % vars()
  1117. methoddeclend = """\
  1118. {NULL}
  1119. };
  1120. """ % vars()
  1121. memberdeclname = 'pyadv_%s_members' % aid
  1122. memberdeclstart = """
  1123. local PyMemberDef %(memberdeclname)s[] = {
  1124. """ % vars()
  1125. memberdeclend = """\
  1126. {NULL}
  1127. };
  1128. """ % vars()
  1129. typestructname = 'pyadv_%s_type' % aid
  1130. typedecl = """
  1131. #pragma GCC diagnostic push
  1132. #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  1133. local PyTypeObject %(typestructname)s = {
  1134. PyObject_HEAD_INIT(NULL)
  1135. 0, /*ob_size*/
  1136. "asss.%(ifstruct)s", /*tp_name*/
  1137. sizeof(%(objstructname)s), /*tp_basicsize*/
  1138. 0, /*tp_itemsize*/
  1139. (destructor)pyadv_generic_dealloc, /*tp_dealloc*/
  1140. 0, /*tp_print*/
  1141. 0, /*tp_getattr*/
  1142. 0, /*tp_setattr*/
  1143. 0, /*tp_compare*/
  1144. 0, /*tp_repr*/
  1145. 0, /*tp_as_number*/
  1146. 0, /*tp_as_sequence*/
  1147. 0, /*tp_as_mapping*/
  1148. 0, /*tp_hash */
  1149. 0, /*tp_call*/
  1150. 0, /*tp_str*/
  1151. 0, /*tp_getattro*/
  1152. 0, /*tp_setattro*/
  1153. 0, /*tp_as_buffer*/
  1154. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  1155. 0, /*tp_doc */
  1156. 0, /*tp_traverse */
  1157. 0, /*tp_clear */
  1158. 0, /*tp_richcompare*/
  1159. 0, /*tp_weaklistoffset*/
  1160. 0, /*tp_iter*/
  1161. 0, /*tp_iternext*/
  1162. %(methoddeclname)s, /*tp_methods*/
  1163. %(memberdeclname)s, /*tp_members*/
  1164. /* rest are null */
  1165. };
  1166. #pragma GCC diagnostic pop
  1167. """ % vars()
  1168. doinit = """\
  1169. if (PyType_Ready(&%(typestructname)s) < 0) return;
  1170. HashReplace(pyadv_advs, %(aid)s, &%(typestructname)s);
  1171. """ % vars()
  1172. pyadv_init_code.append(doinit)
  1173. adv_file.write('\n/* using adviser %(aid)s from python {{{ */\n' % vars())
  1174. adv_file.write(objstructdecl)
  1175. for m in methods:
  1176. adv_file.write(m)
  1177. adv_file.write(methoddeclstart)
  1178. for m in methoddecls:
  1179. adv_file.write(m)
  1180. adv_file.write(methoddeclend)
  1181. for m in members:
  1182. adv_file.write(m)
  1183. adv_file.write(memberdeclstart)
  1184. for m in memberdecls:
  1185. adv_file.write(m)
  1186. adv_file.write(memberdeclend)
  1187. adv_file.write(typedecl)
  1188. adv_file.write('\n/* }}} */\n')
  1189. if 'impl' in allowed:
  1190. advisname = 'pyadv_adv_%s' % aid
  1191. funcs = []
  1192. funcnames = []
  1193. lastout = None
  1194. for name, thing in dirs:
  1195. try:
  1196. tokens = tokenize_signature(thing)
  1197. func = parse_func(tokens)
  1198. except:
  1199. print "bad declaration '%s'" % thing
  1200. continue
  1201. funcname = 'pyadv_func_%s_%s' % (aid, name)
  1202. funcdict = create_c_to_py_func('%s::%s' % (aid, name), func)
  1203. funcdict.update(vars())
  1204. code = []
  1205. code.append("""
  1206. local %(retdecl)s %(funcname)s(%(allargs)s)
  1207. {
  1208. NEEDS_GIL;
  1209. PyObject *args, *out;
  1210. GI_LOCK();
  1211. %(decls)s
  1212. args = Py_BuildValue("(%(informat)s)"%(inargs)s);
  1213. if (!args)
  1214. {
  1215. log_py_exception(L_ERROR, "python error building args for "
  1216. "function %(name)s in adviser %(aid)s");
  1217. GI_UNLOCK();
  1218. return %(defretval)s;
  1219. }
  1220. out = call_gen_py_adviser(PYADVPREFIX %(aid)s, "%(name)s", args, %(arenaval)s);
  1221. if (!out)
  1222. {
  1223. log_py_exception(L_ERROR, "python error calling "
  1224. "function %(name)s in adviser %(aid)s");
  1225. GI_UNLOCK();
  1226. return %(defretval)s;
  1227. }
  1228. """)
  1229. if funcdict['outargs']:
  1230. code.append("""
  1231. if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
  1232. {
  1233. Py_DECREF(out);
  1234. log_py_exception(L_ERROR, "python error unpacking results of "
  1235. "function %(name)s in adviser %(aid)s");
  1236. GI_UNLOCK();
  1237. return %(defretval)s;
  1238. }
  1239. """)
  1240. else:
  1241. code.append("""
  1242. if (out != Py_None)
  1243. {
  1244. Py_DECREF(out);
  1245. log_py_exception(L_ERROR, "adviser func %(name)s didn't return None as expected");
  1246. GI_UNLOCK();
  1247. return %(defretval)s;
  1248. }
  1249. """)
  1250. code.append("""
  1251. %(extras3)s
  1252. Py_DECREF(out);
  1253. GI_UNLOCK();
  1254. return %(retorblank)s;
  1255. }
  1256. """)
  1257. code = ''.join(code) % funcdict
  1258. funcs.append(code)
  1259. funcnames.append(funcname)
  1260. funcnames = ',\n\t'.join(funcnames)
  1261. ifstructdecl = """
  1262. local struct %(ifstruct)s %(advisname)s = {
  1263. ADVISER_HEAD_INIT(%(aid)s)
  1264. %(funcnames)s
  1265. };
  1266. """ % vars()
  1267. init = "\tHashReplace(pyadv_impl_ints, PYADVPREFIX %(aid)s, &%(advisname)s);\n" % vars()
  1268. pyadv_init_code.append(init)
  1269. adv_file.write('\n/* implementing adviser %(aid)s in python {{{ */\n' % vars())
  1270. for func in funcs:
  1271. adv_file.write(func)
  1272. adv_file.write(ifstructdecl)
  1273. adv_file.write('\n/* }}} */\n')
  1274. def finish_pyadv():
  1275. out = adv_file
  1276. out.write("""
  1277. local HashTable *pyadv_advs;
  1278. local HashTable *pyadv_impl_advs;
  1279. local void init_py_advisers(void)
  1280. {
  1281. pyadv_advs = HashAlloc();
  1282. pyadv_impl_advs = HashAlloc();
  1283. """)
  1284. for line in pyadv_init_code:
  1285. out.write(line)
  1286. out.write("""\
  1287. }
  1288. local void deinit_py_advisers(void)
  1289. {
  1290. """)
  1291. out.write("""\
  1292. HashFree(pyadv_advs);
  1293. HashFree(pyadv_impl_advs);
  1294. }
  1295. """)
  1296. def handle_pyconst_directive(tp, pat):
  1297. def clear():
  1298. del extra_patterns[:]
  1299. pat = pat.replace('*', '[A-Z_0-9]*')
  1300. if tp == 'enum':
  1301. # these are always ints, and last until a line with a close-brace
  1302. pat = r'\s*(%s)' % pat
  1303. newre = re.compile(pat)
  1304. extra_patterns.append((newre, const_int))
  1305. extra_patterns.append((re.compile(r'.*}.*;.*'), clear))
  1306. elif tp.startswith('define'):
  1307. # these can be ints or strings, and last until a blank line
  1308. pat = r'#define (%s)' % pat
  1309. newre = re.compile(pat)
  1310. subtp = tp.split()[1].strip()
  1311. func = { 'int': const_int, 'string': const_string, }[subtp]
  1312. extra_patterns.append((newre, func))
  1313. extra_patterns.append((re.compile(r'^$'), clear))
  1314. elif tp == 'config':
  1315. pat = r'#define (%s)' % pat
  1316. extra_patterns.append((re.compile(pat + ' "'), const_string))
  1317. extra_patterns.append((re.compile(pat + ' [0-9]'), const_int))
  1318. extra_patterns.append((re.compile(pat + '$'), const_one))
  1319. extra_patterns.append((re.compile(r'/\* pyconst: config end \*/'), clear))
  1320. def add_converted_type(ctype, name, isstruct):
  1321. class mytype(type_gen):
  1322. def format_char(me):
  1323. return 'O&'
  1324. if isstruct:
  1325. def decl(me, s):
  1326. return '%s *%s' % (ctype, s)
  1327. def ptr_decl(me, s):
  1328. return '%s *%s' % (ctype, s)
  1329. else:
  1330. def decl(me, s):
  1331. return '%s %s' % (ctype, s)
  1332. if isstruct:
  1333. def buf_decl(me, s):
  1334. return '%s %s' % (ctype, s)
  1335. if isstruct:
  1336. def buf_init(me):
  1337. return '{ 0 }';
  1338. else:
  1339. def buf_init(me):
  1340. raise Exception()
  1341. def build_converter(me):
  1342. return 'cvt_c2p_' + name
  1343. def parse_converter(me):
  1344. return 'cvt_p2c_' + name
  1345. if isstruct:
  1346. def out_prefix(me):
  1347. return '&'
  1348. def ptr_val(me):
  1349. return ''
  1350. globals()['type_' + name] = mytype
  1351. def make_opaque_type(ctype, name):
  1352. code = """
  1353. /* dummy value for uniqueness */
  1354. static int pytype_desc_%(name)s;
  1355. ATTR_UNUSED()
  1356. local PyObject * cvt_c2p_%(name)s(void *p)
  1357. {
  1358. if (p == NULL)
  1359. {
  1360. Py_INCREF(Py_None);
  1361. return Py_None;
  1362. }
  1363. else
  1364. return PyCObject_FromVoidPtrAndDesc(p, &pytype_desc_%(name)s, NULL);
  1365. }
  1366. ATTR_UNUSED()
  1367. local int cvt_p2c_%(name)s(PyObject *o, void **pp)
  1368. {
  1369. if (o == Py_None)
  1370. {
  1371. *pp = NULL;
  1372. return TRUE;
  1373. }
  1374. else if (PyCObject_Check(o) &&
  1375. PyCObject_GetDesc(o) == &pytype_desc_%(name)s)
  1376. {
  1377. *pp = PyCObject_AsVoidPtr(o);
  1378. return TRUE;
  1379. }
  1380. else
  1381. {
  1382. PyErr_Format(PyExc_TypeError, "arg isn't a '%%s'", "%(name)s");
  1383. return FALSE;
  1384. }
  1385. }
  1386. """ % vars()
  1387. type_file.write(code)
  1388. add_converted_type(ctype, name, 0)
  1389. def map_struct_type(tp):
  1390. return {
  1391. 'Player': 'player',
  1392. 'Arena': 'arena',
  1393. 'ticks_t': 'int',
  1394. }.get(tp, tp)
  1395. def getter_name(tp):
  1396. return 'pytype_getter_%s' % tp
  1397. def setter_name(tp):
  1398. return 'pytype_setter_%s' % tp
  1399. pytype_made_getsetters = {}
  1400. pytype_objects = []
  1401. def generate_getset_code(tp):
  1402. if pytype_made_getsetters.has_key(tp):
  1403. return []
  1404. pytype_made_getsetters[tp] = 1
  1405. typ = get_type(tp)
  1406. if not typ:
  1407. return []
  1408. ctype = typ.decl('')
  1409. getname = getter_name(tp)
  1410. setname = setter_name(tp)
  1411. getter = """
  1412. local PyObject * %(getname)s(PyObject *obj, void *v)
  1413. {
  1414. int offset = (long)v;
  1415. %(ctype)s *ptr = (%(ctype)s*)(((char*)obj)+offset);
  1416. """ % vars()
  1417. try:
  1418. getter += """\
  1419. return %s(*ptr);
  1420. }
  1421. """ % typ.build_converter()
  1422. except:
  1423. getter += """\
  1424. return %s;
  1425. }
  1426. """ % typ.to_obj('*ptr')
  1427. setter = """
  1428. local int %(setname)s(PyObject *obj, PyObject *newval, void *v)
  1429. {
  1430. int offset = (long)v;
  1431. %(ctype)s *ptr = (%(ctype)s*)(((char*)obj)+offset);
  1432. """ % vars()
  1433. if isinstance(typ,type_void):
  1434. setter = """
  1435. local int %(setname)s(PyObject *obj, PyObject *newval, void *v)
  1436. {
  1437. int offset = (long)v;
  1438. int *ptr = (int*)(((char*)obj)+offset);
  1439. """ % vars()
  1440. try:
  1441. setter += """\
  1442. return %s(newval, ptr) ? 0 : -1;
  1443. }
  1444. """ % typ.parse_converter()
  1445. except:
  1446. setter += """\
  1447. *ptr = %s;
  1448. return 0;
  1449. }
  1450. """ % typ.from_obj('newval')
  1451. return [getter, setter]
  1452. class struct_context:
  1453. def __init__(me, ctype, name):
  1454. me.ctype = ctype
  1455. me.name = name
  1456. me.fields = []
  1457. def finish(me):
  1458. del extra_patterns[:]
  1459. typeobj = 'pytype_%s_typeobj' % me.name
  1460. pytype_objects.append((me.name, typeobj))
  1461. objtype = 'pytype_%s_struct' % me.name
  1462. getsetters = 'pytype_%s_getset' % me.name
  1463. code = []
  1464. code.append("""
  1465. typedef struct %(objtype)s
  1466. {
  1467. PyObject_HEAD
  1468. %(ctype)s data;
  1469. } %(objtype)s;
  1470. """)
  1471. for tp, vname in me.fields:
  1472. code.extend(generate_getset_code(tp))
  1473. code.append("""
  1474. local PyGetSetDef %(getsetters)s[] =
  1475. {
  1476. """)
  1477. for tp, vname in me.fields:
  1478. code.append('\t{ "%s", %s, %s, NULL, (void*)offsetof(%s, data.%s) },\n' % (
  1479. vname,
  1480. getter_name(tp),
  1481. setter_name(tp),
  1482. objtype,
  1483. vname))
  1484. code.append("""
  1485. {NULL}
  1486. };
  1487. #pragma GCC diagnostic push
  1488. #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  1489. local PyTypeObject %(typeobj)s =
  1490. {
  1491. PyObject_HEAD_INIT(NULL)
  1492. 0, /* ob_size */
  1493. "asss.%(name)s_wrapper", /* tp_name */
  1494. sizeof(%(objtype)s), /* tp_basicsize */
  1495. 0, /* tp_itemsize */
  1496. 0, /* tp_dealloc */
  1497. 0, /* tp_print */
  1498. 0, /* tp_getattr */
  1499. 0, /* tp_setattr */
  1500. 0, /* tp_compare */
  1501. 0, /* tp_repr */
  1502. 0, /* tp_as_number */
  1503. 0, /* tp_as_sequence */
  1504. 0, /* tp_as_mapping */
  1505. 0, /* tp_hash */
  1506. 0, /* tp_call */
  1507. 0, /* tp_str */
  1508. 0, /* tp_getattro */
  1509. 0, /* tp_setattro */
  1510. 0, /* tp_as_buffer */
  1511. Py_TPFLAGS_DEFAULT, /* tp_flags */
  1512. "type object for %(name)s", /* tp_doc */
  1513. 0, /* tp_traverse */
  1514. 0, /* tp_clear */
  1515. 0, /* tp_richcompare */
  1516. 0, /* tp_weaklistoffset */
  1517. 0, /* tp_iter */
  1518. 0, /* tp_iternext */
  1519. 0, /* tp_methods */
  1520. 0, /* tp_members */
  1521. %(getsetters)s, /* tp_getset */
  1522. 0, /* tp_base */
  1523. 0, /* tp_dict */
  1524. 0, /* tp_descr_get */
  1525. 0, /* tp_descr_set */
  1526. 0, /* tp_dictoffset */
  1527. 0, /* tp_init */
  1528. 0, /* tp_alloc */
  1529. 0, /* tp_new */
  1530. };
  1531. #pragma GCC diagnostic push
  1532. ATTR_UNUSED()
  1533. local PyObject * cvt_c2p_%(name)s(void *p)
  1534. {
  1535. if (p == NULL)
  1536. {
  1537. Py_INCREF(Py_None);
  1538. return Py_None;
  1539. }
  1540. else
  1541. {
  1542. struct %(objtype)s *o = PyObject_New(%(objtype)s, &%(typeobj)s);
  1543. if (o)
  1544. o->data = *(%(ctype)s*)p;
  1545. return (PyObject*)o;
  1546. }
  1547. }
  1548. ATTR_UNUSED()
  1549. local int cvt_p2c_%(name)s(PyObject *o, void **pp)
  1550. {
  1551. if (o->ob_type == &%(typeobj)s)
  1552. {
  1553. *(%(ctype)s*)pp = ((%(objtype)s*)o)->data;
  1554. return TRUE;
  1555. }
  1556. else
  1557. {
  1558. PyErr_Format(PyExc_TypeError, "arg isn't a '%%s'", "%(name)s");
  1559. return FALSE;
  1560. }
  1561. }
  1562. """)
  1563. dict = vars()
  1564. dict['name'] = me.name
  1565. dict['ctype'] = me.ctype
  1566. type_file.write(''.join(code) % dict)
  1567. def handle_line(me, unsigned, tp, vs):
  1568. if unsigned:
  1569. tp = 'u' + tp
  1570. tp = map_struct_type(tp)
  1571. vs = [v.strip(' \t*') for v in vs.split(',')]
  1572. for v in vs:
  1573. me.fields.append((tp, v))
  1574. def start_struct_type(ctype, name):
  1575. ctx = struct_context(ctype, name)
  1576. extra_patterns.append((re.compile(r'\s*(unsigned\s+)?([A-Za-z_0-9]+)\s+([^;]+);'),
  1577. ctx.handle_line))
  1578. extra_patterns.append((re.compile(r'.*}.*;.*'), ctx.finish))
  1579. add_converted_type(ctype, name, 1)
  1580. def handle_pytype(line):
  1581. things = map(string.strip, line.split(','))
  1582. if things[0] == 'opaque':
  1583. make_opaque_type(things[1], things[2])
  1584. elif things[0] == 'struct':
  1585. start_struct_type(things[1], things[2])
  1586. def finish_pytype():
  1587. type_file.write("""
  1588. local int ready_generated_types(void)
  1589. {
  1590. """)
  1591. for n, t in pytype_objects:
  1592. type_file.write("""\
  1593. %(t)s.tp_dealloc = (destructor)PyObject_Del;
  1594. %(t)s.tp_new = PyType_GenericNew;
  1595. if (PyType_Ready(&%(t)s) < 0) return -1;
  1596. """ % {'t': t})
  1597. type_file.write("""
  1598. return 0;
  1599. }
  1600. """)
  1601. type_file.write("""
  1602. local void add_type_objects_to_module(PyObject *m)
  1603. {
  1604. """)
  1605. for n, t in pytype_objects:
  1606. type_file.write('\tPy_INCREF(&%s);\n' % (t))
  1607. type_file.write('\tPyModule_AddObject(m, "%s", (PyObject*)&%s);\n' % (n, t))
  1608. type_file.write("""
  1609. }
  1610. """)
  1611. # output files
  1612. prefix = sys.argv[1]
  1613. const_file = open(os.path.join(prefix, 'py_constants.inc'), 'w')
  1614. callback_file = open(os.path.join(prefix, 'py_callbacks.inc'), 'w')
  1615. int_file = open(os.path.join(prefix, 'py_interfaces.inc'), 'w')
  1616. adv_file = open(os.path.join(prefix, 'py_advisers.inc'), 'w')
  1617. type_file = open(os.path.join(prefix, 'py_types.inc'), 'w')
  1618. include_file = open(os.path.join(prefix, 'py_include.inc'), 'w')
  1619. warning = """
  1620. /* THIS IS AN AUTOMATICALLY GENERATED FILE */
  1621. """
  1622. const_file.write(warning)
  1623. callback_file.write(warning)
  1624. int_file.write(warning)
  1625. type_file.write(warning)
  1626. include_file.write(warning)
  1627. type_file.write("""
  1628. typedef char charbuf[%d];
  1629. """ % DEFBUFLEN)
  1630. lines = []
  1631. for pat in sys.argv[2:]:
  1632. for f in glob.glob(pat):
  1633. lines.extend(map(lambda l: l.rstrip("\r\n"), open(f).readlines()))
  1634. # default constants
  1635. const_string('ASSSVERSION')
  1636. const_string('BUILDDATE')
  1637. const_int('ASSSVERSION_NUM')
  1638. const_int('TRUE')
  1639. const_int('FALSE')
  1640. init_pyint()
  1641. init_pyadv()
  1642. extra_patterns = []
  1643. # now process file
  1644. intdirs = []
  1645. advdirs = []
  1646. lastfunc = ''
  1647. lastadvfunc = ''
  1648. for l in lines:
  1649. # includes
  1650. m = re_pyinclude.match(l)
  1651. if m:
  1652. include_file.write('#include "%s"\n' % m.group(1).strip())
  1653. # constants
  1654. m = re_pyconst_dir.match(l)
  1655. if m:
  1656. handle_pyconst_directive(m.group(1), m.group(2))
  1657. # callbacks
  1658. m = re_pycb_cbdef.match(l)
  1659. if m:
  1660. lastcbdef = m.group(1)
  1661. m = re_pycb_typedef.match(l)
  1662. if m:
  1663. lasttypedef = m.group(1)
  1664. m = re_pycb_dir.match(l)
  1665. if m:
  1666. const_callback(lastcbdef)
  1667. translate_pycb(lastcbdef, lasttypedef, m.group(1))
  1668. # interfaces
  1669. m = re_pyint_intdef.match(l)
  1670. if m:
  1671. lastintdef = m.group(1)
  1672. intdirs = []
  1673. m = re_pyint_typedef.match(l)
  1674. if m:
  1675. lasttypedef = m.group(1)
  1676. m = re_pyint_func.match(l)
  1677. if m:
  1678. lastfunc = m.group(2)
  1679. m = re_pyint_dir.match(l)
  1680. if m:
  1681. intdirs.append((lastfunc, m.group(1)))
  1682. m = re_pyint_done.match(l)
  1683. if m:
  1684. if intdirs:
  1685. const_interface(lastintdef)
  1686. translate_pyint(lastintdef, lasttypedef, intdirs)
  1687. intdirs = []
  1688. # advisers
  1689. m = re_pyadv_advdef.match(l)
  1690. if m:
  1691. lastadvdef = m.group(1)
  1692. advdirs = []
  1693. m = re_pyadv_typedef.match(l)
  1694. if m:
  1695. lastadvtypedef = m.group(1)
  1696. m = re_pyadv_func.match(l)
  1697. if m:
  1698. lastadvfunc = m.group(2)
  1699. m = re_pyadv_dir.match(l)
  1700. if m:
  1701. advdirs.append((lastadvfunc, m.group(1)))
  1702. m = re_pyadv_done.match(l)
  1703. if m:
  1704. if advdirs:
  1705. const_adviser(lastadvdef)
  1706. translate_pyadv(lastadvdef, lastadvtypedef, advdirs)
  1707. advdirs = []
  1708. # types
  1709. m = re_pytype.match(l)
  1710. if m:
  1711. handle_pytype(m.group(1))
  1712. # generic stuff
  1713. for myre, func in extra_patterns:
  1714. m = myre.match(l)
  1715. if m:
  1716. apply(func, m.groups())
  1717. finish_pycb()
  1718. finish_pyint()
  1719. finish_pyadv()
  1720. finish_pytype()