Added Python (Thanks to Beholder) - it fails to build properly using my build system,
so there's a precompiled binary included, with a hack in Android.mk to make it work on NDK r4b
This commit is contained in:
48
project/jni/python/src/Tools/README
Normal file
48
project/jni/python/src/Tools/README
Normal file
@@ -0,0 +1,48 @@
|
||||
This directory contains a number of Python programs that are useful
|
||||
while building or extending Python.
|
||||
|
||||
audiopy Audiopy is a program to control the Solaris audio
|
||||
device, allowing you to choose both the input and
|
||||
output devices, and to set the output volume, that can
|
||||
be run either as a command-line script, or as a
|
||||
Tkinter application.
|
||||
|
||||
bgen Generate complete extension modules from a
|
||||
description. Still under development!
|
||||
WARNING: bgen has been removed in 3.0.
|
||||
|
||||
compiler Tools used to maintain the compiler package in the
|
||||
standard library.
|
||||
|
||||
faqwiz FAQ Wizard.
|
||||
See http://www.python.org/cgi-bin/faqw.py
|
||||
for a live example.
|
||||
|
||||
freeze Create a stand-alone executable from a Python program.
|
||||
|
||||
i18n Tools for internationalization. pygettext.py
|
||||
parses Python source code and generates .pot files,
|
||||
and msgfmt.py generates a binary message catalog
|
||||
from a catalog in text format.
|
||||
|
||||
modulator Interactively generate boiler plate for an extension
|
||||
module. Works easiest if you have Tk.
|
||||
|
||||
pynche A Tkinter-based color editor.
|
||||
|
||||
scripts A number of useful single-file programs, e.g. tabnanny.py
|
||||
(by Tim Peters), which checks for inconsistent mixing
|
||||
of tabs and spaces.
|
||||
|
||||
unicode Tools used to generate unicode database files for
|
||||
Python 2.0 (by Fredrik Lundh).
|
||||
|
||||
versioncheck A tool to automate checking whether you have the latest
|
||||
version of a package (by Jack Jansen).
|
||||
|
||||
webchecker A link checker for web sites.
|
||||
|
||||
world Script to take a list of Internet addresses and print
|
||||
out where in the world those addresses originate from,
|
||||
based on the top-level domain country code found in
|
||||
the address.
|
||||
112
project/jni/python/src/Tools/audiopy/README
Normal file
112
project/jni/python/src/Tools/audiopy/README
Normal file
@@ -0,0 +1,112 @@
|
||||
audiopy - a program to control the Solaris audio device.
|
||||
|
||||
Contact: Barry Warsaw
|
||||
Email: bwarsaw@python.org
|
||||
Version: 1.1
|
||||
|
||||
Introduction
|
||||
|
||||
Audiopy is a program to control the Solaris audio device, allowing
|
||||
you to choose both the input and output devices, and to set the
|
||||
output volume. It can be run either as a standalone command-line
|
||||
script, or as a Tkinter based GUI application.
|
||||
|
||||
Note that your version of Python must have been built with the
|
||||
sunaudiodev module enabled. It is not enabled by default however!
|
||||
You will need to edit your Modules/Setup file, uncomment the
|
||||
sunaudiodev module spec line and rebuild Python.
|
||||
|
||||
Using audiopy, you can select one of three possible input devices:
|
||||
the microphone, the line-in jack, or the CD in. These choices are
|
||||
mutually exclusive; you can only have one active input device at
|
||||
any one time (this is enforced by the underlying device). Some
|
||||
input devices may not be supported on all Solaris machines.
|
||||
|
||||
You can also choose to enable any of the three possible output
|
||||
devices: the headphone jack, the speakers, or the line-out jack.
|
||||
You can enable any combination of these three devices.
|
||||
|
||||
You can also set the output gain (volume) level.
|
||||
|
||||
Running as a GUI
|
||||
|
||||
Simply start audiopy with no arguments to start it as a Tkinter
|
||||
based GUI application. It will pop up a window with two sections:
|
||||
the top portion contains three radio buttons indicating your
|
||||
selected input device; the middle portion contains three
|
||||
checkboxes indicating your selected output devices; the bottom
|
||||
portion contains a slider that changes the output gain.
|
||||
|
||||
Note the underlined characters in the button labels. These
|
||||
indicate keyboard accelerators so that pressing Alt+character you
|
||||
can select that device. For example, Alt-s toggles the Speaker
|
||||
device. The Alt accelerators are the same as those you'd use in
|
||||
as the short-form command line switches (see below).
|
||||
|
||||
Alt-q is also an accelerator for selecting Quit from the File
|
||||
menu.
|
||||
|
||||
Unsupported devices will appear dimmed out in the GUI. When run
|
||||
as a GUI, audiopy monitors the audio device and automatically
|
||||
updates its display if the state of the device is changed by some
|
||||
other means. With Python versions before 1.5.2 this is done by
|
||||
occasionally polling the device, but in Python 1.5.2 no polling is
|
||||
necessary (you don't really need to know this, but I thought I'd
|
||||
plug 1.5.2 :-).
|
||||
|
||||
Running as a Command Line Program
|
||||
|
||||
You can run audiopy from the command line to select any
|
||||
combination of input or output device, by using the command line
|
||||
options. Actually, any option forces audiopy to run as a command
|
||||
line program and not display its GUI.
|
||||
|
||||
Options have the general form
|
||||
|
||||
--device[={0,1}]
|
||||
-d[-{0,1}]
|
||||
|
||||
meaning there is both a long-form and short-form of the switch,
|
||||
where `device' or `d' is one of the following:
|
||||
|
||||
(input)
|
||||
microphone -- m
|
||||
linein -- i
|
||||
cd -- c
|
||||
|
||||
(output)
|
||||
headphones -- p
|
||||
speaker -- s
|
||||
lineout -- o
|
||||
|
||||
When no value is given, the switch just toggles the specified
|
||||
device. With a value, 0 turns the device off and 1 turns the
|
||||
device on. Any other value is an error.
|
||||
|
||||
For example, to turn the speakers off, turn the headphones on, and
|
||||
toggle the cd input device, run audiopy from the command line like
|
||||
so:
|
||||
|
||||
% ./audiopy -s=0 -p=1 -c
|
||||
|
||||
Audiopy understands these other command line options:
|
||||
|
||||
--gain volume
|
||||
-g volume
|
||||
Sets the output volume to the specified gain level. This must
|
||||
be an integer between MIN_GAIN and MAX_GAIN (usually [0..255],
|
||||
but use the -h option to find the exact values).
|
||||
|
||||
--version
|
||||
-v
|
||||
Print the version number and exit
|
||||
|
||||
--help
|
||||
-h
|
||||
Print a help message and exit
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
507
project/jni/python/src/Tools/audiopy/audiopy
Normal file
507
project/jni/python/src/Tools/audiopy/audiopy
Normal file
@@ -0,0 +1,507 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""audiopy -- a program to control the Solaris audio device.
|
||||
|
||||
Contact: Barry Warsaw
|
||||
Email: bwarsaw@python.org
|
||||
Version: %(__version__)s
|
||||
|
||||
When no arguments are given, this pops up a graphical window which lets you
|
||||
choose the audio input and output devices, and set the output volume.
|
||||
|
||||
This program can be driven via the command line, and when done so, no window
|
||||
pops up. Most options have the general form:
|
||||
|
||||
--device[={0,1}]
|
||||
-d[={0,1}]
|
||||
Set the I/O device. With no value, it toggles the specified device.
|
||||
With a value, 0 turns the device off and 1 turns the device on.
|
||||
|
||||
The list of devices and their short options are:
|
||||
|
||||
(input)
|
||||
microphone -- m
|
||||
linein -- i
|
||||
cd -- c
|
||||
|
||||
(output)
|
||||
headphones -- p
|
||||
speaker -- s
|
||||
lineout -- o
|
||||
|
||||
Other options are:
|
||||
|
||||
--gain volume
|
||||
-g volume
|
||||
Sets the output gain to the specified volume, which must be an integer
|
||||
in the range [%(MIN_GAIN)s..%(MAX_GAIN)s]
|
||||
|
||||
--version
|
||||
-v
|
||||
Print the version number and exit.
|
||||
|
||||
--help
|
||||
-h
|
||||
Print this message and exit.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import errno
|
||||
import sunaudiodev
|
||||
from SUNAUDIODEV import *
|
||||
|
||||
# Milliseconds between interrupt checks
|
||||
KEEPALIVE_TIMER = 500
|
||||
|
||||
__version__ = '1.1'
|
||||
|
||||
|
||||
|
||||
class MainWindow:
|
||||
def __init__(self, device):
|
||||
from Tkinter import *
|
||||
self.__helpwin = None
|
||||
self.__devctl = device
|
||||
info = device.getinfo()
|
||||
#
|
||||
self.__tkroot = tkroot = Tk(className='Audiopy')
|
||||
tkroot.withdraw()
|
||||
# create the menubar
|
||||
menubar = Menu(tkroot)
|
||||
filemenu = Menu(menubar, tearoff=0)
|
||||
filemenu.add_command(label='Quit',
|
||||
command=self.__quit,
|
||||
accelerator='Alt-Q',
|
||||
underline=0)
|
||||
helpmenu = Menu(menubar, name='help', tearoff=0)
|
||||
helpmenu.add_command(label='About Audiopy...',
|
||||
command=self.__popup_about,
|
||||
underline=0)
|
||||
helpmenu.add_command(label='Help...',
|
||||
command=self.__popup_using,
|
||||
underline=0)
|
||||
menubar.add_cascade(label='File',
|
||||
menu=filemenu,
|
||||
underline=0)
|
||||
menubar.add_cascade(label='Help',
|
||||
menu=helpmenu,
|
||||
underline=0)
|
||||
# now create the top level window
|
||||
root = self.__root = Toplevel(tkroot, class_='Audiopy', menu=menubar)
|
||||
root.protocol('WM_DELETE_WINDOW', self.__quit)
|
||||
root.title('audiopy ' + __version__)
|
||||
root.iconname('audiopy ' + __version__)
|
||||
root.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
|
||||
#
|
||||
buttons = []
|
||||
#
|
||||
# where does input come from?
|
||||
frame = Frame(root, bd=1, relief=RAISED)
|
||||
frame.grid(row=1, column=0, sticky='NSEW')
|
||||
label = Label(frame, text='Input From:')
|
||||
label.grid(row=0, column=0, sticky=E)
|
||||
self.__inputvar = IntVar()
|
||||
##
|
||||
btn = Radiobutton(frame,
|
||||
text='None',
|
||||
variable=self.__inputvar,
|
||||
value=0,
|
||||
command=self.__pushtodev,
|
||||
underline=0)
|
||||
btn.grid(row=0, column=1, sticky=W)
|
||||
root.bind('<Alt-n>', self.__none)
|
||||
root.bind('<Alt-N>', self.__none)
|
||||
if not info.i_avail_ports & MICROPHONE:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
##
|
||||
btn = Radiobutton(frame,
|
||||
text='Microphone',
|
||||
variable=self.__inputvar,
|
||||
value=MICROPHONE,
|
||||
command=self.__pushtodev,
|
||||
underline=0)
|
||||
btn.grid(row=1, column=1, sticky=W)
|
||||
root.bind('<Alt-m>', self.__mic)
|
||||
root.bind('<Alt-M>', self.__mic)
|
||||
if not info.i_avail_ports & MICROPHONE:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
##
|
||||
btn = Radiobutton(frame,
|
||||
text='Line In',
|
||||
variable=self.__inputvar,
|
||||
value=LINE_IN,
|
||||
command=self.__pushtodev,
|
||||
underline=5)
|
||||
btn.grid(row=2, column=1, sticky=W)
|
||||
root.bind('<Alt-i>', self.__linein)
|
||||
root.bind('<Alt-I>', self.__linein)
|
||||
if not info.i_avail_ports & LINE_IN:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
## if SUNAUDIODEV was built on an older version of Solaris, the CD
|
||||
## input device won't exist
|
||||
try:
|
||||
btn = Radiobutton(frame,
|
||||
text='CD',
|
||||
variable=self.__inputvar,
|
||||
value=CD,
|
||||
command=self.__pushtodev,
|
||||
underline=0)
|
||||
btn.grid(row=3, column=1, sticky=W)
|
||||
root.bind('<Alt-c>', self.__cd)
|
||||
root.bind('<Alt-C>', self.__cd)
|
||||
if not info.i_avail_ports & CD:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
except NameError:
|
||||
pass
|
||||
#
|
||||
# where does output go to?
|
||||
frame = Frame(root, bd=1, relief=RAISED)
|
||||
frame.grid(row=2, column=0, sticky='NSEW')
|
||||
label = Label(frame, text='Output To:')
|
||||
label.grid(row=0, column=0, sticky=E)
|
||||
self.__spkvar = IntVar()
|
||||
btn = Checkbutton(frame,
|
||||
text='Speaker',
|
||||
variable=self.__spkvar,
|
||||
onvalue=SPEAKER,
|
||||
command=self.__pushtodev,
|
||||
underline=0)
|
||||
btn.grid(row=0, column=1, sticky=W)
|
||||
root.bind('<Alt-s>', self.__speaker)
|
||||
root.bind('<Alt-S>', self.__speaker)
|
||||
if not info.o_avail_ports & SPEAKER:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
##
|
||||
self.__headvar = IntVar()
|
||||
btn = Checkbutton(frame,
|
||||
text='Headphones',
|
||||
variable=self.__headvar,
|
||||
onvalue=HEADPHONE,
|
||||
command=self.__pushtodev,
|
||||
underline=4)
|
||||
btn.grid(row=1, column=1, sticky=W)
|
||||
root.bind('<Alt-p>', self.__headphones)
|
||||
root.bind('<Alt-P>', self.__headphones)
|
||||
if not info.o_avail_ports & HEADPHONE:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
##
|
||||
self.__linevar = IntVar()
|
||||
btn = Checkbutton(frame,
|
||||
variable=self.__linevar,
|
||||
onvalue=LINE_OUT,
|
||||
text='Line Out',
|
||||
command=self.__pushtodev,
|
||||
underline=0)
|
||||
btn.grid(row=2, column=1, sticky=W)
|
||||
root.bind('<Alt-l>', self.__lineout)
|
||||
root.bind('<Alt-L>', self.__lineout)
|
||||
if not info.o_avail_ports & LINE_OUT:
|
||||
btn.configure(state=DISABLED)
|
||||
buttons.append(btn)
|
||||
#
|
||||
# Fix up widths
|
||||
widest = 0
|
||||
for b in buttons:
|
||||
width = b['width']
|
||||
if width > widest:
|
||||
widest = width
|
||||
for b in buttons:
|
||||
b.configure(width=widest)
|
||||
# root bindings
|
||||
root.bind('<Alt-q>', self.__quit)
|
||||
root.bind('<Alt-Q>', self.__quit)
|
||||
#
|
||||
# Volume
|
||||
frame = Frame(root, bd=1, relief=RAISED)
|
||||
frame.grid(row=3, column=0, sticky='NSEW')
|
||||
label = Label(frame, text='Output Volume:')
|
||||
label.grid(row=0, column=0, sticky=W)
|
||||
self.__scalevar = IntVar()
|
||||
self.__scale = Scale(frame,
|
||||
orient=HORIZONTAL,
|
||||
from_=MIN_GAIN,
|
||||
to=MAX_GAIN,
|
||||
length=200,
|
||||
variable=self.__scalevar,
|
||||
command=self.__volume)
|
||||
self.__scale.grid(row=1, column=0, sticky=EW)
|
||||
#
|
||||
# do we need to poll for changes?
|
||||
self.__needtopoll = 1
|
||||
try:
|
||||
fd = self.__devctl.fileno()
|
||||
self.__needtopoll = 0
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
import fcntl
|
||||
import signal
|
||||
import STROPTS
|
||||
# set up the signal handler
|
||||
signal.signal(signal.SIGPOLL, self.__update)
|
||||
fcntl.ioctl(fd, STROPTS.I_SETSIG, STROPTS.S_MSG)
|
||||
self.__update()
|
||||
|
||||
def __quit(self, event=None):
|
||||
self.__devctl.close()
|
||||
self.__root.quit()
|
||||
|
||||
def __popup_about(self, event=None):
|
||||
import tkMessageBox
|
||||
tkMessageBox.showinfo('About Audiopy ' + __version__,
|
||||
'''\
|
||||
Audiopy %s
|
||||
Control the Solaris audio device
|
||||
|
||||
For information
|
||||
Contact: Barry A. Warsaw
|
||||
Email: bwarsaw@python.org''' % __version__)
|
||||
|
||||
def __popup_using(self, event=None):
|
||||
if not self.__helpwin:
|
||||
self.__helpwin = Helpwin(self.__tkroot, self.__quit)
|
||||
self.__helpwin.deiconify()
|
||||
|
||||
|
||||
def __keepalive(self):
|
||||
# Exercise the Python interpreter regularly so keyboard interrupts get
|
||||
# through.
|
||||
self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
|
||||
if self.__needtopoll:
|
||||
self.__update()
|
||||
|
||||
def __update(self, num=None, frame=None):
|
||||
# It's possible (although I have never seen it) to get an interrupted
|
||||
# system call during the getinfo() call. If so, and we're polling,
|
||||
# don't sweat it because we'll come around again later. Otherwise,
|
||||
# we'll give it a couple of tries and then give up until next time.
|
||||
tries = 0
|
||||
while 1:
|
||||
try:
|
||||
info = self.__devctl.getinfo()
|
||||
break
|
||||
except sunaudiodev.error:
|
||||
if self.__needtopoll or tries > 3:
|
||||
return
|
||||
tries = tries + 1
|
||||
# input
|
||||
self.__inputvar.set(info.i_port)
|
||||
# output
|
||||
self.__spkvar.set(info.o_port & SPEAKER)
|
||||
self.__headvar.set(info.o_port & HEADPHONE)
|
||||
self.__linevar.set(info.o_port & LINE_OUT)
|
||||
# volume
|
||||
self.__scalevar.set(info.o_gain)
|
||||
|
||||
def __pushtodev(self, event=None):
|
||||
info = self.__devctl.getinfo()
|
||||
info.o_port = self.__spkvar.get() + \
|
||||
self.__headvar.get() + \
|
||||
self.__linevar.get()
|
||||
info.i_port = self.__inputvar.get()
|
||||
info.o_gain = self.__scalevar.get()
|
||||
try:
|
||||
self.__devctl.setinfo(info)
|
||||
except sunaudiodev.error, msg:
|
||||
# TBD: what to do? it's probably temporary.
|
||||
pass
|
||||
|
||||
def __getset(self, var, onvalue):
|
||||
if var.get() == onvalue:
|
||||
var.set(0)
|
||||
else:
|
||||
var.set(onvalue)
|
||||
self.__pushtodev()
|
||||
|
||||
def __none(self, event=None):
|
||||
self.__inputvar.set(0)
|
||||
self.__pushtodev()
|
||||
|
||||
def __mic(self, event=None):
|
||||
self.__getset(self.__inputvar, MICROPHONE)
|
||||
|
||||
def __linein(self, event=None):
|
||||
self.__getset(self.__inputvar, LINE_IN)
|
||||
|
||||
def __cd(self, event=None):
|
||||
self.__getset(self.__inputvar, CD)
|
||||
|
||||
def __speaker(self, event=None):
|
||||
self.__getset(self.__spkvar, SPEAKER)
|
||||
|
||||
def __headphones(self, event=None):
|
||||
self.__getset(self.__headvar, HEADPHONE)
|
||||
|
||||
def __lineout(self, event=None):
|
||||
self.__getset(self.__linevar, LINE_OUT)
|
||||
|
||||
def __volume(self, event=None):
|
||||
self.__pushtodev()
|
||||
|
||||
def start(self):
|
||||
self.__keepalive()
|
||||
self.__tkroot.mainloop()
|
||||
|
||||
|
||||
|
||||
class Helpwin:
|
||||
def __init__(self, master, quitfunc):
|
||||
from Tkinter import *
|
||||
self.__root = root = Toplevel(master, class_='Audiopy')
|
||||
root.protocol('WM_DELETE_WINDOW', self.__withdraw)
|
||||
root.title('Audiopy Help Window')
|
||||
root.iconname('Audiopy Help Window')
|
||||
root.bind('<Alt-q>', quitfunc)
|
||||
root.bind('<Alt-Q>', quitfunc)
|
||||
root.bind('<Alt-w>', self.__withdraw)
|
||||
root.bind('<Alt-W>', self.__withdraw)
|
||||
|
||||
# more elaborate help is available in the README file
|
||||
readmefile = os.path.join(sys.path[0], 'README')
|
||||
try:
|
||||
fp = None
|
||||
try:
|
||||
fp = open(readmefile)
|
||||
contents = fp.read()
|
||||
# wax the last page, it contains Emacs cruft
|
||||
i = contents.rfind('\f')
|
||||
if i > 0:
|
||||
contents = contents[:i].rstrip()
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
except IOError:
|
||||
sys.stderr.write("Couldn't open audiopy's README, "
|
||||
'using docstring instead.\n')
|
||||
contents = __doc__ % globals()
|
||||
|
||||
self.__text = text = Text(root, relief=SUNKEN,
|
||||
width=80, height=24)
|
||||
text.insert(0.0, contents)
|
||||
scrollbar = Scrollbar(root)
|
||||
scrollbar.pack(fill=Y, side=RIGHT)
|
||||
text.pack(fill=BOTH, expand=YES)
|
||||
text.configure(yscrollcommand=(scrollbar, 'set'))
|
||||
scrollbar.configure(command=(text, 'yview'))
|
||||
|
||||
def __withdraw(self, event=None):
|
||||
self.__root.withdraw()
|
||||
|
||||
def deiconify(self):
|
||||
self.__root.deiconify()
|
||||
|
||||
|
||||
|
||||
|
||||
def usage(code, msg=''):
|
||||
print __doc__ % globals()
|
||||
if msg:
|
||||
print msg
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
def main():
|
||||
#
|
||||
# Open up the audio control device and query for the current output
|
||||
# device
|
||||
device = sunaudiodev.open('control')
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
# GUI
|
||||
w = MainWindow(device)
|
||||
try:
|
||||
w.start()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
return
|
||||
|
||||
# spec: LONG OPT, SHORT OPT, 0=input,1=output, MASK
|
||||
options = [('--microphone', '-m', 0, MICROPHONE),
|
||||
('--linein', '-i', 0, LINE_IN),
|
||||
('--headphones', '-p', 1, HEADPHONE),
|
||||
('--speaker', '-s', 1, SPEAKER),
|
||||
('--lineout', '-o', 1, LINE_OUT),
|
||||
]
|
||||
# See the comment above about `CD'
|
||||
try:
|
||||
options.append(('--cd', '-c', 0, CD))
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
info = device.getinfo()
|
||||
# first get the existing values
|
||||
i = 0
|
||||
while i < len(sys.argv)-1:
|
||||
i = i + 1
|
||||
arg = sys.argv[i]
|
||||
if arg in ('-h', '--help'):
|
||||
usage(0)
|
||||
# does not return
|
||||
elif arg in ('-g', '--gain'):
|
||||
gainspec = '<missing>'
|
||||
try:
|
||||
gainspec = sys.argv[i+1]
|
||||
gain = int(gainspec)
|
||||
except (ValueError, IndexError):
|
||||
usage(1, 'Bad gain specification: ' + gainspec)
|
||||
info.o_gain = gain
|
||||
i = i + 1
|
||||
continue
|
||||
elif arg in ('-v', '--version'):
|
||||
print '''\
|
||||
audiopy -- a program to control the Solaris audio device.
|
||||
Contact: Barry Warsaw
|
||||
Email: bwarsaw@python.org
|
||||
Version: %s''' % __version__
|
||||
sys.exit(0)
|
||||
for long, short, io, mask in options:
|
||||
if arg in (long, short):
|
||||
# toggle the option
|
||||
if io == 0:
|
||||
info.i_port = info.i_port ^ mask
|
||||
else:
|
||||
info.o_port = info.o_port ^ mask
|
||||
break
|
||||
val = None
|
||||
try:
|
||||
if arg[:len(long)+1] == long+'=':
|
||||
val = int(arg[len(long)+1:])
|
||||
elif arg[:len(short)+1] == short+'=':
|
||||
val = int(arg[len(short)+1:])
|
||||
except ValueError:
|
||||
usage(1, msg='Invalid option: ' + arg)
|
||||
# does not return
|
||||
if val == 0:
|
||||
if io == 0:
|
||||
info.i_port = info.i_port & ~mask
|
||||
else:
|
||||
info.o_port = info.o_port & ~mask
|
||||
break
|
||||
elif val == 1:
|
||||
if io == 0:
|
||||
info.i_port = info.i_port | mask
|
||||
else:
|
||||
info.o_port = info.o_port | mask
|
||||
break
|
||||
# else keep trying next option
|
||||
else:
|
||||
usage(1, msg='Invalid option: ' + arg)
|
||||
# now set the values
|
||||
try:
|
||||
device.setinfo(info)
|
||||
except sunaudiodev.error, (code, msg):
|
||||
if code <> errno.EINVAL:
|
||||
raise
|
||||
device.close()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
9
project/jni/python/src/Tools/bgen/README
Normal file
9
project/jni/python/src/Tools/bgen/README
Normal file
@@ -0,0 +1,9 @@
|
||||
BGEN -- Automatic Generation of Extension Modules
|
||||
=================================================
|
||||
|
||||
This directory contains BGEN -- a package that helps in generating
|
||||
complete source code for Python extension module. For examples of its
|
||||
use, see the Mac Python source distribution (available separately
|
||||
from the Python ftp archives). Note that BGEN is not Mac specific!
|
||||
|
||||
WARNING: bgen has been removed in 3.0.
|
||||
12
project/jni/python/src/Tools/bgen/bgen/bgen.py
Normal file
12
project/jni/python/src/Tools/bgen/bgen/bgen.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"Export everything in the various bgen submodules."
|
||||
|
||||
from bgenType import *
|
||||
from bgenVariable import *
|
||||
from bgenBuffer import *
|
||||
from bgenStackBuffer import *
|
||||
from bgenHeapBuffer import *
|
||||
from bgenStringBuffer import *
|
||||
from bgenOutput import *
|
||||
from bgenGenerator import *
|
||||
from bgenModule import *
|
||||
from bgenObjectDefinition import *
|
||||
301
project/jni/python/src/Tools/bgen/bgen/bgenBuffer.py
Normal file
301
project/jni/python/src/Tools/bgen/bgen/bgenBuffer.py
Normal file
@@ -0,0 +1,301 @@
|
||||
"""Buffers are character arrays that may contain null bytes.
|
||||
|
||||
There are a number of variants depending on:
|
||||
- how the buffer is allocated (for output buffers), and
|
||||
- whether and how the size is passed into and/or out of the called function.
|
||||
"""
|
||||
|
||||
|
||||
from bgenType import Type, InputOnlyMixIn, OutputOnlyMixIn, InputOnlyType, OutputOnlyType
|
||||
from bgenOutput import *
|
||||
|
||||
|
||||
# Map common types to their format characters
|
||||
type2format = {
|
||||
'long': 'l',
|
||||
'int': 'i',
|
||||
'short': 'h',
|
||||
'char': 'b',
|
||||
'unsigned long': 'l',
|
||||
'unsigned int': 'i',
|
||||
'unsigned short': 'h',
|
||||
'unsigned char': 'b',
|
||||
}
|
||||
|
||||
|
||||
# ----- PART 1: Fixed character buffers -----
|
||||
|
||||
|
||||
class FixedInputOutputBufferType(InputOnlyType):
|
||||
|
||||
"""Fixed buffer -- passed as (inbuffer, outbuffer)."""
|
||||
|
||||
def __init__(self, size, datatype = 'char', sizetype = 'int', sizeformat = None):
|
||||
self.typeName = "Buffer"
|
||||
self.size = str(size)
|
||||
self.datatype = datatype
|
||||
self.sizetype = sizetype
|
||||
self.sizeformat = sizeformat or type2format[sizetype]
|
||||
self.label_needed = 0
|
||||
|
||||
def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
|
||||
if reference:
|
||||
raise RuntimeError, "Cannot pass buffer types by reference"
|
||||
return (self.getBufferDeclarations(name, constmode, outmode) +
|
||||
self.getSizeDeclarations(name, outmode))
|
||||
|
||||
def getBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
return self.getInputBufferDeclarations(name, constmode) + \
|
||||
self.getOutputBufferDeclarations(name, constmode, outmode)
|
||||
|
||||
def getInputBufferDeclarations(self, name, constmode=False):
|
||||
if constmode:
|
||||
const = "const "
|
||||
else:
|
||||
const = ""
|
||||
return ["%s%s *%s__in__" % (const, self.datatype, name)]
|
||||
|
||||
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
if constmode:
|
||||
raise RuntimeError, "Cannot use const output buffer"
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s %s__out__[%s]" % (self.datatype, out, name, self.size)]
|
||||
|
||||
def getSizeDeclarations(self, name, outmode=False):
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s %s__len__" %(self.sizetype, out, name)]
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return ["int %s__in_len__" %(name)]
|
||||
|
||||
def getargsFormat(self):
|
||||
return "s#"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "&%s__in__, &%s__in_len__" % (name, name)
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("if (%s__in_len__ != %s)", name, self.size)
|
||||
OutLbrace()
|
||||
Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");',
|
||||
self.size)
|
||||
Output("goto %s__error__;", name)
|
||||
self.label_needed = 1
|
||||
OutRbrace()
|
||||
self.transferSize(name)
|
||||
|
||||
def transferSize(self, name):
|
||||
Output("%s__len__ = %s__in_len__;", name, name)
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__in__, %s__out__" % (name, name)
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "s#"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__, (int)%s" % (name, self.size)
|
||||
|
||||
def cleanup(self, name):
|
||||
if self.label_needed:
|
||||
DedentLevel()
|
||||
Output(" %s__error__: ;", name)
|
||||
IndentLevel()
|
||||
|
||||
|
||||
class FixedCombinedInputOutputBufferType(FixedInputOutputBufferType):
|
||||
|
||||
"""Like fixed buffer -- but same parameter is input and output."""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "(%s *)memcpy(%s__out__, %s__in__, %s)" % \
|
||||
(self.datatype, name, name, self.size)
|
||||
|
||||
|
||||
class InputOnlyBufferMixIn(InputOnlyMixIn):
|
||||
|
||||
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
return []
|
||||
|
||||
|
||||
class OutputOnlyBufferMixIn(OutputOnlyMixIn):
|
||||
|
||||
def getInputBufferDeclarations(self, name, constmode=False):
|
||||
return []
|
||||
|
||||
class OptionalInputBufferMixIn:
|
||||
|
||||
"""Add to input buffers if the buffer may be omitted: pass None in Python
|
||||
and the C code will get a NULL pointer and zero size"""
|
||||
|
||||
def getargsFormat(self):
|
||||
return "z#"
|
||||
|
||||
|
||||
class FixedInputBufferType(InputOnlyBufferMixIn, FixedInputOutputBufferType):
|
||||
|
||||
"""Fixed size input buffer -- passed without size information.
|
||||
|
||||
Instantiate with the size as parameter.
|
||||
"""
|
||||
|
||||
def passInput(self, name):
|
||||
return "%s__in__" % name
|
||||
|
||||
class OptionalFixedInputBufferType(OptionalInputBufferMixIn, FixedInputBufferType):
|
||||
pass
|
||||
|
||||
class FixedOutputBufferType(OutputOnlyBufferMixIn, FixedInputOutputBufferType):
|
||||
|
||||
"""Fixed size output buffer -- passed without size information.
|
||||
|
||||
Instantiate with the size as parameter.
|
||||
"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__" % name
|
||||
|
||||
|
||||
class VarInputBufferType(FixedInputBufferType):
|
||||
|
||||
"""Variable size input buffer -- passed as (buffer, size).
|
||||
|
||||
Instantiate without size parameter.
|
||||
"""
|
||||
|
||||
def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None):
|
||||
FixedInputBufferType.__init__(self, "0", datatype, sizetype, sizeformat)
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("%s__len__ = %s__in_len__;", name, name)
|
||||
|
||||
def passInput(self, name):
|
||||
return "%s__in__, %s__len__" % (name, name)
|
||||
|
||||
class ReverseInputBufferMixin:
|
||||
""" Mixin for input buffers that are passed as (size, buffer) """
|
||||
|
||||
def passInput(self, name):
|
||||
return "%s__len__, %s__in__" % (name, name)
|
||||
|
||||
class OptionalVarInputBufferType(OptionalInputBufferMixIn, VarInputBufferType):
|
||||
pass
|
||||
|
||||
# ----- PART 2: Structure buffers -----
|
||||
|
||||
|
||||
class StructInputOutputBufferType(FixedInputOutputBufferType):
|
||||
|
||||
"""Structure buffer -- passed as a structure pointer.
|
||||
|
||||
Instantiate with the struct type as parameter.
|
||||
"""
|
||||
|
||||
def __init__(self, type):
|
||||
FixedInputOutputBufferType.__init__(self, "sizeof(%s)" % type)
|
||||
self.typeName = self.type = type
|
||||
|
||||
def getInputBufferDeclarations(self, name, constmode=False):
|
||||
if constmode:
|
||||
const = "const "
|
||||
else:
|
||||
const = ""
|
||||
return ["%s%s *%s__in__" % (const, self.type, name)]
|
||||
|
||||
def getSizeDeclarations(self, name, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return ["int %s__in_len__" % (name)]
|
||||
|
||||
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
if constmode:
|
||||
raise RuntimeError, "Cannot use const output buffer"
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s %s__out__" % (self.type, out, name)]
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "(char **)&%s__in__, &%s__in_len__" % (name, name)
|
||||
|
||||
def transferSize(self, name):
|
||||
pass
|
||||
|
||||
def passInput(self, name):
|
||||
return "%s__in__" % name
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__in__, &%s__out__" % (name, name)
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "(char *)&%s__out__, (int)%s" % (name, self.size)
|
||||
|
||||
|
||||
class StructCombinedInputOutputBufferType(StructInputOutputBufferType):
|
||||
|
||||
"""Like structure buffer -- but same parameter is input and output."""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "(%s *)memcpy((char *)%s__out__, (char *)%s__in__, %s)" % \
|
||||
(self.type, name, name, self.size)
|
||||
|
||||
|
||||
class StructInputBufferType(InputOnlyBufferMixIn, StructInputOutputBufferType):
|
||||
|
||||
"""Fixed size input buffer -- passed as a pointer to a structure.
|
||||
|
||||
Instantiate with the struct type as parameter.
|
||||
"""
|
||||
|
||||
|
||||
class StructByValueBufferType(StructInputBufferType):
|
||||
|
||||
"""Fixed size input buffer -- passed as a structure BY VALUE.
|
||||
|
||||
Instantiate with the struct type as parameter.
|
||||
"""
|
||||
|
||||
def passInput(self, name):
|
||||
return "*%s__in__" % name
|
||||
|
||||
|
||||
class StructOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType):
|
||||
|
||||
"""Fixed size output buffer -- passed as a pointer to a structure.
|
||||
|
||||
Instantiate with the struct type as parameter.
|
||||
"""
|
||||
|
||||
def getSizeDeclarations(self, name, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def passOutput(self, name):
|
||||
return "&%s__out__" % name
|
||||
|
||||
|
||||
class ArrayOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType):
|
||||
|
||||
"""Fixed size output buffer -- declared as a typedef, passed as an array.
|
||||
|
||||
Instantiate with the struct type as parameter.
|
||||
"""
|
||||
|
||||
def getSizeDeclarations(self, name, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__" % name
|
||||
302
project/jni/python/src/Tools/bgen/bgen/bgenGenerator.py
Normal file
302
project/jni/python/src/Tools/bgen/bgen/bgenGenerator.py
Normal file
@@ -0,0 +1,302 @@
|
||||
from bgenOutput import *
|
||||
from bgenType import *
|
||||
from bgenVariable import *
|
||||
|
||||
|
||||
Error = "bgenGenerator.Error"
|
||||
|
||||
DEBUG=0
|
||||
|
||||
# Strings to specify argument transfer modes in generator calls
|
||||
IN = "in"
|
||||
OUT = "out"
|
||||
INOUT = IN_OUT = "in-out"
|
||||
|
||||
|
||||
class BaseFunctionGenerator:
|
||||
|
||||
def __init__(self, name, condition=None, callname=None, modifiers=None):
|
||||
if DEBUG: print "<--", name
|
||||
self.name = name
|
||||
if callname:
|
||||
self.callname = callname
|
||||
else:
|
||||
self.callname = name
|
||||
self.prefix = name
|
||||
self.objecttype = "PyObject" # Type of _self argument to function
|
||||
self.condition = condition
|
||||
self.modifiers = modifiers
|
||||
|
||||
def setprefix(self, prefix):
|
||||
self.prefix = prefix
|
||||
|
||||
def checkgenerate(self):
|
||||
return True
|
||||
|
||||
def generate(self):
|
||||
if not self.checkgenerate():
|
||||
return
|
||||
if DEBUG: print "-->", self.name
|
||||
if self.condition:
|
||||
Output()
|
||||
Output(self.condition)
|
||||
self.functionheader()
|
||||
self.functionbody()
|
||||
self.functiontrailer()
|
||||
if self.condition:
|
||||
Output("#endif")
|
||||
|
||||
def functionheader(self):
|
||||
Output()
|
||||
Output("static PyObject *%s_%s(%s *_self, PyObject *_args)",
|
||||
self.prefix, self.name, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("PyObject *_res = NULL;")
|
||||
|
||||
def functionbody(self):
|
||||
Output("/* XXX To be provided */")
|
||||
|
||||
def functiontrailer(self):
|
||||
OutRbrace()
|
||||
|
||||
def reference(self, name = None):
|
||||
if not self.checkgenerate():
|
||||
return
|
||||
if name is None:
|
||||
name = self.name
|
||||
docstring = self.docstring()
|
||||
if self.condition:
|
||||
Output()
|
||||
Output(self.condition)
|
||||
Output("{\"%s\", (PyCFunction)%s_%s, 1,", name, self.prefix, self.name)
|
||||
Output(" PyDoc_STR(%s)},", stringify(docstring))
|
||||
if self.condition:
|
||||
Output("#endif")
|
||||
|
||||
def docstring(self):
|
||||
return None
|
||||
|
||||
def __cmp__(self, other):
|
||||
if not hasattr(other, 'name'):
|
||||
return cmp(id(self), id(other))
|
||||
return cmp(self.name, other.name)
|
||||
|
||||
_stringify_map = {'\n': '\\n', '\t': '\\t', '\r': '\\r', '\b': '\\b',
|
||||
'\e': '\\e', '\a': '\\a', '\f': '\\f', '"': '\\"'}
|
||||
def stringify(str):
|
||||
if str is None: return "NULL"
|
||||
res = '"'
|
||||
map = _stringify_map
|
||||
for c in str:
|
||||
if map.has_key(c): res = res + map[c]
|
||||
elif ' ' <= c <= '~': res = res + c
|
||||
else: res = res + '\\%03o' % ord(c)
|
||||
res = res + '"'
|
||||
return res
|
||||
|
||||
|
||||
class ManualGenerator(BaseFunctionGenerator):
|
||||
|
||||
def __init__(self, name, body, condition=None):
|
||||
BaseFunctionGenerator.__init__(self, name, condition=condition)
|
||||
self.body = body
|
||||
|
||||
def functionbody(self):
|
||||
Output("%s", self.body)
|
||||
|
||||
def setselftype(self, selftype, itselftype):
|
||||
self.objecttype = selftype
|
||||
self.itselftype = itselftype
|
||||
|
||||
|
||||
class FunctionGenerator(BaseFunctionGenerator):
|
||||
|
||||
def __init__(self, returntype, name, *argumentList, **conditionlist):
|
||||
BaseFunctionGenerator.__init__(self, name, **conditionlist)
|
||||
self.returntype = returntype
|
||||
self.argumentList = []
|
||||
self.setreturnvar()
|
||||
self.parseArgumentList(argumentList)
|
||||
self.prefix = "XXX" # Will be changed by setprefix() call
|
||||
self.itselftype = None # Type of _self->ob_itself, if defined
|
||||
|
||||
def setreturnvar(self):
|
||||
if self.returntype:
|
||||
self.rv = self.makereturnvar()
|
||||
self.argumentList.append(self.rv)
|
||||
else:
|
||||
self.rv = None
|
||||
|
||||
def makereturnvar(self):
|
||||
return Variable(self.returntype, "_rv", OutMode)
|
||||
|
||||
def setselftype(self, selftype, itselftype):
|
||||
self.objecttype = selftype
|
||||
self.itselftype = itselftype
|
||||
|
||||
def parseArgumentList(self, argumentList):
|
||||
iarg = 0
|
||||
for type, name, mode in argumentList:
|
||||
iarg = iarg + 1
|
||||
if name is None: name = "_arg%d" % iarg
|
||||
arg = Variable(type, name, mode)
|
||||
self.argumentList.append(arg)
|
||||
|
||||
def docstring(self):
|
||||
input = []
|
||||
output = []
|
||||
for arg in self.argumentList:
|
||||
if arg.flags == ErrorMode or arg.flags == SelfMode:
|
||||
continue
|
||||
if arg.type is None:
|
||||
str = 'void'
|
||||
else:
|
||||
if hasattr(arg.type, 'typeName'):
|
||||
typeName = arg.type.typeName
|
||||
if typeName is None: # Suppressed type
|
||||
continue
|
||||
else:
|
||||
typeName = "?"
|
||||
print "Nameless type", arg.type
|
||||
|
||||
str = typeName + ' ' + arg.name
|
||||
if arg.mode in (InMode, InOutMode):
|
||||
input.append(str)
|
||||
if arg.mode in (InOutMode, OutMode):
|
||||
output.append(str)
|
||||
if not input:
|
||||
instr = "()"
|
||||
else:
|
||||
instr = "(%s)" % ", ".join(input)
|
||||
if not output or output == ["void"]:
|
||||
outstr = "None"
|
||||
else:
|
||||
outstr = "(%s)" % ", ".join(output)
|
||||
return instr + " -> " + outstr
|
||||
|
||||
def functionbody(self):
|
||||
self.declarations()
|
||||
self.precheck()
|
||||
self.getargs()
|
||||
self.callit()
|
||||
self.checkit()
|
||||
self.returnvalue()
|
||||
|
||||
def declarations(self):
|
||||
for arg in self.argumentList:
|
||||
arg.declare()
|
||||
|
||||
def getargs(self):
|
||||
sep = ",\n" + ' '*len("if (!PyArg_ParseTuple(")
|
||||
fmt, lst = self.getargsFormatArgs(sep)
|
||||
Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
|
||||
IndentLevel()
|
||||
Output("return NULL;")
|
||||
DedentLevel()
|
||||
for arg in self.argumentList:
|
||||
if arg.flags == SelfMode:
|
||||
continue
|
||||
if arg.mode in (InMode, InOutMode):
|
||||
arg.getargsCheck()
|
||||
|
||||
def getargsFormatArgs(self, sep):
|
||||
fmt = ""
|
||||
lst = ""
|
||||
for arg in self.argumentList:
|
||||
if arg.flags == SelfMode:
|
||||
continue
|
||||
if arg.mode in (InMode, InOutMode):
|
||||
arg.getargsPreCheck()
|
||||
fmt = fmt + arg.getargsFormat()
|
||||
args = arg.getargsArgs()
|
||||
if args:
|
||||
lst = lst + sep + args
|
||||
return fmt, lst
|
||||
|
||||
def precheck(self):
|
||||
pass
|
||||
|
||||
def beginallowthreads(self):
|
||||
pass
|
||||
|
||||
def endallowthreads(self):
|
||||
pass
|
||||
|
||||
def callit(self):
|
||||
args = ""
|
||||
s = "%s%s(" % (self.getrvforcallit(), self.callname)
|
||||
sep = ",\n" + ' '*len(s)
|
||||
for arg in self.argumentList:
|
||||
if arg is self.rv:
|
||||
continue
|
||||
s = arg.passArgument()
|
||||
if args: s = sep + s
|
||||
args = args + s
|
||||
self.beginallowthreads()
|
||||
Output("%s%s(%s);",
|
||||
self.getrvforcallit(), self.callname, args)
|
||||
self.endallowthreads()
|
||||
|
||||
def getrvforcallit(self):
|
||||
if self.rv:
|
||||
return "%s = " % self.rv.name
|
||||
else:
|
||||
return ""
|
||||
|
||||
def checkit(self):
|
||||
for arg in self.argumentList:
|
||||
arg.errorCheck()
|
||||
|
||||
def returnvalue(self):
|
||||
sep = ",\n" + ' '*len("return Py_BuildValue(")
|
||||
fmt, lst = self.mkvalueFormatArgs(sep)
|
||||
if fmt == "":
|
||||
Output("Py_INCREF(Py_None);")
|
||||
Output("_res = Py_None;");
|
||||
else:
|
||||
Output("_res = Py_BuildValue(\"%s\"%s);", fmt, lst)
|
||||
tmp = self.argumentList[:]
|
||||
tmp.reverse()
|
||||
for arg in tmp:
|
||||
if not arg: continue
|
||||
arg.cleanup()
|
||||
Output("return _res;")
|
||||
|
||||
def mkvalueFormatArgs(self, sep):
|
||||
fmt = ""
|
||||
lst = ""
|
||||
for arg in self.argumentList:
|
||||
if not arg: continue
|
||||
if arg.flags == ErrorMode: continue
|
||||
if arg.mode in (OutMode, InOutMode):
|
||||
arg.mkvaluePreCheck()
|
||||
fmt = fmt + arg.mkvalueFormat()
|
||||
lst = lst + sep + arg.mkvalueArgs()
|
||||
return fmt, lst
|
||||
|
||||
class MethodGenerator(FunctionGenerator):
|
||||
|
||||
def parseArgumentList(self, args):
|
||||
a0, args = args[0], args[1:]
|
||||
t0, n0, m0 = a0
|
||||
if m0 != InMode:
|
||||
raise ValueError, "method's 'self' must be 'InMode'"
|
||||
self.itself = Variable(t0, "_self->ob_itself", SelfMode)
|
||||
self.argumentList.append(self.itself)
|
||||
FunctionGenerator.parseArgumentList(self, args)
|
||||
|
||||
def _test():
|
||||
void = None
|
||||
eggs = FunctionGenerator(void, "eggs",
|
||||
(stringptr, 'cmd', InMode),
|
||||
(int, 'x', InMode),
|
||||
(double, 'y', InOutMode),
|
||||
(int, 'status', ErrorMode),
|
||||
)
|
||||
eggs.setprefix("spam")
|
||||
print "/* START */"
|
||||
eggs.generate()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
||||
40
project/jni/python/src/Tools/bgen/bgen/bgenGeneratorGroup.py
Normal file
40
project/jni/python/src/Tools/bgen/bgen/bgenGeneratorGroup.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from bgenOutput import *
|
||||
|
||||
class GeneratorGroup:
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix
|
||||
self.generators = []
|
||||
|
||||
def add(self, g, dupcheck=0):
|
||||
if dupcheck:
|
||||
if g in self.generators:
|
||||
print 'DUP', g.name
|
||||
return
|
||||
g.setprefix(self.prefix)
|
||||
self.generators.append(g)
|
||||
|
||||
def generate(self):
|
||||
for g in self.generators:
|
||||
g.generate()
|
||||
Output()
|
||||
Output("static PyMethodDef %s_methods[] = {", self.prefix)
|
||||
IndentLevel()
|
||||
for g in self.generators:
|
||||
g.reference()
|
||||
Output("{NULL, NULL, 0}")
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
|
||||
|
||||
def _test():
|
||||
void = None
|
||||
from bgenGenerator import FunctionGenerator
|
||||
group = GeneratorGroup("spam")
|
||||
eggs = FunctionGenerator(void, "eggs")
|
||||
group.add(eggs)
|
||||
print "/* START */"
|
||||
group.generate()
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
||||
145
project/jni/python/src/Tools/bgen/bgen/bgenHeapBuffer.py
Normal file
145
project/jni/python/src/Tools/bgen/bgen/bgenHeapBuffer.py
Normal file
@@ -0,0 +1,145 @@
|
||||
# Buffers allocated on the heap
|
||||
|
||||
from bgenOutput import *
|
||||
from bgenType import OutputOnlyMixIn
|
||||
from bgenBuffer import FixedInputOutputBufferType
|
||||
|
||||
|
||||
class HeapInputOutputBufferType(FixedInputOutputBufferType):
|
||||
|
||||
"""Input-output buffer allocated on the heap -- passed as (inbuffer, outbuffer, size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python with input buffer.
|
||||
"""
|
||||
|
||||
def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None):
|
||||
FixedInputOutputBufferType.__init__(self, "0", datatype, sizetype, sizeformat)
|
||||
|
||||
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
if constmode:
|
||||
raise RuntimeError, "Cannot use const output buffer"
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s *%s__out__" % (self.datatype, out, name)]
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("if ((%s__out__ = malloc(%s__in_len__)) == NULL)", name, name)
|
||||
OutLbrace()
|
||||
Output('PyErr_NoMemory();')
|
||||
Output("goto %s__error__;", name)
|
||||
self.label_needed = 1
|
||||
OutRbrace()
|
||||
Output("%s__len__ = %s__in_len__;", name, name)
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__in__, %s__out__, (%s)%s__len__" % \
|
||||
(name, name, self.sizetype, name)
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__, (int)%s__len__" % (name, name)
|
||||
|
||||
def cleanup(self, name):
|
||||
Output("free(%s__out__);", name)
|
||||
FixedInputOutputBufferType.cleanup(self, name)
|
||||
|
||||
|
||||
class VarHeapInputOutputBufferType(HeapInputOutputBufferType):
|
||||
|
||||
"""same as base class, but passed as (inbuffer, outbuffer, &size)"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__in__, %s__out__, &%s__len__" % (name, name, name)
|
||||
|
||||
|
||||
class HeapCombinedInputOutputBufferType(HeapInputOutputBufferType):
|
||||
|
||||
"""same as base class, but passed as (inoutbuffer, size)"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "(%s *)memcpy(%s__out__, %s__in__, %s__len__)" % \
|
||||
(self.datatype, name, name, name)
|
||||
|
||||
|
||||
class VarHeapCombinedInputOutputBufferType(HeapInputOutputBufferType):
|
||||
|
||||
"""same as base class, but passed as (inoutbuffer, &size)"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "(%s *)memcpy(%s__out__, %s__in__, &%s__len__)" % \
|
||||
(self.datatype, name, name, name)
|
||||
|
||||
|
||||
class HeapOutputBufferType(OutputOnlyMixIn, HeapInputOutputBufferType):
|
||||
|
||||
"""Output buffer allocated on the heap -- passed as (buffer, size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python with buffer size.
|
||||
"""
|
||||
|
||||
def getInputBufferDeclarations(self, name, constmode=False):
|
||||
return []
|
||||
|
||||
def getargsFormat(self):
|
||||
return "i"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "&%s__in_len__" % name
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, %s__len__" % (name, name)
|
||||
|
||||
|
||||
class VarHeapOutputBufferType(HeapOutputBufferType):
|
||||
|
||||
"""Output buffer allocated on the heap -- passed as (buffer, &size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python with buffer size.
|
||||
"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, &%s__len__" % (name, name)
|
||||
|
||||
|
||||
class VarVarHeapOutputBufferType(VarHeapOutputBufferType):
|
||||
|
||||
"""Output buffer allocated on the heap -- passed as (buffer, size, &size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python with buffer size.
|
||||
"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, %s__len__, &%s__len__" % (name, name, name)
|
||||
|
||||
class MallocHeapOutputBufferType(HeapOutputBufferType):
|
||||
"""Output buffer allocated by the called function -- passed as (&buffer, &size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python without parameters.
|
||||
"""
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("%s__out__ = NULL;", name)
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def passOutput(self, name):
|
||||
return "&%s__out__, &%s__len__" % (name, name)
|
||||
|
||||
def getargsFormat(self):
|
||||
return ""
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return None
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "z#"
|
||||
|
||||
def cleanup(self, name):
|
||||
Output("if( %s__out__ ) free(%s__out__);", name, name)
|
||||
94
project/jni/python/src/Tools/bgen/bgen/bgenModule.py
Normal file
94
project/jni/python/src/Tools/bgen/bgen/bgenModule.py
Normal file
@@ -0,0 +1,94 @@
|
||||
from bgenOutput import *
|
||||
from bgenGeneratorGroup import GeneratorGroup
|
||||
|
||||
class Module(GeneratorGroup):
|
||||
|
||||
def __init__(self, name, prefix = None,
|
||||
includestuff = None,
|
||||
finalstuff = None,
|
||||
initstuff = None,
|
||||
variablestuff = None,
|
||||
longname = None):
|
||||
GeneratorGroup.__init__(self, prefix or name)
|
||||
self.name = name
|
||||
if longname:
|
||||
self.longname = longname
|
||||
else:
|
||||
self.longname = name
|
||||
self.includestuff = includestuff
|
||||
self.initstuff = initstuff
|
||||
self.finalstuff = finalstuff
|
||||
self.variablestuff = variablestuff
|
||||
self.typeobjects = []
|
||||
|
||||
def addobject(self, od):
|
||||
self.generators.append(od)
|
||||
self.typeobjects.append(od)
|
||||
od.setmodulename(self.longname)
|
||||
|
||||
def generate(self):
|
||||
OutHeader1("Module " + self.name)
|
||||
Output("#include \"Python.h\"")
|
||||
Output()
|
||||
|
||||
if self.includestuff:
|
||||
Output()
|
||||
Output("%s", self.includestuff)
|
||||
|
||||
self.declareModuleVariables()
|
||||
|
||||
GeneratorGroup.generate(self)
|
||||
|
||||
if self.finalstuff:
|
||||
Output()
|
||||
Output("%s", self.finalstuff)
|
||||
|
||||
Output()
|
||||
Output("void init%s(void)", self.name)
|
||||
OutLbrace()
|
||||
Output("PyObject *m;")
|
||||
Output("PyObject *d;")
|
||||
Output()
|
||||
|
||||
if self.initstuff:
|
||||
Output("%s", self.initstuff)
|
||||
Output()
|
||||
|
||||
Output("m = Py_InitModule(\"%s\", %s_methods);",
|
||||
self.name, self.prefix)
|
||||
Output("d = PyModule_GetDict(m);")
|
||||
self.createModuleVariables()
|
||||
OutRbrace()
|
||||
OutHeader1("End module " + self.name)
|
||||
|
||||
def declareModuleVariables(self):
|
||||
self.errorname = self.prefix + "_Error"
|
||||
Output("static PyObject *%s;", self.errorname)
|
||||
|
||||
def createModuleVariables(self):
|
||||
Output("""%s = %s;""", self.errorname, self.exceptionInitializer())
|
||||
Output("""if (%s == NULL ||""", self.errorname)
|
||||
Output(""" PyDict_SetItemString(d, "Error", %s) != 0)""",
|
||||
self.errorname)
|
||||
IndentLevel()
|
||||
Output("""return;""")
|
||||
DedentLevel()
|
||||
for tp in self.typeobjects:
|
||||
tp.outputTypeObjectInitializer()
|
||||
if self.variablestuff:
|
||||
Output("%s", self.variablestuff)
|
||||
Output()
|
||||
|
||||
def exceptionInitializer(self):
|
||||
return """PyErr_NewException("%s.Error", NULL, NULL)""" % self.name
|
||||
|
||||
|
||||
def _test():
|
||||
from bgenGenerator import FunctionGenerator
|
||||
m = Module("spam", "", "#include <stdio.h>")
|
||||
g = FunctionGenerator(None, "bacon")
|
||||
m.add(g)
|
||||
m.generate()
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
||||
512
project/jni/python/src/Tools/bgen/bgen/bgenObjectDefinition.py
Normal file
512
project/jni/python/src/Tools/bgen/bgen/bgenObjectDefinition.py
Normal file
@@ -0,0 +1,512 @@
|
||||
from bgenOutput import *
|
||||
from bgenGeneratorGroup import GeneratorGroup
|
||||
|
||||
class ObjectDefinition(GeneratorGroup):
|
||||
"Spit out code that together defines a new Python object type"
|
||||
basechain = "NULL"
|
||||
tp_flags = "Py_TPFLAGS_DEFAULT"
|
||||
basetype = None
|
||||
argref = "" # set to "*" if arg to <type>_New should be pointer
|
||||
argconst = "" # set to "const " if arg to <type>_New should be const
|
||||
|
||||
def __init__(self, name, prefix, itselftype):
|
||||
"""ObjectDefinition constructor. May be extended, but do not override.
|
||||
|
||||
- name: the object's official name, e.g. 'SndChannel'.
|
||||
- prefix: the prefix used for the object's functions and data, e.g. 'SndCh'.
|
||||
- itselftype: the C type actually contained in the object, e.g. 'SndChannelPtr'.
|
||||
|
||||
XXX For official Python data types, rules for the 'Py' prefix are a problem.
|
||||
"""
|
||||
|
||||
GeneratorGroup.__init__(self, prefix or name)
|
||||
self.name = name
|
||||
self.itselftype = itselftype
|
||||
self.objecttype = name + 'Object'
|
||||
self.typename = name + '_Type'
|
||||
self.static = "static " # set to "" to make <type>_New and <type>_Convert public
|
||||
self.modulename = None
|
||||
if hasattr(self, "assertions"):
|
||||
self.assertions()
|
||||
|
||||
def add(self, g, dupcheck=0):
|
||||
g.setselftype(self.objecttype, self.itselftype)
|
||||
GeneratorGroup.add(self, g, dupcheck)
|
||||
|
||||
def reference(self):
|
||||
# In case we are referenced from a module
|
||||
pass
|
||||
|
||||
def setmodulename(self, name):
|
||||
self.modulename = name
|
||||
|
||||
def generate(self):
|
||||
# XXX This should use long strings and %(varname)s substitution!
|
||||
|
||||
OutHeader2("Object type " + self.name)
|
||||
|
||||
self.outputCheck()
|
||||
|
||||
Output("typedef struct %s {", self.objecttype)
|
||||
IndentLevel()
|
||||
Output("PyObject_HEAD")
|
||||
self.outputStructMembers()
|
||||
DedentLevel()
|
||||
Output("} %s;", self.objecttype)
|
||||
|
||||
self.outputNew()
|
||||
|
||||
self.outputConvert()
|
||||
|
||||
self.outputDealloc()
|
||||
|
||||
GeneratorGroup.generate(self)
|
||||
|
||||
Output()
|
||||
self.outputMethodChain()
|
||||
|
||||
self.outputGetattr()
|
||||
|
||||
self.outputSetattr()
|
||||
|
||||
self.outputCompare()
|
||||
|
||||
self.outputRepr()
|
||||
|
||||
self.outputHash()
|
||||
|
||||
self.outputPEP253Hooks()
|
||||
|
||||
self.outputTypeObject()
|
||||
|
||||
OutHeader2("End object type " + self.name)
|
||||
|
||||
def outputCheck(self):
|
||||
sf = self.static and "static "
|
||||
Output("%sPyTypeObject %s;", sf, self.typename)
|
||||
Output()
|
||||
Output("#define %s_Check(x) ((x)->ob_type == &%s || PyObject_TypeCheck((x), &%s))",
|
||||
self.prefix, self.typename, self.typename)
|
||||
Output()
|
||||
|
||||
def outputMethodChain(self):
|
||||
Output("%sPyMethodChain %s_chain = { %s_methods, %s };",
|
||||
self.static, self.prefix, self.prefix, self.basechain)
|
||||
|
||||
def outputStructMembers(self):
|
||||
Output("%s ob_itself;", self.itselftype)
|
||||
|
||||
def outputNew(self):
|
||||
Output()
|
||||
Output("%sPyObject *%s_New(%s%s %sitself)", self.static, self.prefix,
|
||||
self.argconst, self.itselftype, self.argref)
|
||||
OutLbrace()
|
||||
Output("%s *it;", self.objecttype)
|
||||
self.outputCheckNewArg()
|
||||
Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
|
||||
Output("if (it == NULL) return NULL;")
|
||||
if self.basetype:
|
||||
Output("/* XXXX Should we tp_init or tp_new our basetype? */")
|
||||
self.outputInitStructMembers()
|
||||
Output("return (PyObject *)it;")
|
||||
OutRbrace()
|
||||
|
||||
def outputInitStructMembers(self):
|
||||
Output("it->ob_itself = %sitself;", self.argref)
|
||||
|
||||
def outputCheckNewArg(self):
|
||||
"Override this method to apply additional checks/conversions"
|
||||
|
||||
def outputConvert(self):
|
||||
Output()
|
||||
Output("%sint %s_Convert(PyObject *v, %s *p_itself)", self.static, self.prefix,
|
||||
self.itselftype)
|
||||
OutLbrace()
|
||||
self.outputCheckConvertArg()
|
||||
Output("if (!%s_Check(v))", self.prefix)
|
||||
OutLbrace()
|
||||
Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name)
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
Output("*p_itself = ((%s *)v)->ob_itself;", self.objecttype)
|
||||
Output("return 1;")
|
||||
OutRbrace()
|
||||
|
||||
def outputCheckConvertArg(self):
|
||||
"Override this method to apply additional conversions"
|
||||
|
||||
def outputDealloc(self):
|
||||
Output()
|
||||
Output("static void %s_dealloc(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
self.outputCleanupStructMembers()
|
||||
if self.basetype:
|
||||
Output("%s.tp_dealloc((PyObject *)self);", self.basetype)
|
||||
elif hasattr(self, 'output_tp_free'):
|
||||
# This is a new-style object with tp_free slot
|
||||
Output("self->ob_type->tp_free((PyObject *)self);")
|
||||
else:
|
||||
Output("PyObject_Free((PyObject *)self);")
|
||||
OutRbrace()
|
||||
|
||||
def outputCleanupStructMembers(self):
|
||||
self.outputFreeIt("self->ob_itself")
|
||||
|
||||
def outputFreeIt(self, name):
|
||||
Output("/* Cleanup of %s goes here */", name)
|
||||
|
||||
def outputGetattr(self):
|
||||
Output()
|
||||
Output("static PyObject *%s_getattr(%s *self, char *name)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
self.outputGetattrBody()
|
||||
OutRbrace()
|
||||
|
||||
def outputGetattrBody(self):
|
||||
self.outputGetattrHook()
|
||||
Output("return Py_FindMethodInChain(&%s_chain, (PyObject *)self, name);",
|
||||
self.prefix)
|
||||
|
||||
def outputGetattrHook(self):
|
||||
pass
|
||||
|
||||
def outputSetattr(self):
|
||||
Output()
|
||||
Output("#define %s_setattr NULL", self.prefix)
|
||||
|
||||
def outputCompare(self):
|
||||
Output()
|
||||
Output("#define %s_compare NULL", self.prefix)
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("#define %s_repr NULL", self.prefix)
|
||||
|
||||
def outputHash(self):
|
||||
Output()
|
||||
Output("#define %s_hash NULL", self.prefix)
|
||||
|
||||
def outputTypeObject(self):
|
||||
sf = self.static and "static "
|
||||
Output()
|
||||
Output("%sPyTypeObject %s = {", sf, self.typename)
|
||||
IndentLevel()
|
||||
Output("PyObject_HEAD_INIT(NULL)")
|
||||
Output("0, /*ob_size*/")
|
||||
if self.modulename:
|
||||
Output("\"%s.%s\", /*tp_name*/", self.modulename, self.name)
|
||||
else:
|
||||
Output("\"%s\", /*tp_name*/", self.name)
|
||||
Output("sizeof(%s), /*tp_basicsize*/", self.objecttype)
|
||||
Output("0, /*tp_itemsize*/")
|
||||
Output("/* methods */")
|
||||
Output("(destructor) %s_dealloc, /*tp_dealloc*/", self.prefix)
|
||||
Output("0, /*tp_print*/")
|
||||
Output("(getattrfunc) %s_getattr, /*tp_getattr*/", self.prefix)
|
||||
Output("(setattrfunc) %s_setattr, /*tp_setattr*/", self.prefix)
|
||||
Output("(cmpfunc) %s_compare, /*tp_compare*/", self.prefix)
|
||||
Output("(reprfunc) %s_repr, /*tp_repr*/", self.prefix)
|
||||
Output("(PyNumberMethods *)0, /* tp_as_number */")
|
||||
Output("(PySequenceMethods *)0, /* tp_as_sequence */")
|
||||
Output("(PyMappingMethods *)0, /* tp_as_mapping */")
|
||||
Output("(hashfunc) %s_hash, /*tp_hash*/", self.prefix)
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
|
||||
def outputTypeObjectInitializer(self):
|
||||
Output("""%s.ob_type = &PyType_Type;""", self.typename)
|
||||
if self.basetype:
|
||||
Output("%s.tp_base = &%s;", self.typename, self.basetype)
|
||||
Output("if (PyType_Ready(&%s) < 0) return;", self.typename)
|
||||
Output("""Py_INCREF(&%s);""", self.typename)
|
||||
Output("PyModule_AddObject(m, \"%s\", (PyObject *)&%s);", self.name, self.typename);
|
||||
self.outputTypeObjectInitializerCompat()
|
||||
|
||||
def outputTypeObjectInitializerCompat(self):
|
||||
Output("/* Backward-compatible name */")
|
||||
Output("""Py_INCREF(&%s);""", self.typename);
|
||||
Output("PyModule_AddObject(m, \"%sType\", (PyObject *)&%s);", self.name, self.typename);
|
||||
|
||||
def outputPEP253Hooks(self):
|
||||
pass
|
||||
|
||||
class PEP252Mixin:
|
||||
getsetlist = []
|
||||
|
||||
def assertions(self):
|
||||
# Check that various things aren't overridden. If they are it could
|
||||
# signify a bgen-client that has been partially converted to PEP252.
|
||||
assert self.outputGetattr.im_func == PEP252Mixin.outputGetattr.im_func
|
||||
assert self.outputSetattr.im_func == PEP252Mixin.outputSetattr.im_func
|
||||
assert self.outputGetattrBody == None
|
||||
assert self.outputGetattrHook == None
|
||||
assert self.basechain == "NULL"
|
||||
|
||||
def outputGetattr(self):
|
||||
pass
|
||||
|
||||
outputGetattrBody = None
|
||||
|
||||
outputGetattrHook = None
|
||||
|
||||
def outputSetattr(self):
|
||||
pass
|
||||
|
||||
def outputMethodChain(self):
|
||||
# This is a good place to output the getters and setters
|
||||
self.outputGetSetList()
|
||||
|
||||
def outputHook(self, name):
|
||||
methodname = "outputHook_" + name
|
||||
if hasattr(self, methodname):
|
||||
func = getattr(self, methodname)
|
||||
func()
|
||||
else:
|
||||
Output("0, /*%s*/", name)
|
||||
|
||||
def outputTypeObject(self):
|
||||
sf = self.static and "static "
|
||||
Output()
|
||||
Output("%sPyTypeObject %s = {", sf, self.typename)
|
||||
IndentLevel()
|
||||
Output("PyObject_HEAD_INIT(NULL)")
|
||||
Output("0, /*ob_size*/")
|
||||
if self.modulename:
|
||||
Output("\"%s.%s\", /*tp_name*/", self.modulename, self.name)
|
||||
else:
|
||||
Output("\"%s\", /*tp_name*/", self.name)
|
||||
Output("sizeof(%s), /*tp_basicsize*/", self.objecttype)
|
||||
Output("0, /*tp_itemsize*/")
|
||||
|
||||
Output("/* methods */")
|
||||
Output("(destructor) %s_dealloc, /*tp_dealloc*/", self.prefix)
|
||||
Output("0, /*tp_print*/")
|
||||
Output("(getattrfunc)0, /*tp_getattr*/")
|
||||
Output("(setattrfunc)0, /*tp_setattr*/")
|
||||
Output("(cmpfunc) %s_compare, /*tp_compare*/", self.prefix)
|
||||
Output("(reprfunc) %s_repr, /*tp_repr*/", self.prefix)
|
||||
|
||||
Output("(PyNumberMethods *)0, /* tp_as_number */")
|
||||
Output("(PySequenceMethods *)0, /* tp_as_sequence */")
|
||||
Output("(PyMappingMethods *)0, /* tp_as_mapping */")
|
||||
|
||||
Output("(hashfunc) %s_hash, /*tp_hash*/", self.prefix)
|
||||
self.outputHook("tp_call")
|
||||
Output("0, /*tp_str*/")
|
||||
Output("PyObject_GenericGetAttr, /*tp_getattro*/")
|
||||
Output("PyObject_GenericSetAttr, /*tp_setattro */")
|
||||
|
||||
self.outputHook("tp_as_buffer")
|
||||
Output("%s, /* tp_flags */", self.tp_flags)
|
||||
self.outputHook("tp_doc")
|
||||
self.outputHook("tp_traverse")
|
||||
self.outputHook("tp_clear")
|
||||
self.outputHook("tp_richcompare")
|
||||
self.outputHook("tp_weaklistoffset")
|
||||
self.outputHook("tp_iter")
|
||||
self.outputHook("tp_iternext")
|
||||
Output("%s_methods, /* tp_methods */", self.prefix)
|
||||
self.outputHook("tp_members")
|
||||
Output("%s_getsetlist, /*tp_getset*/", self.prefix)
|
||||
self.outputHook("tp_base")
|
||||
self.outputHook("tp_dict")
|
||||
self.outputHook("tp_descr_get")
|
||||
self.outputHook("tp_descr_set")
|
||||
self.outputHook("tp_dictoffset")
|
||||
self.outputHook("tp_init")
|
||||
self.outputHook("tp_alloc")
|
||||
self.outputHook("tp_new")
|
||||
self.outputHook("tp_free")
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
|
||||
def outputGetSetList(self):
|
||||
if self.getsetlist:
|
||||
for name, get, set, doc in self.getsetlist:
|
||||
if get:
|
||||
self.outputGetter(name, get)
|
||||
else:
|
||||
Output("#define %s_get_%s NULL", self.prefix, name)
|
||||
Output()
|
||||
if set:
|
||||
self.outputSetter(name, set)
|
||||
else:
|
||||
Output("#define %s_set_%s NULL", self.prefix, name)
|
||||
Output()
|
||||
|
||||
Output("static PyGetSetDef %s_getsetlist[] = {", self.prefix)
|
||||
IndentLevel()
|
||||
for name, get, set, doc in self.getsetlist:
|
||||
if doc:
|
||||
doc = '"' + doc + '"'
|
||||
else:
|
||||
doc = "NULL"
|
||||
Output("{\"%s\", (getter)%s_get_%s, (setter)%s_set_%s, %s},",
|
||||
name, self.prefix, name, self.prefix, name, doc)
|
||||
Output("{NULL, NULL, NULL, NULL},")
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
else:
|
||||
Output("#define %s_getsetlist NULL", self.prefix)
|
||||
Output()
|
||||
|
||||
def outputGetter(self, name, code):
|
||||
Output("static PyObject *%s_get_%s(%s *self, void *closure)",
|
||||
self.prefix, name, self.objecttype)
|
||||
OutLbrace()
|
||||
Output(code)
|
||||
OutRbrace()
|
||||
Output()
|
||||
|
||||
def outputSetter(self, name, code):
|
||||
Output("static int %s_set_%s(%s *self, PyObject *v, void *closure)",
|
||||
self.prefix, name, self.objecttype)
|
||||
OutLbrace()
|
||||
Output(code)
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
Output()
|
||||
|
||||
class PEP253Mixin(PEP252Mixin):
|
||||
tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE"
|
||||
|
||||
def outputHook_tp_init(self):
|
||||
Output("%s_tp_init, /* tp_init */", self.prefix)
|
||||
|
||||
def outputHook_tp_alloc(self):
|
||||
Output("%s_tp_alloc, /* tp_alloc */", self.prefix)
|
||||
|
||||
def outputHook_tp_new(self):
|
||||
Output("%s_tp_new, /* tp_new */", self.prefix)
|
||||
|
||||
def outputHook_tp_free(self):
|
||||
Output("%s_tp_free, /* tp_free */", self.prefix)
|
||||
|
||||
def output_tp_initBody_basecall(self):
|
||||
"""If a type shares its init call with its base type set output_tp_initBody
|
||||
to output_tp_initBody_basecall"""
|
||||
if self.basetype:
|
||||
Output("if (%s.tp_init)", self.basetype)
|
||||
OutLbrace()
|
||||
Output("if ( (*%s.tp_init)(_self, _args, _kwds) < 0) return -1;", self.basetype)
|
||||
OutRbrace()
|
||||
|
||||
output_tp_initBody = None
|
||||
|
||||
def output_tp_init(self):
|
||||
if self.output_tp_initBody:
|
||||
Output("static int %s_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds)", self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_initBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_init 0", self.prefix)
|
||||
Output()
|
||||
|
||||
output_tp_allocBody = None
|
||||
|
||||
def output_tp_alloc(self):
|
||||
if self.output_tp_allocBody:
|
||||
Output("static PyObject *%s_tp_alloc(PyTypeObject *type, int nitems)",
|
||||
self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_allocBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_alloc PyType_GenericAlloc", self.prefix)
|
||||
Output()
|
||||
|
||||
def output_tp_newBody(self):
|
||||
Output("PyObject *_self;");
|
||||
Output("%s itself;", self.itselftype);
|
||||
Output("char *kw[] = {\"itself\", 0};")
|
||||
Output()
|
||||
Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, %s_Convert, &itself)) return NULL;",
|
||||
self.prefix);
|
||||
if self.basetype:
|
||||
Output("if (%s.tp_new)", self.basetype)
|
||||
OutLbrace()
|
||||
Output("if ( (*%s.tp_new)(type, _args, _kwds) == NULL) return NULL;", self.basetype)
|
||||
Dedent()
|
||||
Output("} else {")
|
||||
Indent()
|
||||
Output("if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL;")
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL;")
|
||||
Output("((%s *)_self)->ob_itself = itself;", self.objecttype)
|
||||
Output("return _self;")
|
||||
|
||||
def output_tp_new(self):
|
||||
if self.output_tp_newBody:
|
||||
Output("static PyObject *%s_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds)", self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_newBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_new PyType_GenericNew", self.prefix)
|
||||
Output()
|
||||
|
||||
output_tp_freeBody = None
|
||||
|
||||
def output_tp_free(self):
|
||||
if self.output_tp_freeBody:
|
||||
Output("static void %s_tp_free(PyObject *self)", self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_freeBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_free PyObject_Del", self.prefix)
|
||||
Output()
|
||||
|
||||
def outputPEP253Hooks(self):
|
||||
self.output_tp_init()
|
||||
self.output_tp_alloc()
|
||||
self.output_tp_new()
|
||||
self.output_tp_free()
|
||||
|
||||
class GlobalObjectDefinition(ObjectDefinition):
|
||||
"""Like ObjectDefinition but exports some parts.
|
||||
|
||||
XXX Should also somehow generate a .h file for them.
|
||||
"""
|
||||
|
||||
def __init__(self, name, prefix = None, itselftype = None):
|
||||
ObjectDefinition.__init__(self, name, prefix or name, itselftype or name)
|
||||
self.static = ""
|
||||
|
||||
class ObjectIdentityMixin:
|
||||
"""A mixin class for objects that makes the identity of ob_itself
|
||||
govern comparisons and dictionary lookups. Useful if the C object can
|
||||
be returned by library calls and it is difficult (or impossible) to find
|
||||
the corresponding Python objects. With this you can create Python object
|
||||
wrappers on the fly"""
|
||||
|
||||
def outputCompare(self):
|
||||
Output()
|
||||
Output("static int %s_compare(%s *self, %s *other)", self.prefix, self.objecttype,
|
||||
self.objecttype)
|
||||
OutLbrace()
|
||||
Output("unsigned long v, w;")
|
||||
Output()
|
||||
Output("if (!%s_Check((PyObject *)other))", self.prefix)
|
||||
OutLbrace()
|
||||
Output("v=(unsigned long)self;")
|
||||
Output("w=(unsigned long)other;")
|
||||
OutRbrace()
|
||||
Output("else")
|
||||
OutLbrace()
|
||||
Output("v=(unsigned long)self->ob_itself;")
|
||||
Output("w=(unsigned long)other->ob_itself;")
|
||||
OutRbrace()
|
||||
Output("if( v < w ) return -1;")
|
||||
Output("if( v > w ) return 1;")
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
|
||||
def outputHash(self):
|
||||
Output()
|
||||
Output("static long %s_hash(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("return (long)self->ob_itself;")
|
||||
OutRbrace()
|
||||
219
project/jni/python/src/Tools/bgen/bgen/bgenOutput.py
Normal file
219
project/jni/python/src/Tools/bgen/bgen/bgenOutput.py
Normal file
@@ -0,0 +1,219 @@
|
||||
"""Output primitives for the binding generator classes.
|
||||
|
||||
This should really be a class, but then everybody would be passing
|
||||
the output object to each other. I chose for the simpler approach
|
||||
of a module with a global variable. Use SetOutputFile() or
|
||||
SetOutputFileName() to change the output file.
|
||||
"""
|
||||
|
||||
_NeedClose = 0
|
||||
|
||||
def SetOutputFile(file = None, needclose = 0):
|
||||
"""Call this with an open file object to make it the output file.
|
||||
|
||||
Call it without arguments to close the current file (if necessary)
|
||||
and reset it to sys.stdout.
|
||||
If the second argument is true, the new file will be explicitly closed
|
||||
on a subsequence call.
|
||||
"""
|
||||
global _File, _NeedClose
|
||||
if _NeedClose:
|
||||
tmp = _File
|
||||
_NeedClose = 0
|
||||
_File = None
|
||||
tmp.close()
|
||||
if file is None:
|
||||
import sys
|
||||
file = sys.stdout
|
||||
_File = file
|
||||
_NeedClose = file and needclose
|
||||
|
||||
def SetOutputFileName(filename = None):
|
||||
"""Call this with a filename to make it the output file.
|
||||
|
||||
Call it without arguments to close the current file (if necessary)
|
||||
and reset it to sys.stdout.
|
||||
"""
|
||||
SetOutputFile()
|
||||
if filename:
|
||||
SetOutputFile(open(filename, 'w'), 1)
|
||||
|
||||
SetOutputFile() # Initialize _File
|
||||
|
||||
_Level = 0 # Indentation level
|
||||
|
||||
def GetLevel():
|
||||
"""Return the current indentation level."""
|
||||
return _Level
|
||||
|
||||
def SetLevel(level):
|
||||
"""Set the current indentation level.
|
||||
|
||||
This does no type or range checking -- use at own risk.
|
||||
"""
|
||||
global _Level
|
||||
_Level = level
|
||||
|
||||
def Output(format = "", *args):
|
||||
VaOutput(format, args)
|
||||
|
||||
def VaOutput(format, args):
|
||||
"""Call this with a format string and argument tuple for the format.
|
||||
|
||||
A newline is always added. Each line in the output is indented
|
||||
to the proper indentation level -- even if the result of the
|
||||
format expansion contains embedded newlines. Exception: lines
|
||||
beginning with '#' are not indented -- these are assumed to be
|
||||
C preprprocessor lines.
|
||||
"""
|
||||
text = format % args
|
||||
if _Level > 0:
|
||||
indent = '\t' * _Level
|
||||
lines = text.split('\n')
|
||||
for i in range(len(lines)):
|
||||
if lines[i] and lines[i][0] != '#':
|
||||
lines[i] = indent + lines[i]
|
||||
text = '\n'.join(lines)
|
||||
_File.write(text + '\n')
|
||||
|
||||
def IndentLevel(by = 1):
|
||||
"""Increment the indentation level by one.
|
||||
|
||||
When called with an argument, adds it to the indentation level.
|
||||
"""
|
||||
global _Level
|
||||
if _Level+by < 0:
|
||||
raise Error, "indentation underflow (internal error)"
|
||||
_Level = _Level + by
|
||||
|
||||
def DedentLevel(by = 1):
|
||||
"""Decrement the indentation level by one.
|
||||
|
||||
When called with an argument, subtracts it from the indentation level.
|
||||
"""
|
||||
IndentLevel(-by)
|
||||
|
||||
def OutIndent(format = "", *args):
|
||||
"""Combine Output() followed by IndentLevel().
|
||||
|
||||
If no text is given, acts like lone IndentLevel().
|
||||
"""
|
||||
if format: VaOutput(format, args)
|
||||
IndentLevel()
|
||||
|
||||
def OutDedent(format = "", *args):
|
||||
"""Combine Output() followed by DedentLevel().
|
||||
|
||||
If no text is given, acts like loneDedentLevel().
|
||||
"""
|
||||
if format: VaOutput(format, args)
|
||||
DedentLevel()
|
||||
|
||||
def OutLbrace(format = "", *args):
|
||||
"""Like Output, but add a '{' and increase the indentation level.
|
||||
|
||||
If no text is given a lone '{' is output.
|
||||
"""
|
||||
if format:
|
||||
format = format + " {"
|
||||
else:
|
||||
format = "{"
|
||||
VaOutput(format, args)
|
||||
IndentLevel()
|
||||
|
||||
def OutRbrace():
|
||||
"""Decrease the indentation level and output a '}' on a line by itself."""
|
||||
DedentLevel()
|
||||
Output("}")
|
||||
|
||||
def OutHeader(text, dash):
|
||||
"""Output a header comment using a given dash character."""
|
||||
n = 64 - len(text)
|
||||
Output()
|
||||
Output("/* %s %s %s */", dash * (n/2), text, dash * (n - n/2))
|
||||
Output()
|
||||
|
||||
def OutHeader1(text):
|
||||
"""Output a level 1 header comment (uses '=' dashes)."""
|
||||
OutHeader(text, "=")
|
||||
|
||||
def OutHeader2(text):
|
||||
"""Output a level 2 header comment (uses '-' dashes)."""
|
||||
OutHeader(text, "-")
|
||||
|
||||
def Out(text):
|
||||
"""Output multiline text that's internally indented.
|
||||
|
||||
Pass this a multiline character string. The whitespace before the
|
||||
first nonblank line of the string will be subtracted from all lines.
|
||||
The lines are then output using Output(), but without interpretation
|
||||
of formatting (if you need formatting you can do it before the call).
|
||||
Recommended use:
|
||||
|
||||
Out('''
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv;
|
||||
{
|
||||
printf("Hello, world\\n");
|
||||
exit(0);
|
||||
}
|
||||
''')
|
||||
|
||||
Caveat: the indentation must be consistent -- if you use three tabs
|
||||
in the first line, (up to) three tabs are removed from following lines,
|
||||
but a line beginning with 24 spaces is not trimmed at all. Don't use
|
||||
this as a feature.
|
||||
"""
|
||||
# (Don't you love using triple quotes *inside* triple quotes? :-)
|
||||
|
||||
lines = text.split('\n')
|
||||
indent = ""
|
||||
for line in lines:
|
||||
if line.strip():
|
||||
for c in line:
|
||||
if not c.isspace():
|
||||
break
|
||||
indent = indent + c
|
||||
break
|
||||
n = len(indent)
|
||||
for line in lines:
|
||||
if line[:n] == indent:
|
||||
line = line[n:]
|
||||
else:
|
||||
for c in indent:
|
||||
if line[:1] <> c: break
|
||||
line = line[1:]
|
||||
VaOutput("%s", line)
|
||||
|
||||
|
||||
def _test():
|
||||
"""Test program. Run when the module is run as a script."""
|
||||
OutHeader1("test bgenOutput")
|
||||
Out("""
|
||||
#include <Python.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
""")
|
||||
IndentLevel()
|
||||
Output("""\
|
||||
/* Here are a few comment lines.
|
||||
Just to test indenting multiple lines.
|
||||
|
||||
End of the comment lines. */
|
||||
""")
|
||||
Output("for (i = 0; i < argc; i++)")
|
||||
OutLbrace()
|
||||
Output('printf("argv[%%d] = %%s\\n", i, argv[i]);')
|
||||
OutRbrace()
|
||||
Output("exit(0)")
|
||||
OutRbrace()
|
||||
OutHeader2("end test")
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
62
project/jni/python/src/Tools/bgen/bgen/bgenStackBuffer.py
Normal file
62
project/jni/python/src/Tools/bgen/bgen/bgenStackBuffer.py
Normal file
@@ -0,0 +1,62 @@
|
||||
"""Buffers allocated on the stack."""
|
||||
|
||||
|
||||
from bgenBuffer import FixedInputBufferType, FixedOutputBufferType
|
||||
|
||||
|
||||
class StackOutputBufferType(FixedOutputBufferType):
|
||||
|
||||
"""Fixed output buffer allocated on the stack -- passed as (buffer, size).
|
||||
|
||||
Instantiate with the buffer size as parameter.
|
||||
"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, %s" % (name, self.size)
|
||||
|
||||
|
||||
class VarStackOutputBufferType(StackOutputBufferType):
|
||||
|
||||
"""Output buffer allocated on the stack -- passed as (buffer, &size).
|
||||
|
||||
Instantiate with the buffer size as parameter.
|
||||
"""
|
||||
|
||||
def getSizeDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return ["int %s__len__ = %s" % (name, self.size)]
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, &%s__len__" % (name, name)
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__, (int)%s__len__" % (name, name)
|
||||
|
||||
|
||||
class VarVarStackOutputBufferType(VarStackOutputBufferType):
|
||||
|
||||
"""Output buffer allocated on the stack -- passed as (buffer, size, &size).
|
||||
|
||||
Instantiate with the buffer size as parameter.
|
||||
"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, %s__len__, &%s__len__" % (name, name, name)
|
||||
|
||||
|
||||
class ReturnVarStackOutputBufferType(VarStackOutputBufferType):
|
||||
|
||||
"""Output buffer allocated on the stack -- passed as (buffer, size) -> size.
|
||||
|
||||
Instantiate with the buffer size as parameter.
|
||||
The function's return value is the size.
|
||||
(XXX Should have a way to suppress returning it separately, too.)
|
||||
"""
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__, %s__len__" % (name, name)
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__, (int)_rv" % name
|
||||
67
project/jni/python/src/Tools/bgen/bgen/bgenStringBuffer.py
Normal file
67
project/jni/python/src/Tools/bgen/bgen/bgenStringBuffer.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""Buffers used to hold null-terminated strings."""
|
||||
|
||||
|
||||
from bgenBuffer import FixedOutputBufferType
|
||||
from bgenStackBuffer import StackOutputBufferType
|
||||
from bgenHeapBuffer import HeapOutputBufferType
|
||||
|
||||
|
||||
class StringBufferMixIn:
|
||||
|
||||
"""Mix-in class to create various string buffer types.
|
||||
|
||||
Strings are character arrays terminated by a null byte.
|
||||
(For input, this is also covered by stringptr.)
|
||||
For output, there are again three variants:
|
||||
- Fixed: size is a constant given in the documentation; or
|
||||
- Stack: size is passed to the C function but we decide on a size at
|
||||
code generation time so we can still allocate on the heap); or
|
||||
- Heap: size is passed to the C function and we let the Python caller
|
||||
pass a size.
|
||||
(Note that this doesn't cover output parameters in which a string
|
||||
pointer is returned. These are actually easier (no allocation) but far
|
||||
less common. I'll write the classes when there is demand.)
|
||||
"""
|
||||
|
||||
def getSizeDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def getargsFormat(self):
|
||||
return "s"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "&%s__in__" % name
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "s"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__" % name
|
||||
|
||||
|
||||
class FixedOutputStringType(StringBufferMixIn, FixedOutputBufferType):
|
||||
|
||||
"""Null-terminated output string -- passed without size.
|
||||
|
||||
Instantiate with buffer size as parameter.
|
||||
"""
|
||||
|
||||
|
||||
class StackOutputStringType(StringBufferMixIn, StackOutputBufferType):
|
||||
|
||||
"""Null-terminated output string -- passed as (buffer, size).
|
||||
|
||||
Instantiate with buffer size as parameter.
|
||||
"""
|
||||
|
||||
|
||||
class HeapOutputStringType(StringBufferMixIn, HeapOutputBufferType):
|
||||
|
||||
"""Null-terminated output string -- passed as (buffer, size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python with buffer size.
|
||||
"""
|
||||
328
project/jni/python/src/Tools/bgen/bgen/bgenType.py
Normal file
328
project/jni/python/src/Tools/bgen/bgen/bgenType.py
Normal file
@@ -0,0 +1,328 @@
|
||||
"""Type classes and a modest collection of standard types."""
|
||||
|
||||
|
||||
from bgenOutput import *
|
||||
|
||||
|
||||
class Type:
|
||||
|
||||
"""Define the various things you can do with a C type.
|
||||
|
||||
Most methods are intended to be extended or overridden.
|
||||
"""
|
||||
|
||||
def __init__(self, typeName, fmt):
|
||||
"""Call with the C name and getargs format for the type.
|
||||
|
||||
Example: int = Type("int", "i")
|
||||
"""
|
||||
self.typeName = typeName
|
||||
self.fmt = fmt
|
||||
|
||||
def declare(self, name, reference=False):
|
||||
"""Declare a variable of the type with a given name.
|
||||
|
||||
Example: int.declare('spam') prints "int spam;"
|
||||
"""
|
||||
for decl in self.getArgDeclarations(name, reference):
|
||||
Output("%s;", decl)
|
||||
for decl in self.getAuxDeclarations(name):
|
||||
Output("%s;", decl)
|
||||
|
||||
def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
|
||||
"""Return the main part of the declarations for this type: the items
|
||||
that will be passed as arguments in the C/C++ function call."""
|
||||
if reference:
|
||||
ref = "&"
|
||||
else:
|
||||
ref = ""
|
||||
if constmode:
|
||||
const = "const "
|
||||
else:
|
||||
const = ""
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s%s%s %s" % (const, self.typeName, ref, out, name)]
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
"""Return any auxiliary declarations needed for implementing this
|
||||
type, such as helper variables used to hold sizes, etc. These declarations
|
||||
are not part of the C/C++ function call interface."""
|
||||
return []
|
||||
|
||||
def getargs(self):
|
||||
return self.getargsFormat(), self.getargsArgs()
|
||||
|
||||
def getargsFormat(self):
|
||||
"""Return the format for this type for use with PyArg_Parse().
|
||||
|
||||
Example: int.getargsFormat() returns the string "i".
|
||||
(getargs is a very old name for PyArg_Parse, hence the name of this method).
|
||||
"""
|
||||
return self.fmt
|
||||
|
||||
def getargsArgs(self, name):
|
||||
"""Return an argument for use with PyArg_Parse().
|
||||
|
||||
Example: int.getargsArgs("spam") returns the string "&spam".
|
||||
"""
|
||||
return "&" + name
|
||||
|
||||
def getargsPreCheck(self, name):
|
||||
"""Perform any actions needed before calling getargs().
|
||||
|
||||
This could include declaring temporary variables and such.
|
||||
"""
|
||||
|
||||
def getargsCheck(self, name):
|
||||
"""Perform any needed post-[new]getargs() checks.
|
||||
|
||||
This is type-dependent; the default does not check for errors.
|
||||
An example would be a check for a maximum string length, or it
|
||||
could do post-getargs() copying or conversion."""
|
||||
|
||||
def passInput(self, name):
|
||||
"""Return an argument for passing a variable into a call.
|
||||
|
||||
Example: int.passInput("spam") returns the string "spam".
|
||||
"""
|
||||
return name
|
||||
|
||||
def passOutput(self, name):
|
||||
"""Return an argument for returning a variable out of a call.
|
||||
|
||||
Example: int.passOutput("spam") returns the string "&spam".
|
||||
"""
|
||||
return "&" + name
|
||||
|
||||
def passReference(self, name):
|
||||
"""Return an argument for C++ pass-by-reference.
|
||||
Default is to call passInput().
|
||||
"""
|
||||
return self.passInput(name)
|
||||
|
||||
def errorCheck(self, name):
|
||||
"""Check for an error returned in the variable.
|
||||
|
||||
This is type-dependent; the default does not check for errors.
|
||||
An example would be a check for a NULL pointer.
|
||||
If an error is found, the generated routine should
|
||||
raise an exception and return NULL.
|
||||
|
||||
XXX There should be a way to add error clean-up code.
|
||||
"""
|
||||
Output("/* XXX no err check for %s %s */", self.typeName, name)
|
||||
|
||||
def mkvalue(self):
|
||||
return self.mkvalueFormat(), self.mkvalueArgs()
|
||||
|
||||
def mkvalueFormat(self):
|
||||
"""Return the format for this type for use with Py_BuildValue().
|
||||
|
||||
This is normally the same as getargsFormat() but it is
|
||||
a separate function to allow future divergence.
|
||||
(mkvalue is a very old name for Py_BuildValue, hence the name of this
|
||||
method).
|
||||
"""
|
||||
return self.getargsFormat()
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
"""Return an argument for use with Py_BuildValue().
|
||||
|
||||
Example: int.mkvalueArgs("spam") returns the string "spam".
|
||||
"""
|
||||
return name
|
||||
|
||||
def mkvaluePreCheck(self, name):
|
||||
"""Perform any actions needed before calling mkvalue().
|
||||
|
||||
This could include declaring temporary variables and such.
|
||||
"""
|
||||
|
||||
def cleanup(self, name):
|
||||
"""Clean up if necessary.
|
||||
|
||||
This is normally empty; it may deallocate buffers etc.
|
||||
"""
|
||||
pass
|
||||
|
||||
class ByAddressType(Type):
|
||||
"Simple type that is also passed by address for input"
|
||||
|
||||
def passInput(self, name):
|
||||
return "&%s" % name
|
||||
|
||||
|
||||
|
||||
# Sometimes it's useful to define a type that's only usable as input or output parameter
|
||||
|
||||
class InputOnlyMixIn:
|
||||
|
||||
"Mix-in class to boobytrap passOutput"
|
||||
|
||||
def passOutput(self, name):
|
||||
raise RuntimeError, "Type '%s' can only be used for input parameters" % self.typeName
|
||||
|
||||
class InputOnlyType(InputOnlyMixIn, Type):
|
||||
|
||||
"Same as Type, but only usable for input parameters -- passOutput is boobytrapped"
|
||||
|
||||
class OutputOnlyMixIn:
|
||||
|
||||
"Mix-in class to boobytrap passInput"
|
||||
|
||||
def passInput(self, name):
|
||||
raise RuntimeError, "Type '%s' can only be used for output parameters" % self.typeName
|
||||
|
||||
class OutputOnlyType(OutputOnlyMixIn, Type):
|
||||
|
||||
"Same as Type, but only usable for output parameters -- passInput is boobytrapped"
|
||||
|
||||
|
||||
# A modest collection of standard C types.
|
||||
void = None
|
||||
char = Type("char", "c")
|
||||
short = Type("short", "h")
|
||||
unsigned_short = Type("unsigned short", "H")
|
||||
int = Type("int", "i")
|
||||
long = Type("long", "l")
|
||||
unsigned_long = Type("unsigned long", "l")
|
||||
float = Type("float", "f")
|
||||
double = Type("double", "d")
|
||||
|
||||
|
||||
# The most common use of character pointers is a null-terminated string.
|
||||
# For input, this is easy. For output, and for other uses of char *,
|
||||
# see the module bgenBuffer.
|
||||
stringptr = InputOnlyType("char*", "s")
|
||||
unicodestringptr = InputOnlyType("wchar_t *", "u")
|
||||
|
||||
|
||||
# Some Python related types.
|
||||
objectptr = Type("PyObject*", "O")
|
||||
stringobjectptr = Type("PyStringObject*", "S")
|
||||
# Etc.
|
||||
|
||||
|
||||
class FakeType(InputOnlyType):
|
||||
|
||||
"""A type that is not represented in the Python version of the interface.
|
||||
|
||||
Instantiate with a value to pass in the call.
|
||||
"""
|
||||
|
||||
def __init__(self, substitute):
|
||||
self.substitute = substitute
|
||||
self.typeName = None # Don't show this argument in __doc__ string
|
||||
|
||||
def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name, reference=False):
|
||||
return []
|
||||
|
||||
def getargsFormat(self):
|
||||
return ""
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return None
|
||||
|
||||
def passInput(self, name):
|
||||
return self.substitute
|
||||
|
||||
|
||||
class OpaqueType(Type):
|
||||
|
||||
"""A type represented by an opaque object type, always passed by address.
|
||||
|
||||
Instantiate with the type name and the names of the new and convert procs.
|
||||
If fewer than three arguments are passed, the second argument is used
|
||||
to derive the new and convert procs by appending _New and _Convert; it
|
||||
defaults to the first argument.
|
||||
"""
|
||||
|
||||
def __init__(self, name, arg = None, extra = None):
|
||||
self.typeName = name
|
||||
if extra is None:
|
||||
# Two arguments (name, usetype) or one (name)
|
||||
arg = arg or name
|
||||
self.new = arg + '_New'
|
||||
self.convert = arg + '_Convert'
|
||||
else:
|
||||
# Three arguments (name, new, convert)
|
||||
self.new = arg
|
||||
self.convert = extra
|
||||
|
||||
def getargsFormat(self):
|
||||
return "O&"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "%s, &%s" % (self.convert, name)
|
||||
|
||||
def passInput(self, name):
|
||||
return "&%s" % name
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "O&"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, &%s" % (self.new, name)
|
||||
|
||||
|
||||
class OpaqueByValueType(OpaqueType):
|
||||
|
||||
"""A type represented by an opaque object type, on input passed BY VALUE.
|
||||
|
||||
Instantiate with the type name, and optionally an object type name whose
|
||||
New/Convert functions will be used.
|
||||
"""
|
||||
|
||||
def passInput(self, name):
|
||||
return name
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, %s" % (self.new, name)
|
||||
|
||||
class OpaqueByRefType(OpaqueType):
|
||||
"""An opaque object type, passed by reference.
|
||||
|
||||
Instantiate with the type name, and optionally an object type name whose
|
||||
New/Convert functions will be used.
|
||||
"""
|
||||
|
||||
def passInput(self, name):
|
||||
return name
|
||||
|
||||
# def passOutput(self, name):
|
||||
# return name
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "O"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s(%s)" % (self.new, name)
|
||||
|
||||
class OpaqueByValueStructType(OpaqueByValueType):
|
||||
"""Similar to OpaqueByValueType, but we also pass this to mkvalue by
|
||||
address, in stead of by value.
|
||||
"""
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, &%s" % (self.new, name)
|
||||
|
||||
|
||||
class OpaqueArrayType(OpaqueByValueType):
|
||||
|
||||
"""A type represented by an opaque object type, with ARRAY passing semantics.
|
||||
|
||||
Instantiate with the type name, and optional an object type name whose
|
||||
New/Convert functions will be used.
|
||||
"""
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "%s, %s" % (self.convert, name)
|
||||
|
||||
def passOutput(self, name):
|
||||
return name
|
||||
112
project/jni/python/src/Tools/bgen/bgen/bgenVariable.py
Normal file
112
project/jni/python/src/Tools/bgen/bgen/bgenVariable.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""Variables, arguments and argument transfer modes etc."""
|
||||
|
||||
|
||||
# Values to represent argument transfer modes
|
||||
InMode = 1 # input-only argument
|
||||
OutMode = 2 # output-only argument
|
||||
InOutMode = 3 # input-output argument
|
||||
ModeMask = 3 # bits to keep for mode
|
||||
|
||||
|
||||
# Special cases for mode/flags argument
|
||||
# XXX This is still a mess!
|
||||
SelfMode = 4+InMode # this is 'self' -- don't declare it
|
||||
ReturnMode = 8+OutMode # this is the function return value
|
||||
ErrorMode = 16+OutMode # this is an error status -- turn it into an exception
|
||||
RefMode = 32
|
||||
ConstMode = 64
|
||||
|
||||
class Variable:
|
||||
|
||||
"""A Variable holds a type, a name, a transfer mode and flags.
|
||||
|
||||
Most of its methods call the correponding type method with the
|
||||
variable name.
|
||||
"""
|
||||
|
||||
def __init__(self, type, name = None, flags = InMode):
|
||||
"""Call with a type, a name and flags.
|
||||
|
||||
If name is None, it muse be set later.
|
||||
flags defaults to InMode.
|
||||
"""
|
||||
self.type = type
|
||||
self.name = name
|
||||
self.flags = flags
|
||||
self.mode = flags & ModeMask
|
||||
|
||||
def declare(self):
|
||||
"""Declare the variable if necessary.
|
||||
|
||||
If it is "self", it is not declared.
|
||||
"""
|
||||
if self.flags == ReturnMode+RefMode:
|
||||
self.type.declare(self.name, reference=True)
|
||||
elif self.flags != SelfMode:
|
||||
self.type.declare(self.name)
|
||||
|
||||
def getArgDeclarations(self, fullmodes=False):
|
||||
refmode = (self.flags & RefMode)
|
||||
constmode = False
|
||||
outmode = False
|
||||
if fullmodes:
|
||||
constmode = (self.flags & ConstMode)
|
||||
outmode = (self.flags & OutMode)
|
||||
return self.type.getArgDeclarations(self.name,
|
||||
reference=refmode, constmode=constmode, outmode=outmode)
|
||||
|
||||
def getAuxDeclarations(self):
|
||||
return self.type.getAuxDeclarations(self.name)
|
||||
|
||||
def getargsFormat(self):
|
||||
"""Call the type's getargsFormatmethod."""
|
||||
return self.type.getargsFormat()
|
||||
|
||||
def getargsArgs(self):
|
||||
"""Call the type's getargsArgsmethod."""
|
||||
return self.type.getargsArgs(self.name)
|
||||
|
||||
def getargsCheck(self):
|
||||
return self.type.getargsCheck(self.name)
|
||||
|
||||
def getargsPreCheck(self):
|
||||
return self.type.getargsPreCheck(self.name)
|
||||
|
||||
def passArgument(self):
|
||||
"""Return the string required to pass the variable as argument.
|
||||
|
||||
For "in" arguments, return the variable name.
|
||||
For "out" and "in out" arguments,
|
||||
return its name prefixed with "&".
|
||||
"""
|
||||
if self.mode == InMode:
|
||||
return self.type.passInput(self.name)
|
||||
if self.mode & RefMode:
|
||||
return self.type.passReference(self.name)
|
||||
if self.mode in (OutMode, InOutMode):
|
||||
return self.type.passOutput(self.name)
|
||||
# XXX Shouldn't get here
|
||||
return "/*mode?*/" + self.type.passInput(self.name)
|
||||
|
||||
def errorCheck(self):
|
||||
"""Check for an error if necessary.
|
||||
|
||||
This only generates code if the variable's mode is ErrorMode.
|
||||
"""
|
||||
if self.flags == ErrorMode:
|
||||
self.type.errorCheck(self.name)
|
||||
|
||||
def mkvalueFormat (self):
|
||||
"""Call the type's mkvalueFormat method."""
|
||||
return self.type.mkvalueFormat()
|
||||
|
||||
def mkvalueArgs(self):
|
||||
"""Call the type's mkvalueArgs method."""
|
||||
return self.type.mkvalueArgs(self.name)
|
||||
|
||||
def mkvaluePreCheck(self):
|
||||
return self.type.mkvaluePreCheck(self.name)
|
||||
|
||||
def cleanup(self):
|
||||
"""Call the type's cleanup method."""
|
||||
return self.type.cleanup(self.name)
|
||||
197
project/jni/python/src/Tools/bgen/bgen/macsupport.py
Normal file
197
project/jni/python/src/Tools/bgen/bgen/macsupport.py
Normal file
@@ -0,0 +1,197 @@
|
||||
"""\
|
||||
Augment the "bgen" package with definitions that are useful on the Apple Macintosh.
|
||||
|
||||
Intended usage is "from macsupport import *" -- this implies all bgen's goodies.
|
||||
"""
|
||||
|
||||
|
||||
# Import everything from bgen (for ourselves as well as for re-export)
|
||||
from bgen import *
|
||||
|
||||
|
||||
# Simple types
|
||||
Boolean = Type("Boolean", "b")
|
||||
SignedByte = Type("SignedByte", "b")
|
||||
Size = Type("Size", "l")
|
||||
Style = Type("Style", "b")
|
||||
StyleParameter = Type("StyleParameter", "h")
|
||||
CharParameter = Type("CharParameter", "h")
|
||||
TextEncoding = Type("TextEncoding", "l")
|
||||
ByteCount = Type("ByteCount", "l")
|
||||
Duration = Type("Duration", "l")
|
||||
ByteOffset = Type("ByteOffset", "l")
|
||||
OptionBits = Type("OptionBits", "l")
|
||||
ItemCount = Type("ItemCount", "l")
|
||||
PBVersion = Type("PBVersion", "l")
|
||||
ScriptCode = Type("ScriptCode", "h")
|
||||
LangCode = Type("LangCode", "h")
|
||||
RegionCode = Type("RegionCode", "h")
|
||||
|
||||
UInt8 = Type("UInt8", "b")
|
||||
SInt8 = Type("SInt8", "b")
|
||||
UInt16 = Type("UInt16", "H")
|
||||
SInt16 = Type("SInt16", "h")
|
||||
UInt32 = Type("UInt32", "l")
|
||||
SInt32 = Type("SInt32", "l")
|
||||
Float32 = Type("Float32", "f")
|
||||
|
||||
wide = OpaqueByValueType("wide", "PyMac_Buildwide", "PyMac_Getwide")
|
||||
wide_ptr = OpaqueType("wide", "PyMac_Buildwide", "PyMac_Getwide")
|
||||
|
||||
# Pascal strings
|
||||
ConstStr255Param = OpaqueArrayType("Str255", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||
Str255 = OpaqueArrayType("Str255", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||
StringPtr = OpaqueByValueType("StringPtr", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||
ConstStringPtr = StringPtr
|
||||
|
||||
# File System Specifications
|
||||
FSSpec_ptr = OpaqueType("FSSpec", "PyMac_BuildFSSpec", "PyMac_GetFSSpec")
|
||||
FSSpec = OpaqueByValueStructType("FSSpec", "PyMac_BuildFSSpec", "PyMac_GetFSSpec")
|
||||
FSRef_ptr = OpaqueType("FSRef", "PyMac_BuildFSRef", "PyMac_GetFSRef")
|
||||
FSRef = OpaqueByValueStructType("FSRef", "PyMac_BuildFSRef", "PyMac_GetFSRef")
|
||||
|
||||
# OSType and ResType: 4-byte character strings
|
||||
def OSTypeType(typename):
|
||||
return OpaqueByValueType(typename, "PyMac_BuildOSType", "PyMac_GetOSType")
|
||||
OSType = OSTypeType("OSType")
|
||||
ResType = OSTypeType("ResType")
|
||||
FourCharCode = OSTypeType("FourCharCode")
|
||||
|
||||
# Version numbers
|
||||
NumVersion = OpaqueByValueType("NumVersion", "PyMac_BuildNumVersion", "BUG")
|
||||
|
||||
# Handles (always resources in our case)
|
||||
Handle = OpaqueByValueType("Handle", "ResObj")
|
||||
MenuHandle = OpaqueByValueType("MenuHandle", "MenuObj")
|
||||
MenuRef = MenuHandle
|
||||
ControlHandle = OpaqueByValueType("ControlHandle", "CtlObj")
|
||||
ControlRef = ControlHandle
|
||||
|
||||
# Windows and Dialogs
|
||||
WindowPtr = OpaqueByValueType("WindowPtr", "WinObj")
|
||||
WindowRef = WindowPtr
|
||||
DialogPtr = OpaqueByValueType("DialogPtr", "DlgObj")
|
||||
DialogRef = DialogPtr
|
||||
ExistingWindowPtr = OpaqueByValueType("WindowPtr", "WinObj_WhichWindow", "BUG")
|
||||
ExistingDialogPtr = OpaqueByValueType("DialogPtr", "DlgObj_WhichDialog", "BUG")
|
||||
|
||||
# NULL pointer passed in as optional storage -- not present in Python version
|
||||
NullStorage = FakeType("(void *)0")
|
||||
|
||||
# More standard datatypes
|
||||
Fixed = OpaqueByValueType("Fixed", "PyMac_BuildFixed", "PyMac_GetFixed")
|
||||
|
||||
# Quickdraw data types
|
||||
Rect = Rect_ptr = OpaqueType("Rect", "PyMac_BuildRect", "PyMac_GetRect")
|
||||
Point = OpaqueByValueType("Point", "PyMac_BuildPoint", "PyMac_GetPoint")
|
||||
Point_ptr = OpaqueType("Point", "PyMac_BuildPoint", "PyMac_GetPoint")
|
||||
|
||||
# Event records
|
||||
EventRecord = OpaqueType("EventRecord", "PyMac_BuildEventRecord", "PyMac_GetEventRecord")
|
||||
EventRecord_ptr = EventRecord
|
||||
|
||||
# CoreFoundation datatypes
|
||||
CFTypeRef = OpaqueByValueType("CFTypeRef", "CFTypeRefObj")
|
||||
CFStringRef = OpaqueByValueType("CFStringRef", "CFStringRefObj")
|
||||
CFMutableStringRef = OpaqueByValueType("CFMutableStringRef", "CFMutableStringRefObj")
|
||||
CFArrayRef = OpaqueByValueType("CFArrayRef", "CFArrayRefObj")
|
||||
CFMutableArrayRef = OpaqueByValueType("CFMutableArrayRef", "CFMutableArrayRefObj")
|
||||
CFDictionaryRef = OpaqueByValueType("CFDictionaryRef", "CFDictionaryRefObj")
|
||||
CFMutableDictionaryRef = OpaqueByValueType("CFMutableDictionaryRef", "CFMutableDictionaryRefObj")
|
||||
CFURLRef = OpaqueByValueType("CFURLRef", "CFURLRefObj")
|
||||
OptionalCFURLRef = OpaqueByValueType("CFURLRef", "OptionalCFURLRefObj")
|
||||
|
||||
# OSErr is special because it is turned into an exception
|
||||
# (Could do this with less code using a variant of mkvalue("O&")?)
|
||||
class OSErrType(Type):
|
||||
def errorCheck(self, name):
|
||||
Output("if (%s != noErr) return PyMac_Error(%s);", name, name)
|
||||
self.used = 1
|
||||
OSErr = OSErrType("OSErr", 'h')
|
||||
OSStatus = OSErrType("OSStatus", 'l')
|
||||
|
||||
|
||||
# Various buffer types
|
||||
|
||||
InBuffer = VarInputBufferType('char', 'long', 'l') # (buf, len)
|
||||
UcharInBuffer = VarInputBufferType('unsigned char', 'long', 'l') # (buf, len)
|
||||
OptionalInBuffer = OptionalVarInputBufferType('char', 'long', 'l') # (buf, len)
|
||||
|
||||
InOutBuffer = HeapInputOutputBufferType('char', 'long', 'l') # (inbuf, outbuf, len)
|
||||
VarInOutBuffer = VarHeapInputOutputBufferType('char', 'long', 'l') # (inbuf, outbuf, &len)
|
||||
|
||||
OutBuffer = HeapOutputBufferType('char', 'long', 'l') # (buf, len)
|
||||
VarOutBuffer = VarHeapOutputBufferType('char', 'long', 'l') # (buf, &len)
|
||||
VarVarOutBuffer = VarVarHeapOutputBufferType('char', 'long', 'l') # (buf, len, &len)
|
||||
|
||||
# Unicode arguments sometimes have reversed len, buffer (don't understand why Apple did this...)
|
||||
class VarUnicodeInputBufferType(VarInputBufferType):
|
||||
|
||||
def getargsFormat(self):
|
||||
return "u#"
|
||||
|
||||
class VarUnicodeReverseInputBufferType(ReverseInputBufferMixin, VarUnicodeInputBufferType):
|
||||
pass
|
||||
|
||||
UnicodeInBuffer = VarUnicodeInputBufferType('UniChar', 'UniCharCount', 'l')
|
||||
UnicodeReverseInBuffer = VarUnicodeReverseInputBufferType('UniChar', 'UniCharCount', 'l')
|
||||
UniChar_ptr = InputOnlyType("UniCharPtr", "u")
|
||||
|
||||
|
||||
# Predefine various pieces of program text to be passed to Module() later:
|
||||
|
||||
# Stuff added immediately after the system include files
|
||||
includestuff = """
|
||||
#include "pymactoolbox.h"
|
||||
|
||||
/* Macro to test whether a weak-loaded CFM function exists */
|
||||
#define PyMac_PRECHECK(rtn) do { if ( &rtn == NULL ) {\\
|
||||
PyErr_SetString(PyExc_NotImplementedError, \\
|
||||
"Not available in this shared library/OS version"); \\
|
||||
return NULL; \\
|
||||
}} while(0)
|
||||
|
||||
"""
|
||||
|
||||
# Stuff added just before the module's init function
|
||||
finalstuff = """
|
||||
"""
|
||||
|
||||
# Stuff added inside the module's init function
|
||||
initstuff = """
|
||||
"""
|
||||
|
||||
|
||||
# Generator classes with a twist -- if the function returns OSErr,
|
||||
# its mode is manipulated so that it turns into an exception or disappears
|
||||
# (and its name is changed to _err, for documentation purposes).
|
||||
# This requires that the OSErr type (defined above) has a non-trivial
|
||||
# errorCheck method.
|
||||
class OSErrMixIn:
|
||||
"Mix-in class to treat OSErr/OSStatus return values special"
|
||||
def makereturnvar(self):
|
||||
if self.returntype.__class__ == OSErrType:
|
||||
return Variable(self.returntype, "_err", ErrorMode)
|
||||
else:
|
||||
return Variable(self.returntype, "_rv", OutMode)
|
||||
|
||||
class OSErrFunctionGenerator(OSErrMixIn, FunctionGenerator): pass
|
||||
class OSErrMethodGenerator(OSErrMixIn, MethodGenerator): pass
|
||||
|
||||
class WeakLinkMixIn:
|
||||
"Mix-in to test the function actually exists (!= NULL) before calling"
|
||||
|
||||
def precheck(self):
|
||||
Output('#ifndef %s', self.name)
|
||||
Output('PyMac_PRECHECK(%s);', self.name)
|
||||
Output('#endif')
|
||||
|
||||
class WeakLinkFunctionGenerator(WeakLinkMixIn, FunctionGenerator): pass
|
||||
class WeakLinkMethodGenerator(WeakLinkMixIn, MethodGenerator): pass
|
||||
class OSErrWeakLinkFunctionGenerator(OSErrMixIn, WeakLinkMixIn, FunctionGenerator): pass
|
||||
class OSErrWeakLinkMethodGenerator(OSErrMixIn, WeakLinkMixIn, MethodGenerator): pass
|
||||
|
||||
class MacModule(Module):
|
||||
"Subclass which gets the exception initializer from macglue.c"
|
||||
def exceptionInitializer(self):
|
||||
return "PyMac_GetOSErrException()"
|
||||
849
project/jni/python/src/Tools/bgen/bgen/scantools.py
Normal file
849
project/jni/python/src/Tools/bgen/bgen/scantools.py
Normal file
@@ -0,0 +1,849 @@
|
||||
"""\
|
||||
|
||||
Tools for scanning header files in search of function prototypes.
|
||||
|
||||
Often, the function prototypes in header files contain enough information
|
||||
to automatically generate (or reverse-engineer) interface specifications
|
||||
from them. The conventions used are very vendor specific, but once you've
|
||||
figured out what they are they are often a great help, and it sure beats
|
||||
manually entering the interface specifications. (These are needed to generate
|
||||
the glue used to access the functions from Python.)
|
||||
|
||||
In order to make this class useful, almost every component can be overridden.
|
||||
The defaults are (currently) tuned to scanning Apple Macintosh header files,
|
||||
although most Mac specific details are contained in header-specific subclasses.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
import fnmatch
|
||||
from types import *
|
||||
try:
|
||||
import MacOS
|
||||
except ImportError:
|
||||
MacOS = None
|
||||
|
||||
try:
|
||||
from bgenlocations import CREATOR, INCLUDEDIR
|
||||
except ImportError:
|
||||
CREATOR = None
|
||||
INCLUDEDIR = os.curdir
|
||||
|
||||
Error = "scantools.Error"
|
||||
|
||||
BEGINHTMLREPORT="""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
.unmatched { }
|
||||
.commentstripping { color: grey; text-decoration: line-through }
|
||||
.comment { text-decoration: line-through }
|
||||
.notcomment { color: black }
|
||||
.incomplete { color: maroon }
|
||||
.constant { color: green }
|
||||
.pyconstant { background-color: yellow }
|
||||
.blconstant { background-color: yellow; color: red }
|
||||
.declaration { color: blue }
|
||||
.pydeclaration { background-color: yellow }
|
||||
.type { font-style: italic }
|
||||
.name { font-weight: bold }
|
||||
.value { font-style: italic }
|
||||
.arglist { text-decoration: underline }
|
||||
.blacklisted { background-color: yellow; color: red }
|
||||
</style>
|
||||
<title>Bgen scan report</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bgen scan report</h1>
|
||||
<h2>Legend</h2>
|
||||
<p>This scan report is intended to help you debug the regular expressions
|
||||
used by the bgen scanner. It consists of the original ".h" header file(s)
|
||||
marked up to show you what the regular expressions in the bgen parser matched
|
||||
for each line. NOTE: comments in the original source files may or may not be
|
||||
shown.</p>
|
||||
<p>The typographic conventions of this file are as follows:</p>
|
||||
<dl>
|
||||
<dt>comment stripping</dt>
|
||||
<dd><pre><span class="commentstripping"><span class="notcomment">comment stripping is </span><span class="comment">/* marked up */</span><span class="notcomment"> and the line is repeated if needed</span></span></pre>
|
||||
<p>If anything here does not appear to happen correctly look at
|
||||
<tt>comment1_pat</tt> and <tt>comment2_pat</tt>.</p>
|
||||
</dd>
|
||||
<dt>constant definitions</dt>
|
||||
<dd><pre><span class="constant">#define <span class="name">name</span> <span class="value">value</span></pre>
|
||||
<p>Highlights name and value of the constant. Governed by <tt>sym_pat</tt>.</p>
|
||||
</dd>
|
||||
<dt>function declaration</dt>
|
||||
<dd><pre><span class="declaration"><span class="type">char *</span><span class="name">rindex</span><span class="arglist">(<span class="type">const char *</span><span class="name">s</span>, <span class="type">int </span><span class="name">c</span>)</span>;</span></pre>
|
||||
<p>Highlights type, name and argument list. <tt>type_pat</tt>,
|
||||
<tt>name_pat</tt> and <tt>args_pat</tt> are combined into <tt>whole_pat</tt>, which
|
||||
is what is used here.</p></dd>
|
||||
</dd>
|
||||
<dt>incomplete match for function declaration</dt>
|
||||
<dd><pre><span class="incomplete"><span class="type">char *</span>foo;</span></pre>
|
||||
<p>The beginning of this looked promising, but it did not match a function declaration.
|
||||
In other words, it matched <tt>head_pat</tt> but not <tt>whole_pat</tt>. If the next
|
||||
declaration has also been gobbled up you need to look at <tt>end_pat</tt>.</p>
|
||||
</dd>
|
||||
<dt>unrecognized input</dt>
|
||||
<dd><pre><span class="unmatched">#include "type.h"</span></pre>
|
||||
<p>If there are function declarations the scanner has missed (i.e. things
|
||||
are in this class but you want them to be declarations) you need to adapt
|
||||
<tt>head_pat</tt>.
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>Output</h2>
|
||||
<pre>
|
||||
<span class="unmatched">
|
||||
"""
|
||||
ENDHTMLREPORT="""</span>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
class Scanner:
|
||||
|
||||
# Set to 1 in subclass to debug your scanner patterns.
|
||||
debug = 0
|
||||
|
||||
def __init__(self, input = None, output = None, defsoutput = None):
|
||||
self.initsilent()
|
||||
self.initblacklists()
|
||||
self.initrepairinstructions()
|
||||
self.initpaths()
|
||||
self.initfiles()
|
||||
self.initpatterns()
|
||||
self.compilepatterns()
|
||||
self.initosspecifics()
|
||||
self.initusedtypes()
|
||||
if output:
|
||||
self.setoutput(output, defsoutput)
|
||||
if input:
|
||||
self.setinput(input)
|
||||
|
||||
def initusedtypes(self):
|
||||
self.usedtypes = {}
|
||||
|
||||
def typeused(self, type, mode):
|
||||
if not self.usedtypes.has_key(type):
|
||||
self.usedtypes[type] = {}
|
||||
self.usedtypes[type][mode] = None
|
||||
|
||||
def reportusedtypes(self):
|
||||
types = self.usedtypes.keys()
|
||||
types.sort()
|
||||
for type in types:
|
||||
modes = self.usedtypes[type].keys()
|
||||
modes.sort()
|
||||
self.report("%s %s", type, " ".join(modes))
|
||||
|
||||
def gentypetest(self, file):
|
||||
fp = open(file, "w")
|
||||
fp.write("types=[\n")
|
||||
types = self.usedtypes.keys()
|
||||
types.sort()
|
||||
for type in types:
|
||||
fp.write("\t'%s',\n"%type)
|
||||
fp.write("]\n")
|
||||
fp.write("""missing=0
|
||||
for t in types:
|
||||
try:
|
||||
tt = eval(t)
|
||||
except NameError:
|
||||
print "** Missing type:", t
|
||||
missing = 1
|
||||
if missing: raise "Missing Types"
|
||||
""")
|
||||
fp.close()
|
||||
|
||||
def initsilent(self):
|
||||
self.silent = 1
|
||||
|
||||
def error(self, format, *args):
|
||||
if self.silent >= 0:
|
||||
print format%args
|
||||
|
||||
def report(self, format, *args):
|
||||
if not self.silent:
|
||||
print format%args
|
||||
|
||||
def writeinitialdefs(self):
|
||||
pass
|
||||
|
||||
def initblacklists(self):
|
||||
self.blacklistnames = self.makeblacklistnames()
|
||||
self.blacklisttypes = ["unknown", "-"] + self.makeblacklisttypes()
|
||||
self.greydictnames = self.greylist2dict(self.makegreylist())
|
||||
|
||||
def greylist2dict(self, list):
|
||||
rv = {}
|
||||
for define, namelist in list:
|
||||
for name in namelist:
|
||||
rv[name] = define
|
||||
return rv
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return []
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return []
|
||||
|
||||
def makegreylist(self):
|
||||
return []
|
||||
|
||||
def initrepairinstructions(self):
|
||||
self.repairinstructions = self.makerepairinstructions()
|
||||
self.inherentpointertypes = self.makeinherentpointertypes()
|
||||
|
||||
def makerepairinstructions(self):
|
||||
"""Parse the repair file into repair instructions.
|
||||
|
||||
The file format is simple:
|
||||
1) use \ to split a long logical line in multiple physical lines
|
||||
2) everything after the first # on a line is ignored (as comment)
|
||||
3) empty lines are ignored
|
||||
4) remaining lines must have exactly 3 colon-separated fields:
|
||||
functionpattern : argumentspattern : argumentsreplacement
|
||||
5) all patterns use shell style pattern matching
|
||||
6) an empty functionpattern means the same as *
|
||||
7) the other two fields are each comma-separated lists of triples
|
||||
8) a triple is a space-separated list of 1-3 words
|
||||
9) a triple with less than 3 words is padded at the end with "*" words
|
||||
10) when used as a pattern, a triple matches the type, name, and mode
|
||||
of an argument, respectively
|
||||
11) when used as a replacement, the words of a triple specify
|
||||
replacements for the corresponding words of the argument,
|
||||
with "*" as a word by itself meaning leave the original word
|
||||
(no other uses of "*" is allowed)
|
||||
12) the replacement need not have the same number of triples
|
||||
as the pattern
|
||||
"""
|
||||
f = self.openrepairfile()
|
||||
if not f: return []
|
||||
print "Reading repair file", repr(f.name), "..."
|
||||
list = []
|
||||
lineno = 0
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
lineno = lineno + 1
|
||||
startlineno = lineno
|
||||
while line[-2:] == '\\\n':
|
||||
line = line[:-2] + ' ' + f.readline()
|
||||
lineno = lineno + 1
|
||||
i = line.find('#')
|
||||
if i >= 0: line = line[:i]
|
||||
words = [s.strip() for s in line.split(':')]
|
||||
if words == ['']: continue
|
||||
if len(words) <> 3:
|
||||
print "Line", startlineno,
|
||||
print ": bad line (not 3 colon-separated fields)"
|
||||
print repr(line)
|
||||
continue
|
||||
[fpat, pat, rep] = words
|
||||
if not fpat: fpat = "*"
|
||||
if not pat:
|
||||
print "Line", startlineno,
|
||||
print "Empty pattern"
|
||||
print repr(line)
|
||||
continue
|
||||
patparts = [s.strip() for s in pat.split(',')]
|
||||
repparts = [s.strip() for s in rep.split(',')]
|
||||
patterns = []
|
||||
for p in patparts:
|
||||
if not p:
|
||||
print "Line", startlineno,
|
||||
print "Empty pattern part"
|
||||
print repr(line)
|
||||
continue
|
||||
pattern = p.split()
|
||||
if len(pattern) > 3:
|
||||
print "Line", startlineno,
|
||||
print "Pattern part has > 3 words"
|
||||
print repr(line)
|
||||
pattern = pattern[:3]
|
||||
else:
|
||||
while len(pattern) < 3:
|
||||
pattern.append("*")
|
||||
patterns.append(pattern)
|
||||
replacements = []
|
||||
for p in repparts:
|
||||
if not p:
|
||||
print "Line", startlineno,
|
||||
print "Empty replacement part"
|
||||
print repr(line)
|
||||
continue
|
||||
replacement = p.split()
|
||||
if len(replacement) > 3:
|
||||
print "Line", startlineno,
|
||||
print "Pattern part has > 3 words"
|
||||
print repr(line)
|
||||
replacement = replacement[:3]
|
||||
else:
|
||||
while len(replacement) < 3:
|
||||
replacement.append("*")
|
||||
replacements.append(replacement)
|
||||
list.append((fpat, patterns, replacements))
|
||||
return list
|
||||
|
||||
def makeinherentpointertypes(self):
|
||||
return []
|
||||
|
||||
def openrepairfile(self, filename = "REPAIR"):
|
||||
try:
|
||||
return open(filename, "rU")
|
||||
except IOError, msg:
|
||||
print repr(filename), ":", msg
|
||||
print "Cannot open repair file -- assume no repair needed"
|
||||
return None
|
||||
|
||||
def initfiles(self):
|
||||
self.specmine = 0
|
||||
self.defsmine = 0
|
||||
self.scanmine = 0
|
||||
self.htmlmine = 0
|
||||
self.specfile = sys.stdout
|
||||
self.defsfile = None
|
||||
self.scanfile = sys.stdin
|
||||
self.htmlfile = None
|
||||
self.lineno = 0
|
||||
self.line = ""
|
||||
|
||||
def initpaths(self):
|
||||
self.includepath = [os.curdir, INCLUDEDIR]
|
||||
|
||||
def initpatterns(self):
|
||||
self.head_pat = r"^EXTERN_API[^_]"
|
||||
self.tail_pat = r"[;={}]"
|
||||
self.type_pat = r"EXTERN_API" + \
|
||||
r"[ \t\n]*\([ \t\n]*" + \
|
||||
r"(?P<type>[a-zA-Z0-9_* \t]*[a-zA-Z0-9_*])" + \
|
||||
r"[ \t\n]*\)[ \t\n]*"
|
||||
self.name_pat = r"(?P<name>[a-zA-Z0-9_]+)[ \t\n]*"
|
||||
self.args_pat = r"\((?P<args>([^\(;=\)]+|\([^\(;=\)]*\))*)\)"
|
||||
self.whole_pat = self.type_pat + self.name_pat + self.args_pat
|
||||
self.sym_pat = r"^[ \t]*(?P<name>[a-zA-Z0-9_]+)[ \t]*=" + \
|
||||
r"[ \t]*(?P<defn>[-0-9_a-zA-Z'\"\(][^\t\n,;}]*),?"
|
||||
self.asplit_pat = r"^(?P<type>.*[^a-zA-Z0-9_])(?P<name>[a-zA-Z0-9_]+)(?P<array>\[\])?$"
|
||||
self.comment1_pat = r"(?P<rest>.*)//.*"
|
||||
# note that the next pattern only removes comments that are wholly within one line
|
||||
self.comment2_pat = r"(?P<rest1>.*)/\*.*\*/(?P<rest2>.*)"
|
||||
|
||||
def compilepatterns(self):
|
||||
for name in dir(self):
|
||||
if name[-4:] == "_pat":
|
||||
pat = getattr(self, name)
|
||||
prog = re.compile(pat)
|
||||
setattr(self, name[:-4], prog)
|
||||
|
||||
def initosspecifics(self):
|
||||
if MacOS and CREATOR:
|
||||
self.filetype = 'TEXT'
|
||||
self.filecreator = CREATOR
|
||||
else:
|
||||
self.filetype = self.filecreator = None
|
||||
|
||||
def setfiletype(self, filename):
|
||||
if MacOS and (self.filecreator or self.filetype):
|
||||
creator, type = MacOS.GetCreatorAndType(filename)
|
||||
if self.filecreator: creator = self.filecreator
|
||||
if self.filetype: type = self.filetype
|
||||
MacOS.SetCreatorAndType(filename, creator, type)
|
||||
|
||||
def close(self):
|
||||
self.closefiles()
|
||||
|
||||
def closefiles(self):
|
||||
self.closespec()
|
||||
self.closedefs()
|
||||
self.closescan()
|
||||
self.closehtml()
|
||||
|
||||
def closespec(self):
|
||||
tmp = self.specmine and self.specfile
|
||||
self.specfile = None
|
||||
if tmp: tmp.close()
|
||||
|
||||
def closedefs(self):
|
||||
tmp = self.defsmine and self.defsfile
|
||||
self.defsfile = None
|
||||
if tmp: tmp.close()
|
||||
|
||||
def closescan(self):
|
||||
tmp = self.scanmine and self.scanfile
|
||||
self.scanfile = None
|
||||
if tmp: tmp.close()
|
||||
|
||||
def closehtml(self):
|
||||
if self.htmlfile: self.htmlfile.write(ENDHTMLREPORT)
|
||||
tmp = self.htmlmine and self.htmlfile
|
||||
self.htmlfile = None
|
||||
if tmp: tmp.close()
|
||||
|
||||
def setoutput(self, spec, defs = None):
|
||||
self.closespec()
|
||||
self.closedefs()
|
||||
if spec:
|
||||
if type(spec) == StringType:
|
||||
file = self.openoutput(spec)
|
||||
mine = 1
|
||||
else:
|
||||
file = spec
|
||||
mine = 0
|
||||
self.specfile = file
|
||||
self.specmine = mine
|
||||
if defs:
|
||||
if type(defs) == StringType:
|
||||
file = self.openoutput(defs)
|
||||
mine = 1
|
||||
else:
|
||||
file = defs
|
||||
mine = 0
|
||||
self.defsfile = file
|
||||
self.defsmine = mine
|
||||
|
||||
def sethtmloutput(self, htmlfile):
|
||||
self.closehtml()
|
||||
if htmlfile:
|
||||
if type(htmlfile) == StringType:
|
||||
file = self.openoutput(htmlfile)
|
||||
mine = 1
|
||||
else:
|
||||
file = htmlfile
|
||||
mine = 0
|
||||
self.htmlfile = file
|
||||
self.htmlmine = mine
|
||||
self.htmlfile.write(BEGINHTMLREPORT)
|
||||
|
||||
def openoutput(self, filename):
|
||||
try:
|
||||
file = open(filename, 'w')
|
||||
except IOError, arg:
|
||||
raise IOError, (filename, arg)
|
||||
self.setfiletype(filename)
|
||||
return file
|
||||
|
||||
def setinput(self, scan = sys.stdin):
|
||||
if not type(scan) in (TupleType, ListType):
|
||||
scan = [scan]
|
||||
self.allscaninputs = scan
|
||||
self._nextinput()
|
||||
|
||||
def _nextinput(self):
|
||||
if not self.allscaninputs:
|
||||
return 0
|
||||
scan = self.allscaninputs[0]
|
||||
self.allscaninputs = self.allscaninputs[1:]
|
||||
self.closescan()
|
||||
if scan:
|
||||
if type(scan) == StringType:
|
||||
file = self.openinput(scan)
|
||||
mine = 1
|
||||
else:
|
||||
file = scan
|
||||
mine = 0
|
||||
self.scanfile = file
|
||||
self.scanmine = mine
|
||||
self.lineno = 0
|
||||
return 1
|
||||
|
||||
def openinput(self, filename):
|
||||
if not os.path.isabs(filename):
|
||||
for dir in self.includepath:
|
||||
fullname = os.path.join(dir, filename)
|
||||
#self.report("trying full name %r", fullname)
|
||||
try:
|
||||
return open(fullname, 'rU')
|
||||
except IOError:
|
||||
pass
|
||||
# If not on the path, or absolute, try default open()
|
||||
try:
|
||||
return open(filename, 'rU')
|
||||
except IOError, arg:
|
||||
raise IOError, (arg, filename)
|
||||
|
||||
def getline(self):
|
||||
if not self.scanfile:
|
||||
raise Error, "input file not set"
|
||||
self.line = self.scanfile.readline()
|
||||
if not self.line:
|
||||
if self._nextinput():
|
||||
return self.getline()
|
||||
raise EOFError
|
||||
self.lineno = self.lineno + 1
|
||||
return self.line
|
||||
|
||||
def scan(self):
|
||||
if not self.scanfile:
|
||||
self.error("No input file has been specified")
|
||||
return
|
||||
inputname = self.scanfile.name
|
||||
self.report("scanfile = %r", inputname)
|
||||
if not self.specfile:
|
||||
self.report("(No interface specifications will be written)")
|
||||
else:
|
||||
self.report("specfile = %r", self.specfile.name)
|
||||
self.specfile.write("# Generated from %r\n\n" % (inputname,))
|
||||
if not self.defsfile:
|
||||
self.report("(No symbol definitions will be written)")
|
||||
else:
|
||||
self.report("defsfile = %r", (self.defsfile.name,))
|
||||
self.defsfile.write("# Generated from %r\n\n" % (os.path.split(inputname)[1],))
|
||||
self.writeinitialdefs()
|
||||
self.alreadydone = []
|
||||
try:
|
||||
while 1:
|
||||
try: line = self.getline()
|
||||
except EOFError: break
|
||||
if self.debug:
|
||||
self.report("LINE: %r" % (line,))
|
||||
match = self.comment1.match(line)
|
||||
if match:
|
||||
self.htmlreport(line, klass='commentstripping', ranges=[(
|
||||
match.start('rest'), match.end('rest'), 'notcomment')])
|
||||
line = match.group('rest')
|
||||
if self.debug:
|
||||
self.report("\tafter comment1: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
while match:
|
||||
if match:
|
||||
self.htmlreport(line, klass='commentstripping', ranges=[
|
||||
(match.start('rest1'), match.end('rest1'), 'notcomment'),
|
||||
(match.start('rest2'), match.end('rest2'), 'notcomment')])
|
||||
line = match.group('rest1')+match.group('rest2')
|
||||
if self.debug:
|
||||
self.report("\tafter comment2: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
if self.defsfile:
|
||||
match = self.sym.match(line)
|
||||
if match:
|
||||
if self.debug:
|
||||
self.report("\tmatches sym.")
|
||||
self.dosymdef(match, line)
|
||||
continue
|
||||
match = self.head.match(line)
|
||||
if match:
|
||||
if self.debug:
|
||||
self.report("\tmatches head.")
|
||||
self.dofuncspec()
|
||||
continue
|
||||
self.htmlreport(line, klass='unmatched')
|
||||
except EOFError:
|
||||
self.error("Uncaught EOF error")
|
||||
self.reportusedtypes()
|
||||
|
||||
def dosymdef(self, match, line):
|
||||
name, defn = match.group('name', 'defn')
|
||||
self.htmlreport(line, klass='constant', ranges=[
|
||||
(match.start('name'), match.end('name'), 'name'),
|
||||
(match.start('defn'), match.end('defn'), 'value')])
|
||||
defn = escape8bit(defn)
|
||||
if self.debug:
|
||||
self.report("\tsym: name=%r, defn=%r" % (name, defn))
|
||||
if not name in self.blacklistnames:
|
||||
oline = "%s = %s\n" % (name, defn)
|
||||
self.defsfile.write(oline)
|
||||
self.htmlreport(oline, klass="pyconstant")
|
||||
else:
|
||||
self.defsfile.write("# %s = %s\n" % (name, defn))
|
||||
self.htmlreport("** no output: name is blacklisted", klass="blconstant")
|
||||
# XXXX No way to handle greylisted names
|
||||
|
||||
def dofuncspec(self):
|
||||
raw = self.line
|
||||
while not self.tail.search(raw):
|
||||
line = self.getline()
|
||||
if self.debug:
|
||||
self.report("* CONTINUATION LINE: %r" % (line,))
|
||||
match = self.comment1.match(line)
|
||||
if match:
|
||||
line = match.group('rest')
|
||||
if self.debug:
|
||||
self.report("\tafter comment1: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
while match:
|
||||
line = match.group('rest1')+match.group('rest2')
|
||||
if self.debug:
|
||||
self.report("\tafter comment1: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
raw = raw + line
|
||||
if self.debug:
|
||||
self.report("* WHOLE LINE: %r" % (raw,))
|
||||
self.processrawspec(raw)
|
||||
return raw
|
||||
|
||||
def processrawspec(self, raw):
|
||||
match = self.whole.search(raw)
|
||||
if not match:
|
||||
self.report("Bad raw spec: %r", raw)
|
||||
if self.debug:
|
||||
match = self.type.search(raw)
|
||||
if not match:
|
||||
self.report("(Type already doesn't match)")
|
||||
self.htmlreport(raw, klass='incomplete', ranges=[(
|
||||
match.start('type'), match.end('type'), 'type')])
|
||||
else:
|
||||
self.report("(but type matched)")
|
||||
self.htmlreport(raw, klass='incomplete')
|
||||
return
|
||||
type, name, args = match.group('type', 'name', 'args')
|
||||
ranges=[
|
||||
(match.start('type'), match.end('type'), 'type'),
|
||||
(match.start('name'), match.end('name'), 'name'),
|
||||
(match.start('args'), match.end('args'), 'arglist')]
|
||||
self.htmlreport(raw, klass='declaration', ranges=ranges)
|
||||
modifiers = self.getmodifiers(match)
|
||||
type = self.pythonizename(type)
|
||||
name = self.pythonizename(name)
|
||||
if self.checkduplicate(name):
|
||||
self.htmlreport("*** no output generated: duplicate name", klass="blacklisted")
|
||||
return
|
||||
self.report("==> %s %s <==", type, name)
|
||||
if self.blacklisted(type, name):
|
||||
self.htmlreport("*** no output generated: function name or return type blacklisted", klass="blacklisted")
|
||||
self.report("*** %s %s blacklisted", type, name)
|
||||
return
|
||||
returnlist = [(type, name, 'ReturnMode')]
|
||||
returnlist = self.repairarglist(name, returnlist)
|
||||
[(type, name, returnmode)] = returnlist
|
||||
arglist = self.extractarglist(args)
|
||||
arglist = self.repairarglist(name, arglist)
|
||||
if self.unmanageable(type, name, arglist):
|
||||
self.htmlreport("*** no output generated: some argument blacklisted", klass="blacklisted")
|
||||
##for arg in arglist:
|
||||
## self.report(" %r", arg)
|
||||
self.report("*** %s %s unmanageable", type, name)
|
||||
return
|
||||
if modifiers:
|
||||
self.generate(type, name, arglist, modifiers)
|
||||
else:
|
||||
self.generate(type, name, arglist)
|
||||
|
||||
def getmodifiers(self, match):
|
||||
return []
|
||||
|
||||
def checkduplicate(self, name):
|
||||
if name in self.alreadydone:
|
||||
self.report("Name has already been defined: %r", name)
|
||||
return True
|
||||
self.alreadydone.append(name)
|
||||
return False
|
||||
|
||||
def pythonizename(self, name):
|
||||
name = re.sub("\*", " ptr", name)
|
||||
name = name.strip()
|
||||
name = re.sub("[ \t]+", "_", name)
|
||||
return name
|
||||
|
||||
def extractarglist(self, args):
|
||||
args = args.strip()
|
||||
if not args or args == "void":
|
||||
return []
|
||||
parts = [s.strip() for s in args.split(",")]
|
||||
arglist = []
|
||||
for part in parts:
|
||||
arg = self.extractarg(part)
|
||||
arglist.append(arg)
|
||||
return arglist
|
||||
|
||||
def extractarg(self, part):
|
||||
mode = "InMode"
|
||||
part = part.strip()
|
||||
match = self.asplit.match(part)
|
||||
if not match:
|
||||
self.error("Indecipherable argument: %r", part)
|
||||
return ("unknown", part, mode)
|
||||
type, name, array = match.group('type', 'name', 'array')
|
||||
if array:
|
||||
# array matches an optional [] after the argument name
|
||||
type = type + " ptr "
|
||||
type = self.pythonizename(type)
|
||||
return self.modifyarg(type, name, mode)
|
||||
|
||||
def modifyarg(self, type, name, mode):
|
||||
if type[:6] == "const_":
|
||||
type = type[6:]
|
||||
elif type[-4:] == "_ptr":
|
||||
type = type[:-4]
|
||||
mode = "OutMode"
|
||||
elif type in self.inherentpointertypes:
|
||||
mode = "OutMode"
|
||||
if type[-4:] == "_far":
|
||||
type = type[:-4]
|
||||
return type, name, mode
|
||||
|
||||
def repairarglist(self, functionname, arglist):
|
||||
arglist = arglist[:]
|
||||
i = 0
|
||||
while i < len(arglist):
|
||||
for item in self.repairinstructions:
|
||||
if len(item) == 2:
|
||||
pattern, replacement = item
|
||||
functionpat = "*"
|
||||
else:
|
||||
functionpat, pattern, replacement = item
|
||||
if not fnmatch.fnmatchcase(functionname, functionpat):
|
||||
continue
|
||||
n = len(pattern)
|
||||
if i+n > len(arglist): continue
|
||||
current = arglist[i:i+n]
|
||||
for j in range(n):
|
||||
if not self.matcharg(pattern[j], current[j]):
|
||||
break
|
||||
else: # All items of the pattern match
|
||||
new = self.substituteargs(
|
||||
pattern, replacement, current)
|
||||
if new is not None:
|
||||
arglist[i:i+n] = new
|
||||
i = i+len(new) # No recursive substitutions
|
||||
break
|
||||
else: # No patterns match
|
||||
i = i+1
|
||||
return arglist
|
||||
|
||||
def matcharg(self, patarg, arg):
|
||||
return len(filter(None, map(fnmatch.fnmatchcase, arg, patarg))) == 3
|
||||
|
||||
def substituteargs(self, pattern, replacement, old):
|
||||
new = []
|
||||
for k in range(len(replacement)):
|
||||
item = replacement[k]
|
||||
newitem = [item[0], item[1], item[2]]
|
||||
for i in range(3):
|
||||
if item[i] == '*':
|
||||
newitem[i] = old[k][i]
|
||||
elif item[i][:1] == '$':
|
||||
index = int(item[i][1:]) - 1
|
||||
newitem[i] = old[index][i]
|
||||
new.append(tuple(newitem))
|
||||
##self.report("old: %r", old)
|
||||
##self.report("new: %r", new)
|
||||
return new
|
||||
|
||||
def generate(self, tp, name, arglist, modifiers=[]):
|
||||
|
||||
self.typeused(tp, 'return')
|
||||
if modifiers:
|
||||
classname, listname = self.destination(tp, name, arglist, modifiers)
|
||||
else:
|
||||
classname, listname = self.destination(tp, name, arglist)
|
||||
if not classname or not listname:
|
||||
self.htmlreport("*** no output generated: self.destination() returned None", klass="blacklisted")
|
||||
return
|
||||
if not self.specfile:
|
||||
self.htmlreport("*** no output generated: no output file specified", klass="blacklisted")
|
||||
return
|
||||
self.specfile.write("f = %s(%s, %r,\n" % (classname, tp, name))
|
||||
for atype, aname, amode in arglist:
|
||||
self.typeused(atype, amode)
|
||||
self.specfile.write(" (%s, %r, %s),\n" %
|
||||
(atype, aname, amode))
|
||||
if self.greydictnames.has_key(name):
|
||||
self.specfile.write(" condition=%r,\n"%(self.greydictnames[name],))
|
||||
self.generatemodifiers(classname, name, modifiers)
|
||||
self.specfile.write(")\n")
|
||||
self.specfile.write("%s.append(f)\n\n" % listname)
|
||||
if self.htmlfile:
|
||||
oline = "Adding to %s:\n%s(returntype=%s, name=%r" % (listname, classname, tp, name)
|
||||
for atype, aname, amode in arglist:
|
||||
oline += ",\n (%s, %r, %s)" % (atype, aname, amode)
|
||||
oline += ")\n"
|
||||
self.htmlreport(oline, klass="pydeclaration")
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
return "FunctionGenerator", "functions"
|
||||
|
||||
def generatemodifiers(self, classname, name, modifiers):
|
||||
pass
|
||||
|
||||
def blacklisted(self, type, name):
|
||||
if type in self.blacklisttypes:
|
||||
##self.report("return type %s is blacklisted", type)
|
||||
return 1
|
||||
if name in self.blacklistnames:
|
||||
##self.report("function name %s is blacklisted", name)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def unmanageable(self, type, name, arglist):
|
||||
for atype, aname, amode in arglist:
|
||||
if atype in self.blacklisttypes:
|
||||
self.report("argument type %s is blacklisted", atype)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def htmlreport(self, line, klass=None, ranges=None):
|
||||
if not self.htmlfile: return
|
||||
if ranges is None:
|
||||
ranges = []
|
||||
if klass:
|
||||
ranges.insert(0, (0, len(line), klass))
|
||||
oline = ''
|
||||
i = 0
|
||||
for c in line:
|
||||
for b, e, name in ranges:
|
||||
if b == i:
|
||||
oline += '<span class="%s">' % name
|
||||
if e == i:
|
||||
oline += '</span>'
|
||||
i += 1
|
||||
|
||||
if c == '<': oline += '<'
|
||||
elif c == '>': oline += '>'
|
||||
else: oline += c
|
||||
for b, e, name in ranges:
|
||||
if b >= i:
|
||||
oline += '<span class="%s">' % name
|
||||
if e >= i:
|
||||
oline += '</span>'
|
||||
if not line or line[-1] != '\n':
|
||||
oline += '\n'
|
||||
self.htmlfile.write(oline)
|
||||
|
||||
class Scanner_PreUH3(Scanner):
|
||||
"""Scanner for Universal Headers before release 3"""
|
||||
def initpatterns(self):
|
||||
Scanner.initpatterns(self)
|
||||
self.head_pat = "^extern pascal[ \t]+" # XXX Mac specific!
|
||||
self.type_pat = "pascal[ \t\n]+(?P<type>[a-zA-Z0-9_ \t]*[a-zA-Z0-9_])[ \t\n]+"
|
||||
self.whole_pat = self.type_pat + self.name_pat + self.args_pat
|
||||
self.sym_pat = "^[ \t]*(?P<name>[a-zA-Z0-9_]+)[ \t]*=" + \
|
||||
"[ \t]*(?P<defn>[-0-9'\"][^\t\n,;}]*),?"
|
||||
|
||||
class Scanner_OSX(Scanner):
|
||||
"""Scanner for modern (post UH3.3) Universal Headers """
|
||||
def initpatterns(self):
|
||||
Scanner.initpatterns(self)
|
||||
self.head_pat = "^EXTERN_API(_C)?"
|
||||
self.type_pat = "EXTERN_API(_C)?" + \
|
||||
"[ \t\n]*\([ \t\n]*" + \
|
||||
"(?P<type>[a-zA-Z0-9_* \t]*[a-zA-Z0-9_*])" + \
|
||||
"[ \t\n]*\)[ \t\n]*"
|
||||
self.whole_pat = self.type_pat + self.name_pat + self.args_pat
|
||||
self.sym_pat = "^[ \t]*(?P<name>[a-zA-Z0-9_]+)[ \t]*=" + \
|
||||
"[ \t]*(?P<defn>[-0-9_a-zA-Z'\"\(][^\t\n,;}]*),?"
|
||||
|
||||
_8bit = re.compile(r"[\200-\377]")
|
||||
|
||||
def escape8bit(s):
|
||||
if _8bit.search(s) is not None:
|
||||
out = []
|
||||
for c in s:
|
||||
o = ord(c)
|
||||
if o >= 128:
|
||||
out.append("\\" + hex(o)[1:])
|
||||
else:
|
||||
out.append(c)
|
||||
s = "".join(out)
|
||||
return s
|
||||
|
||||
def test():
|
||||
input = "D:Development:THINK C:Mac #includes:Apple #includes:AppleEvents.h"
|
||||
output = "@aespecs.py"
|
||||
defsoutput = "@aedefs.py"
|
||||
s = Scanner(input, output, defsoutput)
|
||||
s.scan()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
36
project/jni/python/src/Tools/buildbot/README.tcltk-AMD64
Normal file
36
project/jni/python/src/Tools/buildbot/README.tcltk-AMD64
Normal file
@@ -0,0 +1,36 @@
|
||||
Comments on building tcl/tk for AMD64 with the MS SDK compiler
|
||||
==============================================================
|
||||
|
||||
I did have to build tcl/tk manually.
|
||||
|
||||
First, I had to build the nmakehlp.exe helper utility manually by executing
|
||||
cl nmakehlp.c /link bufferoverflowU.lib
|
||||
in both the tcl8.4.12\win and tk8.4.12\win directories.
|
||||
|
||||
Second, the AMD64 compiler refuses to compile the file
|
||||
tcl8.4.12\generic\tclExecute.c because it insists on using intrinsics
|
||||
for the 'ceil' and 'floor' functions:
|
||||
|
||||
..\generic\tclExecute.c(394) : error C2099: initializer is not a constant
|
||||
..\generic\tclExecute.c(398) : error C2099: initializer is not a constant
|
||||
|
||||
I did comment out these lines; an alternative would have been to use
|
||||
the /Oi- compiler flag to disable the intrinsic functions.
|
||||
The commands then used were these:
|
||||
|
||||
svn export http://svn.python.org/projects/external/tcl8.4.12
|
||||
cd tcl8.4.12\win
|
||||
REM
|
||||
echo patch the tcl8.4.12\generic\tclExecute.c file
|
||||
pause
|
||||
REM
|
||||
cl nmakehlp.c /link bufferoverflowU.lib
|
||||
nmake -f makefile.vc MACHINE=AMD64
|
||||
nmake -f makefile.vc INSTALLDIR=..\..\tcltk install
|
||||
cd ..\..
|
||||
svn export http://svn.python.org/projects/external/tk8.4.12
|
||||
cd tk8.4.12\win
|
||||
cl nmakehlp.c /link bufferoverflowU.lib
|
||||
nmake -f makefile.vc TCLDIR=..\..\tcl8.4.12 MACHINE=AMD64
|
||||
nmake -f makefile.vc TCLDIR=..\..\tcl8.4.12 INSTALLDIR=..\..\tcltk install
|
||||
cd ..\..
|
||||
6
project/jni/python/src/Tools/buildbot/build-amd64.bat
Normal file
6
project/jni/python/src/Tools/buildbot/build-amd64.bat
Normal file
@@ -0,0 +1,6 @@
|
||||
@rem Used by the buildbot "compile" step.
|
||||
cmd /c Tools\buildbot\external-amd64.bat
|
||||
call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||
cmd /c Tools\buildbot\clean-amd64.bat
|
||||
vcbuild /useenv PCbuild\kill_python.vcproj "Debug|x64" && PCbuild\amd64\kill_python_d.exe
|
||||
vcbuild PCbuild\pcbuild.sln "Debug|x64"
|
||||
7
project/jni/python/src/Tools/buildbot/build.bat
Normal file
7
project/jni/python/src/Tools/buildbot/build.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@rem Used by the buildbot "compile" step.
|
||||
cmd /c Tools\buildbot\external.bat
|
||||
call "%VS90COMNTOOLS%vsvars32.bat"
|
||||
cmd /c Tools\buildbot\clean.bat
|
||||
vcbuild /useenv PCbuild\kill_python.vcproj "Debug|Win32" && PCbuild\kill_python_d.exe
|
||||
vcbuild /useenv PCbuild\pcbuild.sln "Debug|Win32"
|
||||
|
||||
20
project/jni/python/src/Tools/buildbot/buildmsi.bat
Normal file
20
project/jni/python/src/Tools/buildbot/buildmsi.bat
Normal file
@@ -0,0 +1,20 @@
|
||||
@rem Used by the buildbot "buildmsi" step.
|
||||
|
||||
cmd /c Tools\buildbot\external.bat
|
||||
@rem build release versions of things
|
||||
call "%VS90COMNTOOLS%vsvars32.bat"
|
||||
|
||||
@rem build Python
|
||||
vcbuild /useenv PCbuild\pcbuild.sln "Release|Win32"
|
||||
|
||||
@rem build the documentation
|
||||
bash.exe -c 'cd Doc;make PYTHON=python2.5 update htmlhelp'
|
||||
"%ProgramFiles%\HTML Help Workshop\hhc.exe" Doc\build\htmlhelp\python26a3.hhp
|
||||
|
||||
@rem buold the MSI file
|
||||
cd PC
|
||||
nmake /f icons.mak
|
||||
cd ..\Tools\msi
|
||||
del *.msi
|
||||
nmake /f msisupport.mak
|
||||
%HOST_PYTHON% msi.py
|
||||
7
project/jni/python/src/Tools/buildbot/clean-amd64.bat
Normal file
7
project/jni/python/src/Tools/buildbot/clean-amd64.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@rem Used by the buildbot "clean" step.
|
||||
call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||
cd PCbuild
|
||||
@echo Deleting .pyc/.pyo files ...
|
||||
del /s Lib\*.pyc Lib\*.pyo
|
||||
vcbuild /clean pcbuild.sln "Release|x64"
|
||||
vcbuild /clean pcbuild.sln "Debug|x64"
|
||||
7
project/jni/python/src/Tools/buildbot/clean.bat
Normal file
7
project/jni/python/src/Tools/buildbot/clean.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@rem Used by the buildbot "clean" step.
|
||||
call "%VS90COMNTOOLS%vsvars32.bat"
|
||||
@echo Deleting .pyc/.pyo files ...
|
||||
del /s Lib\*.pyc Lib\*.pyo
|
||||
cd PCbuild
|
||||
vcbuild /clean pcbuild.sln "Release|Win32"
|
||||
vcbuild /clean pcbuild.sln "Debug|Win32"
|
||||
20
project/jni/python/src/Tools/buildbot/external-amd64.bat
Normal file
20
project/jni/python/src/Tools/buildbot/external-amd64.bat
Normal file
@@ -0,0 +1,20 @@
|
||||
@rem Fetches (and builds if necessary) external dependencies
|
||||
|
||||
@rem Assume we start inside the Python source directory
|
||||
call "Tools\buildbot\external-common.bat"
|
||||
call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||
|
||||
if not exist tcltk64\bin\tcl85g.dll (
|
||||
cd tcl-8.5.2.1\win
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 DEBUG=1 MACHINE=AMD64 INSTALLDIR=..\..\tcltk64 clean all
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 DEBUG=1 MACHINE=AMD64 INSTALLDIR=..\..\tcltk64 install
|
||||
cd ..\..
|
||||
)
|
||||
|
||||
if not exist tcltk64\bin\tk85g.dll (
|
||||
cd tk-8.5.2.0\win
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 OPTS=noxp DEBUG=1 MACHINE=AMD64 INSTALLDIR=..\..\tcltk64 TCLDIR=..\..\tcl-8.5.2.1 clean
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 OPTS=noxp DEBUG=1 MACHINE=AMD64 INSTALLDIR=..\..\tcltk64 TCLDIR=..\..\tcl-8.5.2.1 all
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 OPTS=noxp DEBUG=1 MACHINE=AMD64 INSTALLDIR=..\..\tcltk64 TCLDIR=..\..\tcl-8.5.2.1 install
|
||||
cd ..\..
|
||||
)
|
||||
45
project/jni/python/src/Tools/buildbot/external-common.bat
Normal file
45
project/jni/python/src/Tools/buildbot/external-common.bat
Normal file
@@ -0,0 +1,45 @@
|
||||
@rem Common file shared between external.bat and external-amd64.bat. Responsible for
|
||||
@rem fetching external components into the root\.. buildbot directories.
|
||||
|
||||
cd ..
|
||||
@rem XXX: If you need to force the buildbots to start from a fresh environment, uncomment
|
||||
@rem the following, check it in, then check it out, comment it out, then check it back in.
|
||||
@rem if exist bzip2-1.0.5 rd /s/q bzip2-1.0.5
|
||||
@rem if exist tcltk rd /s/q tcltk
|
||||
@rem if exist tcltk64 rd /s/q tcltk64
|
||||
@rem if exist tcl8.4.12 rd /s/q tcl8.4.12
|
||||
@rem if exist tcl8.4.16 rd /s/q tcl8.4.16
|
||||
@rem if exist tcl-8.4.18.1 rd /s/q tcl-8.4.18.1
|
||||
@rem if exist tk8.4.12 rd /s/q tk8.4.12
|
||||
@rem if exist tk8.4.16 rd /s/q tk8.4.16
|
||||
@rem if exist tk-8.4.18.1 rd /s/q tk-8.4.18.1
|
||||
@rem if exist db-4.4.20 rd /s/q db-4.4.20
|
||||
@rem if exist db-4.7.25.0 rd /s/q db-4.7.25.0
|
||||
@rem if exist openssl-0.9.8g rd /s/q openssl-0.9.8g
|
||||
@rem if exist sqlite-3.5.9 rd /s/q sqlite-3.5.9
|
||||
|
||||
@rem bzip
|
||||
if not exist bzip2-1.0.5 (
|
||||
rd /s/q bzip2-1.0.3
|
||||
svn export http://svn.python.org/projects/external/bzip2-1.0.5
|
||||
)
|
||||
|
||||
@rem Berkeley DB
|
||||
if exist db-4.4.20 rd /s/q db-4.4.20
|
||||
if not exist db-4.7.25.0 svn export http://svn.python.org/projects/external/db-4.7.25.0
|
||||
|
||||
@rem OpenSSL
|
||||
if not exist openssl-0.9.8g svn export http://svn.python.org/projects/external/openssl-0.9.8g
|
||||
|
||||
@rem tcl/tk
|
||||
if not exist tcl-8.5.2.1 (
|
||||
rd /s/q tcltk tcltk64
|
||||
svn export http://svn.python.org/projects/external/tcl-8.5.2.1
|
||||
)
|
||||
if not exist tk-8.5.2.0 svn export http://svn.python.org/projects/external/tk-8.5.2.0
|
||||
|
||||
@rem sqlite3
|
||||
if not exist sqlite-3.5.9 (
|
||||
rd /s/q sqlite-source-3.3.4
|
||||
svn export http://svn.python.org/projects/external/sqlite-3.5.9
|
||||
)
|
||||
21
project/jni/python/src/Tools/buildbot/external.bat
Normal file
21
project/jni/python/src/Tools/buildbot/external.bat
Normal file
@@ -0,0 +1,21 @@
|
||||
@rem Fetches (and builds if necessary) external dependencies
|
||||
|
||||
@rem Assume we start inside the Python source directory
|
||||
call "Tools\buildbot\external-common.bat"
|
||||
call "%VS90COMNTOOLS%\vsvars32.bat"
|
||||
|
||||
if not exist tcltk\bin\tcl85g.dll (
|
||||
@rem all and install need to be separate invocations, otherwise nmakehlp is not found on install
|
||||
cd tcl-8.5.2.1\win
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 DEBUG=1 INSTALLDIR=..\..\tcltk clean all
|
||||
nmake -f makefile.vc DEBUG=1 INSTALLDIR=..\..\tcltk install
|
||||
cd ..\..
|
||||
)
|
||||
|
||||
if not exist tcltk\bin\tk85g.dll (
|
||||
cd tk-8.5.2.0\win
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 OPTS=noxp DEBUG=1 INSTALLDIR=..\..\tcltk TCLDIR=..\..\tcl-8.5.2.1 clean
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 OPTS=noxp DEBUG=1 INSTALLDIR=..\..\tcltk TCLDIR=..\..\tcl-8.5.2.1 all
|
||||
nmake -f makefile.vc COMPILERFLAGS=-DWINVER=0x0500 OPTS=noxp DEBUG=1 INSTALLDIR=..\..\tcltk TCLDIR=..\..\tcl-8.5.2.1 install
|
||||
cd ..\..
|
||||
)
|
||||
3
project/jni/python/src/Tools/buildbot/test-amd64.bat
Normal file
3
project/jni/python/src/Tools/buildbot/test-amd64.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
@rem Used by the buildbot "test" step.
|
||||
cd PCbuild
|
||||
call rt.bat -q -d -x64 -uall -rw
|
||||
3
project/jni/python/src/Tools/buildbot/test.bat
Normal file
3
project/jni/python/src/Tools/buildbot/test.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
@rem Used by the buildbot "test" step.
|
||||
cd PCbuild
|
||||
call rt.bat -d -q -uall -rw
|
||||
8
project/jni/python/src/Tools/compiler/ACKS
Normal file
8
project/jni/python/src/Tools/compiler/ACKS
Normal file
@@ -0,0 +1,8 @@
|
||||
Fred L. Drake, Jr.
|
||||
Mark Hammond
|
||||
Shane Hathaway
|
||||
Neil Schemenauer
|
||||
Evan Simpson
|
||||
Greg Stein
|
||||
Bill Tutt
|
||||
Moshe Zadka
|
||||
18
project/jni/python/src/Tools/compiler/README
Normal file
18
project/jni/python/src/Tools/compiler/README
Normal file
@@ -0,0 +1,18 @@
|
||||
This directory contains support tools for the Python compiler package,
|
||||
which is now part of the standard library.
|
||||
|
||||
compile.py Demo that compiles a Python module into a .pyc file
|
||||
using the pure-Python compiler code.
|
||||
|
||||
demo.py Prints the names of all the methods defined in a module,
|
||||
as a demonstration of walking through the abstract syntax
|
||||
tree produced by the parser.
|
||||
|
||||
dumppyc.py Dumps the contents of a .pyc file, printing
|
||||
the attributes of the code object followed by a
|
||||
code disassembly.
|
||||
|
||||
regrtest.py Runs the Python test suite using bytecode generated
|
||||
by the pure-Python compiler code instead of the
|
||||
builtin compiler.
|
||||
|
||||
104
project/jni/python/src/Tools/compiler/ast.txt
Normal file
104
project/jni/python/src/Tools/compiler/ast.txt
Normal file
@@ -0,0 +1,104 @@
|
||||
# This file describes the nodes of the AST in ast.py. The module is
|
||||
# generated by astgen.py.
|
||||
# The descriptions use the following special notation to describe
|
||||
# properties of the children:
|
||||
# * this child is not a node
|
||||
# ! this child is a sequence that contains nodes in it
|
||||
# & this child may be set to None
|
||||
# = ... a default value for the node constructor (optional args)
|
||||
#
|
||||
# If you add node types here, please be sure to update the list of
|
||||
# Node types in Doc/lib/asttable.tex.
|
||||
Module: doc*, node
|
||||
Stmt: nodes!
|
||||
Decorators: nodes!
|
||||
Function: decorators&, name*, argnames*, defaults!, flags*, doc*, code
|
||||
Lambda: argnames*, defaults!, flags*, code
|
||||
Class: name*, bases!, doc*, code, decorators& = None
|
||||
Pass:
|
||||
Break:
|
||||
Continue:
|
||||
For: assign, list, body, else_&
|
||||
While: test, body, else_&
|
||||
With: expr, vars&, body
|
||||
If: tests!, else_&
|
||||
IfExp: test, then, else_
|
||||
Exec: expr, locals&, globals&
|
||||
From: modname*, names*, level*
|
||||
Import: names*
|
||||
Raise: expr1&, expr2&, expr3&
|
||||
TryFinally: body, final
|
||||
TryExcept: body, handlers!, else_&
|
||||
Return: value
|
||||
Yield: value
|
||||
Const: value*
|
||||
Print: nodes!, dest&
|
||||
Printnl: nodes!, dest&
|
||||
Discard: expr
|
||||
AugAssign: node, op*, expr
|
||||
Assign: nodes!, expr
|
||||
AssTuple: nodes!
|
||||
AssList: nodes!
|
||||
AssName: name*, flags*
|
||||
AssAttr: expr, attrname*, flags*
|
||||
ListComp: expr, quals!
|
||||
ListCompFor: assign, list, ifs!
|
||||
ListCompIf: test
|
||||
GenExpr: code
|
||||
GenExprInner: expr, quals!
|
||||
GenExprFor: assign, iter, ifs!
|
||||
GenExprIf: test
|
||||
List: nodes!
|
||||
Dict: items!
|
||||
Not: expr
|
||||
Compare: expr, ops!
|
||||
Name: name*
|
||||
Global: names*
|
||||
Backquote: expr
|
||||
Getattr: expr, attrname*
|
||||
CallFunc: node, args!, star_args& = None, dstar_args& = None
|
||||
Keyword: name*, expr
|
||||
Subscript: expr, flags*, subs!
|
||||
Ellipsis:
|
||||
Sliceobj: nodes!
|
||||
Slice: expr, flags*, lower&, upper&
|
||||
Assert: test, fail&
|
||||
Tuple: nodes!
|
||||
Or: nodes!
|
||||
And: nodes!
|
||||
Bitor: nodes!
|
||||
Bitxor: nodes!
|
||||
Bitand: nodes!
|
||||
LeftShift: (left, right)
|
||||
RightShift: (left, right)
|
||||
Add: (left, right)
|
||||
Sub: (left, right)
|
||||
Mul: (left, right)
|
||||
Div: (left, right)
|
||||
Mod: (left, right)
|
||||
Power: (left, right)
|
||||
FloorDiv: (left, right)
|
||||
UnaryAdd: expr
|
||||
UnarySub: expr
|
||||
Invert: expr
|
||||
|
||||
init(Function):
|
||||
self.varargs = self.kwargs = None
|
||||
if flags & CO_VARARGS:
|
||||
self.varargs = 1
|
||||
if flags & CO_VARKEYWORDS:
|
||||
self.kwargs = 1
|
||||
|
||||
init(Lambda):
|
||||
self.varargs = self.kwargs = None
|
||||
if flags & CO_VARARGS:
|
||||
self.varargs = 1
|
||||
if flags & CO_VARKEYWORDS:
|
||||
self.kwargs = 1
|
||||
|
||||
init(GenExpr):
|
||||
self.argnames = ['.0']
|
||||
self.varargs = self.kwargs = None
|
||||
|
||||
init(GenExprFor):
|
||||
self.is_outmost = False
|
||||
288
project/jni/python/src/Tools/compiler/astgen.py
Normal file
288
project/jni/python/src/Tools/compiler/astgen.py
Normal file
@@ -0,0 +1,288 @@
|
||||
"""Generate ast module from specification
|
||||
|
||||
This script generates the ast module from a simple specification,
|
||||
which makes it easy to accomodate changes in the grammar. This
|
||||
approach would be quite reasonable if the grammar changed often.
|
||||
Instead, it is rather complex to generate the appropriate code. And
|
||||
the Node interface has changed more often than the grammar.
|
||||
"""
|
||||
|
||||
import fileinput
|
||||
import re
|
||||
import sys
|
||||
from StringIO import StringIO
|
||||
|
||||
SPEC = "ast.txt"
|
||||
COMMA = ", "
|
||||
|
||||
def load_boilerplate(file):
|
||||
f = open(file)
|
||||
buf = f.read()
|
||||
f.close()
|
||||
i = buf.find('### ''PROLOGUE')
|
||||
j = buf.find('### ''EPILOGUE')
|
||||
pro = buf[i+12:j].strip()
|
||||
epi = buf[j+12:].strip()
|
||||
return pro, epi
|
||||
|
||||
def strip_default(arg):
|
||||
"""Return the argname from an 'arg = default' string"""
|
||||
i = arg.find('=')
|
||||
if i == -1:
|
||||
return arg
|
||||
t = arg[:i].strip()
|
||||
return t
|
||||
|
||||
P_NODE = 1
|
||||
P_OTHER = 2
|
||||
P_NESTED = 3
|
||||
P_NONE = 4
|
||||
|
||||
class NodeInfo:
|
||||
"""Each instance describes a specific AST node"""
|
||||
def __init__(self, name, args):
|
||||
self.name = name
|
||||
self.args = args.strip()
|
||||
self.argnames = self.get_argnames()
|
||||
self.argprops = self.get_argprops()
|
||||
self.nargs = len(self.argnames)
|
||||
self.init = []
|
||||
|
||||
def get_argnames(self):
|
||||
if '(' in self.args:
|
||||
i = self.args.find('(')
|
||||
j = self.args.rfind(')')
|
||||
args = self.args[i+1:j]
|
||||
else:
|
||||
args = self.args
|
||||
return [strip_default(arg.strip())
|
||||
for arg in args.split(',') if arg]
|
||||
|
||||
def get_argprops(self):
|
||||
"""Each argument can have a property like '*' or '!'
|
||||
|
||||
XXX This method modifies the argnames in place!
|
||||
"""
|
||||
d = {}
|
||||
hardest_arg = P_NODE
|
||||
for i in range(len(self.argnames)):
|
||||
arg = self.argnames[i]
|
||||
if arg.endswith('*'):
|
||||
arg = self.argnames[i] = arg[:-1]
|
||||
d[arg] = P_OTHER
|
||||
hardest_arg = max(hardest_arg, P_OTHER)
|
||||
elif arg.endswith('!'):
|
||||
arg = self.argnames[i] = arg[:-1]
|
||||
d[arg] = P_NESTED
|
||||
hardest_arg = max(hardest_arg, P_NESTED)
|
||||
elif arg.endswith('&'):
|
||||
arg = self.argnames[i] = arg[:-1]
|
||||
d[arg] = P_NONE
|
||||
hardest_arg = max(hardest_arg, P_NONE)
|
||||
else:
|
||||
d[arg] = P_NODE
|
||||
self.hardest_arg = hardest_arg
|
||||
|
||||
if hardest_arg > P_NODE:
|
||||
self.args = self.args.replace('*', '')
|
||||
self.args = self.args.replace('!', '')
|
||||
self.args = self.args.replace('&', '')
|
||||
|
||||
return d
|
||||
|
||||
def gen_source(self):
|
||||
buf = StringIO()
|
||||
print >> buf, "class %s(Node):" % self.name
|
||||
self._gen_init(buf)
|
||||
print >> buf
|
||||
self._gen_getChildren(buf)
|
||||
print >> buf
|
||||
self._gen_getChildNodes(buf)
|
||||
print >> buf
|
||||
self._gen_repr(buf)
|
||||
buf.seek(0, 0)
|
||||
return buf.read()
|
||||
|
||||
def _gen_init(self, buf):
|
||||
if self.args:
|
||||
print >> buf, " def __init__(self, %s, lineno=None):" % self.args
|
||||
else:
|
||||
print >> buf, " def __init__(self, lineno=None):"
|
||||
if self.argnames:
|
||||
for name in self.argnames:
|
||||
print >> buf, " self.%s = %s" % (name, name)
|
||||
print >> buf, " self.lineno = lineno"
|
||||
# Copy the lines in self.init, indented four spaces. The rstrip()
|
||||
# business is to get rid of the four spaces if line happens to be
|
||||
# empty, so that reindent.py is happy with the output.
|
||||
for line in self.init:
|
||||
print >> buf, (" " + line).rstrip()
|
||||
|
||||
def _gen_getChildren(self, buf):
|
||||
print >> buf, " def getChildren(self):"
|
||||
if len(self.argnames) == 0:
|
||||
print >> buf, " return ()"
|
||||
else:
|
||||
if self.hardest_arg < P_NESTED:
|
||||
clist = COMMA.join(["self.%s" % c
|
||||
for c in self.argnames])
|
||||
if self.nargs == 1:
|
||||
print >> buf, " return %s," % clist
|
||||
else:
|
||||
print >> buf, " return %s" % clist
|
||||
else:
|
||||
if len(self.argnames) == 1:
|
||||
print >> buf, " return tuple(flatten(self.%s))" % self.argnames[0]
|
||||
else:
|
||||
print >> buf, " children = []"
|
||||
template = " children.%s(%sself.%s%s)"
|
||||
for name in self.argnames:
|
||||
if self.argprops[name] == P_NESTED:
|
||||
print >> buf, template % ("extend", "flatten(",
|
||||
name, ")")
|
||||
else:
|
||||
print >> buf, template % ("append", "", name, "")
|
||||
print >> buf, " return tuple(children)"
|
||||
|
||||
def _gen_getChildNodes(self, buf):
|
||||
print >> buf, " def getChildNodes(self):"
|
||||
if len(self.argnames) == 0:
|
||||
print >> buf, " return ()"
|
||||
else:
|
||||
if self.hardest_arg < P_NESTED:
|
||||
clist = ["self.%s" % c
|
||||
for c in self.argnames
|
||||
if self.argprops[c] == P_NODE]
|
||||
if len(clist) == 0:
|
||||
print >> buf, " return ()"
|
||||
elif len(clist) == 1:
|
||||
print >> buf, " return %s," % clist[0]
|
||||
else:
|
||||
print >> buf, " return %s" % COMMA.join(clist)
|
||||
else:
|
||||
print >> buf, " nodelist = []"
|
||||
template = " nodelist.%s(%sself.%s%s)"
|
||||
for name in self.argnames:
|
||||
if self.argprops[name] == P_NONE:
|
||||
tmp = (" if self.%s is not None:\n"
|
||||
" nodelist.append(self.%s)")
|
||||
print >> buf, tmp % (name, name)
|
||||
elif self.argprops[name] == P_NESTED:
|
||||
print >> buf, template % ("extend", "flatten_nodes(",
|
||||
name, ")")
|
||||
elif self.argprops[name] == P_NODE:
|
||||
print >> buf, template % ("append", "", name, "")
|
||||
print >> buf, " return tuple(nodelist)"
|
||||
|
||||
def _gen_repr(self, buf):
|
||||
print >> buf, " def __repr__(self):"
|
||||
if self.argnames:
|
||||
fmt = COMMA.join(["%s"] * self.nargs)
|
||||
if '(' in self.args:
|
||||
fmt = '(%s)' % fmt
|
||||
vals = ["repr(self.%s)" % name for name in self.argnames]
|
||||
vals = COMMA.join(vals)
|
||||
if self.nargs == 1:
|
||||
vals = vals + ","
|
||||
print >> buf, ' return "%s(%s)" %% (%s)' % \
|
||||
(self.name, fmt, vals)
|
||||
else:
|
||||
print >> buf, ' return "%s()"' % self.name
|
||||
|
||||
rx_init = re.compile('init\((.*)\):')
|
||||
|
||||
def parse_spec(file):
|
||||
classes = {}
|
||||
cur = None
|
||||
for line in fileinput.input(file):
|
||||
if line.strip().startswith('#'):
|
||||
continue
|
||||
mo = rx_init.search(line)
|
||||
if mo is None:
|
||||
if cur is None:
|
||||
# a normal entry
|
||||
try:
|
||||
name, args = line.split(':')
|
||||
except ValueError:
|
||||
continue
|
||||
classes[name] = NodeInfo(name, args)
|
||||
cur = None
|
||||
else:
|
||||
# some code for the __init__ method
|
||||
cur.init.append(line)
|
||||
else:
|
||||
# some extra code for a Node's __init__ method
|
||||
name = mo.group(1)
|
||||
cur = classes[name]
|
||||
return sorted(classes.values(), key=lambda n: n.name)
|
||||
|
||||
def main():
|
||||
prologue, epilogue = load_boilerplate(sys.argv[-1])
|
||||
print prologue
|
||||
print
|
||||
classes = parse_spec(SPEC)
|
||||
for info in classes:
|
||||
print info.gen_source()
|
||||
print epilogue
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
sys.exit(0)
|
||||
|
||||
### PROLOGUE
|
||||
"""Python abstract syntax node definitions
|
||||
|
||||
This file is automatically generated by Tools/compiler/astgen.py
|
||||
"""
|
||||
from consts import CO_VARARGS, CO_VARKEYWORDS
|
||||
|
||||
def flatten(seq):
|
||||
l = []
|
||||
for elt in seq:
|
||||
t = type(elt)
|
||||
if t is tuple or t is list:
|
||||
for elt2 in flatten(elt):
|
||||
l.append(elt2)
|
||||
else:
|
||||
l.append(elt)
|
||||
return l
|
||||
|
||||
def flatten_nodes(seq):
|
||||
return [n for n in flatten(seq) if isinstance(n, Node)]
|
||||
|
||||
nodes = {}
|
||||
|
||||
class Node:
|
||||
"""Abstract base class for ast nodes."""
|
||||
def getChildren(self):
|
||||
pass # implemented by subclasses
|
||||
def __iter__(self):
|
||||
for n in self.getChildren():
|
||||
yield n
|
||||
def asList(self): # for backwards compatibility
|
||||
return self.getChildren()
|
||||
def getChildNodes(self):
|
||||
pass # implemented by subclasses
|
||||
|
||||
class EmptyNode(Node):
|
||||
pass
|
||||
|
||||
class Expression(Node):
|
||||
# Expression is an artificial node class to support "eval"
|
||||
nodes["expression"] = "Expression"
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
||||
def getChildren(self):
|
||||
return self.node,
|
||||
|
||||
def getChildNodes(self):
|
||||
return self.node,
|
||||
|
||||
def __repr__(self):
|
||||
return "Expression(%s)" % (repr(self.node))
|
||||
|
||||
### EPILOGUE
|
||||
for name, obj in globals().items():
|
||||
if isinstance(obj, type) and issubclass(obj, Node):
|
||||
nodes[name.lower()] = obj
|
||||
51
project/jni/python/src/Tools/compiler/compile.py
Normal file
51
project/jni/python/src/Tools/compiler/compile.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
from compiler import compileFile, visitor
|
||||
|
||||
import profile
|
||||
|
||||
def main():
|
||||
VERBOSE = 0
|
||||
DISPLAY = 0
|
||||
PROFILE = 0
|
||||
CONTINUE = 0
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'vqdcp')
|
||||
for k, v in opts:
|
||||
if k == '-v':
|
||||
VERBOSE = 1
|
||||
visitor.ASTVisitor.VERBOSE = visitor.ASTVisitor.VERBOSE + 1
|
||||
if k == '-q':
|
||||
if sys.platform[:3]=="win":
|
||||
f = open('nul', 'wb') # /dev/null fails on Windows...
|
||||
else:
|
||||
f = open('/dev/null', 'wb')
|
||||
sys.stdout = f
|
||||
if k == '-d':
|
||||
DISPLAY = 1
|
||||
if k == '-c':
|
||||
CONTINUE = 1
|
||||
if k == '-p':
|
||||
PROFILE = 1
|
||||
if not args:
|
||||
print "no files to compile"
|
||||
else:
|
||||
for filename in args:
|
||||
if VERBOSE:
|
||||
print filename
|
||||
try:
|
||||
if PROFILE:
|
||||
profile.run('compileFile(%r, %r)' % (filename, DISPLAY),
|
||||
filename + ".prof")
|
||||
else:
|
||||
compileFile(filename, DISPLAY)
|
||||
|
||||
except SyntaxError, err:
|
||||
print err
|
||||
if err.lineno is not None:
|
||||
print err.lineno
|
||||
if not CONTINUE:
|
||||
sys.exit(-1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
38
project/jni/python/src/Tools/compiler/demo.py
Normal file
38
project/jni/python/src/Tools/compiler/demo.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Print names of all methods defined in module
|
||||
|
||||
This script demonstrates use of the visitor interface of the compiler
|
||||
package.
|
||||
"""
|
||||
|
||||
import compiler
|
||||
|
||||
class MethodFinder:
|
||||
"""Print the names of all the methods
|
||||
|
||||
Each visit method takes two arguments, the node and its current
|
||||
scope. The scope is the name of the current class or None.
|
||||
"""
|
||||
|
||||
def visitClass(self, node, scope=None):
|
||||
self.visit(node.code, node.name)
|
||||
|
||||
def visitFunction(self, node, scope=None):
|
||||
if scope is not None:
|
||||
print "%s.%s" % (scope, node.name)
|
||||
self.visit(node.code, None)
|
||||
|
||||
def main(files):
|
||||
mf = MethodFinder()
|
||||
for file in files:
|
||||
f = open(file)
|
||||
buf = f.read()
|
||||
f.close()
|
||||
ast = compiler.parse(buf)
|
||||
compiler.walk(ast, mf)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
main(sys.argv[1:])
|
||||
46
project/jni/python/src/Tools/compiler/dumppyc.py
Normal file
46
project/jni/python/src/Tools/compiler/dumppyc.py
Normal file
@@ -0,0 +1,46 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import marshal
|
||||
import dis
|
||||
import types
|
||||
|
||||
def dump(obj):
|
||||
print obj
|
||||
for attr in dir(obj):
|
||||
if attr.startswith('co_'):
|
||||
val = getattr(obj, attr)
|
||||
print "\t", attr, repr(val)
|
||||
|
||||
def loadCode(path):
|
||||
f = open(path)
|
||||
f.read(8)
|
||||
co = marshal.load(f)
|
||||
f.close()
|
||||
return co
|
||||
|
||||
def walk(co, match=None):
|
||||
if match is None or co.co_name == match:
|
||||
dump(co)
|
||||
print
|
||||
dis.dis(co)
|
||||
for obj in co.co_consts:
|
||||
if type(obj) == types.CodeType:
|
||||
walk(obj, match)
|
||||
|
||||
def load(filename, codename=None):
|
||||
co = loadCode(filename)
|
||||
walk(co, codename)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) == 3:
|
||||
filename, codename = sys.argv[1:]
|
||||
else:
|
||||
filename = sys.argv[1]
|
||||
codename = None
|
||||
if filename.endswith('.py'):
|
||||
buf = open(filename).read()
|
||||
co = compile(buf, filename, "exec")
|
||||
walk(co)
|
||||
else:
|
||||
load(filename, codename)
|
||||
78
project/jni/python/src/Tools/compiler/regrtest.py
Normal file
78
project/jni/python/src/Tools/compiler/regrtest.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""Run the Python regression test using the compiler
|
||||
|
||||
This test runs the standard Python test suite using bytecode generated
|
||||
by this compiler instead of by the builtin compiler.
|
||||
|
||||
The regression test is run with the interpreter in verbose mode so
|
||||
that import problems can be observed easily.
|
||||
"""
|
||||
|
||||
from compiler import compileFile
|
||||
|
||||
import os
|
||||
import sys
|
||||
import test
|
||||
import tempfile
|
||||
|
||||
def copy_test_suite():
|
||||
dest = tempfile.mkdtemp()
|
||||
os.system("cp -r %s/* %s" % (test.__path__[0], dest))
|
||||
print "Creating copy of test suite in", dest
|
||||
return dest
|
||||
|
||||
def copy_library():
|
||||
dest = tempfile.mkdtemp()
|
||||
libdir = os.path.split(test.__path__[0])[0]
|
||||
print "Found standard library in", libdir
|
||||
print "Creating copy of standard library in", dest
|
||||
os.system("cp -r %s/* %s" % (libdir, dest))
|
||||
return dest
|
||||
|
||||
def compile_files(dir):
|
||||
print "Compiling", dir, "\n\t",
|
||||
line_len = 10
|
||||
for file in os.listdir(dir):
|
||||
base, ext = os.path.splitext(file)
|
||||
if ext == '.py':
|
||||
source = os.path.join(dir, file)
|
||||
line_len = line_len + len(file) + 1
|
||||
if line_len > 75:
|
||||
print "\n\t",
|
||||
line_len = len(source) + 9
|
||||
print file,
|
||||
try:
|
||||
compileFile(source)
|
||||
except SyntaxError, err:
|
||||
print err
|
||||
continue
|
||||
# make sure the .pyc file is not over-written
|
||||
os.chmod(source + "c", 444)
|
||||
elif file == 'CVS':
|
||||
pass
|
||||
else:
|
||||
path = os.path.join(dir, file)
|
||||
if os.path.isdir(path):
|
||||
print
|
||||
print
|
||||
compile_files(path)
|
||||
print "\t",
|
||||
line_len = 10
|
||||
print
|
||||
|
||||
def run_regrtest(lib_dir):
|
||||
test_dir = os.path.join(lib_dir, "test")
|
||||
os.chdir(test_dir)
|
||||
os.system("PYTHONPATH=%s %s -v regrtest.py" % (lib_dir, sys.executable))
|
||||
|
||||
def cleanup(dir):
|
||||
os.system("rm -rf %s" % dir)
|
||||
|
||||
def main():
|
||||
lib_dir = copy_library()
|
||||
compile_files(lib_dir)
|
||||
run_regrtest(lib_dir)
|
||||
raw_input("Cleanup?")
|
||||
cleanup(lib_dir)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
43
project/jni/python/src/Tools/compiler/stacktest.py
Normal file
43
project/jni/python/src/Tools/compiler/stacktest.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import compiler
|
||||
import dis
|
||||
import types
|
||||
|
||||
def extract_code_objects(co):
|
||||
l = [co]
|
||||
for const in co.co_consts:
|
||||
if type(const) == types.CodeType:
|
||||
l.append(const)
|
||||
return l
|
||||
|
||||
def compare(a, b):
|
||||
if not (a.co_name == "?" or a.co_name.startswith('<lambda')):
|
||||
assert a.co_name == b.co_name, (a, b)
|
||||
if a.co_stacksize != b.co_stacksize:
|
||||
print "stack mismatch %s: %d vs. %d" % (a.co_name,
|
||||
a.co_stacksize,
|
||||
b.co_stacksize)
|
||||
if a.co_stacksize > b.co_stacksize:
|
||||
print "good code"
|
||||
dis.dis(a)
|
||||
print "bad code"
|
||||
dis.dis(b)
|
||||
assert 0
|
||||
|
||||
def main(files):
|
||||
for file in files:
|
||||
print file
|
||||
buf = open(file).read()
|
||||
try:
|
||||
co1 = compile(buf, file, "exec")
|
||||
except SyntaxError:
|
||||
print "skipped"
|
||||
continue
|
||||
co2 = compiler.compile(buf, file, "exec")
|
||||
co1l = extract_code_objects(co1)
|
||||
co2l = extract_code_objects(co2)
|
||||
for a, b in zip(co1l, co2l):
|
||||
compare(a, b)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
main(sys.argv[1:])
|
||||
114
project/jni/python/src/Tools/faqwiz/README
Normal file
114
project/jni/python/src/Tools/faqwiz/README
Normal file
@@ -0,0 +1,114 @@
|
||||
FAQ Wizard
|
||||
----------
|
||||
|
||||
Author: Guido van Rossum <guido@python.org>
|
||||
Version: 1.0
|
||||
Date: 6 April 1998
|
||||
|
||||
|
||||
This is a CGI program that maintains a user-editable FAQ. It uses RCS
|
||||
to keep track of changes to individual FAQ entries. It is fully
|
||||
configurable; everything you might want to change when using this
|
||||
program to maintain some other FAQ than the Python FAQ is contained in
|
||||
the configuration module, faqconf.py.
|
||||
|
||||
Note that the bulk of the code is not an executable script; it's an
|
||||
importable module. The actual script in cgi-bin is minimal.
|
||||
|
||||
Files:
|
||||
|
||||
faqw.py executable script to be edited and installed in cgi-bin
|
||||
faqwiz.py main module, lives in same directory as FAQ entry files
|
||||
faqconf.py main configuration module
|
||||
faqcust.py additional local customization module (optional)
|
||||
move-faqwiz.sh Script to move faqwiz entries.
|
||||
|
||||
|
||||
What's New?
|
||||
-----------
|
||||
|
||||
Version 1.0 corrects some minor bugs and uses tab-agnostic
|
||||
indentation; it is otherwise unchanged from version 0.9.0.
|
||||
|
||||
Version 0.9.0 uses the re module (Perl style regular expressions) for
|
||||
all its regular expression needs, instead of the regex and regsub
|
||||
modules (Emacs style). This affects the syntax for regular
|
||||
expressions entered by the user as search strings (with "regular
|
||||
expression" checked), hence the version number jump.
|
||||
|
||||
|
||||
Setup Information
|
||||
-----------------
|
||||
|
||||
This assumes you are familiar with Python, with your http server, and
|
||||
with running CGI scripts under your http server. You need Python 1.5
|
||||
or better.
|
||||
|
||||
Select a place where the Python modules that constitute the FAQ wizard
|
||||
will live (the directory where you unpacked it is an obvious choice).
|
||||
This will be called the SRCDIR. This directory should not be writable
|
||||
by other users of your system (since they would be able to execute
|
||||
arbitrary code by invoking the FAQ wizard's CGI script).
|
||||
|
||||
Create a dedicated working directory, preferably one that's not
|
||||
directly reachable from your http server. This will be called the
|
||||
FAQDIR. Create a subdirectory named RCS. Make both the working
|
||||
directory and the RCS subdirectory wrld-writable. (This is essential,
|
||||
since the FAQ wizard runs as use nobody, and needs to create
|
||||
additional files here!)
|
||||
|
||||
Edit faqconf.py to reflect your setup. You only need to edit the top
|
||||
part, up till the line of all dashes. The comments should guide you
|
||||
in your edits. (Actually, you can also choose to add your changes to
|
||||
faqcust.py and leave faqconf.py alone. This is essential if you are
|
||||
maintaining multiple FAQs; see below.)
|
||||
|
||||
Don't forget to edit the SECTION_TITLES variables to reflect the set
|
||||
of section titles for your FAQ!
|
||||
|
||||
Next, edit faqw.py to reflect the pathname of your Python interpreter
|
||||
and the values for SRCDIR and FAQDIR that you just chose. Then
|
||||
install faqw.py in your cgi-bin directory. Make sure that it is
|
||||
world-executable. You should now be able to connect to the FAQ wizard
|
||||
by entering the following URL in your web client (subsituting the
|
||||
appropriate host and port for "your.web.server", and perhaps
|
||||
specifying a different directory for "cgi-bin" if local conventions so
|
||||
dictate):
|
||||
|
||||
http://your.web.server/cgi-bin/faqw.py
|
||||
|
||||
If you are unable to get this working, check your server's error_log
|
||||
file. The documentation for Python's cgi module in the Python Library
|
||||
Reference Manual gives plentyu additional information about installing
|
||||
and debugging CGI scripts, including setup debugging. This
|
||||
documentation is repeated in the doc string in the cgi module; try
|
||||
``import cgi; print cgi.__doc__''.
|
||||
|
||||
Assuming this works, you should now be able to add the first entry to
|
||||
your FAQ using the FAQ wizard interface. This creates a file
|
||||
faq01.001.htp in your working directory and an RCS revision history
|
||||
file faq01.001.htp,v in the RCS subdirectory. You can now exercise
|
||||
the other FAQ wizard features (search, index, whole FAQ, what's new,
|
||||
roulette, and so on).
|
||||
|
||||
|
||||
Maintaining Multiple FAQs
|
||||
-------------------------
|
||||
|
||||
If you have multiple FAQs, you need a separate FAQDIR per FAQ, and a
|
||||
different customization file per FAQ. The easiest thing to do would
|
||||
be to have the faqcust.py for each FAQ live in the FAQDIR for that
|
||||
FAQ, but that creates some security concerns, since the FAQDIR must be
|
||||
world writable: *if* someone who breaks into your system (or a
|
||||
legitimate user) manages to edit the faqcust.py file they can get
|
||||
arbitrary code to execute through the FAQ wizard. Therefore, you will
|
||||
need a more complex setup.
|
||||
|
||||
The best way is probably to have a directory that is only writable by
|
||||
you for each FAQ, where you place the copy of faqcust.py for that FAQ,
|
||||
and have a world-writable subdirectory DATA for the data. You then
|
||||
set FAQDIR to point to the DATA directory and change the faqw.py
|
||||
bootstrap script to add FAQDIR/.. to sys.path (in front of SRCDIR, so
|
||||
the dummy faqcust.py from SRCDIR is ignored).
|
||||
|
||||
--Guido van Rossum (home page: http://www.python.org/~guido/)
|
||||
577
project/jni/python/src/Tools/faqwiz/faqconf.py
Normal file
577
project/jni/python/src/Tools/faqwiz/faqconf.py
Normal file
@@ -0,0 +1,577 @@
|
||||
"""FAQ Wizard customization module.
|
||||
|
||||
Edit this file to customize the FAQ Wizard. For normal purposes, you
|
||||
should only have to change the FAQ section titles and the small group
|
||||
of parameters below it.
|
||||
|
||||
"""
|
||||
|
||||
# Titles of FAQ sections
|
||||
|
||||
SECTION_TITLES = {
|
||||
# SectionNumber : SectionTitle; need at least one entry
|
||||
1: "General information and availability",
|
||||
}
|
||||
|
||||
# Parameters you definitely want to change
|
||||
|
||||
SHORTNAME = "Generic" # FAQ name with "FAQ" omitted
|
||||
PASSWORD = "" # Password for editing
|
||||
OWNERNAME = "FAQ owner" # Name for feedback
|
||||
OWNEREMAIL = "nobody@anywhere.org" # Email for feedback
|
||||
HOMEURL = "http://www.python.org" # Related home page
|
||||
HOMENAME = "Python home" # Name of related home page
|
||||
RCSBINDIR = "/usr/local/bin/" # Directory containing RCS commands
|
||||
# (must end in a slash)
|
||||
|
||||
# Parameters you can normally leave alone
|
||||
|
||||
MAXHITS = 10 # Max #hits to be shown directly
|
||||
COOKIE_LIFETIME = 28*24*3600 # Cookie expiration in seconds
|
||||
# (28*24*3600 = 28 days = 4 weeks)
|
||||
PROCESS_PREFORMAT = 1 # toggle whether preformatted text
|
||||
# will replace urls and emails with
|
||||
# HTML links
|
||||
|
||||
# Markers appended to title to indicate recently change
|
||||
# (may contain HTML, e.g. <IMG>); and corresponding
|
||||
|
||||
MARK_VERY_RECENT = " **" # Changed very recently
|
||||
MARK_RECENT = " *" # Changed recently
|
||||
DT_VERY_RECENT = 24*3600 # 24 hours
|
||||
DT_RECENT = 7*24*3600 # 7 days
|
||||
|
||||
EXPLAIN_MARKS = """
|
||||
<P>(Entries marked with ** were changed within the last 24 hours;
|
||||
entries marked with * were changed within the last 7 days.)
|
||||
<P>
|
||||
"""
|
||||
|
||||
# Version -- don't change unless you edit faqwiz.py
|
||||
|
||||
WIZVERSION = "1.0.4" # FAQ Wizard version
|
||||
|
||||
import os, sys
|
||||
if os.name in ['nt',]:
|
||||
# On NT we'll probably be running python from a batch file,
|
||||
# so sys.argv[0] is not helpful
|
||||
FAQCGI = 'faq.bat' # Relative URL of the FAQ cgi script
|
||||
# LOGNAME is not typically set on NT
|
||||
os.environ[ 'LOGNAME' ] = "FAQWizard"
|
||||
else:
|
||||
# This parameter is normally overwritten with a dynamic value
|
||||
FAQCGI = 'faqw.py' # Relative URL of the FAQ cgi script
|
||||
FAQCGI = os.path.basename(sys.argv[0]) or FAQCGI
|
||||
del os, sys
|
||||
|
||||
# Perl (re module) style regular expression to recognize FAQ entry
|
||||
# files: group(1) should be the section number, group(2) should be the
|
||||
# question number. Both should be fixed width so simple-minded
|
||||
# sorting yields the right order.
|
||||
|
||||
OKFILENAME = r"^faq(\d\d)\.(\d\d\d)\.htp$"
|
||||
|
||||
# Format to construct a FAQ entry file name
|
||||
|
||||
NEWFILENAME = "faq%02d.%03d.htp"
|
||||
|
||||
# Load local customizations on top of the previous parameters
|
||||
|
||||
try:
|
||||
from faqcust import *
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Calculated parameter names
|
||||
|
||||
COOKIE_NAME = SHORTNAME + "-FAQ-Wizard" # Name used for Netscape cookie
|
||||
FAQNAME = SHORTNAME + " FAQ" # Name of the FAQ
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# Anything below this point normally needn't be changed; you would
|
||||
# change this if you were to create e.g. a French translation or if
|
||||
# you just aren't happy with the text generated by the FAQ Wizard.
|
||||
|
||||
# Most strings here are subject to substitution (string%dictionary)
|
||||
|
||||
# RCS commands
|
||||
|
||||
import os
|
||||
if os.name in ['nt', ]:
|
||||
SH_RLOG = RCSBINDIR + "rlog %(file)s < NUL"
|
||||
SH_RLOG_H = RCSBINDIR + "rlog -h %(file)s < NUL"
|
||||
SH_RDIFF = RCSBINDIR + "rcsdiff -r%(prev)s -r%(rev)s %(file)s < NUL"
|
||||
SH_REVISION = RCSBINDIR + "co -p%(rev)s %(file)s < NUL"
|
||||
### Have to use co -l, or the file is not marked rw on NT
|
||||
SH_LOCK = RCSBINDIR + "co -l %(file)s < NUL"
|
||||
SH_CHECKIN = RCSBINDIR + "ci -u %(file)s < %(tfn)s"
|
||||
else:
|
||||
SH_RLOG = RCSBINDIR + "rlog %(file)s </dev/null 2>&1"
|
||||
SH_RLOG_H = RCSBINDIR + "rlog -h %(file)s </dev/null 2>&1"
|
||||
SH_RDIFF = RCSBINDIR + "rcsdiff -r%(prev)s -r%(rev)s %(file)s </dev/null 2>&1"
|
||||
SH_REVISION = RCSBINDIR + "co -p%(rev)s %(file)s </dev/null 2>&1"
|
||||
SH_LOCK = RCSBINDIR + "rcs -l %(file)s </dev/null 2>&1"
|
||||
SH_CHECKIN = RCSBINDIR + "ci -u %(file)s <%(tfn)s 2>&1"
|
||||
del os
|
||||
|
||||
# Titles for various output pages (not subject to substitution)
|
||||
|
||||
T_HOME = FAQNAME + " Wizard " + WIZVERSION
|
||||
T_ERROR = "Sorry, an error occurred"
|
||||
T_ROULETTE = FAQNAME + " Roulette"
|
||||
T_ALL = "The Whole " + FAQNAME
|
||||
T_INDEX = FAQNAME + " Index"
|
||||
T_SEARCH = FAQNAME + " Search Results"
|
||||
T_RECENT = "What's New in the " + FAQNAME
|
||||
T_SHOW = FAQNAME + " Entry"
|
||||
T_LOG = "RCS log for %s entry" % FAQNAME
|
||||
T_REVISION = "RCS revision for %s entry" % FAQNAME
|
||||
T_DIFF = "RCS diff for %s entry" % FAQNAME
|
||||
T_ADD = "Add an entry to the " + FAQNAME
|
||||
T_DELETE = "Deleting an entry from the " + FAQNAME
|
||||
T_EDIT = FAQNAME + " Edit Wizard"
|
||||
T_REVIEW = T_EDIT + " - Review Changes"
|
||||
T_COMMITTED = T_EDIT + " - Changes Committed"
|
||||
T_COMMITFAILED = T_EDIT + " - Commit Failed"
|
||||
T_CANTCOMMIT = T_EDIT + " - Commit Rejected"
|
||||
T_HELP = T_EDIT + " - Help"
|
||||
|
||||
# Generic prologue and epilogue
|
||||
|
||||
PROLOGUE = '''
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>%(title)s</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY
|
||||
BGCOLOR="#FFFFFF"
|
||||
TEXT="#000000"
|
||||
LINK="#AA0000"
|
||||
VLINK="#906A6A">
|
||||
<H1>%(title)s</H1>
|
||||
'''
|
||||
|
||||
EPILOGUE = '''
|
||||
<HR>
|
||||
<A HREF="%(HOMEURL)s">%(HOMENAME)s</A> /
|
||||
<A HREF="%(FAQCGI)s?req=home">%(FAQNAME)s Wizard %(WIZVERSION)s</A> /
|
||||
Feedback to <A HREF="mailto:%(OWNEREMAIL)s">%(OWNERNAME)s</A>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
'''
|
||||
|
||||
# Home page
|
||||
|
||||
HOME = """
|
||||
<H2>Search the %(FAQNAME)s:</H2>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<FORM ACTION="%(FAQCGI)s">
|
||||
<INPUT TYPE=text NAME=query>
|
||||
<INPUT TYPE=submit VALUE="Search"><BR>
|
||||
<INPUT TYPE=radio NAME=querytype VALUE=simple CHECKED>
|
||||
Simple string
|
||||
/
|
||||
<INPUT TYPE=radio NAME=querytype VALUE=regex>
|
||||
Regular expression
|
||||
/<BR>
|
||||
<INPUT TYPE=radio NAME=querytype VALUE=anykeywords>
|
||||
Keywords (any)
|
||||
/
|
||||
<INPUT TYPE=radio NAME=querytype VALUE=allkeywords>
|
||||
Keywords (all)
|
||||
<BR>
|
||||
<INPUT TYPE=radio NAME=casefold VALUE=yes CHECKED>
|
||||
Fold case
|
||||
/
|
||||
<INPUT TYPE=radio NAME=casefold VALUE=no>
|
||||
Case sensitive
|
||||
<BR>
|
||||
<INPUT TYPE=hidden NAME=req VALUE=search>
|
||||
</FORM>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2>Other forms of %(FAQNAME)s access:</H2>
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="%(FAQCGI)s?req=index">FAQ index</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=all">The whole FAQ</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent">What's new in the FAQ?</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=roulette">FAQ roulette</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=add">Add a FAQ entry</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=delete">Delete a FAQ entry</A>
|
||||
</UL>
|
||||
"""
|
||||
|
||||
# Index formatting
|
||||
|
||||
INDEX_SECTION = """
|
||||
<P>
|
||||
<HR>
|
||||
<H2>%(sec)s. %(title)s</H2>
|
||||
<UL>
|
||||
"""
|
||||
|
||||
INDEX_ADDSECTION = """
|
||||
<P>
|
||||
<LI><A HREF="%(FAQCGI)s?req=new&section=%(sec)s">Add new entry</A>
|
||||
(at this point)
|
||||
"""
|
||||
|
||||
INDEX_ENDSECTION = """
|
||||
</UL>
|
||||
"""
|
||||
|
||||
INDEX_ENTRY = """\
|
||||
<LI><A HREF="%(FAQCGI)s?req=show&file=%(file)s">%(title)s</A>
|
||||
"""
|
||||
|
||||
LOCAL_ENTRY = """\
|
||||
<LI><A HREF="#%(sec)s.%(num)s">%(title)s</A>
|
||||
"""
|
||||
|
||||
# Entry formatting
|
||||
|
||||
ENTRY_HEADER1 = """
|
||||
<HR>
|
||||
<H2><A NAME="%(sec)s.%(num)s">%(title)s</A>\
|
||||
"""
|
||||
|
||||
ENTRY_HEADER2 = """\
|
||||
</H2>
|
||||
"""
|
||||
|
||||
ENTRY_FOOTER = """
|
||||
<A HREF="%(FAQCGI)s?req=edit&file=%(file)s">Edit this entry</A> /
|
||||
<A HREF="%(FAQCGI)s?req=log&file=%(file)s">Log info</A>
|
||||
"""
|
||||
|
||||
ENTRY_LOGINFO = """
|
||||
/ Last changed on %(last_changed_date)s by
|
||||
<A HREF="mailto:%(last_changed_email)s">%(last_changed_author)s</A>
|
||||
"""
|
||||
|
||||
# Search
|
||||
|
||||
NO_HITS = """
|
||||
No hits.
|
||||
"""
|
||||
|
||||
ONE_HIT = """
|
||||
Your search matched the following entry:
|
||||
"""
|
||||
|
||||
FEW_HITS = """
|
||||
Your search matched the following %(count)s entries:
|
||||
"""
|
||||
|
||||
MANY_HITS = """
|
||||
Your search matched more than %(MAXHITS)s entries.
|
||||
The %(count)s matching entries are presented here ordered by section:
|
||||
"""
|
||||
|
||||
# RCS log and diff
|
||||
|
||||
LOG = """
|
||||
Click on a revision line to see the diff between that revision and the
|
||||
previous one.
|
||||
"""
|
||||
|
||||
REVISIONLINK = """\
|
||||
<A HREF="%(FAQCGI)s?req=revision&file=%(file)s&rev=%(rev)s"
|
||||
>%(line)s</A>\
|
||||
"""
|
||||
DIFFLINK = """\
|
||||
(<A HREF="%(FAQCGI)s?req=diff&file=%(file)s&\
|
||||
prev=%(prev)s&rev=%(rev)s"
|
||||
>diff -r%(prev)s -r%(rev)s</A>)\
|
||||
"""
|
||||
|
||||
# Recently changed entries
|
||||
|
||||
NO_RECENT = """
|
||||
<HR>
|
||||
No %(FAQNAME)s entries were changed in the last %(period)s.
|
||||
"""
|
||||
|
||||
VIEW_MENU = """
|
||||
<HR>
|
||||
View entries changed in the last...
|
||||
<UL>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent&days=1">24 hours</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent&days=2">2 days</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent&days=3">3 days</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent&days=7">week</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent&days=28">4 weeks</A>
|
||||
<LI><A HREF="%(FAQCGI)s?req=recent&days=365250">millennium</A>
|
||||
</UL>
|
||||
"""
|
||||
|
||||
ONE_RECENT = VIEW_MENU + """
|
||||
The following %(FAQNAME)s entry was changed in the last %(period)s:
|
||||
"""
|
||||
|
||||
SOME_RECENT = VIEW_MENU + """
|
||||
The following %(count)s %(FAQNAME)s entries were changed
|
||||
in the last %(period)s, most recently changed shown first:
|
||||
"""
|
||||
|
||||
TAIL_RECENT = VIEW_MENU
|
||||
|
||||
# Last changed banner on "all" (strftime format)
|
||||
LAST_CHANGED = "Last changed on %c %Z"
|
||||
|
||||
# "Compat" command prologue (this has no <BODY> tag)
|
||||
COMPAT = """
|
||||
<H1>The whole %(FAQNAME)s</H1>
|
||||
See also the <A HREF="%(FAQCGI)s?req=home">%(FAQNAME)s Wizard</A>.
|
||||
<P>
|
||||
"""
|
||||
|
||||
# Editing
|
||||
|
||||
EDITHEAD = """
|
||||
<A HREF="%(FAQCGI)s?req=help">Click for Help</A>
|
||||
"""
|
||||
|
||||
REVIEWHEAD = EDITHEAD
|
||||
|
||||
|
||||
EDITFORM1 = """
|
||||
<FORM ACTION="%(FAQCGI)s" METHOD=POST>
|
||||
<INPUT TYPE=hidden NAME=req VALUE=review>
|
||||
<INPUT TYPE=hidden NAME=file VALUE=%(file)s>
|
||||
<INPUT TYPE=hidden NAME=editversion VALUE=%(editversion)s>
|
||||
<HR>
|
||||
"""
|
||||
|
||||
EDITFORM2 = """
|
||||
Title: <INPUT TYPE=text SIZE=70 NAME=title VALUE="%(title)s"><BR>
|
||||
<TEXTAREA COLS=72 ROWS=20 NAME=body>%(body)s
|
||||
</TEXTAREA><BR>
|
||||
Log message (reason for the change):<BR>
|
||||
<TEXTAREA COLS=72 ROWS=5 NAME=log>%(log)s
|
||||
</TEXTAREA><BR>
|
||||
Please provide the following information for logging purposes:
|
||||
<TABLE FRAME=none COLS=2>
|
||||
<TR>
|
||||
<TD>Name:
|
||||
<TD><INPUT TYPE=text SIZE=40 NAME=author VALUE="%(author)s">
|
||||
<TR>
|
||||
<TD>Email:
|
||||
<TD><INPUT TYPE=text SIZE=40 NAME=email VALUE="%(email)s">
|
||||
<TR>
|
||||
<TD>Password:
|
||||
<TD><INPUT TYPE=password SIZE=20 NAME=password VALUE="%(password)s">
|
||||
</TABLE>
|
||||
|
||||
<INPUT TYPE=submit NAME=review VALUE="Preview Edit">
|
||||
Click this button to preview your changes.
|
||||
"""
|
||||
|
||||
EDITFORM3 = """
|
||||
</FORM>
|
||||
"""
|
||||
|
||||
COMMIT = """
|
||||
<INPUT TYPE=submit NAME=commit VALUE="Commit">
|
||||
Click this button to commit your changes.
|
||||
<HR>
|
||||
"""
|
||||
|
||||
NOCOMMIT_HEAD = """
|
||||
To commit your changes, please correct the following errors in the
|
||||
form below and click the Preview Edit button.
|
||||
<UL>
|
||||
"""
|
||||
NOCOMMIT_TAIL = """
|
||||
</UL>
|
||||
<HR>
|
||||
"""
|
||||
|
||||
CANTCOMMIT_HEAD = """
|
||||
Some required information is missing:
|
||||
<UL>
|
||||
"""
|
||||
NEED_PASSWD = "<LI>You must provide the correct password.\n"
|
||||
NEED_AUTHOR = "<LI>You must enter your name.\n"
|
||||
NEED_EMAIL = "<LI>You must enter your email address.\n"
|
||||
NEED_LOG = "<LI>You must enter a log message.\n"
|
||||
CANTCOMMIT_TAIL = """
|
||||
</UL>
|
||||
Please use your browser's Back command to correct the form and commit
|
||||
again.
|
||||
"""
|
||||
|
||||
NEWCONFLICT = """
|
||||
<P>
|
||||
You are creating a new entry, but the entry number specified is not
|
||||
correct.
|
||||
<P>
|
||||
The two most common causes of this problem are:
|
||||
<UL>
|
||||
<LI>After creating the entry yourself, you went back in your browser,
|
||||
edited the entry some more, and clicked Commit again.
|
||||
<LI>Someone else started creating a new entry in the same section and
|
||||
committed before you did.
|
||||
</UL>
|
||||
(It is also possible that the last entry in the section was physically
|
||||
deleted, but this should not happen except through manual intervention
|
||||
by the FAQ maintainer.)
|
||||
<P>
|
||||
<A HREF="%(FAQCGI)s?req=new&section=%(sec)s">Click here to try
|
||||
again.</A>
|
||||
<P>
|
||||
"""
|
||||
|
||||
VERSIONCONFLICT = """
|
||||
<P>
|
||||
You edited version %(editversion)s but the current version is %(version)s.
|
||||
<P>
|
||||
The two most common causes of this problem are:
|
||||
<UL>
|
||||
<LI>After committing a change, you went back in your browser,
|
||||
edited the entry some more, and clicked Commit again.
|
||||
<LI>Someone else started editing the same entry and committed
|
||||
before you did.
|
||||
</UL>
|
||||
<P>
|
||||
<A HREF="%(FAQCGI)s?req=show&file=%(file)s">Click here to reload
|
||||
the entry and try again.</A>
|
||||
<P>
|
||||
"""
|
||||
|
||||
CANTWRITE = """
|
||||
Can't write file %(file)s (%(why)s).
|
||||
"""
|
||||
|
||||
FILEHEADER = """\
|
||||
Title: %(title)s
|
||||
Last-Changed-Date: %(date)s
|
||||
Last-Changed-Author: %(author)s
|
||||
Last-Changed-Email: %(email)s
|
||||
Last-Changed-Remote-Host: %(REMOTE_HOST)s
|
||||
Last-Changed-Remote-Address: %(REMOTE_ADDR)s
|
||||
"""
|
||||
|
||||
LOGHEADER = """\
|
||||
Last-Changed-Date: %(date)s
|
||||
Last-Changed-Author: %(author)s
|
||||
Last-Changed-Email: %(email)s
|
||||
Last-Changed-Remote-Host: %(REMOTE_HOST)s
|
||||
Last-Changed-Remote-Address: %(REMOTE_ADDR)s
|
||||
|
||||
%(log)s
|
||||
"""
|
||||
|
||||
COMMITTED = """
|
||||
Your changes have been committed.
|
||||
"""
|
||||
|
||||
COMMITFAILED = """
|
||||
Exit status %(sts)s.
|
||||
"""
|
||||
|
||||
# Add/Delete
|
||||
|
||||
ADD_HEAD = """
|
||||
At the moment, new entries can only be added at the end of a section.
|
||||
This is because the entry numbers are also their
|
||||
unique identifiers -- it's a bad idea to renumber entries.
|
||||
<P>
|
||||
Click on the section to which you want to add a new entry:
|
||||
<UL>
|
||||
"""
|
||||
|
||||
ADD_SECTION = """\
|
||||
<LI><A HREF="%(FAQCGI)s?req=new&section=%(section)s">%(section)s. %(title)s</A>
|
||||
"""
|
||||
|
||||
ADD_TAIL = """
|
||||
</UL>
|
||||
"""
|
||||
|
||||
ROULETTE = """
|
||||
<P>Hit your browser's Reload button to play again.<P>
|
||||
"""
|
||||
|
||||
DELETE = """
|
||||
At the moment, there's no direct way to delete entries.
|
||||
This is because the entry numbers are also their
|
||||
unique identifiers -- it's a bad idea to renumber entries.
|
||||
<P>
|
||||
If you really think an entry needs to be deleted,
|
||||
change the title to "(deleted)" and make the body
|
||||
empty (keep the entry number in the title though).
|
||||
"""
|
||||
|
||||
# Help file for the FAQ Edit Wizard
|
||||
|
||||
HELP = """
|
||||
Using the %(FAQNAME)s Edit Wizard speaks mostly for itself. Here are
|
||||
some answers to questions you are likely to ask:
|
||||
|
||||
<P><HR>
|
||||
|
||||
<H2>I can review an entry but I can't commit it.</H2>
|
||||
|
||||
The commit button only appears if the following conditions are met:
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The Name field is not empty.
|
||||
|
||||
<LI>The Email field contains at least an @ character.
|
||||
|
||||
<LI>The Log message box is not empty.
|
||||
|
||||
<LI>The Password field contains the proper password.
|
||||
|
||||
</UL>
|
||||
|
||||
<P><HR>
|
||||
|
||||
<H2>What is the password?</H2>
|
||||
|
||||
At the moment, only PSA members will be told the password. This is a
|
||||
good time to join the PSA! See <A
|
||||
HREF="http://www.python.org/psa/">the PSA home page</A>.
|
||||
|
||||
<P><HR>
|
||||
|
||||
<H2>Can I use HTML in the FAQ entry?</H2>
|
||||
|
||||
Yes, if you include it in <HTML&rt; and </HTML> tags.
|
||||
<P>
|
||||
Also, if you include a URL or an email address in the text it will
|
||||
automatigally become an anchor of the right type. Also, *word*
|
||||
is made italic (but only for single alphabetic words).
|
||||
|
||||
<P><HR>
|
||||
|
||||
<H2>How do I delineate paragraphs?</H2>
|
||||
|
||||
Use blank lines to separate paragraphs.
|
||||
|
||||
<P><HR>
|
||||
|
||||
<H2>How do I enter example text?</H2>
|
||||
|
||||
Any line that begins with a space or tab is assumed to be part of
|
||||
literal text. Blocks of literal text delineated by blank lines are
|
||||
placed inside <PRE>...</PRE>.
|
||||
"""
|
||||
|
||||
# Load local customizations again, in case they set some other variables
|
||||
|
||||
try:
|
||||
from faqcust import *
|
||||
except ImportError:
|
||||
pass
|
||||
1
project/jni/python/src/Tools/faqwiz/faqcust.py
Normal file
1
project/jni/python/src/Tools/faqwiz/faqcust.py
Normal file
@@ -0,0 +1 @@
|
||||
# Add your customizations here -- modified copies of what's in faqconf.py.
|
||||
33
project/jni/python/src/Tools/faqwiz/faqw.py
Normal file
33
project/jni/python/src/Tools/faqwiz/faqw.py
Normal file
@@ -0,0 +1,33 @@
|
||||
#! /usr/local/bin/python
|
||||
|
||||
"""FAQ wizard bootstrap."""
|
||||
|
||||
# This is a longer version of the bootstrap script given at the end of
|
||||
# faqwin.py; it prints timing statistics at the end of the regular CGI
|
||||
# script's output (so you can monitor how it is doing).
|
||||
|
||||
# This script should be placed in your cgi-bin directory and made
|
||||
# executable.
|
||||
|
||||
# You need to edit the first line and the lines that define FAQDIR and
|
||||
# SRCDIR, below: change /usr/local/bin/python to where your Python
|
||||
# interpreter lives, change the value for FAQDIR to where your FAQ
|
||||
# lives, and change the value for SRCDIR to where your faqwiz.py
|
||||
# module lives. The faqconf.py and faqcust.py files live there, too.
|
||||
|
||||
import os
|
||||
t1 = os.times() # If this doesn't work, just get rid of the timing code!
|
||||
try:
|
||||
FAQDIR = "/usr/people/guido/python/FAQ"
|
||||
SRCDIR = "/usr/people/guido/python/src/Tools/faqwiz"
|
||||
import os, sys
|
||||
os.chdir(FAQDIR)
|
||||
sys.path.insert(0, SRCDIR)
|
||||
import faqwiz
|
||||
except SystemExit, n:
|
||||
sys.exit(n)
|
||||
except:
|
||||
t, v, tb = sys.exc_info()
|
||||
print
|
||||
import cgi
|
||||
cgi.print_exception(t, v, tb)
|
||||
841
project/jni/python/src/Tools/faqwiz/faqwiz.py
Normal file
841
project/jni/python/src/Tools/faqwiz/faqwiz.py
Normal file
@@ -0,0 +1,841 @@
|
||||
"""Generic FAQ Wizard.
|
||||
|
||||
This is a CGI program that maintains a user-editable FAQ. It uses RCS
|
||||
to keep track of changes to individual FAQ entries. It is fully
|
||||
configurable; everything you might want to change when using this
|
||||
program to maintain some other FAQ than the Python FAQ is contained in
|
||||
the configuration module, faqconf.py.
|
||||
|
||||
Note that this is not an executable script; it's an importable module.
|
||||
The actual script to place in cgi-bin is faqw.py.
|
||||
|
||||
"""
|
||||
|
||||
import sys, time, os, stat, re, cgi, faqconf
|
||||
from faqconf import * # This imports all uppercase names
|
||||
now = time.time()
|
||||
|
||||
class FileError:
|
||||
def __init__(self, file):
|
||||
self.file = file
|
||||
|
||||
class InvalidFile(FileError):
|
||||
pass
|
||||
|
||||
class NoSuchSection(FileError):
|
||||
def __init__(self, section):
|
||||
FileError.__init__(self, NEWFILENAME %(section, 1))
|
||||
self.section = section
|
||||
|
||||
class NoSuchFile(FileError):
|
||||
def __init__(self, file, why=None):
|
||||
FileError.__init__(self, file)
|
||||
self.why = why
|
||||
|
||||
def escape(s):
|
||||
s = s.replace('&', '&')
|
||||
s = s.replace('<', '<')
|
||||
s = s.replace('>', '>')
|
||||
return s
|
||||
|
||||
def escapeq(s):
|
||||
s = escape(s)
|
||||
s = s.replace('"', '"')
|
||||
return s
|
||||
|
||||
def _interpolate(format, args, kw):
|
||||
try:
|
||||
quote = kw['_quote']
|
||||
except KeyError:
|
||||
quote = 1
|
||||
d = (kw,) + args + (faqconf.__dict__,)
|
||||
m = MagicDict(d, quote)
|
||||
return format % m
|
||||
|
||||
def interpolate(format, *args, **kw):
|
||||
return _interpolate(format, args, kw)
|
||||
|
||||
def emit(format, *args, **kw):
|
||||
try:
|
||||
f = kw['_file']
|
||||
except KeyError:
|
||||
f = sys.stdout
|
||||
f.write(_interpolate(format, args, kw))
|
||||
|
||||
translate_prog = None
|
||||
|
||||
def translate(text, pre=0):
|
||||
global translate_prog
|
||||
if not translate_prog:
|
||||
translate_prog = prog = re.compile(
|
||||
r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
|
||||
else:
|
||||
prog = translate_prog
|
||||
i = 0
|
||||
list = []
|
||||
while 1:
|
||||
m = prog.search(text, i)
|
||||
if not m:
|
||||
break
|
||||
j = m.start()
|
||||
list.append(escape(text[i:j]))
|
||||
i = j
|
||||
url = m.group(0)
|
||||
while url[-1] in '();:,.?\'"<>':
|
||||
url = url[:-1]
|
||||
i = i + len(url)
|
||||
url = escape(url)
|
||||
if not pre or (pre and PROCESS_PREFORMAT):
|
||||
if ':' in url:
|
||||
repl = '<A HREF="%s">%s</A>' % (url, url)
|
||||
else:
|
||||
repl = '<A HREF="mailto:%s">%s</A>' % (url, url)
|
||||
else:
|
||||
repl = url
|
||||
list.append(repl)
|
||||
j = len(text)
|
||||
list.append(escape(text[i:j]))
|
||||
return ''.join(list)
|
||||
|
||||
def emphasize(line):
|
||||
return re.sub(r'\*([a-zA-Z]+)\*', r'<I>\1</I>', line)
|
||||
|
||||
revparse_prog = None
|
||||
|
||||
def revparse(rev):
|
||||
global revparse_prog
|
||||
if not revparse_prog:
|
||||
revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1,4})$')
|
||||
m = revparse_prog.match(rev)
|
||||
if not m:
|
||||
return None
|
||||
[major, minor] = map(int, m.group(1, 2))
|
||||
return major, minor
|
||||
|
||||
logon = 0
|
||||
def log(text):
|
||||
if logon:
|
||||
logfile = open("logfile", "a")
|
||||
logfile.write(text + "\n")
|
||||
logfile.close()
|
||||
|
||||
def load_cookies():
|
||||
if not os.environ.has_key('HTTP_COOKIE'):
|
||||
return {}
|
||||
raw = os.environ['HTTP_COOKIE']
|
||||
words = [s.strip() for s in raw.split(';')]
|
||||
cookies = {}
|
||||
for word in words:
|
||||
i = word.find('=')
|
||||
if i >= 0:
|
||||
key, value = word[:i], word[i+1:]
|
||||
cookies[key] = value
|
||||
return cookies
|
||||
|
||||
def load_my_cookie():
|
||||
cookies = load_cookies()
|
||||
try:
|
||||
value = cookies[COOKIE_NAME]
|
||||
except KeyError:
|
||||
return {}
|
||||
import urllib
|
||||
value = urllib.unquote(value)
|
||||
words = value.split('/')
|
||||
while len(words) < 3:
|
||||
words.append('')
|
||||
author = '/'.join(words[:-2])
|
||||
email = words[-2]
|
||||
password = words[-1]
|
||||
return {'author': author,
|
||||
'email': email,
|
||||
'password': password}
|
||||
|
||||
def send_my_cookie(ui):
|
||||
name = COOKIE_NAME
|
||||
value = "%s/%s/%s" % (ui.author, ui.email, ui.password)
|
||||
import urllib
|
||||
value = urllib.quote(value)
|
||||
then = now + COOKIE_LIFETIME
|
||||
gmt = time.gmtime(then)
|
||||
path = os.environ.get('SCRIPT_NAME', '/cgi-bin/')
|
||||
print "Set-Cookie: %s=%s; path=%s;" % (name, value, path),
|
||||
print time.strftime("expires=%a, %d-%b-%y %X GMT", gmt)
|
||||
|
||||
class MagicDict:
|
||||
|
||||
def __init__(self, d, quote):
|
||||
self.__d = d
|
||||
self.__quote = quote
|
||||
|
||||
def __getitem__(self, key):
|
||||
for d in self.__d:
|
||||
try:
|
||||
value = d[key]
|
||||
if value:
|
||||
value = str(value)
|
||||
if self.__quote:
|
||||
value = escapeq(value)
|
||||
return value
|
||||
except KeyError:
|
||||
pass
|
||||
return ''
|
||||
|
||||
class UserInput:
|
||||
|
||||
def __init__(self):
|
||||
self.__form = cgi.FieldStorage()
|
||||
#log("\n\nbody: " + self.body)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[0] == '_':
|
||||
raise AttributeError
|
||||
try:
|
||||
value = self.__form[name].value
|
||||
except (TypeError, KeyError):
|
||||
value = ''
|
||||
else:
|
||||
value = value.strip()
|
||||
setattr(self, name, value)
|
||||
return value
|
||||
|
||||
def __getitem__(self, key):
|
||||
return getattr(self, key)
|
||||
|
||||
class FaqEntry:
|
||||
|
||||
def __init__(self, fp, file, sec_num):
|
||||
self.file = file
|
||||
self.sec, self.num = sec_num
|
||||
if fp:
|
||||
import rfc822
|
||||
self.__headers = rfc822.Message(fp)
|
||||
self.body = fp.read().strip()
|
||||
else:
|
||||
self.__headers = {'title': "%d.%d. " % sec_num}
|
||||
self.body = ''
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[0] == '_':
|
||||
raise AttributeError
|
||||
key = '-'.join(name.split('_'))
|
||||
try:
|
||||
value = self.__headers[key]
|
||||
except KeyError:
|
||||
value = ''
|
||||
setattr(self, name, value)
|
||||
return value
|
||||
|
||||
def __getitem__(self, key):
|
||||
return getattr(self, key)
|
||||
|
||||
def load_version(self):
|
||||
command = interpolate(SH_RLOG_H, self)
|
||||
p = os.popen(command)
|
||||
version = ''
|
||||
while 1:
|
||||
line = p.readline()
|
||||
if not line:
|
||||
break
|
||||
if line[:5] == 'head:':
|
||||
version = line[5:].strip()
|
||||
p.close()
|
||||
self.version = version
|
||||
|
||||
def getmtime(self):
|
||||
if not self.last_changed_date:
|
||||
return 0
|
||||
try:
|
||||
return os.stat(self.file)[stat.ST_MTIME]
|
||||
except os.error:
|
||||
return 0
|
||||
|
||||
def emit_marks(self):
|
||||
mtime = self.getmtime()
|
||||
if mtime >= now - DT_VERY_RECENT:
|
||||
emit(MARK_VERY_RECENT, self)
|
||||
elif mtime >= now - DT_RECENT:
|
||||
emit(MARK_RECENT, self)
|
||||
|
||||
def show(self, edit=1):
|
||||
emit(ENTRY_HEADER1, self)
|
||||
self.emit_marks()
|
||||
emit(ENTRY_HEADER2, self)
|
||||
pre = 0
|
||||
raw = 0
|
||||
for line in self.body.split('\n'):
|
||||
# Allow the user to insert raw html into a FAQ answer
|
||||
# (Skip Montanaro, with changes by Guido)
|
||||
tag = line.rstrip().lower()
|
||||
if tag == '<html>':
|
||||
raw = 1
|
||||
continue
|
||||
if tag == '</html>':
|
||||
raw = 0
|
||||
continue
|
||||
if raw:
|
||||
print line
|
||||
continue
|
||||
if not line.strip():
|
||||
if pre:
|
||||
print '</PRE>'
|
||||
pre = 0
|
||||
else:
|
||||
print '<P>'
|
||||
else:
|
||||
if not line[0].isspace():
|
||||
if pre:
|
||||
print '</PRE>'
|
||||
pre = 0
|
||||
else:
|
||||
if not pre:
|
||||
print '<PRE>'
|
||||
pre = 1
|
||||
if '/' in line or '@' in line:
|
||||
line = translate(line, pre)
|
||||
elif '<' in line or '&' in line:
|
||||
line = escape(line)
|
||||
if not pre and '*' in line:
|
||||
line = emphasize(line)
|
||||
print line
|
||||
if pre:
|
||||
print '</PRE>'
|
||||
pre = 0
|
||||
if edit:
|
||||
print '<P>'
|
||||
emit(ENTRY_FOOTER, self)
|
||||
if self.last_changed_date:
|
||||
emit(ENTRY_LOGINFO, self)
|
||||
print '<P>'
|
||||
|
||||
class FaqDir:
|
||||
|
||||
entryclass = FaqEntry
|
||||
|
||||
__okprog = re.compile(OKFILENAME)
|
||||
|
||||
def __init__(self, dir=os.curdir):
|
||||
self.__dir = dir
|
||||
self.__files = None
|
||||
|
||||
def __fill(self):
|
||||
if self.__files is not None:
|
||||
return
|
||||
self.__files = files = []
|
||||
okprog = self.__okprog
|
||||
for file in os.listdir(self.__dir):
|
||||
if self.__okprog.match(file):
|
||||
files.append(file)
|
||||
files.sort()
|
||||
|
||||
def good(self, file):
|
||||
return self.__okprog.match(file)
|
||||
|
||||
def parse(self, file):
|
||||
m = self.good(file)
|
||||
if not m:
|
||||
return None
|
||||
sec, num = m.group(1, 2)
|
||||
return int(sec), int(num)
|
||||
|
||||
def list(self):
|
||||
# XXX Caller shouldn't modify result
|
||||
self.__fill()
|
||||
return self.__files
|
||||
|
||||
def open(self, file):
|
||||
sec_num = self.parse(file)
|
||||
if not sec_num:
|
||||
raise InvalidFile(file)
|
||||
try:
|
||||
fp = open(file)
|
||||
except IOError, msg:
|
||||
raise NoSuchFile(file, msg)
|
||||
try:
|
||||
return self.entryclass(fp, file, sec_num)
|
||||
finally:
|
||||
fp.close()
|
||||
|
||||
def show(self, file, edit=1):
|
||||
self.open(file).show(edit=edit)
|
||||
|
||||
def new(self, section):
|
||||
if not SECTION_TITLES.has_key(section):
|
||||
raise NoSuchSection(section)
|
||||
maxnum = 0
|
||||
for file in self.list():
|
||||
sec, num = self.parse(file)
|
||||
if sec == section:
|
||||
maxnum = max(maxnum, num)
|
||||
sec_num = (section, maxnum+1)
|
||||
file = NEWFILENAME % sec_num
|
||||
return self.entryclass(None, file, sec_num)
|
||||
|
||||
class FaqWizard:
|
||||
|
||||
def __init__(self):
|
||||
self.ui = UserInput()
|
||||
self.dir = FaqDir()
|
||||
|
||||
def go(self):
|
||||
print 'Content-type: text/html'
|
||||
req = self.ui.req or 'home'
|
||||
mname = 'do_%s' % req
|
||||
try:
|
||||
meth = getattr(self, mname)
|
||||
except AttributeError:
|
||||
self.error("Bad request type %r." % (req,))
|
||||
else:
|
||||
try:
|
||||
meth()
|
||||
except InvalidFile, exc:
|
||||
self.error("Invalid entry file name %s" % exc.file)
|
||||
except NoSuchFile, exc:
|
||||
self.error("No entry with file name %s" % exc.file)
|
||||
except NoSuchSection, exc:
|
||||
self.error("No section number %s" % exc.section)
|
||||
self.epilogue()
|
||||
|
||||
def error(self, message, **kw):
|
||||
self.prologue(T_ERROR)
|
||||
emit(message, kw)
|
||||
|
||||
def prologue(self, title, entry=None, **kw):
|
||||
emit(PROLOGUE, entry, kwdict=kw, title=escape(title))
|
||||
|
||||
def epilogue(self):
|
||||
emit(EPILOGUE)
|
||||
|
||||
def do_home(self):
|
||||
self.prologue(T_HOME)
|
||||
emit(HOME)
|
||||
|
||||
def do_debug(self):
|
||||
self.prologue("FAQ Wizard Debugging")
|
||||
form = cgi.FieldStorage()
|
||||
cgi.print_form(form)
|
||||
cgi.print_environ(os.environ)
|
||||
cgi.print_directory()
|
||||
cgi.print_arguments()
|
||||
|
||||
def do_search(self):
|
||||
query = self.ui.query
|
||||
if not query:
|
||||
self.error("Empty query string!")
|
||||
return
|
||||
if self.ui.querytype == 'simple':
|
||||
query = re.escape(query)
|
||||
queries = [query]
|
||||
elif self.ui.querytype in ('anykeywords', 'allkeywords'):
|
||||
words = filter(None, re.split('\W+', query))
|
||||
if not words:
|
||||
self.error("No keywords specified!")
|
||||
return
|
||||
words = map(lambda w: r'\b%s\b' % w, words)
|
||||
if self.ui.querytype[:3] == 'any':
|
||||
queries = ['|'.join(words)]
|
||||
else:
|
||||
# Each of the individual queries must match
|
||||
queries = words
|
||||
else:
|
||||
# Default to regular expression
|
||||
queries = [query]
|
||||
self.prologue(T_SEARCH)
|
||||
progs = []
|
||||
for query in queries:
|
||||
if self.ui.casefold == 'no':
|
||||
p = re.compile(query)
|
||||
else:
|
||||
p = re.compile(query, re.IGNORECASE)
|
||||
progs.append(p)
|
||||
hits = []
|
||||
for file in self.dir.list():
|
||||
try:
|
||||
entry = self.dir.open(file)
|
||||
except FileError:
|
||||
constants
|
||||
for p in progs:
|
||||
if not p.search(entry.title) and not p.search(entry.body):
|
||||
break
|
||||
else:
|
||||
hits.append(file)
|
||||
if not hits:
|
||||
emit(NO_HITS, self.ui, count=0)
|
||||
elif len(hits) <= MAXHITS:
|
||||
if len(hits) == 1:
|
||||
emit(ONE_HIT, count=1)
|
||||
else:
|
||||
emit(FEW_HITS, count=len(hits))
|
||||
self.format_all(hits, headers=0)
|
||||
else:
|
||||
emit(MANY_HITS, count=len(hits))
|
||||
self.format_index(hits)
|
||||
|
||||
def do_all(self):
|
||||
self.prologue(T_ALL)
|
||||
files = self.dir.list()
|
||||
self.last_changed(files)
|
||||
self.format_index(files, localrefs=1)
|
||||
self.format_all(files)
|
||||
|
||||
def do_compat(self):
|
||||
files = self.dir.list()
|
||||
emit(COMPAT)
|
||||
self.last_changed(files)
|
||||
self.format_index(files, localrefs=1)
|
||||
self.format_all(files, edit=0)
|
||||
sys.exit(0) # XXX Hack to suppress epilogue
|
||||
|
||||
def last_changed(self, files):
|
||||
latest = 0
|
||||
for file in files:
|
||||
entry = self.dir.open(file)
|
||||
if entry:
|
||||
mtime = mtime = entry.getmtime()
|
||||
if mtime > latest:
|
||||
latest = mtime
|
||||
print time.strftime(LAST_CHANGED, time.localtime(latest))
|
||||
emit(EXPLAIN_MARKS)
|
||||
|
||||
def format_all(self, files, edit=1, headers=1):
|
||||
sec = 0
|
||||
for file in files:
|
||||
try:
|
||||
entry = self.dir.open(file)
|
||||
except NoSuchFile:
|
||||
continue
|
||||
if headers and entry.sec != sec:
|
||||
sec = entry.sec
|
||||
try:
|
||||
title = SECTION_TITLES[sec]
|
||||
except KeyError:
|
||||
title = "Untitled"
|
||||
emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n",
|
||||
sec=sec, title=title)
|
||||
entry.show(edit=edit)
|
||||
|
||||
def do_index(self):
|
||||
self.prologue(T_INDEX)
|
||||
files = self.dir.list()
|
||||
self.last_changed(files)
|
||||
self.format_index(files, add=1)
|
||||
|
||||
def format_index(self, files, add=0, localrefs=0):
|
||||
sec = 0
|
||||
for file in files:
|
||||
try:
|
||||
entry = self.dir.open(file)
|
||||
except NoSuchFile:
|
||||
continue
|
||||
if entry.sec != sec:
|
||||
if sec:
|
||||
if add:
|
||||
emit(INDEX_ADDSECTION, sec=sec)
|
||||
emit(INDEX_ENDSECTION, sec=sec)
|
||||
sec = entry.sec
|
||||
try:
|
||||
title = SECTION_TITLES[sec]
|
||||
except KeyError:
|
||||
title = "Untitled"
|
||||
emit(INDEX_SECTION, sec=sec, title=title)
|
||||
if localrefs:
|
||||
emit(LOCAL_ENTRY, entry)
|
||||
else:
|
||||
emit(INDEX_ENTRY, entry)
|
||||
entry.emit_marks()
|
||||
if sec:
|
||||
if add:
|
||||
emit(INDEX_ADDSECTION, sec=sec)
|
||||
emit(INDEX_ENDSECTION, sec=sec)
|
||||
|
||||
def do_recent(self):
|
||||
if not self.ui.days:
|
||||
days = 1
|
||||
else:
|
||||
days = float(self.ui.days)
|
||||
try:
|
||||
cutoff = now - days * 24 * 3600
|
||||
except OverflowError:
|
||||
cutoff = 0
|
||||
list = []
|
||||
for file in self.dir.list():
|
||||
entry = self.dir.open(file)
|
||||
if not entry:
|
||||
continue
|
||||
mtime = entry.getmtime()
|
||||
if mtime >= cutoff:
|
||||
list.append((mtime, file))
|
||||
list.sort()
|
||||
list.reverse()
|
||||
self.prologue(T_RECENT)
|
||||
if days <= 1:
|
||||
period = "%.2g hours" % (days*24)
|
||||
else:
|
||||
period = "%.6g days" % days
|
||||
if not list:
|
||||
emit(NO_RECENT, period=period)
|
||||
elif len(list) == 1:
|
||||
emit(ONE_RECENT, period=period)
|
||||
else:
|
||||
emit(SOME_RECENT, period=period, count=len(list))
|
||||
self.format_all(map(lambda (mtime, file): file, list), headers=0)
|
||||
emit(TAIL_RECENT)
|
||||
|
||||
def do_roulette(self):
|
||||
import random
|
||||
files = self.dir.list()
|
||||
if not files:
|
||||
self.error("No entries.")
|
||||
return
|
||||
file = random.choice(files)
|
||||
self.prologue(T_ROULETTE)
|
||||
emit(ROULETTE)
|
||||
self.dir.show(file)
|
||||
|
||||
def do_help(self):
|
||||
self.prologue(T_HELP)
|
||||
emit(HELP)
|
||||
|
||||
def do_show(self):
|
||||
entry = self.dir.open(self.ui.file)
|
||||
self.prologue(T_SHOW)
|
||||
entry.show()
|
||||
|
||||
def do_add(self):
|
||||
self.prologue(T_ADD)
|
||||
emit(ADD_HEAD)
|
||||
sections = SECTION_TITLES.items()
|
||||
sections.sort()
|
||||
for section, title in sections:
|
||||
emit(ADD_SECTION, section=section, title=title)
|
||||
emit(ADD_TAIL)
|
||||
|
||||
def do_delete(self):
|
||||
self.prologue(T_DELETE)
|
||||
emit(DELETE)
|
||||
|
||||
def do_log(self):
|
||||
entry = self.dir.open(self.ui.file)
|
||||
self.prologue(T_LOG, entry)
|
||||
emit(LOG, entry)
|
||||
self.rlog(interpolate(SH_RLOG, entry), entry)
|
||||
|
||||
def rlog(self, command, entry=None):
|
||||
output = os.popen(command).read()
|
||||
sys.stdout.write('<PRE>')
|
||||
athead = 0
|
||||
lines = output.split('\n')
|
||||
while lines and not lines[-1]:
|
||||
del lines[-1]
|
||||
if lines:
|
||||
line = lines[-1]
|
||||
if line[:1] == '=' and len(line) >= 40 and \
|
||||
line == line[0]*len(line):
|
||||
del lines[-1]
|
||||
headrev = None
|
||||
for line in lines:
|
||||
if entry and athead and line[:9] == 'revision ':
|
||||
rev = line[9:].split()
|
||||
mami = revparse(rev)
|
||||
if not mami:
|
||||
print line
|
||||
else:
|
||||
emit(REVISIONLINK, entry, rev=rev, line=line)
|
||||
if mami[1] > 1:
|
||||
prev = "%d.%d" % (mami[0], mami[1]-1)
|
||||
emit(DIFFLINK, entry, prev=prev, rev=rev)
|
||||
if headrev:
|
||||
emit(DIFFLINK, entry, prev=rev, rev=headrev)
|
||||
else:
|
||||
headrev = rev
|
||||
print
|
||||
athead = 0
|
||||
else:
|
||||
athead = 0
|
||||
if line[:1] == '-' and len(line) >= 20 and \
|
||||
line == len(line) * line[0]:
|
||||
athead = 1
|
||||
sys.stdout.write('<HR>')
|
||||
else:
|
||||
print line
|
||||
print '</PRE>'
|
||||
|
||||
def do_revision(self):
|
||||
entry = self.dir.open(self.ui.file)
|
||||
rev = self.ui.rev
|
||||
mami = revparse(rev)
|
||||
if not mami:
|
||||
self.error("Invalid revision number: %r." % (rev,))
|
||||
self.prologue(T_REVISION, entry)
|
||||
self.shell(interpolate(SH_REVISION, entry, rev=rev))
|
||||
|
||||
def do_diff(self):
|
||||
entry = self.dir.open(self.ui.file)
|
||||
prev = self.ui.prev
|
||||
rev = self.ui.rev
|
||||
mami = revparse(rev)
|
||||
if not mami:
|
||||
self.error("Invalid revision number: %r." % (rev,))
|
||||
if prev:
|
||||
if not revparse(prev):
|
||||
self.error("Invalid previous revision number: %r." % (prev,))
|
||||
else:
|
||||
prev = '%d.%d' % (mami[0], mami[1])
|
||||
self.prologue(T_DIFF, entry)
|
||||
self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev))
|
||||
|
||||
def shell(self, command):
|
||||
output = os.popen(command).read()
|
||||
sys.stdout.write('<PRE>')
|
||||
print escape(output)
|
||||
print '</PRE>'
|
||||
|
||||
def do_new(self):
|
||||
entry = self.dir.new(section=int(self.ui.section))
|
||||
entry.version = '*new*'
|
||||
self.prologue(T_EDIT)
|
||||
emit(EDITHEAD)
|
||||
emit(EDITFORM1, entry, editversion=entry.version)
|
||||
emit(EDITFORM2, entry, load_my_cookie())
|
||||
emit(EDITFORM3)
|
||||
entry.show(edit=0)
|
||||
|
||||
def do_edit(self):
|
||||
entry = self.dir.open(self.ui.file)
|
||||
entry.load_version()
|
||||
self.prologue(T_EDIT)
|
||||
emit(EDITHEAD)
|
||||
emit(EDITFORM1, entry, editversion=entry.version)
|
||||
emit(EDITFORM2, entry, load_my_cookie())
|
||||
emit(EDITFORM3)
|
||||
entry.show(edit=0)
|
||||
|
||||
def do_review(self):
|
||||
send_my_cookie(self.ui)
|
||||
if self.ui.editversion == '*new*':
|
||||
sec, num = self.dir.parse(self.ui.file)
|
||||
entry = self.dir.new(section=sec)
|
||||
entry.version = "*new*"
|
||||
if entry.file != self.ui.file:
|
||||
self.error("Commit version conflict!")
|
||||
emit(NEWCONFLICT, self.ui, sec=sec, num=num)
|
||||
return
|
||||
else:
|
||||
entry = self.dir.open(self.ui.file)
|
||||
entry.load_version()
|
||||
# Check that the FAQ entry number didn't change
|
||||
if self.ui.title.split()[:1] != entry.title.split()[:1]:
|
||||
self.error("Don't change the entry number please!")
|
||||
return
|
||||
# Check that the edited version is the current version
|
||||
if entry.version != self.ui.editversion:
|
||||
self.error("Commit version conflict!")
|
||||
emit(VERSIONCONFLICT, entry, self.ui)
|
||||
return
|
||||
commit_ok = ((not PASSWORD
|
||||
or self.ui.password == PASSWORD)
|
||||
and self.ui.author
|
||||
and '@' in self.ui.email
|
||||
and self.ui.log)
|
||||
if self.ui.commit:
|
||||
if not commit_ok:
|
||||
self.cantcommit()
|
||||
else:
|
||||
self.commit(entry)
|
||||
return
|
||||
self.prologue(T_REVIEW)
|
||||
emit(REVIEWHEAD)
|
||||
entry.body = self.ui.body
|
||||
entry.title = self.ui.title
|
||||
entry.show(edit=0)
|
||||
emit(EDITFORM1, self.ui, entry)
|
||||
if commit_ok:
|
||||
emit(COMMIT)
|
||||
else:
|
||||
emit(NOCOMMIT_HEAD)
|
||||
self.errordetail()
|
||||
emit(NOCOMMIT_TAIL)
|
||||
emit(EDITFORM2, self.ui, entry, load_my_cookie())
|
||||
emit(EDITFORM3)
|
||||
|
||||
def cantcommit(self):
|
||||
self.prologue(T_CANTCOMMIT)
|
||||
print CANTCOMMIT_HEAD
|
||||
self.errordetail()
|
||||
print CANTCOMMIT_TAIL
|
||||
|
||||
def errordetail(self):
|
||||
if PASSWORD and self.ui.password != PASSWORD:
|
||||
emit(NEED_PASSWD)
|
||||
if not self.ui.log:
|
||||
emit(NEED_LOG)
|
||||
if not self.ui.author:
|
||||
emit(NEED_AUTHOR)
|
||||
if not self.ui.email:
|
||||
emit(NEED_EMAIL)
|
||||
|
||||
def commit(self, entry):
|
||||
file = entry.file
|
||||
# Normalize line endings in body
|
||||
if '\r' in self.ui.body:
|
||||
self.ui.body = re.sub('\r\n?', '\n', self.ui.body)
|
||||
# Normalize whitespace in title
|
||||
self.ui.title = ' '.join(self.ui.title.split())
|
||||
# Check that there were any changes
|
||||
if self.ui.body == entry.body and self.ui.title == entry.title:
|
||||
self.error("You didn't make any changes!")
|
||||
return
|
||||
|
||||
# need to lock here because otherwise the file exists and is not writable (on NT)
|
||||
command = interpolate(SH_LOCK, file=file)
|
||||
p = os.popen(command)
|
||||
output = p.read()
|
||||
|
||||
try:
|
||||
os.unlink(file)
|
||||
except os.error:
|
||||
pass
|
||||
try:
|
||||
f = open(file, 'w')
|
||||
except IOError, why:
|
||||
self.error(CANTWRITE, file=file, why=why)
|
||||
return
|
||||
date = time.ctime(now)
|
||||
emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0)
|
||||
f.write('\n')
|
||||
f.write(self.ui.body)
|
||||
f.write('\n')
|
||||
f.close()
|
||||
|
||||
import tempfile
|
||||
tf = tempfile.NamedTemporaryFile()
|
||||
emit(LOGHEADER, self.ui, os.environ, date=date, _file=tf)
|
||||
tf.flush()
|
||||
tf.seek(0)
|
||||
|
||||
command = interpolate(SH_CHECKIN, file=file, tfn=tf.name)
|
||||
log("\n\n" + command)
|
||||
p = os.popen(command)
|
||||
output = p.read()
|
||||
sts = p.close()
|
||||
log("output: " + output)
|
||||
log("done: " + str(sts))
|
||||
log("TempFile:\n" + tf.read() + "end")
|
||||
|
||||
if not sts:
|
||||
self.prologue(T_COMMITTED)
|
||||
emit(COMMITTED)
|
||||
else:
|
||||
self.error(T_COMMITFAILED)
|
||||
emit(COMMITFAILED, sts=sts)
|
||||
print '<PRE>%s</PRE>' % escape(output)
|
||||
|
||||
try:
|
||||
os.unlink(tf.name)
|
||||
except os.error:
|
||||
pass
|
||||
|
||||
entry = self.dir.open(file)
|
||||
entry.show()
|
||||
|
||||
wiz = FaqWizard()
|
||||
wiz.go()
|
||||
55
project/jni/python/src/Tools/faqwiz/move-faqwiz.sh
Normal file
55
project/jni/python/src/Tools/faqwiz/move-faqwiz.sh
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Christian Reis <kiko@async.com.br>
|
||||
#
|
||||
# Moves
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# blackjesus:~> ./move-faqwiz.sh 2\.1 3\.2
|
||||
# Moving FAQ question 02.001 to 03.002
|
||||
|
||||
if [ x$2 = x ]; then
|
||||
echo "Need 2 args: original_version final_version."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -d data -o ! -d data/RCS ]; then
|
||||
echo "Run this inside the faqwiz data/ directory's parent dir."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
cut_n_pad() {
|
||||
t=`echo $1 | cut -d. -f $2`
|
||||
export $3=`echo $t | awk "{ tmp = \\$0; l = length(tmp); for (i = 0; i < $2-l+1; i++) { tmp = "0".tmp } print tmp }"`
|
||||
}
|
||||
|
||||
cut_n_pad $1 1 prefix1
|
||||
cut_n_pad $1 2 suffix1
|
||||
cut_n_pad $2 1 prefix2
|
||||
cut_n_pad $2 2 suffix2
|
||||
if which tempfile >/dev/null; then
|
||||
tmpfile=$(tempfile -d .)
|
||||
elif [ -n "$RANDOM" ]; then
|
||||
tmpfile=tmp$RANDOM.tmp
|
||||
else
|
||||
tmpfile=tmp$$.tmp
|
||||
fi
|
||||
file1=faq$prefix1.$suffix1.htp
|
||||
file2=faq$prefix2.$suffix2.htp
|
||||
|
||||
echo "Moving FAQ question $prefix1.$suffix1 to $prefix2.$suffix2"
|
||||
|
||||
sed -e "s/$1\./$2\./g" data/$file1 > ${tmpfile}1
|
||||
sed -e "s/$1\./$2\./g" data/RCS/$file1,v > ${tmpfile}2
|
||||
|
||||
if [ -f data/$file2 ]; then
|
||||
echo "Target FAQ exists. Won't clobber."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
mv ${tmpfile}1 data/$file2
|
||||
mv ${tmpfile}2 data/RCS/$file2,v
|
||||
mv data/$file1 data/$file1.orig
|
||||
mv data/RCS/$file1,v data/RCS/$file1,v.orig
|
||||
|
||||
8
project/jni/python/src/Tools/framer/README.txt
Normal file
8
project/jni/python/src/Tools/framer/README.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
framer is a tool to generate boilerplate code for C extension types.
|
||||
|
||||
The boilerplate is generated from a specification object written in
|
||||
Python. The specification uses the class statement to describe the
|
||||
extension module and any extension types it contains. From the
|
||||
specification, framer can generate all the boilerplate C code,
|
||||
including function definitions, argument handling code, and type
|
||||
objects.
|
||||
6
project/jni/python/src/Tools/framer/TODO.txt
Normal file
6
project/jni/python/src/Tools/framer/TODO.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Add spec for getsets.
|
||||
Generate a distutils setup script.
|
||||
Handle operator overloading.
|
||||
Generate traverse and clear methods for GC.
|
||||
Handle mapping, sequence, buffer protocols.
|
||||
Finish the todo list.
|
||||
126
project/jni/python/src/Tools/framer/example.py
Normal file
126
project/jni/python/src/Tools/framer/example.py
Normal file
@@ -0,0 +1,126 @@
|
||||
"""Generate the skeleton for cStringIO as an example of framer."""
|
||||
|
||||
from framer.bases import Module, Type
|
||||
from framer.member import member
|
||||
|
||||
class cStringIO(Module):
|
||||
"""A simple fast partial StringIO replacement.
|
||||
|
||||
This module provides a simple useful replacement for the StringIO
|
||||
module that is written in C. It does not provide the full
|
||||
generality of StringIO, but it provides enough for most
|
||||
applications and is especially useful in conjunction with the
|
||||
pickle module.
|
||||
|
||||
Usage:
|
||||
|
||||
from cStringIO import StringIO
|
||||
|
||||
an_output_stream = StringIO()
|
||||
an_output_stream.write(some_stuff)
|
||||
...
|
||||
value = an_output_stream.getvalue()
|
||||
|
||||
an_input_stream = StringIO(a_string)
|
||||
spam = an_input_stream.readline()
|
||||
spam = an_input_stream.read(5)
|
||||
an_input_stream.seek(0) # OK, start over
|
||||
spam = an_input_stream.read() # and read it all
|
||||
"""
|
||||
|
||||
__file__ = "cStringIO.c"
|
||||
|
||||
def StringIO(o):
|
||||
"""Return a StringIO-like stream for reading or writing"""
|
||||
StringIO.pyarg = "|O"
|
||||
|
||||
class InputType(Type):
|
||||
"Simple type for treating strings as input file streams"
|
||||
|
||||
abbrev = "input"
|
||||
|
||||
struct = """\
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
char *buf;
|
||||
int pos;
|
||||
int size;
|
||||
PyObject *pbuf;
|
||||
} InputObject;
|
||||
"""
|
||||
|
||||
def flush(self):
|
||||
"""Does nothing"""
|
||||
|
||||
def getvalue(self):
|
||||
"""Get the string value.
|
||||
|
||||
If use_pos is specified and is a true value, then the
|
||||
string returned will include only the text up to the
|
||||
current file position.
|
||||
"""
|
||||
|
||||
def isatty(self):
|
||||
"""Always returns False"""
|
||||
|
||||
def read(self, s):
|
||||
"""Return s characters or the rest of the string."""
|
||||
read.pyarg = "|i"
|
||||
|
||||
def readline(self):
|
||||
"""Read one line."""
|
||||
|
||||
def readlines(self, hint):
|
||||
"""Read all lines."""
|
||||
readlines.pyarg = "|i"
|
||||
|
||||
def reset(self):
|
||||
"""Reset the file position to the beginning."""
|
||||
|
||||
def tell(self):
|
||||
"""Get the current position."""
|
||||
|
||||
def truncate(self, pos):
|
||||
"""Truncate the file at the current position."""
|
||||
truncate.pyarg = "|i"
|
||||
|
||||
def seek(self, position, mode=0):
|
||||
"""Set the current position.
|
||||
|
||||
The optional mode argument can be 0 for absolute, 1 for relative,
|
||||
and 2 for relative to EOF. The default is absolute.
|
||||
"""
|
||||
seek.pyarg = "i|i"
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
class OutputType(InputType):
|
||||
"Simple type for output strings."
|
||||
|
||||
abbrev = "output"
|
||||
|
||||
struct = """\
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
char *buf;
|
||||
int pos;
|
||||
int size;
|
||||
int softspace;
|
||||
} OutputObject;
|
||||
"""
|
||||
|
||||
softspace = member()
|
||||
|
||||
def close(self):
|
||||
"""Explicitly release resources."""
|
||||
|
||||
def write(self, s):
|
||||
"""Write a string to the file."""
|
||||
# XXX Hack: writing None resets the buffer
|
||||
|
||||
def writelines(self, lines):
|
||||
"""Write each string in lines."""
|
||||
|
||||
|
||||
cStringIO.gen()
|
||||
6
project/jni/python/src/Tools/framer/framer/__init__.py
Normal file
6
project/jni/python/src/Tools/framer/framer/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""A tool to generate basic framework for C extension types.
|
||||
|
||||
The basic ideas is the same as modulator, but the code generates code
|
||||
using many of the new features introduced in Python 2.2. It also
|
||||
takes a more declarative approach to generating code.
|
||||
"""
|
||||
220
project/jni/python/src/Tools/framer/framer/bases.py
Normal file
220
project/jni/python/src/Tools/framer/framer/bases.py
Normal file
@@ -0,0 +1,220 @@
|
||||
"""Provides the Module and Type base classes that user code inherits from."""
|
||||
|
||||
__all__ = ["Module", "Type", "member"]
|
||||
|
||||
from framer import struct, template
|
||||
from framer.function import Function, Method
|
||||
from framer.member import member
|
||||
from framer.slots import *
|
||||
from framer.util import cstring, unindent
|
||||
|
||||
from types import FunctionType
|
||||
|
||||
def sortitems(dict):
|
||||
L = dict.items()
|
||||
L.sort()
|
||||
return L
|
||||
|
||||
# The Module and Type classes are implemented using metaclasses,
|
||||
# because most of the methods are class methods. It is easier to use
|
||||
# metaclasses than the cumbersome classmethod() builtin. They have
|
||||
# class methods because they are exposed to user code as base classes.
|
||||
|
||||
class BaseMetaclass(type):
|
||||
"""Shared infrastructure for generating modules and types."""
|
||||
|
||||
# just methoddef so far
|
||||
|
||||
def dump_methoddef(self, f, functions, vars):
|
||||
def p(templ, vars=vars): # helper function to generate output
|
||||
print >> f, templ % vars
|
||||
|
||||
if not functions:
|
||||
return
|
||||
p(template.methoddef_start)
|
||||
for name, func in sortitems(functions):
|
||||
if func.__doc__:
|
||||
p(template.methoddef_def_doc, func.vars)
|
||||
else:
|
||||
p(template.methoddef_def, func.vars)
|
||||
p(template.methoddef_end)
|
||||
|
||||
class ModuleMetaclass(BaseMetaclass):
|
||||
"""Provides methods for Module class."""
|
||||
|
||||
def gen(self):
|
||||
self.analyze()
|
||||
self.initvars()
|
||||
f = open(self.__filename, "w")
|
||||
self.dump(f)
|
||||
f.close()
|
||||
|
||||
def analyze(self):
|
||||
self.name = getattr(self, "abbrev", self.__name__)
|
||||
self.__functions = {}
|
||||
self.__types = {}
|
||||
self.__members = False
|
||||
|
||||
for name, obj in self.__dict__.iteritems():
|
||||
if isinstance(obj, FunctionType):
|
||||
self.__functions[name] = Function(obj, self)
|
||||
elif isinstance(obj, TypeMetaclass):
|
||||
obj._TypeMetaclass__module = self.name
|
||||
obj.analyze()
|
||||
self.__types[name] = obj
|
||||
if obj.has_members():
|
||||
self.__members = True
|
||||
|
||||
def initvars(self):
|
||||
v = self.__vars = {}
|
||||
filename = getattr(self, "__file__", None)
|
||||
if filename is None:
|
||||
filename = self.__name__ + "module.c"
|
||||
self.__filename = v["FileName"] = filename
|
||||
name = v["ModuleName"] = self.__name__
|
||||
v["MethodDefName"] = "%s_methods" % name
|
||||
v["ModuleDocstring"] = cstring(unindent(self.__doc__))
|
||||
|
||||
def dump(self, f):
|
||||
def p(templ, vars=self.__vars): # helper function to generate output
|
||||
print >> f, templ % vars
|
||||
|
||||
p(template.module_start)
|
||||
if self.__members:
|
||||
p(template.member_include)
|
||||
print >> f
|
||||
|
||||
if self.__doc__:
|
||||
p(template.module_doc)
|
||||
|
||||
for name, type in sortitems(self.__types):
|
||||
type.dump(f)
|
||||
|
||||
for name, func in sortitems(self.__functions):
|
||||
func.dump(f)
|
||||
|
||||
self.dump_methoddef(f, self.__functions, self.__vars)
|
||||
|
||||
p(template.module_init_start)
|
||||
for name, type in sortitems(self.__types):
|
||||
type.dump_init(f)
|
||||
|
||||
p("}")
|
||||
|
||||
class Module:
|
||||
__metaclass__ = ModuleMetaclass
|
||||
|
||||
class TypeMetaclass(BaseMetaclass):
|
||||
|
||||
def dump(self, f):
|
||||
self.initvars()
|
||||
|
||||
# defined after initvars() so that __vars is defined
|
||||
def p(templ, vars=self.__vars):
|
||||
print >> f, templ % vars
|
||||
|
||||
if self.struct is not None:
|
||||
print >> f, unindent(self.struct, False)
|
||||
|
||||
if self.__doc__:
|
||||
p(template.docstring)
|
||||
|
||||
for name, func in sortitems(self.__methods):
|
||||
func.dump(f)
|
||||
|
||||
self.dump_methoddef(f, self.__methods, self.__vars)
|
||||
self.dump_memberdef(f)
|
||||
self.dump_slots(f)
|
||||
|
||||
def has_members(self):
|
||||
if self.__members:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def analyze(self):
|
||||
# called by ModuleMetaclass analyze()
|
||||
self.name = getattr(self, "abbrev", self.__name__)
|
||||
src = getattr(self, "struct", None)
|
||||
if src is not None:
|
||||
self.__struct = struct.parse(src)
|
||||
else:
|
||||
self.__struct = None
|
||||
self.__methods = {}
|
||||
self.__members = {}
|
||||
for cls in self.__mro__:
|
||||
for k, v in cls.__dict__.iteritems():
|
||||
if isinstance(v, FunctionType):
|
||||
self.__methods[k] = Method(v, self)
|
||||
if isinstance(v, member):
|
||||
self.__members[k] = v
|
||||
assert self.__struct is not None
|
||||
v.register(k, self.__struct)
|
||||
self.analyze_slots()
|
||||
|
||||
def analyze_slots(self):
|
||||
self.__slots = {}
|
||||
for s in Slots:
|
||||
if s.special is not None:
|
||||
meth = self.__methods.get(s.special)
|
||||
if meth is not None:
|
||||
self.__slots[s] = meth
|
||||
self.__slots[TP_NAME] = '"%s.%s"' % (self.__module, self.__name__)
|
||||
if self.__doc__:
|
||||
self.__slots[TP_DOC] = "%s_doc" % self.name
|
||||
if self.__struct is not None:
|
||||
self.__slots[TP_BASICSIZE] = "sizeof(%s)" % self.__struct.name
|
||||
self.__slots[TP_DEALLOC] = "%s_dealloc" % self.name
|
||||
if self.__methods:
|
||||
self.__slots[TP_METHODS] = "%s_methods" % self.name
|
||||
if self.__members:
|
||||
self.__slots[TP_MEMBERS] = "%s_members" % self.name
|
||||
|
||||
def initvars(self):
|
||||
v = self.__vars = {}
|
||||
v["TypeName"] = self.__name__
|
||||
v["CTypeName"] = "Py%s_Type" % self.__name__
|
||||
v["MethodDefName"] = self.__slots[TP_METHODS]
|
||||
if self.__doc__:
|
||||
v["DocstringVar"] = self.__slots[TP_DOC]
|
||||
v["Docstring"] = cstring(unindent(self.__doc__))
|
||||
if self.__struct is not None:
|
||||
v["StructName"] = self.__struct.name
|
||||
if self.__members:
|
||||
v["MemberDefName"] = self.__slots[TP_MEMBERS]
|
||||
|
||||
def dump_memberdef(self, f):
|
||||
def p(templ, vars=self.__vars):
|
||||
print >> f, templ % vars
|
||||
|
||||
if not self.__members:
|
||||
return
|
||||
p(template.memberdef_start)
|
||||
for name, slot in sortitems(self.__members):
|
||||
slot.dump(f)
|
||||
p(template.memberdef_end)
|
||||
|
||||
def dump_slots(self, f):
|
||||
def p(templ, vars=self.__vars):
|
||||
print >> f, templ % vars
|
||||
|
||||
if self.struct:
|
||||
p(template.dealloc_func, {"name" : self.__slots[TP_DEALLOC]})
|
||||
|
||||
p(template.type_struct_start)
|
||||
for s in Slots[:-5]: # XXX
|
||||
val = self.__slots.get(s, s.default)
|
||||
ntabs = 4 - (4 + len(val)) / 8
|
||||
line = " %s,%s/* %s */" % (val, "\t" * ntabs, s.name)
|
||||
print >> f, line
|
||||
p(template.type_struct_end)
|
||||
|
||||
def dump_init(self, f):
|
||||
def p(templ):
|
||||
print >> f, templ % self.__vars
|
||||
|
||||
p(template.type_init_type)
|
||||
p(template.module_add_type)
|
||||
|
||||
class Type:
|
||||
__metaclass__ = TypeMetaclass
|
||||
173
project/jni/python/src/Tools/framer/framer/function.py
Normal file
173
project/jni/python/src/Tools/framer/framer/function.py
Normal file
@@ -0,0 +1,173 @@
|
||||
"""Functions."""
|
||||
|
||||
from framer import template
|
||||
from framer.util import cstring, unindent
|
||||
|
||||
METH_O = "METH_O"
|
||||
METH_NOARGS = "METH_NOARGS"
|
||||
METH_VARARGS = "METH_VARARGS"
|
||||
|
||||
def parsefmt(fmt):
|
||||
for c in fmt:
|
||||
if c == '|':
|
||||
continue
|
||||
yield c
|
||||
|
||||
class Argument:
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.ctype = "PyObject *"
|
||||
self.default = None
|
||||
|
||||
def __str__(self):
|
||||
return "%s%s" % (self.ctype, self.name)
|
||||
|
||||
def setfmt(self, code):
|
||||
self.ctype = self._codes[code]
|
||||
if self.ctype[-1] != "*":
|
||||
self.ctype += " "
|
||||
|
||||
_codes = {"O": "PyObject *",
|
||||
"i": "int",
|
||||
}
|
||||
|
||||
def decl(self):
|
||||
if self.default is None:
|
||||
return str(self) + ";"
|
||||
else:
|
||||
return "%s = %s;" % (self, self.default)
|
||||
|
||||
class _ArgumentList(object):
|
||||
|
||||
# these instance variables should be initialized by subclasses
|
||||
ml_meth = None
|
||||
fmt = None
|
||||
|
||||
def __init__(self, args):
|
||||
self.args = map(Argument, args)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.args)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.args[i]
|
||||
|
||||
def dump_decls(self, f):
|
||||
pass
|
||||
|
||||
class NoArgs(_ArgumentList):
|
||||
|
||||
def __init__(self, args):
|
||||
assert len(args) == 0
|
||||
super(NoArgs, self).__init__(args)
|
||||
self.ml_meth = METH_NOARGS
|
||||
|
||||
def c_args(self):
|
||||
return "PyObject *self"
|
||||
|
||||
class OneArg(_ArgumentList):
|
||||
|
||||
def __init__(self, args):
|
||||
assert len(args) == 1
|
||||
super(OneArg, self).__init__(args)
|
||||
self.ml_meth = METH_O
|
||||
|
||||
def c_args(self):
|
||||
return "PyObject *self, %s" % self.args[0]
|
||||
|
||||
class VarArgs(_ArgumentList):
|
||||
|
||||
def __init__(self, args, fmt=None):
|
||||
super(VarArgs, self).__init__(args)
|
||||
self.ml_meth = METH_VARARGS
|
||||
if fmt is not None:
|
||||
self.fmt = fmt
|
||||
i = 0
|
||||
for code in parsefmt(fmt):
|
||||
self.args[i].setfmt(code)
|
||||
i += 1
|
||||
|
||||
def c_args(self):
|
||||
return "PyObject *self, PyObject *args"
|
||||
|
||||
def targets(self):
|
||||
return ", ".join(["&%s" % a.name for a in self.args])
|
||||
|
||||
def dump_decls(self, f):
|
||||
for a in self.args:
|
||||
print >> f, " %s" % a.decl()
|
||||
|
||||
def ArgumentList(func, method):
|
||||
code = func.func_code
|
||||
args = code.co_varnames[:code.co_argcount]
|
||||
if method:
|
||||
args = args[1:]
|
||||
pyarg = getattr(func, "pyarg", None)
|
||||
if pyarg is not None:
|
||||
args = VarArgs(args, pyarg)
|
||||
if func.func_defaults:
|
||||
L = list(func.func_defaults)
|
||||
ndefault = len(L)
|
||||
i = len(args) - ndefault
|
||||
while L:
|
||||
args[i].default = L.pop(0)
|
||||
return args
|
||||
else:
|
||||
if len(args) == 0:
|
||||
return NoArgs(args)
|
||||
elif len(args) == 1:
|
||||
return OneArg(args)
|
||||
else:
|
||||
return VarArgs(args)
|
||||
|
||||
class Function:
|
||||
|
||||
method = False
|
||||
|
||||
def __init__(self, func, parent):
|
||||
self._func = func
|
||||
self._parent = parent
|
||||
self.analyze()
|
||||
self.initvars()
|
||||
|
||||
def dump(self, f):
|
||||
def p(templ, vars=None): # helper function to generate output
|
||||
if vars is None:
|
||||
vars = self.vars
|
||||
print >> f, templ % vars
|
||||
|
||||
if self.__doc__:
|
||||
p(template.docstring)
|
||||
|
||||
d = {"name" : self.vars["CName"],
|
||||
"args" : self.args.c_args(),
|
||||
}
|
||||
p(template.funcdef_start, d)
|
||||
|
||||
self.args.dump_decls(f)
|
||||
|
||||
if self.args.ml_meth == METH_VARARGS:
|
||||
p(template.varargs)
|
||||
|
||||
p(template.funcdef_end)
|
||||
|
||||
def analyze(self):
|
||||
self.__doc__ = self._func.__doc__
|
||||
self.args = ArgumentList(self._func, self.method)
|
||||
|
||||
def initvars(self):
|
||||
v = self.vars = {}
|
||||
v["PythonName"] = self._func.__name__
|
||||
s = v["CName"] = "%s_%s" % (self._parent.name, self._func.__name__)
|
||||
v["DocstringVar"] = s + "_doc"
|
||||
v["MethType"] = self.args.ml_meth
|
||||
if self.__doc__:
|
||||
v["Docstring"] = cstring(unindent(self.__doc__))
|
||||
if self.args.fmt is not None:
|
||||
v["ArgParse"] = self.args.fmt
|
||||
v["ArgTargets"] = self.args.targets()
|
||||
|
||||
class Method(Function):
|
||||
|
||||
method = True
|
||||
73
project/jni/python/src/Tools/framer/framer/member.py
Normal file
73
project/jni/python/src/Tools/framer/framer/member.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from framer import template
|
||||
from framer.util import cstring, unindent
|
||||
|
||||
T_SHORT = "T_SHORT"
|
||||
T_INT = "T_INT"
|
||||
T_LONG = "T_LONG"
|
||||
T_FLOAT = "T_FLOAT"
|
||||
T_DOUBLE = "T_DOUBLE"
|
||||
T_STRING = "T_STRING"
|
||||
T_OBJECT = "T_OBJECT"
|
||||
T_CHAR = "T_CHAR"
|
||||
T_BYTE = "T_BYTE"
|
||||
T_UBYTE = "T_UBYTE"
|
||||
T_UINT = "T_UINT"
|
||||
T_ULONG = "T_ULONG"
|
||||
T_STRING_INPLACE = "T_STRING_INPLACE"
|
||||
T_OBJECT_EX = "T_OBJECT_EX"
|
||||
|
||||
RO = READONLY = "READONLY"
|
||||
READ_RESTRICTED = "READ_RESTRICTED"
|
||||
WRITE_RESTRICTED = "WRITE_RESTRICTED"
|
||||
RESTRICT = "RESTRICTED"
|
||||
|
||||
c2t = {"int" : T_INT,
|
||||
"unsigned int" : T_UINT,
|
||||
"long" : T_LONG,
|
||||
"unsigned long" : T_LONG,
|
||||
"float" : T_FLOAT,
|
||||
"double" : T_DOUBLE,
|
||||
"char *" : T_CHAR,
|
||||
"PyObject *" : T_OBJECT,
|
||||
}
|
||||
|
||||
class member(object):
|
||||
|
||||
def __init__(self, cname=None, type=None, flags=None, doc=None):
|
||||
self.type = type
|
||||
self.flags = flags
|
||||
self.cname = cname
|
||||
self.doc = doc
|
||||
self.name = None
|
||||
self.struct = None
|
||||
|
||||
def register(self, name, struct):
|
||||
self.name = name
|
||||
self.struct = struct
|
||||
self.initvars()
|
||||
|
||||
def initvars(self):
|
||||
v = self.vars = {}
|
||||
v["PythonName"] = self.name
|
||||
if self.cname is not None:
|
||||
v["CName"] = self.cname
|
||||
else:
|
||||
v["CName"] = self.name
|
||||
v["Flags"] = self.flags or "0"
|
||||
v["Type"] = self.get_type()
|
||||
if self.doc is not None:
|
||||
v["Docstring"] = cstring(unindent(self.doc))
|
||||
v["StructName"] = self.struct.name
|
||||
|
||||
def get_type(self):
|
||||
"""Deduce type code from struct specification if not defined"""
|
||||
if self.type is not None:
|
||||
return self.type
|
||||
ctype = self.struct.get_type(self.name)
|
||||
return c2t[ctype]
|
||||
|
||||
def dump(self, f):
|
||||
if self.doc is None:
|
||||
print >> f, template.memberdef_def % self.vars
|
||||
else:
|
||||
print >> f, template.memberdef_def_doc % self.vars
|
||||
64
project/jni/python/src/Tools/framer/framer/slots.py
Normal file
64
project/jni/python/src/Tools/framer/framer/slots.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""Descriptions of all the slots in Python's type objects."""
|
||||
|
||||
class Slot(object):
|
||||
def __init__(self, name, cast=None, special=None, default="0"):
|
||||
self.name = name
|
||||
self.cast = cast
|
||||
self.special = special
|
||||
self.default = default
|
||||
|
||||
Slots = (Slot("ob_size"),
|
||||
Slot("tp_name"),
|
||||
Slot("tp_basicsize"),
|
||||
Slot("tp_itemsize"),
|
||||
Slot("tp_dealloc", "destructor"),
|
||||
Slot("tp_print", "printfunc"),
|
||||
Slot("tp_getattr", "getattrfunc"),
|
||||
Slot("tp_setattr", "setattrfunc"),
|
||||
Slot("tp_compare", "cmpfunc", "__cmp__"),
|
||||
Slot("tp_repr", "reprfunc", "__repr__"),
|
||||
Slot("tp_as_number"),
|
||||
Slot("tp_as_sequence"),
|
||||
Slot("tp_as_mapping"),
|
||||
Slot("tp_hash", "hashfunc", "__hash__"),
|
||||
Slot("tp_call", "ternaryfunc", "__call__"),
|
||||
Slot("tp_str", "reprfunc", "__str__"),
|
||||
Slot("tp_getattro", "getattrofunc", "__getattr__", # XXX
|
||||
"PyObject_GenericGetAttr"),
|
||||
Slot("tp_setattro", "setattrofunc", "__setattr__"),
|
||||
Slot("tp_as_buffer"),
|
||||
Slot("tp_flags", default="Py_TPFLAGS_DEFAULT"),
|
||||
Slot("tp_doc"),
|
||||
Slot("tp_traverse", "traverseprox"),
|
||||
Slot("tp_clear", "inquiry"),
|
||||
Slot("tp_richcompare", "richcmpfunc"),
|
||||
Slot("tp_weaklistoffset"),
|
||||
Slot("tp_iter", "getiterfunc", "__iter__"),
|
||||
Slot("tp_iternext", "iternextfunc", "__next__"), # XXX
|
||||
Slot("tp_methods"),
|
||||
Slot("tp_members"),
|
||||
Slot("tp_getset"),
|
||||
Slot("tp_base"),
|
||||
Slot("tp_dict"),
|
||||
Slot("tp_descr_get", "descrgetfunc"),
|
||||
Slot("tp_descr_set", "descrsetfunc"),
|
||||
Slot("tp_dictoffset"),
|
||||
Slot("tp_init", "initproc", "__init__"),
|
||||
Slot("tp_alloc", "allocfunc"),
|
||||
Slot("tp_new", "newfunc"),
|
||||
Slot("tp_free", "freefunc"),
|
||||
Slot("tp_is_gc", "inquiry"),
|
||||
Slot("tp_bases"),
|
||||
Slot("tp_mro"),
|
||||
Slot("tp_cache"),
|
||||
Slot("tp_subclasses"),
|
||||
Slot("tp_weaklist"),
|
||||
)
|
||||
|
||||
# give some slots symbolic names
|
||||
TP_NAME = Slots[1]
|
||||
TP_BASICSIZE = Slots[2]
|
||||
TP_DEALLOC = Slots[4]
|
||||
TP_DOC = Slots[20]
|
||||
TP_METHODS = Slots[27]
|
||||
TP_MEMBERS = Slots[28]
|
||||
52
project/jni/python/src/Tools/framer/framer/struct.py
Normal file
52
project/jni/python/src/Tools/framer/framer/struct.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""Rudimentary parser for C struct definitions."""
|
||||
|
||||
import re
|
||||
|
||||
PyObject_HEAD = "PyObject_HEAD"
|
||||
PyObject_VAR_HEAD = "PyObject_VAR_HEAD"
|
||||
|
||||
rx_name = re.compile("} (\w+);")
|
||||
|
||||
class Struct:
|
||||
def __init__(self, name, head, members):
|
||||
self.name = name
|
||||
self.head = head
|
||||
self.members = members
|
||||
|
||||
def get_type(self, name):
|
||||
for _name, type in self.members:
|
||||
if name == _name:
|
||||
return type
|
||||
raise ValueError, "no member named %s" % name
|
||||
|
||||
def parse(s):
|
||||
"""Parse a C struct definition.
|
||||
|
||||
The parser is very restricted in what it will accept.
|
||||
"""
|
||||
|
||||
lines = filter(None, s.split("\n")) # get non-empty lines
|
||||
assert lines[0].strip() == "typedef struct {"
|
||||
pyhead = lines[1].strip()
|
||||
assert (pyhead.startswith("PyObject") and
|
||||
pyhead.endswith("HEAD"))
|
||||
members = []
|
||||
for line in lines[2:]:
|
||||
line = line.strip()
|
||||
if line.startswith("}"):
|
||||
break
|
||||
|
||||
assert line.endswith(";")
|
||||
line = line[:-1]
|
||||
words = line.split()
|
||||
name = words[-1]
|
||||
type = " ".join(words[:-1])
|
||||
if name[0] == "*":
|
||||
name = name[1:]
|
||||
type += " *"
|
||||
members.append((name, type))
|
||||
name = None
|
||||
mo = rx_name.search(line)
|
||||
assert mo is not None
|
||||
name = mo.group(1)
|
||||
return Struct(name, pyhead, members)
|
||||
46
project/jni/python/src/Tools/framer/framer/structparse.py
Normal file
46
project/jni/python/src/Tools/framer/framer/structparse.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Rudimentary parser for C struct definitions."""
|
||||
|
||||
import re
|
||||
|
||||
PyObject_HEAD = "PyObject_HEAD"
|
||||
PyObject_VAR_HEAD = "PyObject_VAR_HEAD"
|
||||
|
||||
rx_name = re.compile("} (\w+);")
|
||||
|
||||
class Struct:
|
||||
def __init__(self, name, head, members):
|
||||
self.name = name
|
||||
self.head = head
|
||||
self.members = members
|
||||
|
||||
def parse(s):
|
||||
"""Parse a C struct definition.
|
||||
|
||||
The parser is very restricted in what it will accept.
|
||||
"""
|
||||
|
||||
lines = filter(None, s.split("\n")) # get non-empty lines
|
||||
assert lines[0].strip() == "typedef struct {"
|
||||
pyhead = lines[1].strip()
|
||||
assert (pyhead.startswith("PyObject") and
|
||||
pyhead.endswith("HEAD"))
|
||||
members = []
|
||||
for line in lines[2:]:
|
||||
line = line.strip()
|
||||
if line.startswith("}"):
|
||||
break
|
||||
|
||||
assert line.endswith(";")
|
||||
line = line[:-1]
|
||||
words = line.split()
|
||||
name = words[-1]
|
||||
type = " ".join(words[:-1])
|
||||
if name[0] == "*":
|
||||
name = name[1:]
|
||||
type += " *"
|
||||
members.append((name, type))
|
||||
name = None
|
||||
mo = rx_name.search(line)
|
||||
assert mo is not None
|
||||
name = mo.group(1)
|
||||
return Struct(name, pyhead, members)
|
||||
102
project/jni/python/src/Tools/framer/framer/template.py
Normal file
102
project/jni/python/src/Tools/framer/framer/template.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""framer's C code templates.
|
||||
|
||||
Templates use the following variables:
|
||||
|
||||
FileName: name of the file that contains the C source code
|
||||
ModuleName: name of the module, as in "import ModuleName"
|
||||
ModuleDocstring: C string containing the module doc string
|
||||
"""
|
||||
|
||||
module_start = '#include "Python.h"'
|
||||
member_include = '#include "structmember.h"'
|
||||
|
||||
module_doc = """\
|
||||
PyDoc_STRVAR(%(ModuleName)s_doc,
|
||||
%(ModuleDocstring)s);
|
||||
"""
|
||||
|
||||
methoddef_start = """\
|
||||
static struct PyMethodDef %(MethodDefName)s[] = {"""
|
||||
|
||||
methoddef_def = """\
|
||||
{"%(PythonName)s", (PyCFunction)%(CName)s, %(MethType)s},"""
|
||||
|
||||
methoddef_def_doc = """\
|
||||
{"%(PythonName)s", (PyCFunction)%(CName)s, %(MethType)s,
|
||||
%(DocstringVar)s},"""
|
||||
|
||||
methoddef_end = """\
|
||||
{NULL, NULL}
|
||||
};
|
||||
"""
|
||||
|
||||
memberdef_start = """\
|
||||
#define OFF(X) offsetof(%(StructName)s, X)
|
||||
|
||||
static struct PyMemberDef %(MemberDefName)s[] = {"""
|
||||
|
||||
memberdef_def_doc = """\
|
||||
{"%(PythonName)s", %(Type)s, OFF(%(CName)s), %(Flags)s,
|
||||
%(Docstring)s},"""
|
||||
|
||||
memberdef_def = """\
|
||||
{"%(PythonName)s", %(Type)s, OFF(%(CName)s), %(Flags)s},"""
|
||||
|
||||
memberdef_end = """\
|
||||
{NULL}
|
||||
};
|
||||
|
||||
#undef OFF
|
||||
"""
|
||||
|
||||
dealloc_func = """static void
|
||||
%(name)s(PyObject *ob)
|
||||
{
|
||||
}
|
||||
"""
|
||||
|
||||
docstring = """\
|
||||
PyDoc_STRVAR(%(DocstringVar)s,
|
||||
%(Docstring)s);
|
||||
"""
|
||||
|
||||
funcdef_start = """\
|
||||
static PyObject *
|
||||
%(name)s(%(args)s)
|
||||
{"""
|
||||
|
||||
funcdef_end = """\
|
||||
}
|
||||
"""
|
||||
|
||||
varargs = """\
|
||||
if (!PyArg_ParseTuple(args, \"%(ArgParse)s:%(PythonName)s\",
|
||||
%(ArgTargets)s))
|
||||
return NULL;"""
|
||||
|
||||
module_init_start = """\
|
||||
PyMODINIT_FUNC
|
||||
init%(ModuleName)s(void)
|
||||
{
|
||||
PyObject *mod;
|
||||
|
||||
mod = Py_InitModule3("%(ModuleName)s", %(MethodDefName)s,
|
||||
%(ModuleName)s_doc);
|
||||
if (mod == NULL)
|
||||
return;
|
||||
"""
|
||||
|
||||
type_init_type = " %(CTypeName)s.ob_type = &PyType_Type;"
|
||||
module_add_type = """\
|
||||
if (!PyObject_SetAttrString(mod, "%(TypeName)s",
|
||||
(PyObject *)&%(CTypeName)s))
|
||||
return;
|
||||
"""
|
||||
|
||||
type_struct_start = """\
|
||||
static PyTypeObject %(CTypeName)s = {
|
||||
PyObject_HEAD_INIT(0)"""
|
||||
|
||||
type_struct_end = """\
|
||||
};
|
||||
"""
|
||||
35
project/jni/python/src/Tools/framer/framer/util.py
Normal file
35
project/jni/python/src/Tools/framer/framer/util.py
Normal file
@@ -0,0 +1,35 @@
|
||||
def cstring(s, width=70):
|
||||
"""Return C string representation of a Python string.
|
||||
|
||||
width specifies the maximum width of any line of the C string.
|
||||
"""
|
||||
L = []
|
||||
for l in s.split("\n"):
|
||||
if len(l) < width:
|
||||
L.append(r'"%s\n"' % l)
|
||||
|
||||
return "\n".join(L)
|
||||
|
||||
def unindent(s, skipfirst=True):
|
||||
"""Return an unindented version of a docstring.
|
||||
|
||||
Removes indentation on lines following the first one, using the
|
||||
leading whitespace of the first indented line that is not blank
|
||||
to determine the indentation.
|
||||
"""
|
||||
|
||||
lines = s.split("\n")
|
||||
if skipfirst:
|
||||
first = lines.pop(0)
|
||||
L = [first]
|
||||
else:
|
||||
L = []
|
||||
indent = None
|
||||
for l in lines:
|
||||
ls = l.strip()
|
||||
if ls:
|
||||
indent = len(l) - len(ls)
|
||||
break
|
||||
L += [l[indent:] for l in lines]
|
||||
|
||||
return "\n".join(L)
|
||||
296
project/jni/python/src/Tools/freeze/README
Normal file
296
project/jni/python/src/Tools/freeze/README
Normal file
@@ -0,0 +1,296 @@
|
||||
THE FREEZE SCRIPT
|
||||
=================
|
||||
|
||||
(Directions for Windows are at the end of this file.)
|
||||
|
||||
|
||||
What is Freeze?
|
||||
---------------
|
||||
|
||||
Freeze make it possible to ship arbitrary Python programs to people
|
||||
who don't have Python. The shipped file (called a "frozen" version of
|
||||
your Python program) is an executable, so this only works if your
|
||||
platform is compatible with that on the receiving end (this is usually
|
||||
a matter of having the same major operating system revision and CPU
|
||||
type).
|
||||
|
||||
The shipped file contains a Python interpreter and large portions of
|
||||
the Python run-time. Some measures have been taken to avoid linking
|
||||
unneeded modules, but the resulting binary is usually not small.
|
||||
|
||||
The Python source code of your program (and of the library modules
|
||||
written in Python that it uses) is not included in the binary --
|
||||
instead, the compiled byte-code (the instruction stream used
|
||||
internally by the interpreter) is incorporated. This gives some
|
||||
protection of your Python source code, though not much -- a
|
||||
disassembler for Python byte-code is available in the standard Python
|
||||
library. At least someone running "strings" on your binary won't see
|
||||
the source.
|
||||
|
||||
|
||||
How does Freeze know which modules to include?
|
||||
----------------------------------------------
|
||||
|
||||
Previous versions of Freeze used a pretty simple-minded algorithm to
|
||||
find the modules that your program uses, essentially searching for
|
||||
lines starting with the word "import". It was pretty easy to trick it
|
||||
into making mistakes, either missing valid import statements, or
|
||||
mistaking string literals (e.g. doc strings) for import statements.
|
||||
|
||||
This has been remedied: Freeze now uses the regular Python parser to
|
||||
parse the program (and all its modules) and scans the generated byte
|
||||
code for IMPORT instructions. It may still be confused -- it will not
|
||||
know about calls to the __import__ built-in function, or about import
|
||||
statements constructed on the fly and executed using the 'exec'
|
||||
statement, and it will consider import statements even when they are
|
||||
unreachable (e.g. "if 0: import foobar").
|
||||
|
||||
This new version of Freeze also knows about Python's new package
|
||||
import mechanism, and uses exactly the same rules to find imported
|
||||
modules and packages. One exception: if you write 'from package
|
||||
import *', Python will look into the __all__ variable of the package
|
||||
to determine which modules are to be imported, while Freeze will do a
|
||||
directory listing.
|
||||
|
||||
One tricky issue: Freeze assumes that the Python interpreter and
|
||||
environment you're using to run Freeze is the same one that would be
|
||||
used to run your program, which should also be the same whose sources
|
||||
and installed files you will learn about in the next section. In
|
||||
particular, your PYTHONPATH setting should be the same as for running
|
||||
your program locally. (Tip: if the program doesn't run when you type
|
||||
"python hello.py" there's little chance of getting the frozen version
|
||||
to run.)
|
||||
|
||||
|
||||
How do I use Freeze?
|
||||
--------------------
|
||||
|
||||
Normally, you should be able to use it as follows:
|
||||
|
||||
python freeze.py hello.py
|
||||
|
||||
where hello.py is your program and freeze.py is the main file of
|
||||
Freeze (in actuality, you'll probably specify an absolute pathname
|
||||
such as /usr/joe/python/Tools/freeze/freeze.py).
|
||||
|
||||
|
||||
What do I do next?
|
||||
------------------
|
||||
|
||||
Freeze creates a number of files: frozen.c, config.c and Makefile,
|
||||
plus one file for each Python module that gets included named
|
||||
M_<module>.c. To produce the frozen version of your program, you can
|
||||
simply type "make". This should produce a binary file. If the
|
||||
filename argument to Freeze was "hello.py", the binary will be called
|
||||
"hello".
|
||||
|
||||
Note: you can use the -o option to freeze to specify an alternative
|
||||
directory where these files are created. This makes it easier to
|
||||
clean up after you've shipped the frozen binary. You should invoke
|
||||
"make" in the given directory.
|
||||
|
||||
|
||||
Freezing Tkinter programs
|
||||
-------------------------
|
||||
|
||||
Unfortunately, it is currently not possible to freeze programs that
|
||||
use Tkinter without a Tcl/Tk installation. The best way to ship a
|
||||
frozen Tkinter program is to decide in advance where you are going
|
||||
to place the Tcl and Tk library files in the distributed setup, and
|
||||
then declare these directories in your frozen Python program using
|
||||
the TCL_LIBRARY, TK_LIBRARY and TIX_LIBRARY environment variables.
|
||||
|
||||
For example, assume you will ship your frozen program in the directory
|
||||
<root>/bin/windows-x86 and will place your Tcl library files
|
||||
in <root>/lib/tcl8.2 and your Tk library files in <root>/lib/tk8.2. Then
|
||||
placing the following lines in your frozen Python script before importing
|
||||
Tkinter or Tix would set the environment correctly for Tcl/Tk/Tix:
|
||||
|
||||
import os
|
||||
import os.path
|
||||
RootDir = os.path.dirname(os.path.dirname(os.getcwd()))
|
||||
|
||||
import sys
|
||||
if sys.platform == "win32":
|
||||
sys.path = ['', '..\\..\\lib\\python-2.0']
|
||||
os.environ['TCL_LIBRARY'] = RootDir + '\\lib\\tcl8.2'
|
||||
os.environ['TK_LIBRARY'] = RootDir + '\\lib\\tk8.2'
|
||||
os.environ['TIX_LIBRARY'] = RootDir + '\\lib\\tix8.1'
|
||||
elif sys.platform == "linux2":
|
||||
sys.path = ['', '../../lib/python-2.0']
|
||||
os.environ['TCL_LIBRARY'] = RootDir + '/lib/tcl8.2'
|
||||
os.environ['TK_LIBRARY'] = RootDir + '/lib/tk8.2'
|
||||
os.environ['TIX_LIBRARY'] = RootDir + '/lib/tix8.1'
|
||||
elif sys.platform == "solaris":
|
||||
sys.path = ['', '../../lib/python-2.0']
|
||||
os.environ['TCL_LIBRARY'] = RootDir + '/lib/tcl8.2'
|
||||
os.environ['TK_LIBRARY'] = RootDir + '/lib/tk8.2'
|
||||
os.environ['TIX_LIBRARY'] = RootDir + '/lib/tix8.1'
|
||||
|
||||
This also adds <root>/lib/python-2.0 to your Python path
|
||||
for any Python files such as _tkinter.pyd you may need.
|
||||
|
||||
Note that the dynamic libraries (such as tcl82.dll tk82.dll python20.dll
|
||||
under Windows, or libtcl8.2.so and libtcl8.2.so under Unix) are required
|
||||
at program load time, and are searched by the operating system loader
|
||||
before Python can be started. Under Windows, the environment
|
||||
variable PATH is consulted, and under Unix, it may be the
|
||||
environment variable LD_LIBRARY_PATH and/or the system
|
||||
shared library cache (ld.so). An additional preferred directory for
|
||||
finding the dynamic libraries is built into the .dll or .so files at
|
||||
compile time - see the LIB_RUNTIME_DIR variable in the Tcl makefile.
|
||||
The OS must find the dynamic libraries or your frozen program won't start.
|
||||
Usually I make sure that the .so or .dll files are in the same directory
|
||||
as the executable, but this may not be foolproof.
|
||||
|
||||
A workaround to installing your Tcl library files with your frozen
|
||||
executable would be possible, in which the Tcl/Tk library files are
|
||||
incorporated in a frozen Python module as string literals and written
|
||||
to a temporary location when the program runs; this is currently left
|
||||
as an exercise for the reader. An easier approach is to freeze the
|
||||
Tcl/Tk/Tix code into the dynamic libraries using the Tcl ET code,
|
||||
or the Tix Stand-Alone-Module code. Of course, you can also simply
|
||||
require that Tcl/Tk is required on the target installation, but be
|
||||
careful that the version corresponds.
|
||||
|
||||
There are some caveats using frozen Tkinter applications:
|
||||
Under Windows if you use the -s windows option, writing
|
||||
to stdout or stderr is an error.
|
||||
The Tcl [info nameofexecutable] will be set to where the
|
||||
program was frozen, not where it is run from.
|
||||
The global variables argc and argv do not exist.
|
||||
|
||||
|
||||
A warning about shared library modules
|
||||
--------------------------------------
|
||||
|
||||
When your Python installation uses shared library modules such as
|
||||
_tkinter.pyd, these will not be incorporated in the frozen program.
|
||||
Again, the frozen program will work when you test it, but it won't
|
||||
work when you ship it to a site without a Python installation.
|
||||
|
||||
Freeze prints a warning when this is the case at the end of the
|
||||
freezing process:
|
||||
|
||||
Warning: unknown modules remain: ...
|
||||
|
||||
When this occurs, the best thing to do is usually to rebuild Python
|
||||
using static linking only. Or use the approach described in the previous
|
||||
section to declare a library path using sys.path, and place the modules
|
||||
such as _tkinter.pyd there.
|
||||
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
If you have trouble using Freeze for a large program, it's probably
|
||||
best to start playing with a really simple program first (like the file
|
||||
hello.py). If you can't get that to work there's something
|
||||
fundamentally wrong -- perhaps you haven't installed Python. To do a
|
||||
proper install, you should do "make install" in the Python root
|
||||
directory.
|
||||
|
||||
|
||||
Usage under Windows 95 or NT
|
||||
----------------------------
|
||||
|
||||
Under Windows 95 or NT, you *must* use the -p option and point it to
|
||||
the top of the Python source tree.
|
||||
|
||||
WARNING: the resulting executable is not self-contained; it requires
|
||||
the Python DLL, currently PYTHON20.DLL (it does not require the
|
||||
standard library of .py files though). It may also require one or
|
||||
more extension modules loaded from .DLL or .PYD files; the module
|
||||
names are printed in the warning message about remaining unknown
|
||||
modules.
|
||||
|
||||
The driver script generates a Makefile that works with the Microsoft
|
||||
command line C compiler (CL). To compile, run "nmake"; this will
|
||||
build a target "hello.exe" if the source was "hello.py". Only the
|
||||
files frozenmain.c and frozen.c are used; no config.c is generated or
|
||||
used, since the standard DLL is used.
|
||||
|
||||
In order for this to work, you must have built Python using the VC++
|
||||
(Developer Studio) 5.0 compiler. The provided project builds
|
||||
python20.lib in the subdirectory pcbuild\Release of thje Python source
|
||||
tree, and this is where the generated Makefile expects it to be. If
|
||||
this is not the case, you can edit the Makefile or (probably better)
|
||||
winmakemakefile.py (e.g., if you are using the 4.2 compiler, the
|
||||
python20.lib file is generated in the subdirectory vc40 of the Python
|
||||
source tree).
|
||||
|
||||
It is possible to create frozen programs that don't have a console
|
||||
window, by specifying the option '-s windows'. See the Usage below.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Here is a list of all of the options (taken from freeze.__doc__):
|
||||
|
||||
usage: freeze [options...] script [module]...
|
||||
|
||||
Options:
|
||||
-p prefix: This is the prefix used when you ran ``make install''
|
||||
in the Python build directory.
|
||||
(If you never ran this, freeze won't work.)
|
||||
The default is whatever sys.prefix evaluates to.
|
||||
It can also be the top directory of the Python source
|
||||
tree; then -P must point to the build tree.
|
||||
|
||||
-P exec_prefix: Like -p but this is the 'exec_prefix', used to
|
||||
install objects etc. The default is whatever sys.exec_prefix
|
||||
evaluates to, or the -p argument if given.
|
||||
If -p points to the Python source tree, -P must point
|
||||
to the build tree, if different.
|
||||
|
||||
-e extension: A directory containing additional .o files that
|
||||
may be used to resolve modules. This directory
|
||||
should also have a Setup file describing the .o files.
|
||||
On Windows, the name of a .INI file describing one
|
||||
or more extensions is passed.
|
||||
More than one -e option may be given.
|
||||
|
||||
-o dir: Directory where the output files are created; default '.'.
|
||||
|
||||
-m: Additional arguments are module names instead of filenames.
|
||||
|
||||
-a package=dir: Additional directories to be added to the package's
|
||||
__path__. Used to simulate directories added by the
|
||||
package at runtime (eg, by OpenGL and win32com).
|
||||
More than one -a option may be given for each package.
|
||||
|
||||
-l file: Pass the file to the linker (windows only)
|
||||
|
||||
-d: Debugging mode for the module finder.
|
||||
|
||||
-q: Make the module finder totally quiet.
|
||||
|
||||
-h: Print this help message.
|
||||
|
||||
-x module Exclude the specified module.
|
||||
|
||||
-i filename: Include a file with additional command line options. Used
|
||||
to prevent command lines growing beyond the capabilities of
|
||||
the shell/OS. All arguments specified in filename
|
||||
are read and the -i option replaced with the parsed
|
||||
params (note - quoting args in this file is NOT supported)
|
||||
|
||||
-s subsystem: Specify the subsystem (For Windows only.);
|
||||
'console' (default), 'windows', 'service' or 'com_dll'
|
||||
|
||||
-w: Toggle Windows (NT or 95) behavior.
|
||||
(For debugging only -- on a win32 platform, win32 behavior
|
||||
is automatic.)
|
||||
|
||||
Arguments:
|
||||
|
||||
script: The Python script to be executed by the resulting binary.
|
||||
|
||||
module ...: Additional Python modules (referenced by pathname)
|
||||
that will be included in the resulting binary. These
|
||||
may be .py or .pyc files. If -m is specified, these are
|
||||
module names that are search in the path instead.
|
||||
|
||||
|
||||
|
||||
--Guido van Rossum (home page: http://www.python.org/~guido/)
|
||||
47
project/jni/python/src/Tools/freeze/bkfile.py
Normal file
47
project/jni/python/src/Tools/freeze/bkfile.py
Normal file
@@ -0,0 +1,47 @@
|
||||
_orig_open = open
|
||||
|
||||
class _BkFile:
|
||||
def __init__(self, file, mode, bufsize):
|
||||
import os
|
||||
self.__filename = file
|
||||
self.__backup = file + '~'
|
||||
try:
|
||||
os.unlink(self.__backup)
|
||||
except os.error:
|
||||
pass
|
||||
try:
|
||||
os.rename(file, self.__backup)
|
||||
except os.error:
|
||||
self.__backup = None
|
||||
self.__file = _orig_open(file, mode, bufsize)
|
||||
self.closed = self.__file.closed
|
||||
self.fileno = self.__file.fileno
|
||||
self.flush = self.__file.flush
|
||||
self.isatty = self.__file.isatty
|
||||
self.mode = self.__file.mode
|
||||
self.name = self.__file.name
|
||||
self.read = self.__file.read
|
||||
self.readinto = self.__file.readinto
|
||||
self.readline = self.__file.readline
|
||||
self.readlines = self.__file.readlines
|
||||
self.seek = self.__file.seek
|
||||
self.softspace = self.__file.softspace
|
||||
self.tell = self.__file.tell
|
||||
self.truncate = self.__file.truncate
|
||||
self.write = self.__file.write
|
||||
self.writelines = self.__file.writelines
|
||||
|
||||
def close(self):
|
||||
self.__file.close()
|
||||
if self.__backup is None:
|
||||
return
|
||||
import filecmp
|
||||
if filecmp.cmp(self.__backup, self.__filename, shallow = 0):
|
||||
import os
|
||||
os.unlink(self.__filename)
|
||||
os.rename(self.__backup, self.__filename)
|
||||
|
||||
def open(file, mode = 'r', bufsize = -1):
|
||||
if 'w' not in mode:
|
||||
return _orig_open(file, mode, bufsize)
|
||||
return _BkFile(file, mode, bufsize)
|
||||
90
project/jni/python/src/Tools/freeze/checkextensions.py
Normal file
90
project/jni/python/src/Tools/freeze/checkextensions.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# Check for a module in a set of extension directories.
|
||||
# An extension directory should contain a Setup file
|
||||
# and one or more .o files or a lib.a file.
|
||||
|
||||
import os
|
||||
import parsesetup
|
||||
|
||||
def checkextensions(unknown, extensions):
|
||||
files = []
|
||||
modules = []
|
||||
edict = {}
|
||||
for e in extensions:
|
||||
setup = os.path.join(e, 'Setup')
|
||||
liba = os.path.join(e, 'lib.a')
|
||||
if not os.path.isfile(liba):
|
||||
liba = None
|
||||
edict[e] = parsesetup.getsetupinfo(setup), liba
|
||||
for mod in unknown:
|
||||
for e in extensions:
|
||||
(mods, vars), liba = edict[e]
|
||||
if not mods.has_key(mod):
|
||||
continue
|
||||
modules.append(mod)
|
||||
if liba:
|
||||
# If we find a lib.a, use it, ignore the
|
||||
# .o files, and use *all* libraries for
|
||||
# *all* modules in the Setup file
|
||||
if liba in files:
|
||||
break
|
||||
files.append(liba)
|
||||
for m in mods.keys():
|
||||
files = files + select(e, mods, vars,
|
||||
m, 1)
|
||||
break
|
||||
files = files + select(e, mods, vars, mod, 0)
|
||||
break
|
||||
return files, modules
|
||||
|
||||
def select(e, mods, vars, mod, skipofiles):
|
||||
files = []
|
||||
for w in mods[mod]:
|
||||
w = treatword(w)
|
||||
if not w:
|
||||
continue
|
||||
w = expandvars(w, vars)
|
||||
for w in w.split():
|
||||
if skipofiles and w[-2:] == '.o':
|
||||
continue
|
||||
# Assume $var expands to absolute pathname
|
||||
if w[0] not in ('-', '$') and w[-2:] in ('.o', '.a'):
|
||||
w = os.path.join(e, w)
|
||||
if w[:2] in ('-L', '-R') and w[2:3] != '$':
|
||||
w = w[:2] + os.path.join(e, w[2:])
|
||||
files.append(w)
|
||||
return files
|
||||
|
||||
cc_flags = ['-I', '-D', '-U']
|
||||
cc_exts = ['.c', '.C', '.cc', '.c++']
|
||||
|
||||
def treatword(w):
|
||||
if w[:2] in cc_flags:
|
||||
return None
|
||||
if w[:1] == '-':
|
||||
return w # Assume loader flag
|
||||
head, tail = os.path.split(w)
|
||||
base, ext = os.path.splitext(tail)
|
||||
if ext in cc_exts:
|
||||
tail = base + '.o'
|
||||
w = os.path.join(head, tail)
|
||||
return w
|
||||
|
||||
def expandvars(str, vars):
|
||||
i = 0
|
||||
while i < len(str):
|
||||
i = k = str.find('$', i)
|
||||
if i < 0:
|
||||
break
|
||||
i = i+1
|
||||
var = str[i:i+1]
|
||||
i = i+1
|
||||
if var == '(':
|
||||
j = str.find(')', i)
|
||||
if j < 0:
|
||||
break
|
||||
var = str[i:j]
|
||||
i = j+1
|
||||
if vars.has_key(var):
|
||||
str = str[:k] + vars[var] + str[i:]
|
||||
i = k
|
||||
return str
|
||||
188
project/jni/python/src/Tools/freeze/checkextensions_win32.py
Normal file
188
project/jni/python/src/Tools/freeze/checkextensions_win32.py
Normal file
@@ -0,0 +1,188 @@
|
||||
"""Extension management for Windows.
|
||||
|
||||
Under Windows it is unlikely the .obj files are of use, as special compiler options
|
||||
are needed (primarily to toggle the behavior of "public" symbols.
|
||||
|
||||
I dont consider it worth parsing the MSVC makefiles for compiler options. Even if
|
||||
we get it just right, a specific freeze application may have specific compiler
|
||||
options anyway (eg, to enable or disable specific functionality)
|
||||
|
||||
So my basic stragtegy is:
|
||||
|
||||
* Have some Windows INI files which "describe" one or more extension modules.
|
||||
(Freeze comes with a default one for all known modules - but you can specify
|
||||
your own).
|
||||
* This description can include:
|
||||
- The MSVC .dsp file for the extension. The .c source file names
|
||||
are extraced from there.
|
||||
- Specific compiler/linker options
|
||||
- Flag to indicate if Unicode compilation is expected.
|
||||
|
||||
At the moment the name and location of this INI file is hardcoded,
|
||||
but an obvious enhancement would be to provide command line options.
|
||||
"""
|
||||
|
||||
import os, sys
|
||||
try:
|
||||
import win32api
|
||||
except ImportError:
|
||||
win32api = None # User has already been warned
|
||||
|
||||
class CExtension:
|
||||
"""An abstraction of an extension implemented in C/C++
|
||||
"""
|
||||
def __init__(self, name, sourceFiles):
|
||||
self.name = name
|
||||
# A list of strings defining additional compiler options.
|
||||
self.sourceFiles = sourceFiles
|
||||
# A list of special compiler options to be applied to
|
||||
# all source modules in this extension.
|
||||
self.compilerOptions = []
|
||||
# A list of .lib files the final .EXE will need.
|
||||
self.linkerLibs = []
|
||||
|
||||
def GetSourceFiles(self):
|
||||
return self.sourceFiles
|
||||
|
||||
def AddCompilerOption(self, option):
|
||||
self.compilerOptions.append(option)
|
||||
def GetCompilerOptions(self):
|
||||
return self.compilerOptions
|
||||
|
||||
def AddLinkerLib(self, lib):
|
||||
self.linkerLibs.append(lib)
|
||||
def GetLinkerLibs(self):
|
||||
return self.linkerLibs
|
||||
|
||||
def checkextensions(unknown, extra_inis, prefix):
|
||||
# Create a table of frozen extensions
|
||||
|
||||
defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini")
|
||||
if not os.path.isfile(defaultMapName):
|
||||
sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found\n" % defaultMapName)
|
||||
else:
|
||||
# must go on end, so other inis can override.
|
||||
extra_inis.append(defaultMapName)
|
||||
|
||||
ret = []
|
||||
for mod in unknown:
|
||||
for ini in extra_inis:
|
||||
# print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...",
|
||||
defn = get_extension_defn( mod, ini, prefix )
|
||||
if defn is not None:
|
||||
# print "Yay - found it!"
|
||||
ret.append( defn )
|
||||
break
|
||||
# print "Nope!"
|
||||
else: # For not broken!
|
||||
sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod))
|
||||
|
||||
return ret
|
||||
|
||||
def get_extension_defn(moduleName, mapFileName, prefix):
|
||||
if win32api is None: return None
|
||||
os.environ['PYTHONPREFIX'] = prefix
|
||||
dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName)
|
||||
if dsp=="":
|
||||
return None
|
||||
|
||||
# We allow environment variables in the file name
|
||||
dsp = win32api.ExpandEnvironmentStrings(dsp)
|
||||
# If the path to the .DSP file is not absolute, assume it is relative
|
||||
# to the description file.
|
||||
if not os.path.isabs(dsp):
|
||||
dsp = os.path.join( os.path.split(mapFileName)[0], dsp)
|
||||
# Parse it to extract the source files.
|
||||
sourceFiles = parse_dsp(dsp)
|
||||
if sourceFiles is None:
|
||||
return None
|
||||
|
||||
module = CExtension(moduleName, sourceFiles)
|
||||
# Put the path to the DSP into the environment so entries can reference it.
|
||||
os.environ['dsp_path'] = os.path.split(dsp)[0]
|
||||
os.environ['ini_path'] = os.path.split(mapFileName)[0]
|
||||
|
||||
cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName)
|
||||
if cl_options:
|
||||
module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))
|
||||
|
||||
exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)
|
||||
exclude = exclude.split()
|
||||
|
||||
if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
|
||||
module.AddCompilerOption('/D UNICODE /D _UNICODE')
|
||||
|
||||
libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split()
|
||||
for lib in libs:
|
||||
module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))
|
||||
|
||||
for exc in exclude:
|
||||
if exc in module.sourceFiles:
|
||||
modules.sourceFiles.remove(exc)
|
||||
|
||||
return module
|
||||
|
||||
# Given an MSVC DSP file, locate C source files it uses
|
||||
# returns a list of source files.
|
||||
def parse_dsp(dsp):
|
||||
# print "Processing", dsp
|
||||
# For now, only support
|
||||
ret = []
|
||||
dsp_path, dsp_name = os.path.split(dsp)
|
||||
try:
|
||||
lines = open(dsp, "r").readlines()
|
||||
except IOError, msg:
|
||||
sys.stderr.write("%s: %s\n" % (dsp, msg))
|
||||
return None
|
||||
for line in lines:
|
||||
fields = line.strip().split("=", 2)
|
||||
if fields[0]=="SOURCE":
|
||||
if os.path.splitext(fields[1])[1].lower() in ['.cpp', '.c']:
|
||||
ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )
|
||||
return ret
|
||||
|
||||
def write_extension_table(fname, modules):
|
||||
fp = open(fname, "w")
|
||||
try:
|
||||
fp.write (ext_src_header)
|
||||
# Write fn protos
|
||||
for module in modules:
|
||||
# bit of a hack for .pyd's as part of packages.
|
||||
name = module.name.split('.')[-1]
|
||||
fp.write('extern void init%s(void);\n' % (name) )
|
||||
# Write the table
|
||||
fp.write (ext_tab_header)
|
||||
for module in modules:
|
||||
name = module.name.split('.')[-1]
|
||||
fp.write('\t{"%s", init%s},\n' % (name, name) )
|
||||
|
||||
fp.write (ext_tab_footer)
|
||||
fp.write(ext_src_footer)
|
||||
finally:
|
||||
fp.close()
|
||||
|
||||
|
||||
ext_src_header = """\
|
||||
#include "Python.h"
|
||||
"""
|
||||
|
||||
ext_tab_header = """\
|
||||
|
||||
static struct _inittab extensions[] = {
|
||||
"""
|
||||
|
||||
ext_tab_footer = """\
|
||||
/* Sentinel */
|
||||
{0, 0}
|
||||
};
|
||||
"""
|
||||
|
||||
ext_src_footer = """\
|
||||
extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
|
||||
|
||||
int PyInitFrozenExtensions()
|
||||
{
|
||||
return PyImport_ExtendInittab(extensions);
|
||||
}
|
||||
|
||||
"""
|
||||
171
project/jni/python/src/Tools/freeze/extensions_win32.ini
Normal file
171
project/jni/python/src/Tools/freeze/extensions_win32.ini
Normal file
@@ -0,0 +1,171 @@
|
||||
; This is a list of modules generally build as .pyd files.
|
||||
;
|
||||
; Each section contains enough information about a module for
|
||||
; freeze to include the module as a static, built-in module
|
||||
; in a frozen .EXE/.DLL.
|
||||
|
||||
; This is all setup for all the win32 extension modules
|
||||
; released by Mark Hammond.
|
||||
; You must ensure that the environment variable PYTHONEX is set
|
||||
; to point to the root win32 extensions directory
|
||||
|
||||
; PYTHONPREFIX must point to the Python build root directory
|
||||
; (the *parent* of PCbuild); normally the freeze script takes
|
||||
; care of this.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;
|
||||
; Standard Python extension modules
|
||||
;
|
||||
|
||||
; Here are some of the standard Python extensions modules.
|
||||
; If you need others, add them here
|
||||
|
||||
[_socket]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\_socket.dsp
|
||||
|
||||
[_sre]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\_sre.dsp
|
||||
|
||||
[unicodedata]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\unicodedata.dsp
|
||||
|
||||
[mmap]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\mmap.dsp
|
||||
|
||||
[winsound]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\winsound.dsp
|
||||
libs=winmm.lib
|
||||
|
||||
[parser]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\parser.dsp
|
||||
|
||||
[select]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\select.dsp
|
||||
|
||||
[zlib]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\zlib.dsp
|
||||
cl=/I %PYTHONPREFIX%\..\zlib-1.1.4 /D _WINDOWS /D WIN32
|
||||
libs=%PYTHONPREFIX%\..\zlib-1.1.4\zlib.lib /nodefaultlib:libc
|
||||
|
||||
[_winreg]
|
||||
dsp=%PYTHONPREFIX%\PCBuild\winreg.dsp
|
||||
libs=advapi32.lib
|
||||
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;
|
||||
; Win32 Projects.
|
||||
;
|
||||
[perfmon]
|
||||
dsp=%PYTHONEX%\win32\perfmon.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
Unicode=1
|
||||
|
||||
[pywintypes]
|
||||
dsp=%PYTHONEX%\win32\pywintypes.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
libs=ole32.lib oleaut32.lib
|
||||
|
||||
[win32api]
|
||||
dsp=%PYTHONEX%\win32\win32api.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
libs=kernel32.lib user32.lib shell32.lib advapi32.lib
|
||||
|
||||
[win32service]
|
||||
dsp=%PYTHONEX%\win32\win32service.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
Unicode=1
|
||||
libs=advapi32.lib
|
||||
|
||||
[win32evtlog]
|
||||
dsp=%PYTHONEX%\win32\win32evtlog.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32process]
|
||||
dsp=%PYTHONEX%\win32\win32process.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32event]
|
||||
dsp=%PYTHONEX%\win32\win32event.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32file]
|
||||
dsp=%PYTHONEX%\win32\win32file.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32net]
|
||||
dsp=%PYTHONEX%\win32\win32net.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
libs=netapi32.lib
|
||||
|
||||
[win32pdh]
|
||||
dsp=%PYTHONEX%\win32\win32pdh.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32pipe]
|
||||
dsp=%PYTHONEX%\win32\win32pipe.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32security]
|
||||
dsp=%PYTHONEX%\win32\win32security.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32service]
|
||||
dsp=%PYTHONEX%\win32\win32service.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
[win32trace]
|
||||
dsp=%PYTHONEX%\win32\win32trace.dsp
|
||||
cl=/I %PYTHONEX%\win32\src
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;
|
||||
; COM Projects.
|
||||
;
|
||||
|
||||
[pythoncom]
|
||||
dsp=%PYTHONEX%\com\win32com.dsp
|
||||
cl=/I %PYTHONEX%\com\win32com\src\include /I %PYTHONEX%\win32\src
|
||||
libs=uuid.lib
|
||||
|
||||
[win32com.axcontrol.axcontrol]
|
||||
dsp=%PYTHONEX%\com\axcontrol.dsp
|
||||
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
|
||||
|
||||
[win32com.axscript.axscript]
|
||||
dsp=%PYTHONEX%\com\Active Scripting.dsp
|
||||
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
|
||||
|
||||
[win32com.axdebug.axdebug]
|
||||
dsp=%PYTHONEX%\com\Active Debugging.dsp
|
||||
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
|
||||
|
||||
[win32com.mapi.mapi]
|
||||
dsp=%PYTHONEX%\com\mapi.dsp
|
||||
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
|
||||
libs=MBLOGON.lib ADDRLKUP.LIB mapi32.lib version.lib
|
||||
|
||||
[win32com.mapi.exchange]
|
||||
dsp=%PYTHONEX%\com\exchange.dsp
|
||||
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
|
||||
libs=MBLOGON.lib ADDRLKUP.LIB exchinst.lib EDKCFG.LIB EDKUTILS.LIB EDKMAPI.LIB mapi32.lib version.lib
|
||||
|
||||
[win32com.mapi.exchdapi]
|
||||
dsp=%PYTHONEX%\com\exchdapi.dsp
|
||||
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
|
||||
libs=DAPI.LIB
|
||||
|
||||
[servicemanager]
|
||||
dsp=%PYTHONEX%\win32\PythonService EXE.dsp
|
||||
Unicode = 1
|
||||
|
||||
; Pythonwin
|
||||
[win32ui]
|
||||
dsp=%PYTHONEX%\Pythonwin\win32ui.dsp
|
||||
cl=/D _AFXDLL /D FREEZE_WIN32UI /GX /I %PYTHONEX%\win32\src
|
||||
libs=mfc42.lib
|
||||
497
project/jni/python/src/Tools/freeze/freeze.py
Normal file
497
project/jni/python/src/Tools/freeze/freeze.py
Normal file
@@ -0,0 +1,497 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Freeze a Python script into a binary.
|
||||
|
||||
usage: freeze [options...] script [module]...
|
||||
|
||||
Options:
|
||||
-p prefix: This is the prefix used when you ran ``make install''
|
||||
in the Python build directory.
|
||||
(If you never ran this, freeze won't work.)
|
||||
The default is whatever sys.prefix evaluates to.
|
||||
It can also be the top directory of the Python source
|
||||
tree; then -P must point to the build tree.
|
||||
|
||||
-P exec_prefix: Like -p but this is the 'exec_prefix', used to
|
||||
install objects etc. The default is whatever sys.exec_prefix
|
||||
evaluates to, or the -p argument if given.
|
||||
If -p points to the Python source tree, -P must point
|
||||
to the build tree, if different.
|
||||
|
||||
-e extension: A directory containing additional .o files that
|
||||
may be used to resolve modules. This directory
|
||||
should also have a Setup file describing the .o files.
|
||||
On Windows, the name of a .INI file describing one
|
||||
or more extensions is passed.
|
||||
More than one -e option may be given.
|
||||
|
||||
-o dir: Directory where the output files are created; default '.'.
|
||||
|
||||
-m: Additional arguments are module names instead of filenames.
|
||||
|
||||
-a package=dir: Additional directories to be added to the package's
|
||||
__path__. Used to simulate directories added by the
|
||||
package at runtime (eg, by OpenGL and win32com).
|
||||
More than one -a option may be given for each package.
|
||||
|
||||
-l file: Pass the file to the linker (windows only)
|
||||
|
||||
-d: Debugging mode for the module finder.
|
||||
|
||||
-q: Make the module finder totally quiet.
|
||||
|
||||
-h: Print this help message.
|
||||
|
||||
-x module Exclude the specified module. It will still be imported
|
||||
by the frozen binary if it exists on the host system.
|
||||
|
||||
-X module Like -x, except the module can never be imported by
|
||||
the frozen binary.
|
||||
|
||||
-E: Freeze will fail if any modules can't be found (that
|
||||
were not excluded using -x or -X).
|
||||
|
||||
-i filename: Include a file with additional command line options. Used
|
||||
to prevent command lines growing beyond the capabilities of
|
||||
the shell/OS. All arguments specified in filename
|
||||
are read and the -i option replaced with the parsed
|
||||
params (note - quoting args in this file is NOT supported)
|
||||
|
||||
-s subsystem: Specify the subsystem (For Windows only.);
|
||||
'console' (default), 'windows', 'service' or 'com_dll'
|
||||
|
||||
-w: Toggle Windows (NT or 95) behavior.
|
||||
(For debugging only -- on a win32 platform, win32 behavior
|
||||
is automatic.)
|
||||
|
||||
-r prefix=f: Replace path prefix.
|
||||
Replace prefix with f in the source path references
|
||||
contained in the resulting binary.
|
||||
|
||||
Arguments:
|
||||
|
||||
script: The Python script to be executed by the resulting binary.
|
||||
|
||||
module ...: Additional Python modules (referenced by pathname)
|
||||
that will be included in the resulting binary. These
|
||||
may be .py or .pyc files. If -m is specified, these are
|
||||
module names that are search in the path instead.
|
||||
|
||||
NOTES:
|
||||
|
||||
In order to use freeze successfully, you must have built Python and
|
||||
installed it ("make install").
|
||||
|
||||
The script should not use modules provided only as shared libraries;
|
||||
if it does, the resulting binary is not self-contained.
|
||||
"""
|
||||
|
||||
|
||||
# Import standard modules
|
||||
|
||||
import modulefinder
|
||||
import getopt
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
# Import the freeze-private modules
|
||||
|
||||
import checkextensions
|
||||
import makeconfig
|
||||
import makefreeze
|
||||
import makemakefile
|
||||
import parsesetup
|
||||
import bkfile
|
||||
|
||||
|
||||
# Main program
|
||||
|
||||
def main():
|
||||
# overridable context
|
||||
prefix = None # settable with -p option
|
||||
exec_prefix = None # settable with -P option
|
||||
extensions = []
|
||||
exclude = [] # settable with -x option
|
||||
addn_link = [] # settable with -l, but only honored under Windows.
|
||||
path = sys.path[:]
|
||||
modargs = 0
|
||||
debug = 1
|
||||
odir = ''
|
||||
win = sys.platform[:3] == 'win'
|
||||
replace_paths = [] # settable with -r option
|
||||
error_if_any_missing = 0
|
||||
|
||||
# default the exclude list for each platform
|
||||
if win: exclude = exclude + [
|
||||
'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix',
|
||||
'os2', 'ce', 'riscos', 'riscosenviron', 'riscospath',
|
||||
]
|
||||
|
||||
fail_import = exclude[:]
|
||||
|
||||
# output files
|
||||
frozen_c = 'frozen.c'
|
||||
config_c = 'config.c'
|
||||
target = 'a.out' # normally derived from script name
|
||||
makefile = 'Makefile'
|
||||
subsystem = 'console'
|
||||
|
||||
# parse command line by first replacing any "-i" options with the
|
||||
# file contents.
|
||||
pos = 1
|
||||
while pos < len(sys.argv)-1:
|
||||
# last option can not be "-i", so this ensures "pos+1" is in range!
|
||||
if sys.argv[pos] == '-i':
|
||||
try:
|
||||
options = open(sys.argv[pos+1]).read().split()
|
||||
except IOError, why:
|
||||
usage("File name '%s' specified with the -i option "
|
||||
"can not be read - %s" % (sys.argv[pos+1], why) )
|
||||
# Replace the '-i' and the filename with the read params.
|
||||
sys.argv[pos:pos+2] = options
|
||||
pos = pos + len(options) - 1 # Skip the name and the included args.
|
||||
pos = pos + 1
|
||||
|
||||
# Now parse the command line with the extras inserted.
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'r:a:dEe:hmo:p:P:qs:wX:x:l:')
|
||||
except getopt.error, msg:
|
||||
usage('getopt error: ' + str(msg))
|
||||
|
||||
# proces option arguments
|
||||
for o, a in opts:
|
||||
if o == '-h':
|
||||
print __doc__
|
||||
return
|
||||
if o == '-d':
|
||||
debug = debug + 1
|
||||
if o == '-e':
|
||||
extensions.append(a)
|
||||
if o == '-m':
|
||||
modargs = 1
|
||||
if o == '-o':
|
||||
odir = a
|
||||
if o == '-p':
|
||||
prefix = a
|
||||
if o == '-P':
|
||||
exec_prefix = a
|
||||
if o == '-q':
|
||||
debug = 0
|
||||
if o == '-w':
|
||||
win = not win
|
||||
if o == '-s':
|
||||
if not win:
|
||||
usage("-s subsystem option only on Windows")
|
||||
subsystem = a
|
||||
if o == '-x':
|
||||
exclude.append(a)
|
||||
if o == '-X':
|
||||
exclude.append(a)
|
||||
fail_import.append(a)
|
||||
if o == '-E':
|
||||
error_if_any_missing = 1
|
||||
if o == '-l':
|
||||
addn_link.append(a)
|
||||
if o == '-a':
|
||||
apply(modulefinder.AddPackagePath, tuple(a.split("=", 2)))
|
||||
if o == '-r':
|
||||
f,r = a.split("=", 2)
|
||||
replace_paths.append( (f,r) )
|
||||
|
||||
# modules that are imported by the Python runtime
|
||||
implicits = []
|
||||
for module in ('site', 'warnings',):
|
||||
if module not in exclude:
|
||||
implicits.append(module)
|
||||
|
||||
# default prefix and exec_prefix
|
||||
if not exec_prefix:
|
||||
if prefix:
|
||||
exec_prefix = prefix
|
||||
else:
|
||||
exec_prefix = sys.exec_prefix
|
||||
if not prefix:
|
||||
prefix = sys.prefix
|
||||
|
||||
# determine whether -p points to the Python source tree
|
||||
ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c'))
|
||||
|
||||
# locations derived from options
|
||||
version = sys.version[:3]
|
||||
if win:
|
||||
extensions_c = 'frozen_extensions.c'
|
||||
if ishome:
|
||||
print "(Using Python source directory)"
|
||||
binlib = exec_prefix
|
||||
incldir = os.path.join(prefix, 'Include')
|
||||
config_h_dir = exec_prefix
|
||||
config_c_in = os.path.join(prefix, 'Modules', 'config.c.in')
|
||||
frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c')
|
||||
makefile_in = os.path.join(exec_prefix, 'Makefile')
|
||||
if win:
|
||||
frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c')
|
||||
else:
|
||||
binlib = os.path.join(exec_prefix,
|
||||
'lib', 'python%s' % version, 'config')
|
||||
incldir = os.path.join(prefix, 'include', 'python%s' % version)
|
||||
config_h_dir = os.path.join(exec_prefix, 'include',
|
||||
'python%s' % version)
|
||||
config_c_in = os.path.join(binlib, 'config.c.in')
|
||||
frozenmain_c = os.path.join(binlib, 'frozenmain.c')
|
||||
makefile_in = os.path.join(binlib, 'Makefile')
|
||||
frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c')
|
||||
supp_sources = []
|
||||
defines = []
|
||||
includes = ['-I' + incldir, '-I' + config_h_dir]
|
||||
|
||||
# sanity check of directories and files
|
||||
check_dirs = [prefix, exec_prefix, binlib, incldir]
|
||||
if not win:
|
||||
# These are not directories on Windows.
|
||||
check_dirs = check_dirs + extensions
|
||||
for dir in check_dirs:
|
||||
if not os.path.exists(dir):
|
||||
usage('needed directory %s not found' % dir)
|
||||
if not os.path.isdir(dir):
|
||||
usage('%s: not a directory' % dir)
|
||||
if win:
|
||||
files = supp_sources + extensions # extensions are files on Windows.
|
||||
else:
|
||||
files = [config_c_in, makefile_in] + supp_sources
|
||||
for file in supp_sources:
|
||||
if not os.path.exists(file):
|
||||
usage('needed file %s not found' % file)
|
||||
if not os.path.isfile(file):
|
||||
usage('%s: not a plain file' % file)
|
||||
if not win:
|
||||
for dir in extensions:
|
||||
setup = os.path.join(dir, 'Setup')
|
||||
if not os.path.exists(setup):
|
||||
usage('needed file %s not found' % setup)
|
||||
if not os.path.isfile(setup):
|
||||
usage('%s: not a plain file' % setup)
|
||||
|
||||
# check that enough arguments are passed
|
||||
if not args:
|
||||
usage('at least one filename argument required')
|
||||
|
||||
# check that file arguments exist
|
||||
for arg in args:
|
||||
if arg == '-m':
|
||||
break
|
||||
# if user specified -m on the command line before _any_
|
||||
# file names, then nothing should be checked (as the
|
||||
# very first file should be a module name)
|
||||
if modargs:
|
||||
break
|
||||
if not os.path.exists(arg):
|
||||
usage('argument %s not found' % arg)
|
||||
if not os.path.isfile(arg):
|
||||
usage('%s: not a plain file' % arg)
|
||||
|
||||
# process non-option arguments
|
||||
scriptfile = args[0]
|
||||
modules = args[1:]
|
||||
|
||||
# derive target name from script name
|
||||
base = os.path.basename(scriptfile)
|
||||
base, ext = os.path.splitext(base)
|
||||
if base:
|
||||
if base != scriptfile:
|
||||
target = base
|
||||
else:
|
||||
target = base + '.bin'
|
||||
|
||||
# handle -o option
|
||||
base_frozen_c = frozen_c
|
||||
base_config_c = config_c
|
||||
base_target = target
|
||||
if odir and not os.path.isdir(odir):
|
||||
try:
|
||||
os.mkdir(odir)
|
||||
print "Created output directory", odir
|
||||
except os.error, msg:
|
||||
usage('%s: mkdir failed (%s)' % (odir, str(msg)))
|
||||
base = ''
|
||||
if odir:
|
||||
base = os.path.join(odir, '')
|
||||
frozen_c = os.path.join(odir, frozen_c)
|
||||
config_c = os.path.join(odir, config_c)
|
||||
target = os.path.join(odir, target)
|
||||
makefile = os.path.join(odir, makefile)
|
||||
if win: extensions_c = os.path.join(odir, extensions_c)
|
||||
|
||||
# Handle special entry point requirements
|
||||
# (on Windows, some frozen programs do not use __main__, but
|
||||
# import the module directly. Eg, DLLs, Services, etc
|
||||
custom_entry_point = None # Currently only used on Windows
|
||||
python_entry_is_main = 1 # Is the entry point called __main__?
|
||||
# handle -s option on Windows
|
||||
if win:
|
||||
import winmakemakefile
|
||||
try:
|
||||
custom_entry_point, python_entry_is_main = \
|
||||
winmakemakefile.get_custom_entry_point(subsystem)
|
||||
except ValueError, why:
|
||||
usage(why)
|
||||
|
||||
|
||||
# Actual work starts here...
|
||||
|
||||
# collect all modules of the program
|
||||
dir = os.path.dirname(scriptfile)
|
||||
path[0] = dir
|
||||
mf = modulefinder.ModuleFinder(path, debug, exclude, replace_paths)
|
||||
|
||||
if win and subsystem=='service':
|
||||
# If a Windows service, then add the "built-in" module.
|
||||
mod = mf.add_module("servicemanager")
|
||||
mod.__file__="dummy.pyd" # really built-in to the resulting EXE
|
||||
|
||||
for mod in implicits:
|
||||
mf.import_hook(mod)
|
||||
for mod in modules:
|
||||
if mod == '-m':
|
||||
modargs = 1
|
||||
continue
|
||||
if modargs:
|
||||
if mod[-2:] == '.*':
|
||||
mf.import_hook(mod[:-2], None, ["*"])
|
||||
else:
|
||||
mf.import_hook(mod)
|
||||
else:
|
||||
mf.load_file(mod)
|
||||
|
||||
# Add the main script as either __main__, or the actual module name.
|
||||
if python_entry_is_main:
|
||||
mf.run_script(scriptfile)
|
||||
else:
|
||||
mf.load_file(scriptfile)
|
||||
|
||||
if debug > 0:
|
||||
mf.report()
|
||||
print
|
||||
dict = mf.modules
|
||||
|
||||
if error_if_any_missing:
|
||||
missing = mf.any_missing()
|
||||
if missing:
|
||||
sys.exit("There are some missing modules: %r" % missing)
|
||||
|
||||
# generate output for frozen modules
|
||||
files = makefreeze.makefreeze(base, dict, debug, custom_entry_point,
|
||||
fail_import)
|
||||
|
||||
# look for unfrozen modules (builtin and of unknown origin)
|
||||
builtins = []
|
||||
unknown = []
|
||||
mods = dict.keys()
|
||||
mods.sort()
|
||||
for mod in mods:
|
||||
if dict[mod].__code__:
|
||||
continue
|
||||
if not dict[mod].__file__:
|
||||
builtins.append(mod)
|
||||
else:
|
||||
unknown.append(mod)
|
||||
|
||||
# search for unknown modules in extensions directories (not on Windows)
|
||||
addfiles = []
|
||||
frozen_extensions = [] # Windows list of modules.
|
||||
if unknown or (not win and builtins):
|
||||
if not win:
|
||||
addfiles, addmods = \
|
||||
checkextensions.checkextensions(unknown+builtins,
|
||||
extensions)
|
||||
for mod in addmods:
|
||||
if mod in unknown:
|
||||
unknown.remove(mod)
|
||||
builtins.append(mod)
|
||||
else:
|
||||
# Do the windows thang...
|
||||
import checkextensions_win32
|
||||
# Get a list of CExtension instances, each describing a module
|
||||
# (including its source files)
|
||||
frozen_extensions = checkextensions_win32.checkextensions(
|
||||
unknown, extensions, prefix)
|
||||
for mod in frozen_extensions:
|
||||
unknown.remove(mod.name)
|
||||
|
||||
# report unknown modules
|
||||
if unknown:
|
||||
sys.stderr.write('Warning: unknown modules remain: %s\n' %
|
||||
' '.join(unknown))
|
||||
|
||||
# windows gets different treatment
|
||||
if win:
|
||||
# Taking a shortcut here...
|
||||
import winmakemakefile, checkextensions_win32
|
||||
checkextensions_win32.write_extension_table(extensions_c,
|
||||
frozen_extensions)
|
||||
# Create a module definition for the bootstrap C code.
|
||||
xtras = [frozenmain_c, os.path.basename(frozen_c),
|
||||
frozendllmain_c, os.path.basename(extensions_c)] + files
|
||||
maindefn = checkextensions_win32.CExtension( '__main__', xtras )
|
||||
frozen_extensions.append( maindefn )
|
||||
outfp = open(makefile, 'w')
|
||||
try:
|
||||
winmakemakefile.makemakefile(outfp,
|
||||
locals(),
|
||||
frozen_extensions,
|
||||
os.path.basename(target))
|
||||
finally:
|
||||
outfp.close()
|
||||
return
|
||||
|
||||
# generate config.c and Makefile
|
||||
builtins.sort()
|
||||
infp = open(config_c_in)
|
||||
outfp = bkfile.open(config_c, 'w')
|
||||
try:
|
||||
makeconfig.makeconfig(infp, outfp, builtins)
|
||||
finally:
|
||||
outfp.close()
|
||||
infp.close()
|
||||
|
||||
cflags = ['$(OPT)']
|
||||
cppflags = defines + includes
|
||||
libs = [os.path.join(binlib, 'libpython$(VERSION).a')]
|
||||
|
||||
somevars = {}
|
||||
if os.path.exists(makefile_in):
|
||||
makevars = parsesetup.getmakevars(makefile_in)
|
||||
for key in makevars.keys():
|
||||
somevars[key] = makevars[key]
|
||||
|
||||
somevars['CFLAGS'] = ' '.join(cflags) # override
|
||||
somevars['CPPFLAGS'] = ' '.join(cppflags) # override
|
||||
files = [base_config_c, base_frozen_c] + \
|
||||
files + supp_sources + addfiles + libs + \
|
||||
['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
|
||||
|
||||
outfp = bkfile.open(makefile, 'w')
|
||||
try:
|
||||
makemakefile.makemakefile(outfp, somevars, files, base_target)
|
||||
finally:
|
||||
outfp.close()
|
||||
|
||||
# Done!
|
||||
|
||||
if odir:
|
||||
print 'Now run "make" in', odir,
|
||||
print 'to build the target:', base_target
|
||||
else:
|
||||
print 'Now run "make" to build the target:', base_target
|
||||
|
||||
|
||||
# Print usage message and exit
|
||||
|
||||
def usage(msg):
|
||||
sys.stdout = sys.stderr
|
||||
print "Error:", msg
|
||||
print "Use ``%s -h'' for help" % sys.argv[0]
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
main()
|
||||
1
project/jni/python/src/Tools/freeze/hello.py
Normal file
1
project/jni/python/src/Tools/freeze/hello.py
Normal file
@@ -0,0 +1 @@
|
||||
print 'Hello world...'
|
||||
61
project/jni/python/src/Tools/freeze/makeconfig.py
Normal file
61
project/jni/python/src/Tools/freeze/makeconfig.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import re
|
||||
|
||||
|
||||
# Write the config.c file
|
||||
|
||||
never = ['marshal', '__main__', '__builtin__', 'sys', 'exceptions']
|
||||
|
||||
def makeconfig(infp, outfp, modules, with_ifdef=0):
|
||||
m1 = re.compile('-- ADDMODULE MARKER 1 --')
|
||||
m2 = re.compile('-- ADDMODULE MARKER 2 --')
|
||||
while 1:
|
||||
line = infp.readline()
|
||||
if not line: break
|
||||
outfp.write(line)
|
||||
if m1 and m1.search(line):
|
||||
m1 = None
|
||||
for mod in modules:
|
||||
if mod in never:
|
||||
continue
|
||||
if with_ifdef:
|
||||
outfp.write("#ifndef init%s\n"%mod)
|
||||
outfp.write('extern void init%s(void);\n' % mod)
|
||||
if with_ifdef:
|
||||
outfp.write("#endif\n")
|
||||
elif m2 and m2.search(line):
|
||||
m2 = None
|
||||
for mod in modules:
|
||||
if mod in never:
|
||||
continue
|
||||
outfp.write('\t{"%s", init%s},\n' %
|
||||
(mod, mod))
|
||||
if m1:
|
||||
sys.stderr.write('MARKER 1 never found\n')
|
||||
elif m2:
|
||||
sys.stderr.write('MARKER 2 never found\n')
|
||||
|
||||
|
||||
# Test program.
|
||||
|
||||
def test():
|
||||
import sys
|
||||
if not sys.argv[3:]:
|
||||
print 'usage: python makeconfig.py config.c.in outputfile',
|
||||
print 'modulename ...'
|
||||
sys.exit(2)
|
||||
if sys.argv[1] == '-':
|
||||
infp = sys.stdin
|
||||
else:
|
||||
infp = open(sys.argv[1])
|
||||
if sys.argv[2] == '-':
|
||||
outfp = sys.stdout
|
||||
else:
|
||||
outfp = open(sys.argv[2], 'w')
|
||||
makeconfig(infp, outfp, sys.argv[3:])
|
||||
if outfp != sys.stdout:
|
||||
outfp.close()
|
||||
if infp != sys.stdin:
|
||||
infp.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
90
project/jni/python/src/Tools/freeze/makefreeze.py
Normal file
90
project/jni/python/src/Tools/freeze/makefreeze.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import marshal
|
||||
import bkfile
|
||||
|
||||
|
||||
# Write a file containing frozen code for the modules in the dictionary.
|
||||
|
||||
header = """
|
||||
#include "Python.h"
|
||||
|
||||
static struct _frozen _PyImport_FrozenModules[] = {
|
||||
"""
|
||||
trailer = """\
|
||||
{0, 0, 0} /* sentinel */
|
||||
};
|
||||
"""
|
||||
|
||||
# if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app.
|
||||
default_entry_point = """
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
extern int Py_FrozenMain(int, char **);
|
||||
""" + ((not __debug__ and """
|
||||
Py_OptimizeFlag++;
|
||||
""") or "") + """
|
||||
PyImport_FrozenModules = _PyImport_FrozenModules;
|
||||
return Py_FrozenMain(argc, argv);
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
def makefreeze(base, dict, debug=0, entry_point=None, fail_import=()):
|
||||
if entry_point is None: entry_point = default_entry_point
|
||||
done = []
|
||||
files = []
|
||||
mods = dict.keys()
|
||||
mods.sort()
|
||||
for mod in mods:
|
||||
m = dict[mod]
|
||||
mangled = "__".join(mod.split("."))
|
||||
if m.__code__:
|
||||
file = 'M_' + mangled + '.c'
|
||||
outfp = bkfile.open(base + file, 'w')
|
||||
files.append(file)
|
||||
if debug:
|
||||
print "freezing", mod, "..."
|
||||
str = marshal.dumps(m.__code__)
|
||||
size = len(str)
|
||||
if m.__path__:
|
||||
# Indicate package by negative size
|
||||
size = -size
|
||||
done.append((mod, mangled, size))
|
||||
writecode(outfp, mangled, str)
|
||||
outfp.close()
|
||||
if debug:
|
||||
print "generating table of frozen modules"
|
||||
outfp = bkfile.open(base + 'frozen.c', 'w')
|
||||
for mod, mangled, size in done:
|
||||
outfp.write('extern unsigned char M_%s[];\n' % mangled)
|
||||
outfp.write(header)
|
||||
for mod, mangled, size in done:
|
||||
outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size))
|
||||
outfp.write('\n')
|
||||
# The following modules have a NULL code pointer, indicating
|
||||
# that the prozen program should not search for them on the host
|
||||
# system. Importing them will *always* raise an ImportError.
|
||||
# The zero value size is never used.
|
||||
for mod in fail_import:
|
||||
outfp.write('\t{"%s", NULL, 0},\n' % (mod,))
|
||||
outfp.write(trailer)
|
||||
outfp.write(entry_point)
|
||||
outfp.close()
|
||||
return files
|
||||
|
||||
|
||||
|
||||
# Write a C initializer for a module containing the frozen python code.
|
||||
# The array is called M_<mod>.
|
||||
|
||||
def writecode(outfp, mod, str):
|
||||
outfp.write('unsigned char M_%s[] = {' % mod)
|
||||
for i in range(0, len(str), 16):
|
||||
outfp.write('\n\t')
|
||||
for c in str[i:i+16]:
|
||||
outfp.write('%d,' % ord(c))
|
||||
outfp.write('\n};\n')
|
||||
|
||||
## def writecode(outfp, mod, str):
|
||||
## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str),
|
||||
## '\\"'.join(map(lambda s: repr(s)[1:-1], str.split('"')))))
|
||||
29
project/jni/python/src/Tools/freeze/makemakefile.py
Normal file
29
project/jni/python/src/Tools/freeze/makemakefile.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Write the actual Makefile.
|
||||
|
||||
import os
|
||||
|
||||
def makemakefile(outfp, makevars, files, target):
|
||||
outfp.write("# Makefile generated by freeze.py script\n\n")
|
||||
|
||||
keys = makevars.keys()
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
outfp.write("%s=%s\n" % (key, makevars[key]))
|
||||
outfp.write("\nall: %s\n\n" % target)
|
||||
|
||||
deps = []
|
||||
for i in range(len(files)):
|
||||
file = files[i]
|
||||
if file[-2:] == '.c':
|
||||
base = os.path.basename(file)
|
||||
dest = base[:-2] + '.o'
|
||||
outfp.write("%s: %s\n" % (dest, file))
|
||||
outfp.write("\t$(CC) $(CFLAGS) $(CPPFLAGS) -c %s\n" % file)
|
||||
files[i] = dest
|
||||
deps.append(dest)
|
||||
|
||||
outfp.write("\n%s: %s\n" % (target, ' '.join(deps)))
|
||||
outfp.write("\t$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) %s -o %s $(LDLAST)\n" %
|
||||
(' '.join(files), target))
|
||||
|
||||
outfp.write("\nclean:\n\t-rm -f *.o %s\n" % target)
|
||||
112
project/jni/python/src/Tools/freeze/parsesetup.py
Normal file
112
project/jni/python/src/Tools/freeze/parsesetup.py
Normal file
@@ -0,0 +1,112 @@
|
||||
# Parse Makefiles and Python Setup(.in) files.
|
||||
|
||||
import re
|
||||
|
||||
|
||||
# Extract variable definitions from a Makefile.
|
||||
# Return a dictionary mapping names to values.
|
||||
# May raise IOError.
|
||||
|
||||
makevardef = re.compile('^([a-zA-Z0-9_]+)[ \t]*=(.*)')
|
||||
|
||||
def getmakevars(filename):
|
||||
variables = {}
|
||||
fp = open(filename)
|
||||
pendingline = ""
|
||||
try:
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if pendingline:
|
||||
line = pendingline + line
|
||||
pendingline = ""
|
||||
if not line:
|
||||
break
|
||||
if line.endswith('\\\n'):
|
||||
pendingline = line[:-2]
|
||||
matchobj = makevardef.match(line)
|
||||
if not matchobj:
|
||||
continue
|
||||
(name, value) = matchobj.group(1, 2)
|
||||
# Strip trailing comment
|
||||
i = value.find('#')
|
||||
if i >= 0:
|
||||
value = value[:i]
|
||||
value = value.strip()
|
||||
variables[name] = value
|
||||
finally:
|
||||
fp.close()
|
||||
return variables
|
||||
|
||||
|
||||
# Parse a Python Setup(.in) file.
|
||||
# Return two dictionaries, the first mapping modules to their
|
||||
# definitions, the second mapping variable names to their values.
|
||||
# May raise IOError.
|
||||
|
||||
setupvardef = re.compile('^([a-zA-Z0-9_]+)=(.*)')
|
||||
|
||||
def getsetupinfo(filename):
|
||||
modules = {}
|
||||
variables = {}
|
||||
fp = open(filename)
|
||||
pendingline = ""
|
||||
try:
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if pendingline:
|
||||
line = pendingline + line
|
||||
pendingline = ""
|
||||
if not line:
|
||||
break
|
||||
# Strip comments
|
||||
i = line.find('#')
|
||||
if i >= 0:
|
||||
line = line[:i]
|
||||
if line.endswith('\\\n'):
|
||||
pendingline = line[:-2]
|
||||
continue
|
||||
matchobj = setupvardef.match(line)
|
||||
if matchobj:
|
||||
(name, value) = matchobj.group(1, 2)
|
||||
variables[name] = value.strip()
|
||||
else:
|
||||
words = line.split()
|
||||
if words:
|
||||
modules[words[0]] = words[1:]
|
||||
finally:
|
||||
fp.close()
|
||||
return modules, variables
|
||||
|
||||
|
||||
# Test the above functions.
|
||||
|
||||
def test():
|
||||
import sys
|
||||
import os
|
||||
if not sys.argv[1:]:
|
||||
print 'usage: python parsesetup.py Makefile*|Setup* ...'
|
||||
sys.exit(2)
|
||||
for arg in sys.argv[1:]:
|
||||
base = os.path.basename(arg)
|
||||
if base[:8] == 'Makefile':
|
||||
print 'Make style parsing:', arg
|
||||
v = getmakevars(arg)
|
||||
prdict(v)
|
||||
elif base[:5] == 'Setup':
|
||||
print 'Setup style parsing:', arg
|
||||
m, v = getsetupinfo(arg)
|
||||
prdict(m)
|
||||
prdict(v)
|
||||
else:
|
||||
print arg, 'is neither a Makefile nor a Setup file'
|
||||
print '(name must begin with "Makefile" or "Setup")'
|
||||
|
||||
def prdict(d):
|
||||
keys = d.keys()
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
value = d[key]
|
||||
print "%-15s" % key, str(value)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
119
project/jni/python/src/Tools/freeze/win32.html
Normal file
119
project/jni/python/src/Tools/freeze/win32.html
Normal file
@@ -0,0 +1,119 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
|
||||
<META NAME="Generator" CONTENT="Microsoft Word 97">
|
||||
<TITLE>win32</TITLE>
|
||||
<META NAME="Version" CONTENT="8.0.3410">
|
||||
<META NAME="Date" CONTENT="10/11/96">
|
||||
<META NAME="Template" CONTENT="D:\Program Files\Microsoft Office\Office\HTML.DOT">
|
||||
</HEAD>
|
||||
<BODY TEXT="#000000" BGCOLOR="#ffffff">
|
||||
|
||||
<H1>Freeze for Win32</H1>
|
||||
<P>This document describes how to use Freeze for the Win32 platform. </P>
|
||||
<P>Freeze itself is a Python tool for creating stand-alone executables from Python source code. This document does not attempt to document freeze itself - only the win32 specific changes.</P>
|
||||
<H2>Frozen programs under Win32</H2>
|
||||
<P>Frozen programs under Win32 can (theoretically) freeze any type of program supported by Python on Win32 - At the moment, Console .EXE and NT Service .EXE programs are supported. GUI Python programs and COM .EXE programs are very nearly all ready to go.</P>
|
||||
<H3>Program Dependencies</H3>
|
||||
<P>The person freezing the program has control over what external DLLs are required by a frozen program. The following dependencies are supported:</P>
|
||||
<H4>Minimal frozen programs</H4>
|
||||
<P>These programs freeze only .py files in your program. All external DLLs are required at run-time. This includes all .pyd/.dll modules used by your program, Python20.dll, and msvcrt.dll. </P>
|
||||
<P>A small Python program would typically create a .EXE around 300kb.</P>
|
||||
<H4>Frozen Extension programs</H4>
|
||||
<B><I><P>Note:</B></I> For Python1.5.1, you must get a patch from Guido to import.c for this to work.</P>
|
||||
<P>These programs also freeze in the sources from all .pyd and .dll files used at runtime. This means the resulting .EXE is only dependent on Python20.dll and msvcrt.dll.</P>
|
||||
<P>A small Python program using win32api, win32con and one or 2 other win32 extensions would typically create a .EXE around 400kb.</P>
|
||||
<H4>Completely frozen programs</H4>
|
||||
<P>Completely stand-alone programs, as is the default on Unix systems. These are currently not supported, mainly as the size of a decent Python program gets very large. However, by tweaking the existing Unix support, this would not be difficult to do.</P>
|
||||
<H2>Freezing Extension Modules</H2>
|
||||
<P>By default, a file in the main "freeze" directory called "extensions_win32.ini" is used to obtain information about frozen extensions. A typical entry is:</P>
|
||||
<CODE><P>[win32api]</P>
|
||||
<P>dsp=%PYTHONEX%\win32\win32api.dsp</P>
|
||||
<P>cl=/I %PYTHONEX%\win32\src</P>
|
||||
<P>libs=kernel32.lib user32.lib shell32.lib advapi32.lib</P>
|
||||
</CODE><P> </P>
|
||||
<P>This entry indicates that the win32api extension module is defined in the MSVC project file "<CODE>%PYTHONEX%\win32\win32api.dsp</CODE>". Note the use of<CODE> </CODE>"<CODE>%PYTHONEX%" </CODE>- most strings are substituted with environment variables. In this case, it is assumed variable PYTHONEX points to the main "Python Extensions" source directory (which is assumed to be in the same structure as the release of the extension sources).</P>
|
||||
<P>An entry in a .INI file can also control specific compiler options, and also the .lib files necessary to be linked with the application.</P>
|
||||
<H3>Freezing Extension Module Considerations</H3>
|
||||
<P>To prevent freezing extension modules, simply exclude that module using the freeze "-x" switch.</P>
|
||||
<P>Occasionally, it will be necessary to explicitly include dependent modules. For example, many win32 modules are dependent on the "pywintypes" module - for example, the win32api module. In this case, the module may be explicitly included using the freeze "-m" option.</P>
|
||||
<H3>Freezing win32com and PythonCOM</H3>
|
||||
<P>PythonCOM.dll can be frozen as long as you are not implementing COM Servers. Ie, you can freeze programs which control other applications, but can not implement programs that are themselves controlled by other applications.</P>
|
||||
<P>If you use any of the win32com .pyd extensions (ex, axscript, mapi, internet, axcontrol), then you will need to specify an additional "-a" option to point to the win32comext directory. There is an example below.</P>
|
||||
<P>The use of the "win32com.client.gencache" module is not supported (although could be quite easily??)</P>
|
||||
<H2>Examples</H2>
|
||||
<P>Before we start, we must:</P>
|
||||
<CODE><P>D:\temp\delme>set PYTHONEX=d:\src\pythonex</P>
|
||||
</CODE><H3>Helloworld.py</H3>
|
||||
<H4>Source Code</H4><DIR>
|
||||
<DIR>
|
||||
|
||||
<CODE><P>import sys</P>
|
||||
<P> </P>
|
||||
<P>print " ".join( ["Hello", "world"] + sys.argv[1:] )</P></DIR>
|
||||
</DIR>
|
||||
|
||||
</CODE><H4>Command Line used</H4><DIR>
|
||||
<DIR>
|
||||
|
||||
<FONT FACE="Courier New" SIZE=2><P>\src\python-1.5.1\tools\freeze\freeze.py helloworld.py</P>
|
||||
<P>nmake</P></DIR>
|
||||
</DIR>
|
||||
|
||||
</FONT><P>Resulting helloworld.exe: 114,688 bytes.</P>
|
||||
<H3>Helloworld2.py</H3>
|
||||
<P>Uses win32api. Demonstrates requirement for pywintypes, and difference between freezing extensions and not.</P>
|
||||
<H4>Source Code</H4><DIR>
|
||||
<DIR>
|
||||
|
||||
<P>import win32api</P>
|
||||
<P>print "Hello from", win32api.GetComputerName()</P></DIR>
|
||||
</DIR>
|
||||
|
||||
<H4>Command Line used</H4>
|
||||
<P>By default, win32api will be frozen in with the .EXE. If you do not provide the "pywintypes" inclusion, then the link step will fail looking for all the pywintypes modules.</P><DIR>
|
||||
<DIR>
|
||||
|
||||
<FONT FACE="Courier New" SIZE=2><P>\src\python-1.5.1\tools\freeze\freeze.py helloworld2.py -m pywintypes</P>
|
||||
<P>nmake</P></DIR>
|
||||
</DIR>
|
||||
|
||||
</FONT><P>Resulting helloworld2.exe: 167,936 bytes</P>
|
||||
<P>Simply adding win32con to the mix gives an EXE of size: 352,768 bytes.</P>
|
||||
<H4>Command Line used</H4>
|
||||
<P>Using this build, we are dependent at runtime on the win32api.pyd and pywintypes15.dll files.</P><DIR>
|
||||
<DIR>
|
||||
|
||||
<P>\src\python-1.5.1\tools\freeze\freeze.py -x win32api helloworld.py</P></DIR>
|
||||
</DIR>
|
||||
|
||||
<P>Resulting helloworld2.exe: 114,688</P>
|
||||
<P>Adding win32con to this build results in a size of: 252,928</P>
|
||||
<H3>Testmapi.py</H3>
|
||||
<P>Uses MAPI, a PythonCOM extension, and win32api.</P>
|
||||
<H4>Source Code</H4>
|
||||
<P>from win32com.mapi import mapi</P>
|
||||
<P>import win32api</P>
|
||||
<P>mapi.MAPIInitialize( (mapi.MAPI_INIT_VERSION, 0) )</P>
|
||||
<P>print "Hello from", win32api.GetComputerName()</P>
|
||||
<P>mapi.MAPIUninitialize()</P>
|
||||
<H4>Command Line used</H4>
|
||||
<P>As it does not import pythoncom or pywintypes itself, they must be specified. As it uses the win32comext directory, -a must be used. If you have built the win32com extensions from sources, then the second -a is required.</P><DIR>
|
||||
<DIR>
|
||||
|
||||
<CODE><P>\src\python-1.5.1\tools\freeze\freeze.py -a win32com=%PYTHONEX%\com\win32comext -a win32com.mapi=%PYTHONEX%\com\build\release testmapi.py -m pywintypes -m pythoncom</P></DIR>
|
||||
</DIR>
|
||||
|
||||
</CODE><P>Resulting testmapi.exe: 352,768 bytes</P>
|
||||
<H3>PipeTestService.py</H3>
|
||||
<P>This is a standard Python demo in the Win32 extensions. It can be found in the "win32\demos\service" directory.</P>
|
||||
<H4>Command Line used</H4>
|
||||
<P>This will create a native NT Service EXE, dependent only on the main Python20.dll. All other modules are built-in to the final .EXE</P><DIR>
|
||||
<DIR>
|
||||
|
||||
<CODE><P>\src\python-1.5.1\tools\freeze\freeze.py -s service %PYTHONEX%\win32\demos\service\pipeTestService.py</P></DIR>
|
||||
</DIR>
|
||||
|
||||
<P>Resulting pipeTestService.exe: </CODE><FONT FACE="Courier New" SIZE=2>533,504 bytes.</P></FONT></BODY>
|
||||
</HTML>
|
||||
|
||||
146
project/jni/python/src/Tools/freeze/winmakemakefile.py
Normal file
146
project/jni/python/src/Tools/freeze/winmakemakefile.py
Normal file
@@ -0,0 +1,146 @@
|
||||
import sys, os
|
||||
|
||||
# Template used then the program is a GUI program
|
||||
WINMAINTEMPLATE = """
|
||||
#include <windows.h>
|
||||
|
||||
int WINAPI WinMain(
|
||||
HINSTANCE hInstance, // handle to current instance
|
||||
HINSTANCE hPrevInstance, // handle to previous instance
|
||||
LPSTR lpCmdLine, // pointer to command line
|
||||
int nCmdShow // show state of window
|
||||
)
|
||||
{
|
||||
extern int Py_FrozenMain(int, char **);
|
||||
PyImport_FrozenModules = _PyImport_FrozenModules;
|
||||
return Py_FrozenMain(__argc, __argv);
|
||||
}
|
||||
"""
|
||||
|
||||
SERVICETEMPLATE = """
|
||||
extern int PythonService_main(int, char **);
|
||||
|
||||
int main( int argc, char **argv)
|
||||
{
|
||||
PyImport_FrozenModules = _PyImport_FrozenModules;
|
||||
return PythonService_main(argc, argv);
|
||||
}
|
||||
"""
|
||||
|
||||
subsystem_details = {
|
||||
# -s flag : (C entry point template), (is it __main__?), (is it a DLL?)
|
||||
'console' : (None, 1, 0),
|
||||
'windows' : (WINMAINTEMPLATE, 1, 0),
|
||||
'service' : (SERVICETEMPLATE, 0, 0),
|
||||
'com_dll' : ("", 0, 1),
|
||||
}
|
||||
|
||||
def get_custom_entry_point(subsystem):
|
||||
try:
|
||||
return subsystem_details[subsystem][:2]
|
||||
except KeyError:
|
||||
raise ValueError, "The subsystem %s is not known" % subsystem
|
||||
|
||||
|
||||
def makemakefile(outfp, vars, files, target):
|
||||
save = sys.stdout
|
||||
try:
|
||||
sys.stdout = outfp
|
||||
realwork(vars, files, target)
|
||||
finally:
|
||||
sys.stdout = save
|
||||
|
||||
def realwork(vars, moddefns, target):
|
||||
version_suffix = "%r%r" % sys.version_info[:2]
|
||||
print "# Makefile for Microsoft Visual C++ generated by freeze.py script"
|
||||
print
|
||||
print 'target = %s' % target
|
||||
print 'pythonhome = %s' % vars['prefix']
|
||||
print
|
||||
print 'DEBUG=0 # Set to 1 to use the _d versions of Python.'
|
||||
print '!IF $(DEBUG)'
|
||||
print 'debug_suffix=_d'
|
||||
print 'c_debug=/Zi /Od /DDEBUG /D_DEBUG'
|
||||
print 'l_debug=/DEBUG'
|
||||
print 'temp_dir=Build\\Debug'
|
||||
print '!ELSE'
|
||||
print 'debug_suffix='
|
||||
print 'c_debug=/Ox'
|
||||
print 'l_debug='
|
||||
print 'temp_dir=Build\\Release'
|
||||
print '!ENDIF'
|
||||
print
|
||||
|
||||
print '# The following line assumes you have built Python using the standard instructions'
|
||||
print '# Otherwise fix the following line to point to the library.'
|
||||
print 'pythonlib = "$(pythonhome)/pcbuild/python%s$(debug_suffix).lib"' % version_suffix
|
||||
print
|
||||
|
||||
# We only ever write one "entry point" symbol - either
|
||||
# "main" or "WinMain". Therefore, there is no need to
|
||||
# pass a subsystem switch to the linker as it works it
|
||||
# out all by itself. However, the subsystem _does_ determine
|
||||
# the file extension and additional linker flags.
|
||||
target_link_flags = ""
|
||||
target_ext = ".exe"
|
||||
if subsystem_details[vars['subsystem']][2]:
|
||||
target_link_flags = "-dll"
|
||||
target_ext = ".dll"
|
||||
|
||||
|
||||
print "# As the target uses Python%s.dll, we must use this compiler option!" % version_suffix
|
||||
print "cdl = /MD"
|
||||
print
|
||||
print "all: $(target)$(debug_suffix)%s" % (target_ext)
|
||||
print
|
||||
|
||||
print '$(temp_dir):'
|
||||
print ' if not exist $(temp_dir)\. mkdir $(temp_dir)'
|
||||
print
|
||||
|
||||
objects = []
|
||||
libs = ["shell32.lib", "comdlg32.lib", "wsock32.lib", "user32.lib", "oleaut32.lib"]
|
||||
for moddefn in moddefns:
|
||||
print "# Module", moddefn.name
|
||||
for file in moddefn.sourceFiles:
|
||||
base = os.path.basename(file)
|
||||
base, ext = os.path.splitext(base)
|
||||
objects.append(base + ".obj")
|
||||
print '$(temp_dir)\%s.obj: "%s"' % (base, file)
|
||||
print "\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE",
|
||||
print '"-I$(pythonhome)/Include" "-I$(pythonhome)/PC" \\'
|
||||
print "\t\t$(cflags) $(cdebug) $(cinclude) \\"
|
||||
extra = moddefn.GetCompilerOptions()
|
||||
if extra:
|
||||
print "\t\t%s \\" % (' '.join(extra),)
|
||||
print '\t\t"%s"' % file
|
||||
print
|
||||
|
||||
# Add .lib files this module needs
|
||||
for modlib in moddefn.GetLinkerLibs():
|
||||
if modlib not in libs:
|
||||
libs.append(modlib)
|
||||
|
||||
print "ADDN_LINK_FILES=",
|
||||
for addn in vars['addn_link']: print '"%s"' % (addn),
|
||||
print ; print
|
||||
|
||||
print "OBJS=",
|
||||
for obj in objects: print '"$(temp_dir)\%s"' % (obj),
|
||||
print ; print
|
||||
|
||||
print "LIBS=",
|
||||
for lib in libs: print '"%s"' % (lib),
|
||||
print ; print
|
||||
|
||||
print "$(target)$(debug_suffix)%s: $(temp_dir) $(OBJS)" % (target_ext)
|
||||
print "\tlink -out:$(target)$(debug_suffix)%s %s" % (target_ext, target_link_flags),
|
||||
print "\t$(OBJS) \\"
|
||||
print "\t$(LIBS) \\"
|
||||
print "\t$(ADDN_LINK_FILES) \\"
|
||||
print "\t$(pythonlib) $(lcustom) $(l_debug)\\"
|
||||
print "\t$(resources)"
|
||||
print
|
||||
print "clean:"
|
||||
print "\t-rm -f *.obj"
|
||||
print "\t-rm -f $(target).exe"
|
||||
73
project/jni/python/src/Tools/i18n/makelocalealias.py
Normal file
73
project/jni/python/src/Tools/i18n/makelocalealias.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Convert the X11 locale.alias file into a mapping dictionary suitable
|
||||
for locale.py.
|
||||
|
||||
Written by Marc-Andre Lemburg <mal@genix.com>, 2004-12-10.
|
||||
|
||||
"""
|
||||
import locale
|
||||
|
||||
# Location of the alias file
|
||||
LOCALE_ALIAS = '/usr/lib/X11/locale/locale.alias'
|
||||
|
||||
def parse(filename):
|
||||
|
||||
f = open(filename)
|
||||
lines = f.read().splitlines()
|
||||
data = {}
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
if line[:1] == '#':
|
||||
continue
|
||||
locale, alias = line.split()
|
||||
# Strip ':'
|
||||
if locale[-1] == ':':
|
||||
locale = locale[:-1]
|
||||
# Lower-case locale
|
||||
locale = locale.lower()
|
||||
# Ignore one letter locale mappings (except for 'c')
|
||||
if len(locale) == 1 and locale != 'c':
|
||||
continue
|
||||
# Normalize encoding, if given
|
||||
if '.' in locale:
|
||||
lang, encoding = locale.split('.')[:2]
|
||||
encoding = encoding.replace('-', '')
|
||||
encoding = encoding.replace('_', '')
|
||||
locale = lang + '.' + encoding
|
||||
if encoding.lower() == 'utf8':
|
||||
# Ignore UTF-8 mappings - this encoding should be
|
||||
# available for all locales
|
||||
continue
|
||||
data[locale] = alias
|
||||
return data
|
||||
|
||||
def pprint(data):
|
||||
|
||||
items = data.items()
|
||||
items.sort()
|
||||
for k,v in items:
|
||||
print ' %-40s%r,' % ('%r:' % k, v)
|
||||
|
||||
def print_differences(data, olddata):
|
||||
|
||||
items = olddata.items()
|
||||
items.sort()
|
||||
for k, v in items:
|
||||
if not data.has_key(k):
|
||||
print '# removed %r' % k
|
||||
elif olddata[k] != data[k]:
|
||||
print '# updated %r -> %r to %r' % \
|
||||
(k, olddata[k], data[k])
|
||||
# Additions are not mentioned
|
||||
|
||||
if __name__ == '__main__':
|
||||
data = locale.locale_alias.copy()
|
||||
data.update(parse(LOCALE_ALIAS))
|
||||
print_differences(data, locale.locale_alias)
|
||||
print
|
||||
print 'locale_alias = {'
|
||||
pprint(data)
|
||||
print '}'
|
||||
203
project/jni/python/src/Tools/i18n/msgfmt.py
Normal file
203
project/jni/python/src/Tools/i18n/msgfmt.py
Normal file
@@ -0,0 +1,203 @@
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Written by Martin v. Löwis <loewis@informatik.hu-berlin.de>
|
||||
|
||||
"""Generate binary message catalog from textual translation description.
|
||||
|
||||
This program converts a textual Uniforum-style message catalog (.po file) into
|
||||
a binary GNU catalog (.mo file). This is essentially the same function as the
|
||||
GNU msgfmt program, however, it is a simpler implementation.
|
||||
|
||||
Usage: msgfmt.py [OPTIONS] filename.po
|
||||
|
||||
Options:
|
||||
-o file
|
||||
--output-file=file
|
||||
Specify the output file to write to. If omitted, output will go to a
|
||||
file named filename.mo (based off the input file name).
|
||||
|
||||
-h
|
||||
--help
|
||||
Print this message and exit.
|
||||
|
||||
-V
|
||||
--version
|
||||
Display version information and exit.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getopt
|
||||
import struct
|
||||
import array
|
||||
|
||||
__version__ = "1.1"
|
||||
|
||||
MESSAGES = {}
|
||||
|
||||
|
||||
|
||||
def usage(code, msg=''):
|
||||
print >> sys.stderr, __doc__
|
||||
if msg:
|
||||
print >> sys.stderr, msg
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
|
||||
def add(id, str, fuzzy):
|
||||
"Add a non-fuzzy translation to the dictionary."
|
||||
global MESSAGES
|
||||
if not fuzzy and str:
|
||||
MESSAGES[id] = str
|
||||
|
||||
|
||||
|
||||
def generate():
|
||||
"Return the generated output."
|
||||
global MESSAGES
|
||||
keys = MESSAGES.keys()
|
||||
# the keys are sorted in the .mo file
|
||||
keys.sort()
|
||||
offsets = []
|
||||
ids = strs = ''
|
||||
for id in keys:
|
||||
# For each string, we need size and file offset. Each string is NUL
|
||||
# terminated; the NUL does not count into the size.
|
||||
offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id])))
|
||||
ids += id + '\0'
|
||||
strs += MESSAGES[id] + '\0'
|
||||
output = ''
|
||||
# The header is 7 32-bit unsigned integers. We don't use hash tables, so
|
||||
# the keys start right after the index tables.
|
||||
# translated string.
|
||||
keystart = 7*4+16*len(keys)
|
||||
# and the values start after the keys
|
||||
valuestart = keystart + len(ids)
|
||||
koffsets = []
|
||||
voffsets = []
|
||||
# The string table first has the list of keys, then the list of values.
|
||||
# Each entry has first the size of the string, then the file offset.
|
||||
for o1, l1, o2, l2 in offsets:
|
||||
koffsets += [l1, o1+keystart]
|
||||
voffsets += [l2, o2+valuestart]
|
||||
offsets = koffsets + voffsets
|
||||
output = struct.pack("Iiiiiii",
|
||||
0x950412deL, # Magic
|
||||
0, # Version
|
||||
len(keys), # # of entries
|
||||
7*4, # start of key index
|
||||
7*4+len(keys)*8, # start of value index
|
||||
0, 0) # size and offset of hash table
|
||||
output += array.array("i", offsets).tostring()
|
||||
output += ids
|
||||
output += strs
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def make(filename, outfile):
|
||||
ID = 1
|
||||
STR = 2
|
||||
|
||||
# Compute .mo name from .po name and arguments
|
||||
if filename.endswith('.po'):
|
||||
infile = filename
|
||||
else:
|
||||
infile = filename + '.po'
|
||||
if outfile is None:
|
||||
outfile = os.path.splitext(infile)[0] + '.mo'
|
||||
|
||||
try:
|
||||
lines = open(infile).readlines()
|
||||
except IOError, msg:
|
||||
print >> sys.stderr, msg
|
||||
sys.exit(1)
|
||||
|
||||
section = None
|
||||
fuzzy = 0
|
||||
|
||||
# Parse the catalog
|
||||
lno = 0
|
||||
for l in lines:
|
||||
lno += 1
|
||||
# If we get a comment line after a msgstr, this is a new entry
|
||||
if l[0] == '#' and section == STR:
|
||||
add(msgid, msgstr, fuzzy)
|
||||
section = None
|
||||
fuzzy = 0
|
||||
# Record a fuzzy mark
|
||||
if l[:2] == '#,' and 'fuzzy' in l:
|
||||
fuzzy = 1
|
||||
# Skip comments
|
||||
if l[0] == '#':
|
||||
continue
|
||||
# Now we are in a msgid section, output previous section
|
||||
if l.startswith('msgid'):
|
||||
if section == STR:
|
||||
add(msgid, msgstr, fuzzy)
|
||||
section = ID
|
||||
l = l[5:]
|
||||
msgid = msgstr = ''
|
||||
# Now we are in a msgstr section
|
||||
elif l.startswith('msgstr'):
|
||||
section = STR
|
||||
l = l[6:]
|
||||
# Skip empty lines
|
||||
l = l.strip()
|
||||
if not l:
|
||||
continue
|
||||
# XXX: Does this always follow Python escape semantics?
|
||||
l = eval(l)
|
||||
if section == ID:
|
||||
msgid += l
|
||||
elif section == STR:
|
||||
msgstr += l
|
||||
else:
|
||||
print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
|
||||
'before:'
|
||||
print >> sys.stderr, l
|
||||
sys.exit(1)
|
||||
# Add last entry
|
||||
if section == STR:
|
||||
add(msgid, msgstr, fuzzy)
|
||||
|
||||
# Compute output
|
||||
output = generate()
|
||||
|
||||
try:
|
||||
open(outfile,"wb").write(output)
|
||||
except IOError,msg:
|
||||
print >> sys.stderr, msg
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
|
||||
['help', 'version', 'output-file='])
|
||||
except getopt.error, msg:
|
||||
usage(1, msg)
|
||||
|
||||
outfile = None
|
||||
# parse options
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage(0)
|
||||
elif opt in ('-V', '--version'):
|
||||
print >> sys.stderr, "msgfmt.py", __version__
|
||||
sys.exit(0)
|
||||
elif opt in ('-o', '--output-file'):
|
||||
outfile = arg
|
||||
# do it
|
||||
if not args:
|
||||
print >> sys.stderr, 'No input file given'
|
||||
print >> sys.stderr, "Try `msgfmt --help' for more information."
|
||||
return
|
||||
|
||||
for filename in args:
|
||||
make(filename, outfile)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
669
project/jni/python/src/Tools/i18n/pygettext.py
Normal file
669
project/jni/python/src/Tools/i18n/pygettext.py
Normal file
@@ -0,0 +1,669 @@
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
# Originally written by Barry Warsaw <barry@zope.com>
|
||||
#
|
||||
# Minimally patched to make it even more xgettext compatible
|
||||
# by Peter Funk <pf@artcom-gmbh.de>
|
||||
#
|
||||
# 2002-11-22 Jürgen Hermann <jh@web.de>
|
||||
# Added checks that _() only contains string literals, and
|
||||
# command line args are resolved to module lists, i.e. you
|
||||
# can now pass a filename, a module or package name, or a
|
||||
# directory (including globbing chars, important for Win32).
|
||||
# Made docstring fit in 80 chars wide displays using pydoc.
|
||||
#
|
||||
|
||||
# for selftesting
|
||||
try:
|
||||
import fintl
|
||||
_ = fintl.gettext
|
||||
except ImportError:
|
||||
_ = lambda s: s
|
||||
|
||||
__doc__ = _("""pygettext -- Python equivalent of xgettext(1)
|
||||
|
||||
Many systems (Solaris, Linux, Gnu) provide extensive tools that ease the
|
||||
internationalization of C programs. Most of these tools are independent of
|
||||
the programming language and can be used from within Python programs.
|
||||
Martin von Loewis' work[1] helps considerably in this regard.
|
||||
|
||||
There's one problem though; xgettext is the program that scans source code
|
||||
looking for message strings, but it groks only C (or C++). Python
|
||||
introduces a few wrinkles, such as dual quoting characters, triple quoted
|
||||
strings, and raw strings. xgettext understands none of this.
|
||||
|
||||
Enter pygettext, which uses Python's standard tokenize module to scan
|
||||
Python source code, generating .pot files identical to what GNU xgettext[2]
|
||||
generates for C and C++ code. From there, the standard GNU tools can be
|
||||
used.
|
||||
|
||||
A word about marking Python strings as candidates for translation. GNU
|
||||
xgettext recognizes the following keywords: gettext, dgettext, dcgettext,
|
||||
and gettext_noop. But those can be a lot of text to include all over your
|
||||
code. C and C++ have a trick: they use the C preprocessor. Most
|
||||
internationalized C source includes a #define for gettext() to _() so that
|
||||
what has to be written in the source is much less. Thus these are both
|
||||
translatable strings:
|
||||
|
||||
gettext("Translatable String")
|
||||
_("Translatable String")
|
||||
|
||||
Python of course has no preprocessor so this doesn't work so well. Thus,
|
||||
pygettext searches only for _() by default, but see the -k/--keyword flag
|
||||
below for how to augment this.
|
||||
|
||||
[1] http://www.python.org/workshops/1997-10/proceedings/loewis.html
|
||||
[2] http://www.gnu.org/software/gettext/gettext.html
|
||||
|
||||
NOTE: pygettext attempts to be option and feature compatible with GNU
|
||||
xgettext where ever possible. However some options are still missing or are
|
||||
not fully implemented. Also, xgettext's use of command line switches with
|
||||
option arguments is broken, and in these cases, pygettext just defines
|
||||
additional switches.
|
||||
|
||||
Usage: pygettext [options] inputfile ...
|
||||
|
||||
Options:
|
||||
|
||||
-a
|
||||
--extract-all
|
||||
Extract all strings.
|
||||
|
||||
-d name
|
||||
--default-domain=name
|
||||
Rename the default output file from messages.pot to name.pot.
|
||||
|
||||
-E
|
||||
--escape
|
||||
Replace non-ASCII characters with octal escape sequences.
|
||||
|
||||
-D
|
||||
--docstrings
|
||||
Extract module, class, method, and function docstrings. These do
|
||||
not need to be wrapped in _() markers, and in fact cannot be for
|
||||
Python to consider them docstrings. (See also the -X option).
|
||||
|
||||
-h
|
||||
--help
|
||||
Print this help message and exit.
|
||||
|
||||
-k word
|
||||
--keyword=word
|
||||
Keywords to look for in addition to the default set, which are:
|
||||
%(DEFAULTKEYWORDS)s
|
||||
|
||||
You can have multiple -k flags on the command line.
|
||||
|
||||
-K
|
||||
--no-default-keywords
|
||||
Disable the default set of keywords (see above). Any keywords
|
||||
explicitly added with the -k/--keyword option are still recognized.
|
||||
|
||||
--no-location
|
||||
Do not write filename/lineno location comments.
|
||||
|
||||
-n
|
||||
--add-location
|
||||
Write filename/lineno location comments indicating where each
|
||||
extracted string is found in the source. These lines appear before
|
||||
each msgid. The style of comments is controlled by the -S/--style
|
||||
option. This is the default.
|
||||
|
||||
-o filename
|
||||
--output=filename
|
||||
Rename the default output file from messages.pot to filename. If
|
||||
filename is `-' then the output is sent to standard out.
|
||||
|
||||
-p dir
|
||||
--output-dir=dir
|
||||
Output files will be placed in directory dir.
|
||||
|
||||
-S stylename
|
||||
--style stylename
|
||||
Specify which style to use for location comments. Two styles are
|
||||
supported:
|
||||
|
||||
Solaris # File: filename, line: line-number
|
||||
GNU #: filename:line
|
||||
|
||||
The style name is case insensitive. GNU style is the default.
|
||||
|
||||
-v
|
||||
--verbose
|
||||
Print the names of the files being processed.
|
||||
|
||||
-V
|
||||
--version
|
||||
Print the version of pygettext and exit.
|
||||
|
||||
-w columns
|
||||
--width=columns
|
||||
Set width of output to columns.
|
||||
|
||||
-x filename
|
||||
--exclude-file=filename
|
||||
Specify a file that contains a list of strings that are not be
|
||||
extracted from the input files. Each string to be excluded must
|
||||
appear on a line by itself in the file.
|
||||
|
||||
-X filename
|
||||
--no-docstrings=filename
|
||||
Specify a file that contains a list of files (one per line) that
|
||||
should not have their docstrings extracted. This is only useful in
|
||||
conjunction with the -D option above.
|
||||
|
||||
If `inputfile' is -, standard input is read.
|
||||
""")
|
||||
|
||||
import os
|
||||
import imp
|
||||
import sys
|
||||
import glob
|
||||
import time
|
||||
import getopt
|
||||
import token
|
||||
import tokenize
|
||||
import operator
|
||||
|
||||
__version__ = '1.5'
|
||||
|
||||
default_keywords = ['_']
|
||||
DEFAULTKEYWORDS = ', '.join(default_keywords)
|
||||
|
||||
EMPTYSTRING = ''
|
||||
|
||||
|
||||
|
||||
# The normal pot-file header. msgmerge and Emacs's po-mode work better if it's
|
||||
# there.
|
||||
pot_header = _('''\
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR ORGANIZATION
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\\n"
|
||||
"POT-Creation-Date: %(time)s\\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\\n"
|
||||
"Content-Transfer-Encoding: ENCODING\\n"
|
||||
"Generated-By: pygettext.py %(version)s\\n"
|
||||
|
||||
''')
|
||||
|
||||
|
||||
def usage(code, msg=''):
|
||||
print >> sys.stderr, __doc__ % globals()
|
||||
if msg:
|
||||
print >> sys.stderr, msg
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
|
||||
escapes = []
|
||||
|
||||
def make_escapes(pass_iso8859):
|
||||
global escapes
|
||||
if pass_iso8859:
|
||||
# Allow iso-8859 characters to pass through so that e.g. 'msgid
|
||||
# "Höhe"' would result not result in 'msgid "H\366he"'. Otherwise we
|
||||
# escape any character outside the 32..126 range.
|
||||
mod = 128
|
||||
else:
|
||||
mod = 256
|
||||
for i in range(256):
|
||||
if 32 <= (i % mod) <= 126:
|
||||
escapes.append(chr(i))
|
||||
else:
|
||||
escapes.append("\\%03o" % i)
|
||||
escapes[ord('\\')] = '\\\\'
|
||||
escapes[ord('\t')] = '\\t'
|
||||
escapes[ord('\r')] = '\\r'
|
||||
escapes[ord('\n')] = '\\n'
|
||||
escapes[ord('\"')] = '\\"'
|
||||
|
||||
|
||||
def escape(s):
|
||||
global escapes
|
||||
s = list(s)
|
||||
for i in range(len(s)):
|
||||
s[i] = escapes[ord(s[i])]
|
||||
return EMPTYSTRING.join(s)
|
||||
|
||||
|
||||
def safe_eval(s):
|
||||
# unwrap quotes, safely
|
||||
return eval(s, {'__builtins__':{}}, {})
|
||||
|
||||
|
||||
def normalize(s):
|
||||
# This converts the various Python string types into a format that is
|
||||
# appropriate for .po files, namely much closer to C style.
|
||||
lines = s.split('\n')
|
||||
if len(lines) == 1:
|
||||
s = '"' + escape(s) + '"'
|
||||
else:
|
||||
if not lines[-1]:
|
||||
del lines[-1]
|
||||
lines[-1] = lines[-1] + '\n'
|
||||
for i in range(len(lines)):
|
||||
lines[i] = escape(lines[i])
|
||||
lineterm = '\\n"\n"'
|
||||
s = '""\n"' + lineterm.join(lines) + '"'
|
||||
return s
|
||||
|
||||
|
||||
def containsAny(str, set):
|
||||
"""Check whether 'str' contains ANY of the chars in 'set'"""
|
||||
return 1 in [c in str for c in set]
|
||||
|
||||
|
||||
def _visit_pyfiles(list, dirname, names):
|
||||
"""Helper for getFilesForName()."""
|
||||
# get extension for python source files
|
||||
if not globals().has_key('_py_ext'):
|
||||
global _py_ext
|
||||
_py_ext = [triple[0] for triple in imp.get_suffixes()
|
||||
if triple[2] == imp.PY_SOURCE][0]
|
||||
|
||||
# don't recurse into CVS directories
|
||||
if 'CVS' in names:
|
||||
names.remove('CVS')
|
||||
|
||||
# add all *.py files to list
|
||||
list.extend(
|
||||
[os.path.join(dirname, file) for file in names
|
||||
if os.path.splitext(file)[1] == _py_ext]
|
||||
)
|
||||
|
||||
|
||||
def _get_modpkg_path(dotted_name, pathlist=None):
|
||||
"""Get the filesystem path for a module or a package.
|
||||
|
||||
Return the file system path to a file for a module, and to a directory for
|
||||
a package. Return None if the name is not found, or is a builtin or
|
||||
extension module.
|
||||
"""
|
||||
# split off top-most name
|
||||
parts = dotted_name.split('.', 1)
|
||||
|
||||
if len(parts) > 1:
|
||||
# we have a dotted path, import top-level package
|
||||
try:
|
||||
file, pathname, description = imp.find_module(parts[0], pathlist)
|
||||
if file: file.close()
|
||||
except ImportError:
|
||||
return None
|
||||
|
||||
# check if it's indeed a package
|
||||
if description[2] == imp.PKG_DIRECTORY:
|
||||
# recursively handle the remaining name parts
|
||||
pathname = _get_modpkg_path(parts[1], [pathname])
|
||||
else:
|
||||
pathname = None
|
||||
else:
|
||||
# plain name
|
||||
try:
|
||||
file, pathname, description = imp.find_module(
|
||||
dotted_name, pathlist)
|
||||
if file:
|
||||
file.close()
|
||||
if description[2] not in [imp.PY_SOURCE, imp.PKG_DIRECTORY]:
|
||||
pathname = None
|
||||
except ImportError:
|
||||
pathname = None
|
||||
|
||||
return pathname
|
||||
|
||||
|
||||
def getFilesForName(name):
|
||||
"""Get a list of module files for a filename, a module or package name,
|
||||
or a directory.
|
||||
"""
|
||||
if not os.path.exists(name):
|
||||
# check for glob chars
|
||||
if containsAny(name, "*?[]"):
|
||||
files = glob.glob(name)
|
||||
list = []
|
||||
for file in files:
|
||||
list.extend(getFilesForName(file))
|
||||
return list
|
||||
|
||||
# try to find module or package
|
||||
name = _get_modpkg_path(name)
|
||||
if not name:
|
||||
return []
|
||||
|
||||
if os.path.isdir(name):
|
||||
# find all python files in directory
|
||||
list = []
|
||||
os.path.walk(name, _visit_pyfiles, list)
|
||||
return list
|
||||
elif os.path.exists(name):
|
||||
# a single file
|
||||
return [name]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class TokenEater:
|
||||
def __init__(self, options):
|
||||
self.__options = options
|
||||
self.__messages = {}
|
||||
self.__state = self.__waiting
|
||||
self.__data = []
|
||||
self.__lineno = -1
|
||||
self.__freshmodule = 1
|
||||
self.__curfile = None
|
||||
|
||||
def __call__(self, ttype, tstring, stup, etup, line):
|
||||
# dispatch
|
||||
## import token
|
||||
## print >> sys.stderr, 'ttype:', token.tok_name[ttype], \
|
||||
## 'tstring:', tstring
|
||||
self.__state(ttype, tstring, stup[0])
|
||||
|
||||
def __waiting(self, ttype, tstring, lineno):
|
||||
opts = self.__options
|
||||
# Do docstring extractions, if enabled
|
||||
if opts.docstrings and not opts.nodocstrings.get(self.__curfile):
|
||||
# module docstring?
|
||||
if self.__freshmodule:
|
||||
if ttype == tokenize.STRING:
|
||||
self.__addentry(safe_eval(tstring), lineno, isdocstring=1)
|
||||
self.__freshmodule = 0
|
||||
elif ttype not in (tokenize.COMMENT, tokenize.NL):
|
||||
self.__freshmodule = 0
|
||||
return
|
||||
# class docstring?
|
||||
if ttype == tokenize.NAME and tstring in ('class', 'def'):
|
||||
self.__state = self.__suiteseen
|
||||
return
|
||||
if ttype == tokenize.NAME and tstring in opts.keywords:
|
||||
self.__state = self.__keywordseen
|
||||
|
||||
def __suiteseen(self, ttype, tstring, lineno):
|
||||
# ignore anything until we see the colon
|
||||
if ttype == tokenize.OP and tstring == ':':
|
||||
self.__state = self.__suitedocstring
|
||||
|
||||
def __suitedocstring(self, ttype, tstring, lineno):
|
||||
# ignore any intervening noise
|
||||
if ttype == tokenize.STRING:
|
||||
self.__addentry(safe_eval(tstring), lineno, isdocstring=1)
|
||||
self.__state = self.__waiting
|
||||
elif ttype not in (tokenize.NEWLINE, tokenize.INDENT,
|
||||
tokenize.COMMENT):
|
||||
# there was no class docstring
|
||||
self.__state = self.__waiting
|
||||
|
||||
def __keywordseen(self, ttype, tstring, lineno):
|
||||
if ttype == tokenize.OP and tstring == '(':
|
||||
self.__data = []
|
||||
self.__lineno = lineno
|
||||
self.__state = self.__openseen
|
||||
else:
|
||||
self.__state = self.__waiting
|
||||
|
||||
def __openseen(self, ttype, tstring, lineno):
|
||||
if ttype == tokenize.OP and tstring == ')':
|
||||
# We've seen the last of the translatable strings. Record the
|
||||
# line number of the first line of the strings and update the list
|
||||
# of messages seen. Reset state for the next batch. If there
|
||||
# were no strings inside _(), then just ignore this entry.
|
||||
if self.__data:
|
||||
self.__addentry(EMPTYSTRING.join(self.__data))
|
||||
self.__state = self.__waiting
|
||||
elif ttype == tokenize.STRING:
|
||||
self.__data.append(safe_eval(tstring))
|
||||
elif ttype not in [tokenize.COMMENT, token.INDENT, token.DEDENT,
|
||||
token.NEWLINE, tokenize.NL]:
|
||||
# warn if we see anything else than STRING or whitespace
|
||||
print >> sys.stderr, _(
|
||||
'*** %(file)s:%(lineno)s: Seen unexpected token "%(token)s"'
|
||||
) % {
|
||||
'token': tstring,
|
||||
'file': self.__curfile,
|
||||
'lineno': self.__lineno
|
||||
}
|
||||
self.__state = self.__waiting
|
||||
|
||||
def __addentry(self, msg, lineno=None, isdocstring=0):
|
||||
if lineno is None:
|
||||
lineno = self.__lineno
|
||||
if not msg in self.__options.toexclude:
|
||||
entry = (self.__curfile, lineno)
|
||||
self.__messages.setdefault(msg, {})[entry] = isdocstring
|
||||
|
||||
def set_filename(self, filename):
|
||||
self.__curfile = filename
|
||||
self.__freshmodule = 1
|
||||
|
||||
def write(self, fp):
|
||||
options = self.__options
|
||||
timestamp = time.strftime('%Y-%m-%d %H:%M+%Z')
|
||||
# The time stamp in the header doesn't have the same format as that
|
||||
# generated by xgettext...
|
||||
print >> fp, pot_header % {'time': timestamp, 'version': __version__}
|
||||
# Sort the entries. First sort each particular entry's keys, then
|
||||
# sort all the entries by their first item.
|
||||
reverse = {}
|
||||
for k, v in self.__messages.items():
|
||||
keys = v.keys()
|
||||
keys.sort()
|
||||
reverse.setdefault(tuple(keys), []).append((k, v))
|
||||
rkeys = reverse.keys()
|
||||
rkeys.sort()
|
||||
for rkey in rkeys:
|
||||
rentries = reverse[rkey]
|
||||
rentries.sort()
|
||||
for k, v in rentries:
|
||||
isdocstring = 0
|
||||
# If the entry was gleaned out of a docstring, then add a
|
||||
# comment stating so. This is to aid translators who may wish
|
||||
# to skip translating some unimportant docstrings.
|
||||
if reduce(operator.__add__, v.values()):
|
||||
isdocstring = 1
|
||||
# k is the message string, v is a dictionary-set of (filename,
|
||||
# lineno) tuples. We want to sort the entries in v first by
|
||||
# file name and then by line number.
|
||||
v = v.keys()
|
||||
v.sort()
|
||||
if not options.writelocations:
|
||||
pass
|
||||
# location comments are different b/w Solaris and GNU:
|
||||
elif options.locationstyle == options.SOLARIS:
|
||||
for filename, lineno in v:
|
||||
d = {'filename': filename, 'lineno': lineno}
|
||||
print >>fp, _(
|
||||
'# File: %(filename)s, line: %(lineno)d') % d
|
||||
elif options.locationstyle == options.GNU:
|
||||
# fit as many locations on one line, as long as the
|
||||
# resulting line length doesn't exceeds 'options.width'
|
||||
locline = '#:'
|
||||
for filename, lineno in v:
|
||||
d = {'filename': filename, 'lineno': lineno}
|
||||
s = _(' %(filename)s:%(lineno)d') % d
|
||||
if len(locline) + len(s) <= options.width:
|
||||
locline = locline + s
|
||||
else:
|
||||
print >> fp, locline
|
||||
locline = "#:" + s
|
||||
if len(locline) > 2:
|
||||
print >> fp, locline
|
||||
if isdocstring:
|
||||
print >> fp, '#, docstring'
|
||||
print >> fp, 'msgid', normalize(k)
|
||||
print >> fp, 'msgstr ""\n'
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
global default_keywords
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
sys.argv[1:],
|
||||
'ad:DEhk:Kno:p:S:Vvw:x:X:',
|
||||
['extract-all', 'default-domain=', 'escape', 'help',
|
||||
'keyword=', 'no-default-keywords',
|
||||
'add-location', 'no-location', 'output=', 'output-dir=',
|
||||
'style=', 'verbose', 'version', 'width=', 'exclude-file=',
|
||||
'docstrings', 'no-docstrings',
|
||||
])
|
||||
except getopt.error, msg:
|
||||
usage(1, msg)
|
||||
|
||||
# for holding option values
|
||||
class Options:
|
||||
# constants
|
||||
GNU = 1
|
||||
SOLARIS = 2
|
||||
# defaults
|
||||
extractall = 0 # FIXME: currently this option has no effect at all.
|
||||
escape = 0
|
||||
keywords = []
|
||||
outpath = ''
|
||||
outfile = 'messages.pot'
|
||||
writelocations = 1
|
||||
locationstyle = GNU
|
||||
verbose = 0
|
||||
width = 78
|
||||
excludefilename = ''
|
||||
docstrings = 0
|
||||
nodocstrings = {}
|
||||
|
||||
options = Options()
|
||||
locations = {'gnu' : options.GNU,
|
||||
'solaris' : options.SOLARIS,
|
||||
}
|
||||
|
||||
# parse options
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage(0)
|
||||
elif opt in ('-a', '--extract-all'):
|
||||
options.extractall = 1
|
||||
elif opt in ('-d', '--default-domain'):
|
||||
options.outfile = arg + '.pot'
|
||||
elif opt in ('-E', '--escape'):
|
||||
options.escape = 1
|
||||
elif opt in ('-D', '--docstrings'):
|
||||
options.docstrings = 1
|
||||
elif opt in ('-k', '--keyword'):
|
||||
options.keywords.append(arg)
|
||||
elif opt in ('-K', '--no-default-keywords'):
|
||||
default_keywords = []
|
||||
elif opt in ('-n', '--add-location'):
|
||||
options.writelocations = 1
|
||||
elif opt in ('--no-location',):
|
||||
options.writelocations = 0
|
||||
elif opt in ('-S', '--style'):
|
||||
options.locationstyle = locations.get(arg.lower())
|
||||
if options.locationstyle is None:
|
||||
usage(1, _('Invalid value for --style: %s') % arg)
|
||||
elif opt in ('-o', '--output'):
|
||||
options.outfile = arg
|
||||
elif opt in ('-p', '--output-dir'):
|
||||
options.outpath = arg
|
||||
elif opt in ('-v', '--verbose'):
|
||||
options.verbose = 1
|
||||
elif opt in ('-V', '--version'):
|
||||
print _('pygettext.py (xgettext for Python) %s') % __version__
|
||||
sys.exit(0)
|
||||
elif opt in ('-w', '--width'):
|
||||
try:
|
||||
options.width = int(arg)
|
||||
except ValueError:
|
||||
usage(1, _('--width argument must be an integer: %s') % arg)
|
||||
elif opt in ('-x', '--exclude-file'):
|
||||
options.excludefilename = arg
|
||||
elif opt in ('-X', '--no-docstrings'):
|
||||
fp = open(arg)
|
||||
try:
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
options.nodocstrings[line[:-1]] = 1
|
||||
finally:
|
||||
fp.close()
|
||||
|
||||
# calculate escapes
|
||||
make_escapes(options.escape)
|
||||
|
||||
# calculate all keywords
|
||||
options.keywords.extend(default_keywords)
|
||||
|
||||
# initialize list of strings to exclude
|
||||
if options.excludefilename:
|
||||
try:
|
||||
fp = open(options.excludefilename)
|
||||
options.toexclude = fp.readlines()
|
||||
fp.close()
|
||||
except IOError:
|
||||
print >> sys.stderr, _(
|
||||
"Can't read --exclude-file: %s") % options.excludefilename
|
||||
sys.exit(1)
|
||||
else:
|
||||
options.toexclude = []
|
||||
|
||||
# resolve args to module lists
|
||||
expanded = []
|
||||
for arg in args:
|
||||
if arg == '-':
|
||||
expanded.append(arg)
|
||||
else:
|
||||
expanded.extend(getFilesForName(arg))
|
||||
args = expanded
|
||||
|
||||
# slurp through all the files
|
||||
eater = TokenEater(options)
|
||||
for filename in args:
|
||||
if filename == '-':
|
||||
if options.verbose:
|
||||
print _('Reading standard input')
|
||||
fp = sys.stdin
|
||||
closep = 0
|
||||
else:
|
||||
if options.verbose:
|
||||
print _('Working on %s') % filename
|
||||
fp = open(filename)
|
||||
closep = 1
|
||||
try:
|
||||
eater.set_filename(filename)
|
||||
try:
|
||||
tokenize.tokenize(fp.readline, eater)
|
||||
except tokenize.TokenError, e:
|
||||
print >> sys.stderr, '%s: %s, line %d, column %d' % (
|
||||
e[0], filename, e[1][0], e[1][1])
|
||||
finally:
|
||||
if closep:
|
||||
fp.close()
|
||||
|
||||
# write the output
|
||||
if options.outfile == '-':
|
||||
fp = sys.stdout
|
||||
closep = 0
|
||||
else:
|
||||
if options.outpath:
|
||||
options.outfile = os.path.join(options.outpath, options.outfile)
|
||||
fp = open(options.outfile, 'w')
|
||||
closep = 1
|
||||
try:
|
||||
eater.write(fp)
|
||||
finally:
|
||||
if closep:
|
||||
fp.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
# some more test strings
|
||||
_(u'a unicode string')
|
||||
# this one creates a warning
|
||||
_('*** Seen unexpected token "%(token)s"') % {'token': 'test'}
|
||||
_('more' 'than' 'one' 'string')
|
||||
53
project/jni/python/src/Tools/modulator/EXAMPLE.py
Normal file
53
project/jni/python/src/Tools/modulator/EXAMPLE.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Example input file for modulator if you don't have tk.
|
||||
#
|
||||
# You may also have to strip some imports out of modulator to make
|
||||
# it work.
|
||||
|
||||
import genmodule
|
||||
|
||||
#
|
||||
# Generate code for a simple object with a method called sample
|
||||
|
||||
o = genmodule.object()
|
||||
o.name = 'simple object'
|
||||
o.abbrev = 'simp'
|
||||
o.methodlist = ['sample']
|
||||
o.funclist = ['new']
|
||||
|
||||
#
|
||||
# Generate code for an object that looks numberish
|
||||
#
|
||||
o2 = genmodule.object()
|
||||
o2.name = 'number-like object'
|
||||
o2.abbrev = 'nl'
|
||||
o2.typelist = ['tp_as_number']
|
||||
o2.funclist = ['new', 'tp_repr', 'tp_compare']
|
||||
|
||||
#
|
||||
# Generate code for a method with a full complement of functions,
|
||||
# some methods, accessible as sequence and allowing structmember.c type
|
||||
# structure access as well.
|
||||
#
|
||||
o3 = genmodule.object()
|
||||
o3.name = 'over-the-top object'
|
||||
o3.abbrev = 'ot'
|
||||
o3.methodlist = ['method1', 'method2']
|
||||
o3.funclist = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
|
||||
'tp_compare', 'tp_repr', 'tp_hash']
|
||||
o3.typelist = ['tp_as_sequence', 'structure']
|
||||
|
||||
#
|
||||
# Now generate code for a module that incorporates these object types.
|
||||
# Also add the boilerplates for functions to create instances of each
|
||||
# type.
|
||||
#
|
||||
m = genmodule.module()
|
||||
m.name = 'sample'
|
||||
m.abbrev = 'sample'
|
||||
m.methodlist = ['newsimple', 'newnumberish', 'newott']
|
||||
m.objects = [o, o2, o3]
|
||||
|
||||
fp = open('EXAMPLEmodule.c', 'w')
|
||||
genmodule.write(fp, m)
|
||||
fp.close()
|
||||
25
project/jni/python/src/Tools/modulator/README
Normal file
25
project/jni/python/src/Tools/modulator/README
Normal file
@@ -0,0 +1,25 @@
|
||||
This is release 1.2 of modulator, a generator of boilerplate code for
|
||||
modules to be written in C.
|
||||
|
||||
Difference between 1.2 and 1.1: __doc__ templates are now generated
|
||||
(thanks to Jim Fulton).
|
||||
|
||||
Difference between 1.1 and 1.0: the templates now use "new-style"
|
||||
naming conventions. Many thanks to Chak Tan <tan@ee.rochester.edu> for
|
||||
supplying them.
|
||||
|
||||
Usage when you have tk is *really* simple: start modulator, fill out
|
||||
the forms specifying all the objects and methods, tell modulator
|
||||
whether objects should also be accessible as sequences, etc and press
|
||||
'generate code'. It will write a complete skeleton module for you.
|
||||
|
||||
Usage when you don't have tk is slightly more difficult. Look at
|
||||
EXAMPLE.py for some details (to run, use "python EXAMPLE.py"). Don't
|
||||
bother with EXAMPLE.py if you have Tkinter!!!
|
||||
|
||||
Oh yeah: you'll probably want to change Templates/copyright, or all
|
||||
your code ends up as being copyrighted to CWI:-)
|
||||
|
||||
Let me know what you think,
|
||||
Jack Jansen, jack@cwi.nl
|
||||
|
||||
37
project/jni/python/src/Tools/modulator/ScrolledListbox.py
Normal file
37
project/jni/python/src/Tools/modulator/ScrolledListbox.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# A ScrolledList widget feels like a list widget but also has a
|
||||
# vertical scroll bar on its right. (Later, options may be added to
|
||||
# add a horizontal bar as well, to make the bars disappear
|
||||
# automatically when not needed, to move them to the other side of the
|
||||
# window, etc.)
|
||||
#
|
||||
# Configuration options are passed to the List widget.
|
||||
# A Frame widget is inserted between the master and the list, to hold
|
||||
# the Scrollbar widget.
|
||||
# Most methods calls are inherited from the List widget; Pack methods
|
||||
# are redirected to the Frame widget however.
|
||||
|
||||
from Tkinter import *
|
||||
from Tkinter import _cnfmerge
|
||||
|
||||
class ScrolledListbox(Listbox):
|
||||
def __init__(self, master=None, cnf={}):
|
||||
cnf = _cnfmerge(cnf)
|
||||
fcnf = {}
|
||||
vcnf = {'name': 'vbar',
|
||||
Pack: {'side': 'right', 'fill': 'y'},}
|
||||
for k in cnf.keys():
|
||||
if type(k) == ClassType or k == 'name':
|
||||
fcnf[k] = cnf[k]
|
||||
del cnf[k]
|
||||
self.frame = Frame(master, fcnf)
|
||||
self.vbar = Scrollbar(self.frame, vcnf)
|
||||
cnf[Pack] = {'side': 'left', 'fill': 'both', 'expand': 'yes'}
|
||||
cnf['name'] = 'list'
|
||||
Listbox.__init__(self, self.frame, cnf)
|
||||
self['yscrollcommand'] = (self.vbar, 'set')
|
||||
self.vbar['command'] = (self, 'yview')
|
||||
|
||||
# Copy Pack methods of self.frame -- hack!
|
||||
for m in Pack.__dict__.keys():
|
||||
if m[0] != '_' and m != 'config':
|
||||
setattr(self, m, getattr(self.frame, m))
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
static PyObject *ErrorObject;
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
static char $abbrev$_$method$__doc__[] =
|
||||
""
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_$method$(PyObject *self /* Not used */, PyObject *args)
|
||||
{
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
37
project/jni/python/src/Tools/modulator/Templates/module_tail
Normal file
37
project/jni/python/src/Tools/modulator/Templates/module_tail
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
/* List of methods defined in the module */
|
||||
|
||||
static struct PyMethodDef $abbrev$_methods[] = {
|
||||
$methodlist$
|
||||
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
/* Initialization function for the module (*must* be called init$name$) */
|
||||
|
||||
static char $name$_module_documentation[] =
|
||||
""
|
||||
;
|
||||
|
||||
void
|
||||
init$name$()
|
||||
{
|
||||
PyObject *m, *d;
|
||||
|
||||
/* Create the module and add the functions */
|
||||
m = Py_InitModule4("$name$", $abbrev$_methods,
|
||||
$name$_module_documentation,
|
||||
(PyObject*)NULL,PYTHON_API_VERSION);
|
||||
|
||||
/* Add some symbolic constants to the module */
|
||||
d = PyModule_GetDict(m);
|
||||
ErrorObject = PyString_FromString("$name$.error");
|
||||
PyDict_SetItemString(d, "error", ErrorObject);
|
||||
|
||||
/* XXXX Add constants here */
|
||||
|
||||
/* Check for errors */
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module $name$");
|
||||
}
|
||||
|
||||
13
project/jni/python/src/Tools/modulator/Templates/object_head
Normal file
13
project/jni/python/src/Tools/modulator/Templates/object_head
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
/* Declarations for objects of type $name$ */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
/* XXXX Add your own stuff here */
|
||||
} $abbrev$object;
|
||||
|
||||
static PyTypeObject $Abbrev$type;
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
static char $abbrev$_$method$__doc__[] =
|
||||
""
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_$method$($abbrev$object *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
static struct PyMethodDef $abbrev$_methods[] = {
|
||||
$methodlist$
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
/* ---------- */
|
||||
|
||||
13
project/jni/python/src/Tools/modulator/Templates/object_new
Normal file
13
project/jni/python/src/Tools/modulator/Templates/object_new
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
static $abbrev$object *
|
||||
new$abbrev$object()
|
||||
{
|
||||
$abbrev$object *self;
|
||||
|
||||
self = PyObject_NEW($abbrev$object, &$Abbrev$type);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
/* XXXX Add your own initializers here */
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
/* Code to access structure members by accessing attributes */
|
||||
|
||||
#include "structmember.h"
|
||||
|
||||
#define OFF(x) offsetof(XXXXobject, x)
|
||||
|
||||
static struct memberlist $abbrev$_memberlist[] = {
|
||||
/* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_getattr($abbrev$object *self, char *name)
|
||||
{
|
||||
PyObject *rv;
|
||||
|
||||
/* XXXX Add your own getattr code here */
|
||||
rv = PyMember_Get((char *)/*XXXX*/0, $abbrev$_memberlist, name);
|
||||
if (rv)
|
||||
return rv;
|
||||
PyErr_Clear();
|
||||
return Py_FindMethod($abbrev$_methods, (PyObject *)self, name);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
$abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
|
||||
{
|
||||
/* XXXX Add your own setattr code here */
|
||||
if ( v == NULL ) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
|
||||
return -1;
|
||||
}
|
||||
return PyMember_Set((char *)/*XXXX*/0, $abbrev$_memberlist, name, v);
|
||||
}
|
||||
33
project/jni/python/src/Tools/modulator/Templates/object_tail
Normal file
33
project/jni/python/src/Tools/modulator/Templates/object_tail
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
static char $Abbrev$type__doc__[] =
|
||||
""
|
||||
;
|
||||
|
||||
static PyTypeObject $Abbrev$type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /*ob_size*/
|
||||
"$name$", /*tp_name*/
|
||||
sizeof($abbrev$object), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)$tp_dealloc$, /*tp_dealloc*/
|
||||
(printfunc)$tp_print$, /*tp_print*/
|
||||
(getattrfunc)$tp_getattr$, /*tp_getattr*/
|
||||
(setattrfunc)$tp_setattr$, /*tp_setattr*/
|
||||
(cmpfunc)$tp_compare$, /*tp_compare*/
|
||||
(reprfunc)$tp_repr$, /*tp_repr*/
|
||||
$tp_as_number$, /*tp_as_number*/
|
||||
$tp_as_sequence$, /*tp_as_sequence*/
|
||||
$tp_as_mapping$, /*tp_as_mapping*/
|
||||
(hashfunc)$tp_hash$, /*tp_hash*/
|
||||
(ternaryfunc)$tp_call$, /*tp_call*/
|
||||
(reprfunc)$tp_str$, /*tp_str*/
|
||||
|
||||
/* Space for future expansion */
|
||||
0L,0L,0L,0L,
|
||||
$Abbrev$type__doc__ /* Documentation string */
|
||||
};
|
||||
|
||||
/* End of code for $name$ objects */
|
||||
/* -------------------------------------------------------- */
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
/* Code to access $name$ objects as mappings */
|
||||
|
||||
static int
|
||||
$abbrev$_length($abbrev$object *self)
|
||||
{
|
||||
/* XXXX Return the size of the mapping */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_subscript($abbrev$object *self, PyObject *key)
|
||||
{
|
||||
/* XXXX Return the item of self indexed by key */
|
||||
}
|
||||
|
||||
static int
|
||||
$abbrev$_ass_sub($abbrev$object *self, PyObject *v, PyObject *w)
|
||||
{
|
||||
/* XXXX Put w in self under key v */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyMappingMethods $abbrev$_as_mapping = {
|
||||
(inquiry)$abbrev$_length, /*mp_length*/
|
||||
(binaryfunc)$abbrev$_subscript, /*mp_subscript*/
|
||||
(objobjargproc)$abbrev$_ass_sub, /*mp_ass_subscript*/
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
@@ -0,0 +1,169 @@
|
||||
|
||||
/* Code to access $name$ objects as numbers */
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_add($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX Add them */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_sub($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX Subtract them */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_mul($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX Multiply them */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_div($abbrev$object *x, $abbrev$object *y)
|
||||
{
|
||||
/* XXXX Divide them */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_mod($abbrev$object *x, $abbrev$object *y)
|
||||
{
|
||||
/* XXXX Modulo them */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_divmod($abbrev$object *x, $abbrev$object *y)
|
||||
{
|
||||
/* XXXX Return 2-tuple with div and mod */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_pow($abbrev$object *v, $abbrev$object *w, $abbrev$object *z)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_neg($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_pos($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_abs($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static int
|
||||
$abbrev$_nonzero($abbrev$object *v)
|
||||
{
|
||||
/* XXXX Return 1 if non-zero */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_invert($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_lshift($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_rshift($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_and($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_xor($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_or($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static int
|
||||
$abbrev$_coerce(PyObject **pv, PyObject **pw)
|
||||
{
|
||||
/* XXXX I haven't a clue... */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_int($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_long($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_float($abbrev$object *v)
|
||||
{
|
||||
/* XXXX */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_oct($abbrev$object *v)
|
||||
{
|
||||
/* XXXX Return object as octal stringobject */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_hex($abbrev$object *v)
|
||||
{
|
||||
/* XXXX Return object as hex stringobject */
|
||||
}
|
||||
|
||||
static PyNumberMethods $abbrev$_as_number = {
|
||||
(binaryfunc)$abbrev$_add, /*nb_add*/
|
||||
(binaryfunc)$abbrev$_sub, /*nb_subtract*/
|
||||
(binaryfunc)$abbrev$_mul, /*nb_multiply*/
|
||||
(binaryfunc)$abbrev$_div, /*nb_divide*/
|
||||
(binaryfunc)$abbrev$_mod, /*nb_remainder*/
|
||||
(binaryfunc)$abbrev$_divmod, /*nb_divmod*/
|
||||
(ternaryfunc)$abbrev$_pow, /*nb_power*/
|
||||
(unaryfunc)$abbrev$_neg, /*nb_negative*/
|
||||
(unaryfunc)$abbrev$_pos, /*nb_positive*/
|
||||
(unaryfunc)$abbrev$_abs, /*nb_absolute*/
|
||||
(inquiry)$abbrev$_nonzero, /*nb_nonzero*/
|
||||
(unaryfunc)$abbrev$_invert, /*nb_invert*/
|
||||
(binaryfunc)$abbrev$_lshift, /*nb_lshift*/
|
||||
(binaryfunc)$abbrev$_rshift, /*nb_rshift*/
|
||||
(binaryfunc)$abbrev$_and, /*nb_and*/
|
||||
(binaryfunc)$abbrev$_xor, /*nb_xor*/
|
||||
(binaryfunc)$abbrev$_or, /*nb_or*/
|
||||
(coercion)$abbrev$_coerce, /*nb_coerce*/
|
||||
(unaryfunc)$abbrev$_int, /*nb_int*/
|
||||
(unaryfunc)$abbrev$_long, /*nb_long*/
|
||||
(unaryfunc)$abbrev$_float, /*nb_float*/
|
||||
(unaryfunc)$abbrev$_oct, /*nb_oct*/
|
||||
(unaryfunc)$abbrev$_hex, /*nb_hex*/
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------- */
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
/* Code to handle accessing $name$ objects as sequence objects */
|
||||
|
||||
static int
|
||||
$abbrev$_length($abbrev$object *self)
|
||||
{
|
||||
/* XXXX Return the size of the object */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_concat($abbrev$object *self, PyObject *bb)
|
||||
{
|
||||
/* XXXX Return the concatenation of self and bb */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_repeat($abbrev$object *self, int n)
|
||||
{
|
||||
/* XXXX Return a new object that is n times self */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_item($abbrev$object *self, int i)
|
||||
{
|
||||
/* XXXX Return the i-th object of self */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_slice($abbrev$object *self, int ilow, int ihigh)
|
||||
{
|
||||
/* XXXX Return the ilow..ihigh slice of self in a new object */
|
||||
}
|
||||
|
||||
static int
|
||||
$abbrev$_ass_item($abbrev$object *self, int i, PyObject *v)
|
||||
{
|
||||
/* XXXX Assign to the i-th element of self */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
$abbrev$_ass_slice(PyListObject *self, int ilow, int ihigh, PyObject *v)
|
||||
{
|
||||
/* XXXX Replace ilow..ihigh slice of self with v */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PySequenceMethods $abbrev$_as_sequence = {
|
||||
(inquiry)$abbrev$_length, /*sq_length*/
|
||||
(binaryfunc)$abbrev$_concat, /*sq_concat*/
|
||||
(intargfunc)$abbrev$_repeat, /*sq_repeat*/
|
||||
(intargfunc)$abbrev$_item, /*sq_item*/
|
||||
(intintargfunc)$abbrev$_slice, /*sq_slice*/
|
||||
(intobjargproc)$abbrev$_ass_item, /*sq_ass_item*/
|
||||
(intintobjargproc)$abbrev$_ass_slice, /*sq_ass_slice*/
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_call($abbrev$object *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
/* XXXX Return the result of calling self with argument args */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
static int
|
||||
$abbrev$_compare($abbrev$object *v, $abbrev$object *w)
|
||||
{
|
||||
/* XXXX Compare objects and return -1, 0 or 1 */
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
static void
|
||||
$abbrev$_dealloc($abbrev$object *self)
|
||||
{
|
||||
/* XXXX Add your own cleanup code here */
|
||||
PyMem_DEL(self);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_getattr($abbrev$object *self, char *name)
|
||||
{
|
||||
/* XXXX Add your own getattr code here */
|
||||
return Py_FindMethod($abbrev$_methods, (PyObject *)self, name);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
static long
|
||||
$abbrev$_hash($abbrev$object *self)
|
||||
{
|
||||
/* XXXX Return a hash of self (or -1) */
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
static int
|
||||
$abbrev$_print($abbrev$object *self, FILE *fp, int flags)
|
||||
{
|
||||
/* XXXX Add code here to print self to fp */
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_repr($abbrev$object *self)
|
||||
{
|
||||
PyObject *s;
|
||||
|
||||
/* XXXX Add code here to put self into s */
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
static int
|
||||
$abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
|
||||
{
|
||||
/* Set attribute 'name' to value 'v'. v==NULL means delete */
|
||||
|
||||
/* XXXX Add your own setattr code here */
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
static PyObject *
|
||||
$abbrev$_str($abbrev$object *self)
|
||||
{
|
||||
PyObject *s;
|
||||
|
||||
/* XXXX Add code here to put self into s */
|
||||
return s;
|
||||
}
|
||||
|
||||
234
project/jni/python/src/Tools/modulator/Tkextra.py
Normal file
234
project/jni/python/src/Tools/modulator/Tkextra.py
Normal file
@@ -0,0 +1,234 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# A Python function that generates dialog boxes with a text message,
|
||||
# optional bitmap, and any number of buttons.
|
||||
# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
|
||||
|
||||
from Tkinter import *
|
||||
|
||||
mainWidget = None
|
||||
|
||||
def dialog(master, title, text, bitmap, default, *args):
|
||||
|
||||
# 1. Create the top-level window and divide it into top
|
||||
# and bottom parts.
|
||||
|
||||
w = Toplevel(master, {'class': 'Dialog'})
|
||||
w.title(title)
|
||||
w.iconname('Dialog')
|
||||
|
||||
top = Frame(w, {'relief': 'raised', 'bd': 1,
|
||||
Pack: {'side': 'top', 'fill': 'both'}})
|
||||
bot = Frame(w, {'relief': 'raised', 'bd': 1,
|
||||
Pack: {'side': 'bottom', 'fill': 'both'}})
|
||||
|
||||
# 2. Fill the top part with the bitmap and message.
|
||||
|
||||
msg = Message(top,
|
||||
{'width': '3i',
|
||||
'text': text,
|
||||
'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
|
||||
Pack: {'side': 'right', 'expand': 1,
|
||||
'fill': 'both',
|
||||
'padx': '3m', 'pady': '3m'}})
|
||||
if bitmap:
|
||||
bm = Label(top, {'bitmap': bitmap,
|
||||
Pack: {'side': 'left',
|
||||
'padx': '3m', 'pady': '3m'}})
|
||||
|
||||
# 3. Create a row of buttons at the bottom of the dialog.
|
||||
|
||||
buttons = []
|
||||
i = 0
|
||||
for but in args:
|
||||
b = Button(bot, {'text': but,
|
||||
'command': ('set', 'button', i)})
|
||||
buttons.append(b)
|
||||
if i == default:
|
||||
bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
|
||||
Pack: {'side': 'left', 'expand': 1,
|
||||
'padx': '3m', 'pady': '2m'}})
|
||||
b.lift()
|
||||
b.pack ({'in': bd, 'side': 'left',
|
||||
'padx': '2m', 'pady': '2m',
|
||||
'ipadx': '2m', 'ipady': '1m'})
|
||||
else:
|
||||
b.pack ({'side': 'left', 'expand': 1,
|
||||
'padx': '3m', 'pady': '3m',
|
||||
'ipady': '2m', 'ipady': '1m'})
|
||||
i = i+1
|
||||
|
||||
# 4. Set up a binding for <Return>, if there's a default,
|
||||
# set a grab, and claim the focus too.
|
||||
|
||||
if default >= 0:
|
||||
w.bind('<Return>',
|
||||
lambda e, b=buttons[default], i=default:
|
||||
(b.flash(),
|
||||
b.setvar('button', i)))
|
||||
|
||||
oldFocus = w.tk.call('focus') # XXX
|
||||
w.grab_set()
|
||||
w.focus()
|
||||
|
||||
# 5. Wait for the user to respond, then restore the focus
|
||||
# and return the index of the selected button.
|
||||
|
||||
w.waitvar('button')
|
||||
w.destroy()
|
||||
w.tk.call('focus', oldFocus) # XXX
|
||||
return w.getint(w.getvar('button'))
|
||||
|
||||
def strdialog(master, title, text, bitmap, default, *args):
|
||||
|
||||
# 1. Create the top-level window and divide it into top
|
||||
# and bottom parts.
|
||||
|
||||
w = Toplevel(master, {'class': 'Dialog'})
|
||||
w.title(title)
|
||||
w.iconname('Dialog')
|
||||
|
||||
top = Frame(w, {'relief': 'raised', 'bd': 1,
|
||||
Pack: {'side': 'top', 'fill': 'both'}})
|
||||
if args:
|
||||
bot = Frame(w, {'relief': 'raised', 'bd': 1,
|
||||
Pack: {'side': 'bottom', 'fill': 'both'}})
|
||||
|
||||
# 2. Fill the top part with the bitmap, message and input field.
|
||||
|
||||
if bitmap:
|
||||
bm = Label(top, {'bitmap': bitmap,
|
||||
Pack: {'side': 'left',
|
||||
'padx': '3m', 'pady': '3m'}})
|
||||
|
||||
msg = Message(top,
|
||||
{'width': '3i',
|
||||
'text': text,
|
||||
'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
|
||||
Pack: {'side': 'left',
|
||||
'fill': 'both',
|
||||
'padx': '3m', 'pady': '3m'}})
|
||||
|
||||
field = Entry(top,
|
||||
{'relief':'sunken',
|
||||
Pack:{'side':'left',
|
||||
'fill':'x',
|
||||
'expand':1,
|
||||
'padx':'3m', 'pady':'3m'}})
|
||||
# 3. Create a row of buttons at the bottom of the dialog.
|
||||
|
||||
buttons = []
|
||||
i = 0
|
||||
for but in args:
|
||||
b = Button(bot, {'text': but,
|
||||
'command': ('set', 'button', i)})
|
||||
buttons.append(b)
|
||||
if i == default:
|
||||
bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
|
||||
Pack: {'side': 'left', 'expand': 1,
|
||||
'padx': '3m', 'pady': '2m'}})
|
||||
b.lift()
|
||||
b.pack ({'in': bd, 'side': 'left',
|
||||
'padx': '2m', 'pady': '2m',
|
||||
'ipadx': '2m', 'ipady': '1m'})
|
||||
else:
|
||||
b.pack ({'side': 'left', 'expand': 1,
|
||||
'padx': '3m', 'pady': '3m',
|
||||
'ipady': '2m', 'ipady': '1m'})
|
||||
i = i+1
|
||||
|
||||
# 4. Set up a binding for <Return>, if there's a default,
|
||||
# set a grab, and claim the focus too.
|
||||
|
||||
if not args:
|
||||
w.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
|
||||
field.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
|
||||
elif default >= 0:
|
||||
w.bind('<Return>',
|
||||
lambda e, b=buttons[default], i=default:
|
||||
(b.flash(),
|
||||
b.setvar('button', i)))
|
||||
field.bind('<Return>',
|
||||
lambda e, b=buttons[default], i=default:
|
||||
(b.flash(),
|
||||
b.setvar('button', i)))
|
||||
|
||||
oldFocus = w.tk.call('focus') # XXX
|
||||
w.grab_set()
|
||||
field.focus()
|
||||
|
||||
# 5. Wait for the user to respond, then restore the focus
|
||||
# and return the index of the selected button.
|
||||
|
||||
w.waitvar('button')
|
||||
v = field.get()
|
||||
w.destroy()
|
||||
w.tk.call('focus', oldFocus) # XXX
|
||||
if args:
|
||||
return v, w.getint(w.getvar('button'))
|
||||
else:
|
||||
return v
|
||||
|
||||
def message(str):
|
||||
i = dialog(mainWidget, 'Message', str, '', 0, 'OK')
|
||||
|
||||
def askyn(str):
|
||||
i = dialog(mainWidget, 'Question', str, '', 0, 'No', 'Yes')
|
||||
return i
|
||||
|
||||
def askync(str):
|
||||
i = dialog(mainWidget, 'Question', str, '', 0, 'Cancel', 'No', 'Yes')
|
||||
return i-1
|
||||
|
||||
def askstr(str):
|
||||
i = strdialog(mainWidget, 'Question', str, '', 0)
|
||||
return i
|
||||
|
||||
def askfile(str): # XXXX For now...
|
||||
i = strdialog(mainWidget, 'Question', str, '', 0)
|
||||
return i
|
||||
|
||||
# The rest is the test program.
|
||||
|
||||
def _go():
|
||||
i = dialog(mainWidget,
|
||||
'Not Responding',
|
||||
"The file server isn't responding right now; "
|
||||
"I'll keep trying.",
|
||||
'',
|
||||
-1,
|
||||
'OK')
|
||||
print 'pressed button', i
|
||||
i = dialog(mainWidget,
|
||||
'File Modified',
|
||||
'File "tcl.h" has been modified since '
|
||||
'the last time it was saved. '
|
||||
'Do you want to save it before exiting the application?',
|
||||
'warning',
|
||||
0,
|
||||
'Save File',
|
||||
'Discard Changes',
|
||||
'Return To Editor')
|
||||
print 'pressed button', i
|
||||
print message('Test of message')
|
||||
print askyn('Test of yes/no')
|
||||
print askync('Test of yes/no/cancel')
|
||||
print askstr('Type a string:')
|
||||
print strdialog(mainWidget, 'Question', 'Another string:', '',
|
||||
0, 'Save', 'Save as text')
|
||||
|
||||
def _test():
|
||||
global mainWidget
|
||||
mainWidget = Frame()
|
||||
Pack.config(mainWidget)
|
||||
start = Button(mainWidget,
|
||||
{'text': 'Press Here To Start', 'command': _go})
|
||||
start.pack()
|
||||
endit = Button(mainWidget,
|
||||
{'text': 'Exit',
|
||||
'command': 'exit',
|
||||
Pack: {'fill' : 'both'}})
|
||||
mainWidget.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
160
project/jni/python/src/Tools/modulator/genmodule.py
Normal file
160
project/jni/python/src/Tools/modulator/genmodule.py
Normal file
@@ -0,0 +1,160 @@
|
||||
#
|
||||
# Genmodule - A python program to help you build (template) modules.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# o = genmodule.object()
|
||||
# o.name = 'dwarve object'
|
||||
# o.abbrev = 'dw'
|
||||
# o.funclist = ['new', 'dealloc', 'getattr', 'setattr']
|
||||
# o.methodlist = ['dig']
|
||||
#
|
||||
# m = genmodule.module()
|
||||
# m.name = 'beings'
|
||||
# m.abbrev = 'be'
|
||||
# m.methodlist = ['newdwarve']
|
||||
# m.objects = [o]
|
||||
#
|
||||
# genmodule.write(sys.stdout, m)
|
||||
#
|
||||
import sys
|
||||
import os
|
||||
import varsubst
|
||||
|
||||
error = 'genmodule.error'
|
||||
|
||||
#
|
||||
# Names of functions in the object-description struct.
|
||||
#
|
||||
FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
|
||||
'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str']
|
||||
TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure']
|
||||
|
||||
#
|
||||
# writer is a base class for the object and module classes
|
||||
# it contains code common to both.
|
||||
#
|
||||
class writer:
|
||||
def __init__(self):
|
||||
self._subst = None
|
||||
|
||||
def makesubst(self):
|
||||
if not self._subst:
|
||||
if not self.__dict__.has_key('abbrev'):
|
||||
self.abbrev = self.name
|
||||
self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:]
|
||||
subst = varsubst.Varsubst(self.__dict__)
|
||||
subst.useindent(1)
|
||||
self._subst = subst.subst
|
||||
|
||||
def addcode(self, name, fp):
|
||||
ifp = self.opentemplate(name)
|
||||
self.makesubst()
|
||||
d = ifp.read()
|
||||
d = self._subst(d)
|
||||
fp.write(d)
|
||||
|
||||
def opentemplate(self, name):
|
||||
for p in sys.path:
|
||||
fn = os.path.join(p, name)
|
||||
if os.path.exists(fn):
|
||||
return open(fn, 'r')
|
||||
fn = os.path.join(p, 'Templates')
|
||||
fn = os.path.join(fn, name)
|
||||
if os.path.exists(fn):
|
||||
return open(fn, 'r')
|
||||
raise error, 'Template '+name+' not found for '+self._type+' '+ \
|
||||
self.name
|
||||
|
||||
class module(writer):
|
||||
_type = 'module'
|
||||
|
||||
def writecode(self, fp):
|
||||
self.addcode('copyright', fp)
|
||||
self.addcode('module_head', fp)
|
||||
for o in self.objects:
|
||||
o.writehead(fp)
|
||||
for o in self.objects:
|
||||
o.writebody(fp)
|
||||
new_ml = ''
|
||||
for fn in self.methodlist:
|
||||
self.method = fn
|
||||
self.addcode('module_method', fp)
|
||||
new_ml = new_ml + (
|
||||
'{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
|
||||
%(fn, self.abbrev, fn, self.abbrev, fn))
|
||||
self.methodlist = new_ml
|
||||
self.addcode('module_tail', fp)
|
||||
|
||||
class object(writer):
|
||||
_type = 'object'
|
||||
def __init__(self):
|
||||
self.typelist = []
|
||||
self.methodlist = []
|
||||
self.funclist = ['new']
|
||||
writer.__init__(self)
|
||||
|
||||
def writecode(self, fp):
|
||||
self.addcode('copyright', fp)
|
||||
self.writehead(fp)
|
||||
self.writebody(fp)
|
||||
|
||||
def writehead(self, fp):
|
||||
self.addcode('object_head', fp)
|
||||
|
||||
def writebody(self, fp):
|
||||
new_ml = ''
|
||||
for fn in self.methodlist:
|
||||
self.method = fn
|
||||
self.addcode('object_method', fp)
|
||||
new_ml = new_ml + (
|
||||
'{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
|
||||
%(fn, self.abbrev, fn, self.abbrev, fn))
|
||||
self.methodlist = new_ml
|
||||
self.addcode('object_mlist', fp)
|
||||
|
||||
# Add getattr if we have methods
|
||||
if self.methodlist and not 'tp_getattr' in self.funclist:
|
||||
self.funclist.insert(0, 'tp_getattr')
|
||||
|
||||
for fn in FUNCLIST:
|
||||
setattr(self, fn, '0')
|
||||
|
||||
#
|
||||
# Special case for structure-access objects: put getattr in the
|
||||
# list of functions but don't generate code for it directly,
|
||||
# the code is obtained from the object_structure template.
|
||||
# The same goes for setattr.
|
||||
#
|
||||
if 'structure' in self.typelist:
|
||||
if 'tp_getattr' in self.funclist:
|
||||
self.funclist.remove('tp_getattr')
|
||||
if 'tp_setattr' in self.funclist:
|
||||
self.funclist.remove('tp_setattr')
|
||||
self.tp_getattr = self.abbrev + '_getattr'
|
||||
self.tp_setattr = self.abbrev + '_setattr'
|
||||
for fn in self.funclist:
|
||||
self.addcode('object_'+fn, fp)
|
||||
setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:]))
|
||||
for tn in TYPELIST:
|
||||
setattr(self, tn, '0')
|
||||
for tn in self.typelist:
|
||||
self.addcode('object_'+tn, fp)
|
||||
setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:]))
|
||||
self.addcode('object_tail', fp)
|
||||
|
||||
def write(fp, obj):
|
||||
obj.writecode(fp)
|
||||
|
||||
if __name__ == '__main__':
|
||||
o = object()
|
||||
o.name = 'dwarve object'
|
||||
o.abbrev = 'dw'
|
||||
o.funclist = ['new', 'tp_dealloc']
|
||||
o.methodlist = ['dig']
|
||||
m = module()
|
||||
m.name = 'beings'
|
||||
m.abbrev = 'be'
|
||||
m.methodlist = ['newdwarve']
|
||||
m.objects = [o]
|
||||
write(sys.stdout, m)
|
||||
383
project/jni/python/src/Tools/modulator/modulator.py
Normal file
383
project/jni/python/src/Tools/modulator/modulator.py
Normal file
@@ -0,0 +1,383 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
# Modulator - Generate skeleton modules.
|
||||
#
|
||||
# The user fills out some forms with information about what the module
|
||||
# should support (methods, objects), names of these things, prefixes to
|
||||
# use for C code, whether the objects should also support access as numbers,
|
||||
# etc etc etc.
|
||||
# When the user presses 'Generate code' we generate a complete skeleton
|
||||
# module in C.
|
||||
#
|
||||
# Alternatively, the selections made can be save to a python sourcefile and
|
||||
# this sourcefile can be passed on the command line (resulting in the same
|
||||
# skeleton C code).
|
||||
#
|
||||
# Jack Jansen, CWI, October 1994.
|
||||
#
|
||||
|
||||
import sys, os
|
||||
if os.name <> 'mac':
|
||||
sys.path.append(os.path.join(os.environ['HOME'],
|
||||
'src/python/Tools/modulator'))
|
||||
|
||||
from Tkinter import *
|
||||
from Tkextra import *
|
||||
from ScrolledListbox import ScrolledListbox
|
||||
import sys
|
||||
import genmodule
|
||||
import string
|
||||
|
||||
oops = 'oops'
|
||||
|
||||
IDENTSTARTCHARS = string.letters + '_'
|
||||
IDENTCHARS = string.letters + string.digits + '_'
|
||||
|
||||
# Check that string is a legal C identifier
|
||||
def checkid(str):
|
||||
if not str: return 0
|
||||
if not str[0] in IDENTSTARTCHARS:
|
||||
return 0
|
||||
for c in str[1:]:
|
||||
if not c in IDENTCHARS:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def getlistlist(list):
|
||||
rv = []
|
||||
n = list.size()
|
||||
for i in range(n):
|
||||
rv.append(list.get(i))
|
||||
return rv
|
||||
|
||||
class UI:
|
||||
def __init__(self):
|
||||
self.main = Frame()
|
||||
self.main.pack()
|
||||
self.main.master.title('Modulator: Module view')
|
||||
self.cmdframe = Frame(self.main, {'relief':'raised', 'bd':'0.5m',
|
||||
Pack:{'side':'top',
|
||||
'fill':'x'}})
|
||||
self.objframe = Frame(self.main, {Pack:{'side':'top', 'fill':'x',
|
||||
'expand':1}})
|
||||
|
||||
|
||||
self.check_button = Button(self.cmdframe,
|
||||
{'text':'Check', 'command':self.cb_check,
|
||||
Pack:{'side':'left', 'padx':'0.5m'}})
|
||||
self.save_button = Button(self.cmdframe,
|
||||
{'text':'Save...', 'command':self.cb_save,
|
||||
Pack:{'side':'left', 'padx':'0.5m'}})
|
||||
self.code_button = Button(self.cmdframe,
|
||||
{'text':'Generate code...',
|
||||
'command':self.cb_gencode,
|
||||
Pack:{'side':'left', 'padx':'0.5m'}})
|
||||
self.quit_button = Button(self.cmdframe,
|
||||
{'text':'Quit',
|
||||
'command':self.cb_quit,
|
||||
Pack:{'side':'right', 'padx':'0.5m'}})
|
||||
|
||||
self.module = UI_module(self)
|
||||
self.objects = []
|
||||
self.modified = 0
|
||||
|
||||
def run(self):
|
||||
self.main.mainloop()
|
||||
|
||||
def cb_quit(self, *args):
|
||||
if self.modified:
|
||||
if not askyn('You have not saved\nAre you sure you want to quit?'):
|
||||
return
|
||||
sys.exit(0)
|
||||
|
||||
def cb_check(self, *args):
|
||||
try:
|
||||
self.module.synchronize()
|
||||
for o in self.objects:
|
||||
o.synchronize()
|
||||
except oops:
|
||||
pass
|
||||
|
||||
def cb_save(self, *args):
|
||||
try:
|
||||
pycode = self.module.gencode('m', self.objects)
|
||||
except oops:
|
||||
return
|
||||
|
||||
fn = askfile('Python file name: ')
|
||||
if not fn:
|
||||
return
|
||||
|
||||
fp = open(fn, 'w')
|
||||
|
||||
fp.write(pycode)
|
||||
fp.close()
|
||||
|
||||
def cb_gencode(self, *args):
|
||||
try:
|
||||
pycode = self.module.gencode('m', self.objects)
|
||||
except oops:
|
||||
pass
|
||||
|
||||
fn = askfile('C file name: ')
|
||||
if not fn:
|
||||
return
|
||||
|
||||
fp = open(fn, 'w')
|
||||
|
||||
try:
|
||||
exec pycode
|
||||
except:
|
||||
message('An error occurred:-)')
|
||||
return
|
||||
genmodule.write(fp, m)
|
||||
fp.close()
|
||||
|
||||
class UI_module:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
|
||||
Pack:{'side':'top',
|
||||
'fill':'x'}})
|
||||
self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
|
||||
self.l1 = Label(self.f1, {'text':'Module:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.name_entry = Entry(self.f1, {'relief':'sunken',
|
||||
Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
|
||||
self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
|
||||
Pack:{'side':'left', 'padx':'0.5m'}})
|
||||
|
||||
self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
|
||||
Pack:{'side':'left', 'expand':1,
|
||||
'padx':'0.5m', 'fill':'both'}})
|
||||
|
||||
self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.method_entry = Entry(self.f3, {'relief':'sunken',
|
||||
Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
|
||||
self.method_entry.bind('<Return>', self.cb_method)
|
||||
self.delete_button = Button(self.f3, {'text':'Delete method',
|
||||
'command':self.cb_delmethod,
|
||||
Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
|
||||
self.newobj_button = Button(self.f4, {'text':'new object',
|
||||
'command':self.cb_newobj,
|
||||
Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
|
||||
def cb_delmethod(self, *args):
|
||||
list = self.method_list.curselection()
|
||||
for i in list:
|
||||
self.method_list.delete(i)
|
||||
|
||||
def cb_newobj(self, *arg):
|
||||
self.parent.objects.append(UI_object(self.parent))
|
||||
|
||||
def cb_method(self, *arg):
|
||||
name = self.method_entry.get()
|
||||
if not name:
|
||||
return
|
||||
self.method_entry.delete('0', 'end')
|
||||
self.method_list.insert('end', name)
|
||||
|
||||
def synchronize(self):
|
||||
n = self.name_entry.get()
|
||||
if not n:
|
||||
message('Module name not set')
|
||||
raise oops
|
||||
if not checkid(n):
|
||||
message('Module name not an identifier:\n'+n)
|
||||
raise oops
|
||||
if not self.abbrev_entry.get():
|
||||
self.abbrev_entry.insert('end', n)
|
||||
m = getlistlist(self.method_list)
|
||||
for n in m:
|
||||
if not checkid(n):
|
||||
message('Method name not an identifier:\n'+n)
|
||||
raise oops
|
||||
|
||||
def gencode(self, name, objects):
|
||||
rv = ''
|
||||
self.synchronize()
|
||||
for o in objects:
|
||||
o.synchronize()
|
||||
onames = []
|
||||
for i in range(len(objects)):
|
||||
oname = 'o%d' % (i+1)
|
||||
rv = rv + objects[i].gencode(oname)
|
||||
onames.append(oname)
|
||||
rv = rv + '%s = genmodule.module()\n' % (name,)
|
||||
rv = rv + '%s.name = %r\n' % (name, self.name_entry.get())
|
||||
rv = rv + '%s.abbrev = %r\n' % (name, self.abbrev_entry.get())
|
||||
rv = rv + '%s.methodlist = %r\n' % (name, getlistlist(self.method_list))
|
||||
rv = rv + '%s.objects = [%s]\n' % (name, ','.join(onames))
|
||||
rv = rv + '\n'
|
||||
return rv
|
||||
|
||||
object_number = 0
|
||||
|
||||
class UI_object:
|
||||
def __init__(self, parent):
|
||||
global object_number
|
||||
|
||||
object_number = object_number + 1
|
||||
self.num = object_number
|
||||
self.vpref = 'o%r_' % self.num
|
||||
self.frame = Toplevel(parent.objframe)
|
||||
# self.frame.pack()
|
||||
self.frame.title('Modulator: object view')
|
||||
# self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
|
||||
# Pack:{'side':'top',
|
||||
# 'fill':'x'}})
|
||||
self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
|
||||
|
||||
self.l1 = Label(self.f1, {'text':'Object:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.name_entry = Entry(self.f1, {'relief':'sunken',
|
||||
Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
|
||||
self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
|
||||
Pack:{'side':'left', 'padx':'0.5m'}})
|
||||
|
||||
self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
|
||||
Pack:{'side':'left', 'expand':1,
|
||||
'padx':'0.5m', 'fill':'both'}})
|
||||
|
||||
self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.method_entry = Entry(self.f3, {'relief':'sunken',
|
||||
Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
|
||||
self.method_entry.bind('<Return>', self.cb_method)
|
||||
self.delete_button = Button(self.f3, {'text':'Delete method',
|
||||
'command':self.cb_delmethod,
|
||||
Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
|
||||
|
||||
self.l5 = Label(self.f4, {'text':'functions:',
|
||||
Pack:{'side':'left',
|
||||
'padx':'0.5m'}})
|
||||
self.f5 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
|
||||
'fill':'both'}})
|
||||
self.l6 = Label(self.f4, {'text':'Types:',
|
||||
Pack:{'side':'left', 'padx':'0.5m'}})
|
||||
self.f6 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
|
||||
'fill':'x'}})
|
||||
self.funcs = {}
|
||||
for i in genmodule.FUNCLIST:
|
||||
vname = self.vpref+i
|
||||
self.f5.setvar(vname, 0)
|
||||
b = Checkbutton(self.f5, {'variable':vname, 'text':i,
|
||||
Pack:{'side':'top', 'pady':'0.5m',
|
||||
'anchor':'w','expand':1}})
|
||||
self.funcs[i] = b
|
||||
self.f5.setvar(self.vpref+'new', 1)
|
||||
|
||||
self.types = {}
|
||||
for i in genmodule.TYPELIST:
|
||||
vname = self.vpref + i
|
||||
self.f6.setvar(vname, 0)
|
||||
b = Checkbutton(self.f6, {'variable':vname, 'text':i,
|
||||
Pack:{'side':'top', 'pady':'0.5m',
|
||||
'anchor':'w'}})
|
||||
self.types[i] = b
|
||||
|
||||
def cb_method(self, *arg):
|
||||
name = self.method_entry.get()
|
||||
if not name:
|
||||
return
|
||||
self.method_entry.delete('0', 'end')
|
||||
self.method_list.insert('end', name)
|
||||
|
||||
def cb_delmethod(self, *args):
|
||||
list = self.method_list.curselection()
|
||||
for i in list:
|
||||
self.method_list.delete(i)
|
||||
|
||||
def synchronize(self):
|
||||
n = self.name_entry.get()
|
||||
if not n:
|
||||
message('Object name not set')
|
||||
raise oops
|
||||
if not self.abbrev_entry.get():
|
||||
self.abbrev_entry.insert('end', n)
|
||||
n = self.abbrev_entry.get()
|
||||
if not checkid(n):
|
||||
message('Abbreviation not an identifier:\n'+n)
|
||||
raise oops
|
||||
m = getlistlist(self.method_list)
|
||||
for n in m:
|
||||
if not checkid(n):
|
||||
message('Method name not an identifier:\n'+n)
|
||||
raise oops
|
||||
if m:
|
||||
self.f5.setvar(self.vpref+'tp_getattr', 1)
|
||||
pass
|
||||
|
||||
def gencode(self, name):
|
||||
rv = ''
|
||||
rv = rv + '%s = genmodule.object()\n' % (name,)
|
||||
rv = rv + '%s.name = %r\n' % (name, self.name_entry.get())
|
||||
rv = rv + '%s.abbrev = %r\n' % (name, self.abbrev_entry.get())
|
||||
rv = rv + '%s.methodlist = %r\n' % (name, getlistlist(self.method_list))
|
||||
fl = []
|
||||
for fn in genmodule.FUNCLIST:
|
||||
vname = self.vpref + fn
|
||||
if self.f5.getvar(vname) == '1':
|
||||
fl.append(fn)
|
||||
rv = rv + '%s.funclist = %r\n' % (name, fl)
|
||||
|
||||
fl = []
|
||||
for fn in genmodule.TYPELIST:
|
||||
vname = self.vpref + fn
|
||||
if self.f5.getvar(vname) == '1':
|
||||
fl.append(fn)
|
||||
|
||||
rv = rv + '%s.typelist = %r\n' % (name, fl)
|
||||
|
||||
rv = rv + '\n'
|
||||
return rv
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
ui = UI()
|
||||
ui.run()
|
||||
elif len(sys.argv) == 2:
|
||||
fp = open(sys.argv[1])
|
||||
pycode = fp.read()
|
||||
try:
|
||||
exec pycode
|
||||
except:
|
||||
sys.stderr.write('An error occurred:-)\n')
|
||||
sys.exit(1)
|
||||
##genmodule.write(sys.stdout, m)
|
||||
else:
|
||||
sys.stderr.write('Usage: modulator [file]\n')
|
||||
sys.exit(1)
|
||||
|
||||
main()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user