Showing the changes to sys/src/cmd/python/Modules (314 of 3706 files). Show all
Unified · Split
| @@ -0,0 +1,488 @@ | ||
| 1 | +# -*- makefile -*- | |
| 2 | +# The file Setup is used by the makesetup script to construct the files | |
| 3 | +# Makefile and config.c, from Makefile.pre and config.c.in, | |
| 4 | +# respectively. The file Setup itself is initially copied from | |
| 5 | +# Setup.dist; once it exists it will not be overwritten, so you can edit | |
| 6 | +# Setup to your heart's content. Note that Makefile.pre is created | |
| 7 | +# from Makefile.pre.in by the toplevel configure script. | |
| 8 | + | |
| 9 | +# (VPATH notes: Setup and Makefile.pre are in the build directory, as | |
| 10 | +# are Makefile and config.c; the *.in and *.dist files are in the source | |
| 11 | +# directory.) | |
| 12 | + | |
| 13 | +# Each line in this file describes one or more optional modules. | |
| 14 | +# Modules enabled here will not be compiled by the setup.py script, | |
| 15 | +# so the file can be used to override setup.py's behavior. | |
| 16 | + | |
| 17 | +# Lines have the following structure: | |
| 18 | +# | |
| 19 | +# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...] | |
| 20 | +# | |
| 21 | +# <sourcefile> is anything ending in .c (.C, .cc, .c++ are C++ files) | |
| 22 | +# <cpparg> is anything starting with -I, -D, -U or -C | |
| 23 | +# <library> is anything ending in .a or beginning with -l or -L | |
| 24 | +# <module> is anything else but should be a valid Python | |
| 25 | +# identifier (letters, digits, underscores, beginning with non-digit) | |
| 26 | +# | |
| 27 | +# (As the makesetup script changes, it may recognize some other | |
| 28 | +# arguments as well, e.g. *.so and *.sl as libraries. See the big | |
| 29 | +# case statement in the makesetup script.) | |
| 30 | +# | |
| 31 | +# Lines can also have the form | |
| 32 | +# | |
| 33 | +# <name> = <value> | |
| 34 | +# | |
| 35 | +# which defines a Make variable definition inserted into Makefile.in | |
| 36 | +# | |
| 37 | +# Finally, if a line contains just the word "*shared*" (without the | |
| 38 | +# quotes but with the stars), then the following modules will not be | |
| 39 | +# built statically. The build process works like this: | |
| 40 | +# | |
| 41 | +# 1. Build all modules that are declared as static in Modules/Setup, | |
| 42 | +# combine them into libpythonxy.a, combine that into python. | |
| 43 | +# 2. Build all modules that are listed as shared in Modules/Setup. | |
| 44 | +# 3. Invoke setup.py. That builds all modules that | |
| 45 | +# a) are not builtin, and | |
| 46 | +# b) are not listed in Modules/Setup, and | |
| 47 | +# c) can be build on the target | |
| 48 | +# | |
| 49 | +# Therefore, modules declared to be shared will not be | |
| 50 | +# included in the config.c file, nor in the list of objects to be | |
| 51 | +# added to the library archive, and their linker options won't be | |
| 52 | +# added to the linker options. Rules to create their .o files and | |
| 53 | +# their shared libraries will still be added to the Makefile, and | |
| 54 | +# their names will be collected in the Make variable SHAREDMODS. This | |
| 55 | +# is used to build modules as shared libraries. (They can be | |
| 56 | +# installed using "make sharedinstall", which is implied by the | |
| 57 | +# toplevel "make install" target.) (For compatibility, | |
| 58 | +# *noconfig* has the same effect as *shared*.) | |
| 59 | +# | |
| 60 | +# In addition, *static* explicitly declares the following modules to | |
| 61 | +# be static. Lines containing "*static*" and "*shared*" may thus | |
| 62 | +# alternate throughout this file. | |
| 63 | + | |
| 64 | +# NOTE: As a standard policy, as many modules as can be supported by a | |
| 65 | +# platform should be present. The distribution comes with all modules | |
| 66 | +# enabled that are supported by most platforms and don't require you | |
| 67 | +# to ftp sources from elsewhere. | |
| 68 | + | |
| 69 | + | |
| 70 | +# Some special rules to define PYTHONPATH. | |
| 71 | +# Edit the definitions below to indicate which options you are using. | |
| 72 | +# Don't add any whitespace or comments! | |
| 73 | + | |
| 74 | +# Directories where library files get installed. | |
| 75 | +# DESTLIB is for Python modules; MACHDESTLIB for shared libraries. | |
| 76 | +DESTLIB=$(LIBDEST) | |
| 77 | +MACHDESTLIB=$(BINLIBDEST) | |
| 78 | + | |
| 79 | +# NOTE: all the paths are now relative to the prefix that is computed | |
| 80 | +# at run time! | |
| 81 | + | |
| 82 | +# Standard path -- don't edit. | |
| 83 | +# No leading colon since this is the first entry. | |
| 84 | +# Empty since this is now just the runtime prefix. | |
| 85 | +DESTPATH= | |
| 86 | + | |
| 87 | +# Site specific path components -- should begin with : if non-empty | |
| 88 | +SITEPATH= | |
| 89 | + | |
| 90 | +# Standard path components for test modules | |
| 91 | +TESTPATH= | |
| 92 | + | |
| 93 | +# Path components for machine- or system-dependent modules and shared libraries | |
| 94 | +MACHDEPPATH=:plat-$(MACHDEP) | |
| 95 | +EXTRAMACHDEPPATH= | |
| 96 | + | |
| 97 | +# Path component for the Tkinter-related modules | |
| 98 | +# The TKPATH variable is always enabled, to save you the effort. | |
| 99 | +TKPATH=:lib-tk | |
| 100 | + | |
| 101 | +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH) | |
| 102 | +PYTHONPATH=$(COREPYTHONPATH) | |
| 103 | + | |
| 104 | + | |
| 105 | +# The modules listed here can't be built as shared libraries for | |
| 106 | +# various reasons; therefore they are listed here instead of in the | |
| 107 | +# normal order. | |
| 108 | + | |
| 109 | +# This only contains the minimal set of modules required to run the | |
| 110 | +# setup.py script in the root of the Python source tree. | |
| 111 | + | |
| 112 | +posix posixmodule.c # posix (UNIX) system calls | |
| 113 | +errno errnomodule.c # posix (UNIX) errno values | |
| 114 | +pwd pwdmodule.c # this is needed to find out the user's home dir | |
| 115 | + # if $HOME is not set | |
| 116 | +_sre _sre.c # Fredrik Lundh's new regular expressions | |
| 117 | +_codecs _codecsmodule.c # access to the builtin codecs and codec registry | |
| 118 | +_ssl _ssl.c | |
| 119 | + | |
| 120 | +# The zipimport module is always imported at startup. Having it as a | |
| 121 | +# builtin module avoids some bootstrapping problems and reduces overhead. | |
| 122 | +zipimport zipimport.c | |
| 123 | + | |
| 124 | +# The rest of the modules listed in this file are all commented out by | |
| 125 | +# default. Usually they can be detected and built as dynamically | |
| 126 | +# loaded modules by the new setup.py script added in Python 2.1. If | |
| 127 | +# you're on a platform that doesn't support dynamic loading, want to | |
| 128 | +# compile modules statically into the Python binary, or need to | |
| 129 | +# specify some odd set of compiler switches, you can uncomment the | |
| 130 | +# appropriate lines below. | |
| 131 | + | |
| 132 | +# ====================================================================== | |
| 133 | + | |
| 134 | +# The Python symtable module depends on .h files that setup.py doesn't track | |
| 135 | +_symtable symtablemodule.c | |
| 136 | + | |
| 137 | +# The SGI specific GL module: | |
| 138 | + | |
| 139 | +GLHACK=-Dclear=__GLclear | |
| 140 | +#gl glmodule.c cgensupport.c -I$(srcdir) $(GLHACK) -lgl -lX11 | |
| 141 | + | |
| 142 | +# Pure module. Cannot be linked dynamically. | |
| 143 | +# -DWITH_QUANTIFY, -DWITH_PURIFY, or -DWITH_ALL_PURE | |
| 144 | +#WHICH_PURE_PRODUCTS=-DWITH_ALL_PURE | |
| 145 | +#PURE_INCLS=-I/usr/local/include | |
| 146 | +#PURE_STUBLIBS=-L/usr/local/lib -lpurify_stubs -lquantify_stubs | |
| 147 | +#pure puremodule.c $(WHICH_PURE_PRODUCTS) $(PURE_INCLS) $(PURE_STUBLIBS) | |
| 148 | + | |
| 149 | +# Uncommenting the following line tells makesetup that all following | |
| 150 | +# modules are to be built as shared libraries (see above for more | |
| 151 | +# detail; also note that *static* reverses this effect): | |
| 152 | + | |
| 153 | +#*shared* | |
| 154 | + | |
| 155 | +# GNU readline. Unlike previous Python incarnations, GNU readline is | |
| 156 | +# now incorporated in an optional module, configured in the Setup file | |
| 157 | +# instead of by a configure script switch. You may have to insert a | |
| 158 | +# -L option pointing to the directory where libreadline.* lives, | |
| 159 | +# and you may have to change -ltermcap to -ltermlib or perhaps remove | |
| 160 | +# it, depending on your system -- see the GNU readline instructions. | |
| 161 | +# It's okay for this to be a shared library, too. | |
| 162 | + | |
| 163 | +#readline readline.c -lreadline -ltermcap | |
| 164 | + | |
| 165 | + | |
| 166 | +# Modules that should always be present (non UNIX dependent): | |
| 167 | + | |
| 168 | +#array arraymodule.c # array objects | |
| 169 | +#cmath cmathmodule.c # -lm # complex math library functions | |
| 170 | +#math mathmodule.c # -lm # math library functions, e.g. sin() | |
| 171 | +#_struct _struct.c # binary structure packing/unpacking | |
| 172 | +#time timemodule.c # -lm # time operations and variables | |
| 173 | +#operator operator.c # operator.add() and similar goodies | |
| 174 | +#_weakref _weakref.c # basic weak reference support | |
| 175 | +#_testcapi _testcapimodule.c # Python C API test module | |
| 176 | +#_random _randommodule.c # Random number generator | |
| 177 | +#collections collectionsmodule.c # Container types | |
| 178 | +#itertools itertoolsmodule.c # Functions creating iterators for efficient looping | |
| 179 | +#strop stropmodule.c # String manipulations | |
| 180 | + | |
| 181 | +#unicodedata unicodedata.c # static Unicode character database | |
| 182 | + | |
| 183 | +# access to ISO C locale support | |
| 184 | +#_locale _localemodule.c # -lintl | |
| 185 | + | |
| 186 | + | |
| 187 | +# Modules with some UNIX dependencies -- on by default: | |
| 188 | +# (If you have a really backward UNIX, select and socket may not be | |
| 189 | +# supported...) | |
| 190 | + | |
| 191 | +#fcntl fcntlmodule.c # fcntl(2) and ioctl(2) | |
| 192 | +#spwd spwdmodule.c # spwd(3) | |
| 193 | +#grp grpmodule.c # grp(3) | |
| 194 | +#select selectmodule.c # select(2); not on ancient System V | |
| 195 | + | |
| 196 | +# Memory-mapped files (also works on Win32). | |
| 197 | +#mmap mmapmodule.c | |
| 198 | + | |
| 199 | +# CSV file helper | |
| 200 | +#_csv _csv.c | |
| 201 | + | |
| 202 | +# Socket module helper for socket(2) | |
| 203 | +#_socket socketmodule.c | |
| 204 | + | |
| 205 | +# Socket module helper for SSL support; you must comment out the other | |
| 206 | +# socket line above, and possibly edit the SSL variable: | |
| 207 | +#SSL=/usr/local/ssl | |
| 208 | +#_ssl _ssl.c \ | |
| 209 | +# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \ | |
| 210 | +# -L$(SSL)/lib -lssl -lcrypto | |
| 211 | + | |
| 212 | +# The crypt module is now disabled by default because it breaks builds | |
| 213 | +# on many systems (where -lcrypt is needed), e.g. Linux (I believe). | |
| 214 | +# | |
| 215 | +# First, look at Setup.config; configure may have set this for you. | |
| 216 | + | |
| 217 | +#crypt cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems | |
| 218 | + | |
| 219 | + | |
| 220 | +# Some more UNIX dependent modules -- off by default, since these | |
| 221 | +# are not supported by all UNIX systems: | |
| 222 | + | |
| 223 | +#nis nismodule.c -lnsl # Sun yellow pages -- not everywhere | |
| 224 | +#termios termios.c # Steen Lumholt's termios module | |
| 225 | +#resource resource.c # Jeremy Hylton's rlimit interface | |
| 226 | + | |
| 227 | + | |
| 228 | +# Multimedia modules -- off by default. | |
| 229 | +# These don't work for 64-bit platforms!!! | |
| 230 | +# #993173 says audioop works on 64-bit platforms, though. | |
| 231 | +# These represent audio samples or images as strings: | |
| 232 | + | |
| 233 | +#audioop audioop.c # Operations on audio samples | |
| 234 | +#imageop imageop.c # Operations on images | |
| 235 | +#rgbimg rgbimgmodule.c # Read SGI RGB image files (but coded portably) | |
| 236 | + | |
| 237 | + | |
| 238 | +# Note that the _md5 and _sha modules are normally only built if the | |
| 239 | +# system does not have the OpenSSL libs containing an optimized version. | |
| 240 | + | |
| 241 | +# The _md5 module implements the RSA Data Security, Inc. MD5 | |
| 242 | +# Message-Digest Algorithm, described in RFC 1321. The necessary files | |
| 243 | +# md5.c and md5.h are included here. | |
| 244 | + | |
| 245 | +#_md5 md5module.c md5.c | |
| 246 | + | |
| 247 | + | |
| 248 | +# The _sha module implements the SHA checksum algorithm. | |
| 249 | +# (NIST's Secure Hash Algorithm.) | |
| 250 | +#_sha shamodule.c | |
| 251 | + | |
| 252 | + | |
| 253 | +# SGI IRIX specific modules -- off by default. | |
| 254 | + | |
| 255 | +# These module work on any SGI machine: | |
| 256 | + | |
| 257 | +# *** gl must be enabled higher up in this file *** | |
| 258 | +#fm fmmodule.c $(GLHACK) -lfm -lgl # Font Manager | |
| 259 | +#sgi sgimodule.c # sgi.nap() and a few more | |
| 260 | + | |
| 261 | +# This module requires the header file | |
| 262 | +# /usr/people/4Dgifts/iristools/include/izoom.h: | |
| 263 | +#imgfile imgfile.c -limage -lgutil -lgl -lm # Image Processing Utilities | |
| 264 | + | |
| 265 | + | |
| 266 | +# These modules require the Multimedia Development Option (I think): | |
| 267 | + | |
| 268 | +#al almodule.c -laudio # Audio Library | |
| 269 | +#cd cdmodule.c -lcdaudio -lds -lmediad # CD Audio Library | |
| 270 | +#cl clmodule.c -lcl -lawareaudio # Compression Library | |
| 271 | +#sv svmodule.c yuvconvert.c -lsvideo -lXext -lX11 # Starter Video | |
| 272 | + | |
| 273 | + | |
| 274 | +# The FORMS library, by Mark Overmars, implements user interface | |
| 275 | +# components such as dialogs and buttons using SGI's GL and FM | |
| 276 | +# libraries. You must ftp the FORMS library separately from | |
| 277 | +# ftp://ftp.cs.ruu.nl/pub/SGI/FORMS. It was tested with FORMS 2.2a. | |
| 278 | +# NOTE: if you want to be able to use FORMS and curses simultaneously | |
| 279 | +# (or both link them statically into the same binary), you must | |
| 280 | +# compile all of FORMS with the cc option "-Dclear=__GLclear". | |
| 281 | + | |
| 282 | +# The FORMS variable must point to the FORMS subdirectory of the forms | |
| 283 | +# toplevel directory: | |
| 284 | + | |
| 285 | +#FORMS=/ufs/guido/src/forms/FORMS | |
| 286 | +#fl flmodule.c -I$(FORMS) $(GLHACK) $(FORMS)/libforms.a -lfm -lgl | |
| 287 | + | |
| 288 | + | |
| 289 | +# SunOS specific modules -- off by default: | |
| 290 | + | |
| 291 | +#sunaudiodev sunaudiodev.c | |
| 292 | + | |
| 293 | + | |
| 294 | +# A Linux specific module -- off by default; this may also work on | |
| 295 | +# some *BSDs. | |
| 296 | + | |
| 297 | +#linuxaudiodev linuxaudiodev.c | |
| 298 | + | |
| 299 | + | |
| 300 | +# George Neville-Neil's timing module: | |
| 301 | + | |
| 302 | +#timing timingmodule.c | |
| 303 | + | |
| 304 | + | |
| 305 | +# The _tkinter module. | |
| 306 | +# | |
| 307 | +# The command for _tkinter is long and site specific. Please | |
| 308 | +# uncomment and/or edit those parts as indicated. If you don't have a | |
| 309 | +# specific extension (e.g. Tix or BLT), leave the corresponding line | |
| 310 | +# commented out. (Leave the trailing backslashes in! If you | |
| 311 | +# experience strange errors, you may want to join all uncommented | |
| 312 | +# lines and remove the backslashes -- the backslash interpretation is | |
| 313 | +# done by the shell's "read" command and it may not be implemented on | |
| 314 | +# every system. | |
| 315 | + | |
| 316 | +# *** Always uncomment this (leave the leading underscore in!): | |
| 317 | +# _tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \ | |
| 318 | +# *** Uncomment and edit to reflect where your Tcl/Tk libraries are: | |
| 319 | +# -L/usr/local/lib \ | |
| 320 | +# *** Uncomment and edit to reflect where your Tcl/Tk headers are: | |
| 321 | +# -I/usr/local/include \ | |
| 322 | +# *** Uncomment and edit to reflect where your X11 header files are: | |
| 323 | +# -I/usr/X11R6/include \ | |
| 324 | +# *** Or uncomment this for Solaris: | |
| 325 | +# -I/usr/openwin/include \ | |
| 326 | +# *** Uncomment and edit for Tix extension only: | |
| 327 | +# -DWITH_TIX -ltix8.1.8.2 \ | |
| 328 | +# *** Uncomment and edit for BLT extension only: | |
| 329 | +# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \ | |
| 330 | +# *** Uncomment and edit for PIL (TkImaging) extension only: | |
| 331 | +# (See http://www.pythonware.com/products/pil/ for more info) | |
| 332 | +# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \ | |
| 333 | +# *** Uncomment and edit for TOGL extension only: | |
| 334 | +# -DWITH_TOGL togl.c \ | |
| 335 | +# *** Uncomment and edit to reflect your Tcl/Tk versions: | |
| 336 | +# -ltk8.2 -ltcl8.2 \ | |
| 337 | +# *** Uncomment and edit to reflect where your X11 libraries are: | |
| 338 | +# -L/usr/X11R6/lib \ | |
| 339 | +# *** Or uncomment this for Solaris: | |
| 340 | +# -L/usr/openwin/lib \ | |
| 341 | +# *** Uncomment these for TOGL extension only: | |
| 342 | +# -lGL -lGLU -lXext -lXmu \ | |
| 343 | +# *** Uncomment for AIX: | |
| 344 | +# -lld \ | |
| 345 | +# *** Always uncomment this; X11 libraries to link with: | |
| 346 | +# -lX11 | |
| 347 | + | |
| 348 | +# Lance Ellinghaus's syslog module | |
| 349 | +#syslog syslogmodule.c # syslog daemon interface | |
| 350 | + | |
| 351 | + | |
| 352 | +# Curses support, requring the System V version of curses, often | |
| 353 | +# provided by the ncurses library. e.g. on Linux, link with -lncurses | |
| 354 | +# instead of -lcurses). | |
| 355 | +# | |
| 356 | +# First, look at Setup.config; configure may have set this for you. | |
| 357 | + | |
| 358 | +#_curses _cursesmodule.c -lcurses -ltermcap | |
| 359 | +# Wrapper for the panel library that's part of ncurses and SYSV curses. | |
| 360 | +#_curses_panel _curses_panel.c -lpanel -lncurses | |
| 361 | + | |
| 362 | + | |
| 363 | +# Generic (SunOS / SVR4) dynamic loading module. | |
| 364 | +# This is not needed for dynamic loading of Python modules -- | |
| 365 | +# it is a highly experimental and dangerous device for calling | |
| 366 | +# *arbitrary* C functions in *arbitrary* shared libraries: | |
| 367 | + | |
| 368 | +#dl dlmodule.c | |
| 369 | + | |
| 370 | + | |
| 371 | +# Modules that provide persistent dictionary-like semantics. You will | |
| 372 | +# probably want to arrange for at least one of them to be available on | |
| 373 | +# your machine, though none are defined by default because of library | |
| 374 | +# dependencies. The Python module anydbm.py provides an | |
| 375 | +# implementation independent wrapper for these; dumbdbm.py provides | |
| 376 | +# similar functionality (but slower of course) implemented in Python. | |
| 377 | + | |
| 378 | +# The standard Unix dbm module has been moved to Setup.config so that | |
| 379 | +# it will be compiled as a shared library by default. Compiling it as | |
| 380 | +# a built-in module causes conflicts with the pybsddb3 module since it | |
| 381 | +# creates a static dependency on an out-of-date version of db.so. | |
| 382 | +# | |
| 383 | +# First, look at Setup.config; configure may have set this for you. | |
| 384 | + | |
| 385 | +#dbm dbmmodule.c # dbm(3) may require -lndbm or similar | |
| 386 | + | |
| 387 | +# Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: | |
| 388 | +# | |
| 389 | +# First, look at Setup.config; configure may have set this for you. | |
| 390 | + | |
| 391 | +#gdbm gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm | |
| 392 | + | |
| 393 | + | |
| 394 | +# Sleepycat Berkeley DB interface. | |
| 395 | +# | |
| 396 | +# This requires the Sleepycat DB code, see http://www.sleepycat.com/ | |
| 397 | +# The earliest supported version of that library is 3.0, the latest | |
| 398 | +# supported version is 4.0 (4.1 is specifically not supported, as that | |
| 399 | +# changes the semantics of transactional databases). A list of available | |
| 400 | +# releases can be found at | |
| 401 | +# | |
| 402 | +# http://www.sleepycat.com/update/index.html | |
| 403 | +# | |
| 404 | +# Edit the variables DB and DBLIBVERto point to the db top directory | |
| 405 | +# and the subdirectory of PORT where you built it. | |
| 406 | +#DB=/usr/local/BerkeleyDB.4.0 | |
| 407 | +#DBLIBVER=4.0 | |
| 408 | +#DBINC=$(DB)/include | |
| 409 | +#DBLIB=$(DB)/lib | |
| 410 | +#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER) | |
| 411 | + | |
| 412 | +# Historical Berkeley DB 1.85 | |
| 413 | +# | |
| 414 | +# This module is deprecated; the 1.85 version of the Berkeley DB library has | |
| 415 | +# bugs that can cause data corruption. If you can, use later versions of the | |
| 416 | +# library instead, available from <http://www.sleepycat.com/>. | |
| 417 | + | |
| 418 | +#DB=/depot/sundry/src/berkeley-db/db.1.85 | |
| 419 | +#DBPORT=$(DB)/PORT/irix.5.3 | |
| 420 | +#bsddb185 bsddbmodule.c -I$(DBPORT)/include -I$(DBPORT) $(DBPORT)/libdb.a | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | +# Helper module for various ascii-encoders | |
| 425 | +#binascii binascii.c | |
| 426 | + | |
| 427 | +# Fred Drake's interface to the Python parser | |
| 428 | +#parser parsermodule.c | |
| 429 | + | |
| 430 | +# cStringIO and cPickle | |
| 431 | +#cStringIO cStringIO.c | |
| 432 | +#cPickle cPickle.c | |
| 433 | + | |
| 434 | + | |
| 435 | +# Lee Busby's SIGFPE modules. | |
| 436 | +# The library to link fpectl with is platform specific. | |
| 437 | +# Choose *one* of the options below for fpectl: | |
| 438 | + | |
| 439 | +# For SGI IRIX (tested on 5.3): | |
| 440 | +#fpectl fpectlmodule.c -lfpe | |
| 441 | + | |
| 442 | +# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2): | |
| 443 | +# (Without the compiler you don't have -lsunmath.) | |
| 444 | +#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm | |
| 445 | + | |
| 446 | +# For other systems: see instructions in fpectlmodule.c. | |
| 447 | +#fpectl fpectlmodule.c ... | |
| 448 | + | |
| 449 | +# Test module for fpectl. No extra libraries needed. | |
| 450 | +#fpetest fpetestmodule.c | |
| 451 | + | |
| 452 | +# Andrew Kuchling's zlib module. | |
| 453 | +# This require zlib 1.1.3 (or later). | |
| 454 | +# See http://www.gzip.org/zlib/ | |
| 455 | +#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz | |
| 456 | + | |
| 457 | +# Interface to the Expat XML parser | |
| 458 | +# | |
| 459 | +# Expat was written by James Clark and is now maintained by a group of | |
| 460 | +# developers on SourceForge; see www.libexpat.org for more | |
| 461 | +# information. The pyexpat module was written by Paul Prescod after a | |
| 462 | +# prototype by Jack Jansen. Source of Expat 1.95.2 is included in | |
| 463 | +# Modules/expat/. Usage of a system shared libexpat.so/expat.dll is | |
| 464 | +# not advised. | |
| 465 | +# | |
| 466 | +# More information on Expat can be found at www.libexpat.org. | |
| 467 | +# | |
| 468 | +#EXPAT_DIR=/usr/local/src/expat-1.95.2 | |
| 469 | +#pyexpat pyexpat.c -DHAVE_EXPAT_H -I$(EXPAT_DIR)/lib -L$(EXPAT_DIR) -lexpat | |
| 470 | + | |
| 471 | + | |
| 472 | +# Hye-Shik Chang's CJKCodecs | |
| 473 | + | |
| 474 | +# multibytecodec is required for all the other CJK codec modules | |
| 475 | +#_multibytecodec cjkcodecs/multibytecodec.c | |
| 476 | + | |
| 477 | +#_codecs_cn cjkcodecs/_codecs_cn.c | |
| 478 | +#_codecs_hk cjkcodecs/_codecs_hk.c | |
| 479 | +#_codecs_iso2022 cjkcodecs/_codecs_iso2022.c | |
| 480 | +#_codecs_jp cjkcodecs/_codecs_jp.c | |
| 481 | +#_codecs_kr cjkcodecs/_codecs_kr.c | |
| 482 | +#_codecs_tw cjkcodecs/_codecs_tw.c | |
| 483 | + | |
| 484 | +# Example -- included for reference only: | |
| 485 | +# xx xxmodule.c | |
| 486 | + | |
| 487 | +# Another example -- the 'xxsubtype' module shows C-level subtyping in action | |
| 488 | +xxsubtype xxsubtype.c | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +# This file is transmogrified into Setup.config by config.status. | |
| 2 | + | |
| 3 | +# The purpose of this file is to conditionally enable certain modules | |
| 4 | +# based on configure-time options. | |
| 5 | + | |
| 6 | +# Threading | |
| 7 | +#thread threadmodule.c | |
| 8 | + | |
| 9 | +# The signal module | |
| 10 | +signal signalmodule.c | |
| 11 | + | |
| 12 | +# The rest of the modules previously listed in this file are built | |
| 13 | +# by the setup.py script in Python 2.1 and later. | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +# This file is transmogrified into Setup.config by config.status. | |
| 2 | + | |
| 3 | +# The purpose of this file is to conditionally enable certain modules | |
| 4 | +# based on configure-time options. | |
| 5 | + | |
| 6 | +# Threading | |
| 7 | +@USE_THREAD_MODULE@thread threadmodule.c | |
| 8 | + | |
| 9 | +# The signal module | |
| 10 | +@USE_SIGNAL_MODULE@signal signalmodule.c | |
| 11 | + | |
| 12 | +# The rest of the modules previously listed in this file are built | |
| 13 | +# by the setup.py script in Python 2.1 and later. | |
| @@ -0,0 +1,487 @@ | ||
| 1 | +# -*- makefile -*- | |
| 2 | +# The file Setup is used by the makesetup script to construct the files | |
| 3 | +# Makefile and config.c, from Makefile.pre and config.c.in, | |
| 4 | +# respectively. The file Setup itself is initially copied from | |
| 5 | +# Setup.dist; once it exists it will not be overwritten, so you can edit | |
| 6 | +# Setup to your heart's content. Note that Makefile.pre is created | |
| 7 | +# from Makefile.pre.in by the toplevel configure script. | |
| 8 | + | |
| 9 | +# (VPATH notes: Setup and Makefile.pre are in the build directory, as | |
| 10 | +# are Makefile and config.c; the *.in and *.dist files are in the source | |
| 11 | +# directory.) | |
| 12 | + | |
| 13 | +# Each line in this file describes one or more optional modules. | |
| 14 | +# Modules enabled here will not be compiled by the setup.py script, | |
| 15 | +# so the file can be used to override setup.py's behavior. | |
| 16 | + | |
| 17 | +# Lines have the following structure: | |
| 18 | +# | |
| 19 | +# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...] | |
| 20 | +# | |
| 21 | +# <sourcefile> is anything ending in .c (.C, .cc, .c++ are C++ files) | |
| 22 | +# <cpparg> is anything starting with -I, -D, -U or -C | |
| 23 | +# <library> is anything ending in .a or beginning with -l or -L | |
| 24 | +# <module> is anything else but should be a valid Python | |
| 25 | +# identifier (letters, digits, underscores, beginning with non-digit) | |
| 26 | +# | |
| 27 | +# (As the makesetup script changes, it may recognize some other | |
| 28 | +# arguments as well, e.g. *.so and *.sl as libraries. See the big | |
| 29 | +# case statement in the makesetup script.) | |
| 30 | +# | |
| 31 | +# Lines can also have the form | |
| 32 | +# | |
| 33 | +# <name> = <value> | |
| 34 | +# | |
| 35 | +# which defines a Make variable definition inserted into Makefile.in | |
| 36 | +# | |
| 37 | +# Finally, if a line contains just the word "*shared*" (without the | |
| 38 | +# quotes but with the stars), then the following modules will not be | |
| 39 | +# built statically. The build process works like this: | |
| 40 | +# | |
| 41 | +# 1. Build all modules that are declared as static in Modules/Setup, | |
| 42 | +# combine them into libpythonxy.a, combine that into python. | |
| 43 | +# 2. Build all modules that are listed as shared in Modules/Setup. | |
| 44 | +# 3. Invoke setup.py. That builds all modules that | |
| 45 | +# a) are not builtin, and | |
| 46 | +# b) are not listed in Modules/Setup, and | |
| 47 | +# c) can be build on the target | |
| 48 | +# | |
| 49 | +# Therefore, modules declared to be shared will not be | |
| 50 | +# included in the config.c file, nor in the list of objects to be | |
| 51 | +# added to the library archive, and their linker options won't be | |
| 52 | +# added to the linker options. Rules to create their .o files and | |
| 53 | +# their shared libraries will still be added to the Makefile, and | |
| 54 | +# their names will be collected in the Make variable SHAREDMODS. This | |
| 55 | +# is used to build modules as shared libraries. (They can be | |
| 56 | +# installed using "make sharedinstall", which is implied by the | |
| 57 | +# toplevel "make install" target.) (For compatibility, | |
| 58 | +# *noconfig* has the same effect as *shared*.) | |
| 59 | +# | |
| 60 | +# In addition, *static* explicitly declares the following modules to | |
| 61 | +# be static. Lines containing "*static*" and "*shared*" may thus | |
| 62 | +# alternate throughout this file. | |
| 63 | + | |
| 64 | +# NOTE: As a standard policy, as many modules as can be supported by a | |
| 65 | +# platform should be present. The distribution comes with all modules | |
| 66 | +# enabled that are supported by most platforms and don't require you | |
| 67 | +# to ftp sources from elsewhere. | |
| 68 | + | |
| 69 | + | |
| 70 | +# Some special rules to define PYTHONPATH. | |
| 71 | +# Edit the definitions below to indicate which options you are using. | |
| 72 | +# Don't add any whitespace or comments! | |
| 73 | + | |
| 74 | +# Directories where library files get installed. | |
| 75 | +# DESTLIB is for Python modules; MACHDESTLIB for shared libraries. | |
| 76 | +DESTLIB=$(LIBDEST) | |
| 77 | +MACHDESTLIB=$(BINLIBDEST) | |
| 78 | + | |
| 79 | +# NOTE: all the paths are now relative to the prefix that is computed | |
| 80 | +# at run time! | |
| 81 | + | |
| 82 | +# Standard path -- don't edit. | |
| 83 | +# No leading colon since this is the first entry. | |
| 84 | +# Empty since this is now just the runtime prefix. | |
| 85 | +DESTPATH= | |
| 86 | + | |
| 87 | +# Site specific path components -- should begin with : if non-empty | |
| 88 | +SITEPATH= | |
| 89 | + | |
| 90 | +# Standard path components for test modules | |
| 91 | +TESTPATH= | |
| 92 | + | |
| 93 | +# Path components for machine- or system-dependent modules and shared libraries | |
| 94 | +MACHDEPPATH=:plat-$(MACHDEP) | |
| 95 | +EXTRAMACHDEPPATH= | |
| 96 | + | |
| 97 | +# Path component for the Tkinter-related modules | |
| 98 | +# The TKPATH variable is always enabled, to save you the effort. | |
| 99 | +TKPATH=:lib-tk | |
| 100 | + | |
| 101 | +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH) | |
| 102 | +PYTHONPATH=$(COREPYTHONPATH) | |
| 103 | + | |
| 104 | + | |
| 105 | +# The modules listed here can't be built as shared libraries for | |
| 106 | +# various reasons; therefore they are listed here instead of in the | |
| 107 | +# normal order. | |
| 108 | + | |
| 109 | +# This only contains the minimal set of modules required to run the | |
| 110 | +# setup.py script in the root of the Python source tree. | |
| 111 | + | |
| 112 | +posix posixmodule.c # posix (UNIX) system calls | |
| 113 | +errno errnomodule.c # posix (UNIX) errno values | |
| 114 | +pwd pwdmodule.c # this is needed to find out the user's home dir | |
| 115 | + # if $HOME is not set | |
| 116 | +_sre _sre.c # Fredrik Lundh's new regular expressions | |
| 117 | +_codecs _codecsmodule.c # access to the builtin codecs and codec registry | |
| 118 | + | |
| 119 | +# The zipimport module is always imported at startup. Having it as a | |
| 120 | +# builtin module avoids some bootstrapping problems and reduces overhead. | |
| 121 | +zipimport zipimport.c | |
| 122 | + | |
| 123 | +# The rest of the modules listed in this file are all commented out by | |
| 124 | +# default. Usually they can be detected and built as dynamically | |
| 125 | +# loaded modules by the new setup.py script added in Python 2.1. If | |
| 126 | +# you're on a platform that doesn't support dynamic loading, want to | |
| 127 | +# compile modules statically into the Python binary, or need to | |
| 128 | +# specify some odd set of compiler switches, you can uncomment the | |
| 129 | +# appropriate lines below. | |
| 130 | + | |
| 131 | +# ====================================================================== | |
| 132 | + | |
| 133 | +# The Python symtable module depends on .h files that setup.py doesn't track | |
| 134 | +_symtable symtablemodule.c | |
| 135 | + | |
| 136 | +# The SGI specific GL module: | |
| 137 | + | |
| 138 | +GLHACK=-Dclear=__GLclear | |
| 139 | +#gl glmodule.c cgensupport.c -I$(srcdir) $(GLHACK) -lgl -lX11 | |
| 140 | + | |
| 141 | +# Pure module. Cannot be linked dynamically. | |
| 142 | +# -DWITH_QUANTIFY, -DWITH_PURIFY, or -DWITH_ALL_PURE | |
| 143 | +#WHICH_PURE_PRODUCTS=-DWITH_ALL_PURE | |
| 144 | +#PURE_INCLS=-I/usr/local/include | |
| 145 | +#PURE_STUBLIBS=-L/usr/local/lib -lpurify_stubs -lquantify_stubs | |
| 146 | +#pure puremodule.c $(WHICH_PURE_PRODUCTS) $(PURE_INCLS) $(PURE_STUBLIBS) | |
| 147 | + | |
| 148 | +# Uncommenting the following line tells makesetup that all following | |
| 149 | +# modules are to be built as shared libraries (see above for more | |
| 150 | +# detail; also note that *static* reverses this effect): | |
| 151 | + | |
| 152 | +#*shared* | |
| 153 | + | |
| 154 | +# GNU readline. Unlike previous Python incarnations, GNU readline is | |
| 155 | +# now incorporated in an optional module, configured in the Setup file | |
| 156 | +# instead of by a configure script switch. You may have to insert a | |
| 157 | +# -L option pointing to the directory where libreadline.* lives, | |
| 158 | +# and you may have to change -ltermcap to -ltermlib or perhaps remove | |
| 159 | +# it, depending on your system -- see the GNU readline instructions. | |
| 160 | +# It's okay for this to be a shared library, too. | |
| 161 | + | |
| 162 | +#readline readline.c -lreadline -ltermcap | |
| 163 | + | |
| 164 | + | |
| 165 | +# Modules that should always be present (non UNIX dependent): | |
| 166 | + | |
| 167 | +#array arraymodule.c # array objects | |
| 168 | +#cmath cmathmodule.c # -lm # complex math library functions | |
| 169 | +#math mathmodule.c # -lm # math library functions, e.g. sin() | |
| 170 | +#_struct _struct.c # binary structure packing/unpacking | |
| 171 | +#time timemodule.c # -lm # time operations and variables | |
| 172 | +#operator operator.c # operator.add() and similar goodies | |
| 173 | +#_weakref _weakref.c # basic weak reference support | |
| 174 | +#_testcapi _testcapimodule.c # Python C API test module | |
| 175 | +#_random _randommodule.c # Random number generator | |
| 176 | +#collections collectionsmodule.c # Container types | |
| 177 | +#itertools itertoolsmodule.c # Functions creating iterators for efficient looping | |
| 178 | +#strop stropmodule.c # String manipulations | |
| 179 | + | |
| 180 | +#unicodedata unicodedata.c # static Unicode character database | |
| 181 | + | |
| 182 | +# access to ISO C locale support | |
| 183 | +#_locale _localemodule.c # -lintl | |
| 184 | + | |
| 185 | + | |
| 186 | +# Modules with some UNIX dependencies -- on by default: | |
| 187 | +# (If you have a really backward UNIX, select and socket may not be | |
| 188 | +# supported...) | |
| 189 | + | |
| 190 | +#fcntl fcntlmodule.c # fcntl(2) and ioctl(2) | |
| 191 | +#spwd spwdmodule.c # spwd(3) | |
| 192 | +#grp grpmodule.c # grp(3) | |
| 193 | +#select selectmodule.c # select(2); not on ancient System V | |
| 194 | + | |
| 195 | +# Memory-mapped files (also works on Win32). | |
| 196 | +#mmap mmapmodule.c | |
| 197 | + | |
| 198 | +# CSV file helper | |
| 199 | +#_csv _csv.c | |
| 200 | + | |
| 201 | +# Socket module helper for socket(2) | |
| 202 | +#_socket socketmodule.c | |
| 203 | + | |
| 204 | +# Socket module helper for SSL support; you must comment out the other | |
| 205 | +# socket line above, and possibly edit the SSL variable: | |
| 206 | +#SSL=/usr/local/ssl | |
| 207 | +#_ssl _ssl.c \ | |
| 208 | +# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \ | |
| 209 | +# -L$(SSL)/lib -lssl -lcrypto | |
| 210 | + | |
| 211 | +# The crypt module is now disabled by default because it breaks builds | |
| 212 | +# on many systems (where -lcrypt is needed), e.g. Linux (I believe). | |
| 213 | +# | |
| 214 | +# First, look at Setup.config; configure may have set this for you. | |
| 215 | + | |
| 216 | +#crypt cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems | |
| 217 | + | |
| 218 | + | |
| 219 | +# Some more UNIX dependent modules -- off by default, since these | |
| 220 | +# are not supported by all UNIX systems: | |
| 221 | + | |
| 222 | +#nis nismodule.c -lnsl # Sun yellow pages -- not everywhere | |
| 223 | +#termios termios.c # Steen Lumholt's termios module | |
| 224 | +#resource resource.c # Jeremy Hylton's rlimit interface | |
| 225 | + | |
| 226 | + | |
| 227 | +# Multimedia modules -- off by default. | |
| 228 | +# These don't work for 64-bit platforms!!! | |
| 229 | +# #993173 says audioop works on 64-bit platforms, though. | |
| 230 | +# These represent audio samples or images as strings: | |
| 231 | + | |
| 232 | +#audioop audioop.c # Operations on audio samples | |
| 233 | +#imageop imageop.c # Operations on images | |
| 234 | +#rgbimg rgbimgmodule.c # Read SGI RGB image files (but coded portably) | |
| 235 | + | |
| 236 | + | |
| 237 | +# Note that the _md5 and _sha modules are normally only built if the | |
| 238 | +# system does not have the OpenSSL libs containing an optimized version. | |
| 239 | + | |
| 240 | +# The _md5 module implements the RSA Data Security, Inc. MD5 | |
| 241 | +# Message-Digest Algorithm, described in RFC 1321. The necessary files | |
| 242 | +# md5.c and md5.h are included here. | |
| 243 | + | |
| 244 | +#_md5 md5module.c md5.c | |
| 245 | + | |
| 246 | + | |
| 247 | +# The _sha module implements the SHA checksum algorithm. | |
| 248 | +# (NIST's Secure Hash Algorithm.) | |
| 249 | +#_sha shamodule.c | |
| 250 | + | |
| 251 | + | |
| 252 | +# SGI IRIX specific modules -- off by default. | |
| 253 | + | |
| 254 | +# These module work on any SGI machine: | |
| 255 | + | |
| 256 | +# *** gl must be enabled higher up in this file *** | |
| 257 | +#fm fmmodule.c $(GLHACK) -lfm -lgl # Font Manager | |
| 258 | +#sgi sgimodule.c # sgi.nap() and a few more | |
| 259 | + | |
| 260 | +# This module requires the header file | |
| 261 | +# /usr/people/4Dgifts/iristools/include/izoom.h: | |
| 262 | +#imgfile imgfile.c -limage -lgutil -lgl -lm # Image Processing Utilities | |
| 263 | + | |
| 264 | + | |
| 265 | +# These modules require the Multimedia Development Option (I think): | |
| 266 | + | |
| 267 | +#al almodule.c -laudio # Audio Library | |
| 268 | +#cd cdmodule.c -lcdaudio -lds -lmediad # CD Audio Library | |
| 269 | +#cl clmodule.c -lcl -lawareaudio # Compression Library | |
| 270 | +#sv svmodule.c yuvconvert.c -lsvideo -lXext -lX11 # Starter Video | |
| 271 | + | |
| 272 | + | |
| 273 | +# The FORMS library, by Mark Overmars, implements user interface | |
| 274 | +# components such as dialogs and buttons using SGI's GL and FM | |
| 275 | +# libraries. You must ftp the FORMS library separately from | |
| 276 | +# ftp://ftp.cs.ruu.nl/pub/SGI/FORMS. It was tested with FORMS 2.2a. | |
| 277 | +# NOTE: if you want to be able to use FORMS and curses simultaneously | |
| 278 | +# (or both link them statically into the same binary), you must | |
| 279 | +# compile all of FORMS with the cc option "-Dclear=__GLclear". | |
| 280 | + | |
| 281 | +# The FORMS variable must point to the FORMS subdirectory of the forms | |
| 282 | +# toplevel directory: | |
| 283 | + | |
| 284 | +#FORMS=/ufs/guido/src/forms/FORMS | |
| 285 | +#fl flmodule.c -I$(FORMS) $(GLHACK) $(FORMS)/libforms.a -lfm -lgl | |
| 286 | + | |
| 287 | + | |
| 288 | +# SunOS specific modules -- off by default: | |
| 289 | + | |
| 290 | +#sunaudiodev sunaudiodev.c | |
| 291 | + | |
| 292 | + | |
| 293 | +# A Linux specific module -- off by default; this may also work on | |
| 294 | +# some *BSDs. | |
| 295 | + | |
| 296 | +#linuxaudiodev linuxaudiodev.c | |
| 297 | + | |
| 298 | + | |
| 299 | +# George Neville-Neil's timing module: | |
| 300 | + | |
| 301 | +#timing timingmodule.c | |
| 302 | + | |
| 303 | + | |
| 304 | +# The _tkinter module. | |
| 305 | +# | |
| 306 | +# The command for _tkinter is long and site specific. Please | |
| 307 | +# uncomment and/or edit those parts as indicated. If you don't have a | |
| 308 | +# specific extension (e.g. Tix or BLT), leave the corresponding line | |
| 309 | +# commented out. (Leave the trailing backslashes in! If you | |
| 310 | +# experience strange errors, you may want to join all uncommented | |
| 311 | +# lines and remove the backslashes -- the backslash interpretation is | |
| 312 | +# done by the shell's "read" command and it may not be implemented on | |
| 313 | +# every system. | |
| 314 | + | |
| 315 | +# *** Always uncomment this (leave the leading underscore in!): | |
| 316 | +# _tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \ | |
| 317 | +# *** Uncomment and edit to reflect where your Tcl/Tk libraries are: | |
| 318 | +# -L/usr/local/lib \ | |
| 319 | +# *** Uncomment and edit to reflect where your Tcl/Tk headers are: | |
| 320 | +# -I/usr/local/include \ | |
| 321 | +# *** Uncomment and edit to reflect where your X11 header files are: | |
| 322 | +# -I/usr/X11R6/include \ | |
| 323 | +# *** Or uncomment this for Solaris: | |
| 324 | +# -I/usr/openwin/include \ | |
| 325 | +# *** Uncomment and edit for Tix extension only: | |
| 326 | +# -DWITH_TIX -ltix8.1.8.2 \ | |
| 327 | +# *** Uncomment and edit for BLT extension only: | |
| 328 | +# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \ | |
| 329 | +# *** Uncomment and edit for PIL (TkImaging) extension only: | |
| 330 | +# (See http://www.pythonware.com/products/pil/ for more info) | |
| 331 | +# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \ | |
| 332 | +# *** Uncomment and edit for TOGL extension only: | |
| 333 | +# -DWITH_TOGL togl.c \ | |
| 334 | +# *** Uncomment and edit to reflect your Tcl/Tk versions: | |
| 335 | +# -ltk8.2 -ltcl8.2 \ | |
| 336 | +# *** Uncomment and edit to reflect where your X11 libraries are: | |
| 337 | +# -L/usr/X11R6/lib \ | |
| 338 | +# *** Or uncomment this for Solaris: | |
| 339 | +# -L/usr/openwin/lib \ | |
| 340 | +# *** Uncomment these for TOGL extension only: | |
| 341 | +# -lGL -lGLU -lXext -lXmu \ | |
| 342 | +# *** Uncomment for AIX: | |
| 343 | +# -lld \ | |
| 344 | +# *** Always uncomment this; X11 libraries to link with: | |
| 345 | +# -lX11 | |
| 346 | + | |
| 347 | +# Lance Ellinghaus's syslog module | |
| 348 | +#syslog syslogmodule.c # syslog daemon interface | |
| 349 | + | |
| 350 | + | |
| 351 | +# Curses support, requring the System V version of curses, often | |
| 352 | +# provided by the ncurses library. e.g. on Linux, link with -lncurses | |
| 353 | +# instead of -lcurses). | |
| 354 | +# | |
| 355 | +# First, look at Setup.config; configure may have set this for you. | |
| 356 | + | |
| 357 | +#_curses _cursesmodule.c -lcurses -ltermcap | |
| 358 | +# Wrapper for the panel library that's part of ncurses and SYSV curses. | |
| 359 | +#_curses_panel _curses_panel.c -lpanel -lncurses | |
| 360 | + | |
| 361 | + | |
| 362 | +# Generic (SunOS / SVR4) dynamic loading module. | |
| 363 | +# This is not needed for dynamic loading of Python modules -- | |
| 364 | +# it is a highly experimental and dangerous device for calling | |
| 365 | +# *arbitrary* C functions in *arbitrary* shared libraries: | |
| 366 | + | |
| 367 | +#dl dlmodule.c | |
| 368 | + | |
| 369 | + | |
| 370 | +# Modules that provide persistent dictionary-like semantics. You will | |
| 371 | +# probably want to arrange for at least one of them to be available on | |
| 372 | +# your machine, though none are defined by default because of library | |
| 373 | +# dependencies. The Python module anydbm.py provides an | |
| 374 | +# implementation independent wrapper for these; dumbdbm.py provides | |
| 375 | +# similar functionality (but slower of course) implemented in Python. | |
| 376 | + | |
| 377 | +# The standard Unix dbm module has been moved to Setup.config so that | |
| 378 | +# it will be compiled as a shared library by default. Compiling it as | |
| 379 | +# a built-in module causes conflicts with the pybsddb3 module since it | |
| 380 | +# creates a static dependency on an out-of-date version of db.so. | |
| 381 | +# | |
| 382 | +# First, look at Setup.config; configure may have set this for you. | |
| 383 | + | |
| 384 | +#dbm dbmmodule.c # dbm(3) may require -lndbm or similar | |
| 385 | + | |
| 386 | +# Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: | |
| 387 | +# | |
| 388 | +# First, look at Setup.config; configure may have set this for you. | |
| 389 | + | |
| 390 | +#gdbm gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm | |
| 391 | + | |
| 392 | + | |
| 393 | +# Sleepycat Berkeley DB interface. | |
| 394 | +# | |
| 395 | +# This requires the Sleepycat DB code, see http://www.sleepycat.com/ | |
| 396 | +# The earliest supported version of that library is 3.0, the latest | |
| 397 | +# supported version is 4.0 (4.1 is specifically not supported, as that | |
| 398 | +# changes the semantics of transactional databases). A list of available | |
| 399 | +# releases can be found at | |
| 400 | +# | |
| 401 | +# http://www.sleepycat.com/update/index.html | |
| 402 | +# | |
| 403 | +# Edit the variables DB and DBLIBVERto point to the db top directory | |
| 404 | +# and the subdirectory of PORT where you built it. | |
| 405 | +#DB=/usr/local/BerkeleyDB.4.0 | |
| 406 | +#DBLIBVER=4.0 | |
| 407 | +#DBINC=$(DB)/include | |
| 408 | +#DBLIB=$(DB)/lib | |
| 409 | +#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER) | |
| 410 | + | |
| 411 | +# Historical Berkeley DB 1.85 | |
| 412 | +# | |
| 413 | +# This module is deprecated; the 1.85 version of the Berkeley DB library has | |
| 414 | +# bugs that can cause data corruption. If you can, use later versions of the | |
| 415 | +# library instead, available from <http://www.sleepycat.com/>. | |
| 416 | + | |
| 417 | +#DB=/depot/sundry/src/berkeley-db/db.1.85 | |
| 418 | +#DBPORT=$(DB)/PORT/irix.5.3 | |
| 419 | +#bsddb185 bsddbmodule.c -I$(DBPORT)/include -I$(DBPORT) $(DBPORT)/libdb.a | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | +# Helper module for various ascii-encoders | |
| 424 | +#binascii binascii.c | |
| 425 | + | |
| 426 | +# Fred Drake's interface to the Python parser | |
| 427 | +#parser parsermodule.c | |
| 428 | + | |
| 429 | +# cStringIO and cPickle | |
| 430 | +#cStringIO cStringIO.c | |
| 431 | +#cPickle cPickle.c | |
| 432 | + | |
| 433 | + | |
| 434 | +# Lee Busby's SIGFPE modules. | |
| 435 | +# The library to link fpectl with is platform specific. | |
| 436 | +# Choose *one* of the options below for fpectl: | |
| 437 | + | |
| 438 | +# For SGI IRIX (tested on 5.3): | |
| 439 | +#fpectl fpectlmodule.c -lfpe | |
| 440 | + | |
| 441 | +# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2): | |
| 442 | +# (Without the compiler you don't have -lsunmath.) | |
| 443 | +#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm | |
| 444 | + | |
| 445 | +# For other systems: see instructions in fpectlmodule.c. | |
| 446 | +#fpectl fpectlmodule.c ... | |
| 447 | + | |
| 448 | +# Test module for fpectl. No extra libraries needed. | |
| 449 | +#fpetest fpetestmodule.c | |
| 450 | + | |
| 451 | +# Andrew Kuchling's zlib module. | |
| 452 | +# This require zlib 1.1.3 (or later). | |
| 453 | +# See http://www.gzip.org/zlib/ | |
| 454 | +#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz | |
| 455 | + | |
| 456 | +# Interface to the Expat XML parser | |
| 457 | +# | |
| 458 | +# Expat was written by James Clark and is now maintained by a group of | |
| 459 | +# developers on SourceForge; see www.libexpat.org for more | |
| 460 | +# information. The pyexpat module was written by Paul Prescod after a | |
| 461 | +# prototype by Jack Jansen. Source of Expat 1.95.2 is included in | |
| 462 | +# Modules/expat/. Usage of a system shared libexpat.so/expat.dll is | |
| 463 | +# not advised. | |
| 464 | +# | |
| 465 | +# More information on Expat can be found at www.libexpat.org. | |
| 466 | +# | |
| 467 | +#EXPAT_DIR=/usr/local/src/expat-1.95.2 | |
| 468 | +#pyexpat pyexpat.c -DHAVE_EXPAT_H -I$(EXPAT_DIR)/lib -L$(EXPAT_DIR) -lexpat | |
| 469 | + | |
| 470 | + | |
| 471 | +# Hye-Shik Chang's CJKCodecs | |
| 472 | + | |
| 473 | +# multibytecodec is required for all the other CJK codec modules | |
| 474 | +#_multibytecodec cjkcodecs/multibytecodec.c | |
| 475 | + | |
| 476 | +#_codecs_cn cjkcodecs/_codecs_cn.c | |
| 477 | +#_codecs_hk cjkcodecs/_codecs_hk.c | |
| 478 | +#_codecs_iso2022 cjkcodecs/_codecs_iso2022.c | |
| 479 | +#_codecs_jp cjkcodecs/_codecs_jp.c | |
| 480 | +#_codecs_kr cjkcodecs/_codecs_kr.c | |
| 481 | +#_codecs_tw cjkcodecs/_codecs_tw.c | |
| 482 | + | |
| 483 | +# Example -- included for reference only: | |
| 484 | +# xx xxmodule.c | |
| 485 | + | |
| 486 | +# Another example -- the 'xxsubtype' module shows C-level subtyping in action | |
| 487 | +xxsubtype xxsubtype.c | |
| @@ -0,0 +1 @@ | ||
| 1 | +# Edit this file for local setup changes | |
| @@ -0,0 +1,235 @@ | ||
| 1 | +/* Bisection algorithms. Drop in replacement for bisect.py | |
| 2 | + | |
| 3 | +Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru). | |
| 4 | +*/ | |
| 5 | + | |
| 6 | +#include "Python.h" | |
| 7 | + | |
| 8 | +static int | |
| 9 | +internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi) | |
| 10 | +{ | |
| 11 | + PyObject *litem; | |
| 12 | + Py_ssize_t mid, res; | |
| 13 | + | |
| 14 | + if (hi == -1) { | |
| 15 | + hi = PySequence_Size(list); | |
| 16 | + if (hi < 0) | |
| 17 | + return -1; | |
| 18 | + } | |
| 19 | + while (lo < hi) { | |
| 20 | + mid = (lo + hi) / 2; | |
| 21 | + litem = PySequence_GetItem(list, mid); | |
| 22 | + if (litem == NULL) | |
| 23 | + return -1; | |
| 24 | + res = PyObject_RichCompareBool(item, litem, Py_LT); | |
| 25 | + Py_DECREF(litem); | |
| 26 | + if (res < 0) | |
| 27 | + return -1; | |
| 28 | + if (res) | |
| 29 | + hi = mid; | |
| 30 | + else | |
| 31 | + lo = mid + 1; | |
| 32 | + } | |
| 33 | + return lo; | |
| 34 | +} | |
| 35 | + | |
| 36 | +static PyObject * | |
| 37 | +bisect_right(PyObject *self, PyObject *args, PyObject *kw) | |
| 38 | +{ | |
| 39 | + PyObject *list, *item; | |
| 40 | + int lo = 0; | |
| 41 | + int hi = -1; | |
| 42 | + int index; | |
| 43 | + static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | |
| 44 | + | |
| 45 | + if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|ii:bisect_right", | |
| 46 | + keywords, &list, &item, &lo, &hi)) | |
| 47 | + return NULL; | |
| 48 | + index = internal_bisect_right(list, item, lo, hi); | |
| 49 | + if (index < 0) | |
| 50 | + return NULL; | |
| 51 | + return PyInt_FromLong(index); | |
| 52 | +} | |
| 53 | + | |
| 54 | +PyDoc_STRVAR(bisect_right_doc, | |
| 55 | +"bisect_right(a, x[, lo[, hi]]) -> index\n\ | |
| 56 | +\n\ | |
| 57 | +Return the index where to insert item x in list a, assuming a is sorted.\n\ | |
| 58 | +\n\ | |
| 59 | +The return value i is such that all e in a[:i] have e <= x, and all e in\n\ | |
| 60 | +a[i:] have e > x. So if x already appears in the list, i points just\n\ | |
| 61 | +beyond the rightmost x already there\n\ | |
| 62 | +\n\ | |
| 63 | +Optional args lo (default 0) and hi (default len(a)) bound the\n\ | |
| 64 | +slice of a to be searched.\n"); | |
| 65 | + | |
| 66 | +static PyObject * | |
| 67 | +insort_right(PyObject *self, PyObject *args, PyObject *kw) | |
| 68 | +{ | |
| 69 | + PyObject *list, *item, *result; | |
| 70 | + int lo = 0; | |
| 71 | + int hi = -1; | |
| 72 | + int index; | |
| 73 | + static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | |
| 74 | + | |
| 75 | + if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|ii:insort_right", | |
| 76 | + keywords, &list, &item, &lo, &hi)) | |
| 77 | + return NULL; | |
| 78 | + index = internal_bisect_right(list, item, lo, hi); | |
| 79 | + if (index < 0) | |
| 80 | + return NULL; | |
| 81 | + if (PyList_Check(list)) { | |
| 82 | + if (PyList_Insert(list, index, item) < 0) | |
| 83 | + return NULL; | |
| 84 | + } else { | |
| 85 | + result = PyObject_CallMethod(list, "insert", "iO", | |
| 86 | + index, item); | |
| 87 | + if (result == NULL) | |
| 88 | + return NULL; | |
| 89 | + Py_DECREF(result); | |
| 90 | + } | |
| 91 | + | |
| 92 | + Py_RETURN_NONE; | |
| 93 | +} | |
| 94 | + | |
| 95 | +PyDoc_STRVAR(insort_right_doc, | |
| 96 | +"insort_right(a, x[, lo[, hi]])\n\ | |
| 97 | +\n\ | |
| 98 | +Insert item x in list a, and keep it sorted assuming a is sorted.\n\ | |
| 99 | +\n\ | |
| 100 | +If x is already in a, insert it to the right of the rightmost x.\n\ | |
| 101 | +\n\ | |
| 102 | +Optional args lo (default 0) and hi (default len(a)) bound the\n\ | |
| 103 | +slice of a to be searched.\n"); | |
| 104 | + | |
| 105 | +static int | |
| 106 | +internal_bisect_left(PyObject *list, PyObject *item, int lo, int hi) | |
| 107 | +{ | |
| 108 | + PyObject *litem; | |
| 109 | + int mid, res; | |
| 110 | + | |
| 111 | + if (hi == -1) { | |
| 112 | + hi = PySequence_Size(list); | |
| 113 | + if (hi < 0) | |
| 114 | + return -1; | |
| 115 | + } | |
| 116 | + while (lo < hi) { | |
| 117 | + mid = (lo + hi) / 2; | |
| 118 | + litem = PySequence_GetItem(list, mid); | |
| 119 | + if (litem == NULL) | |
| 120 | + return -1; | |
| 121 | + res = PyObject_RichCompareBool(litem, item, Py_LT); | |
| 122 | + Py_DECREF(litem); | |
| 123 | + if (res < 0) | |
| 124 | + return -1; | |
| 125 | + if (res) | |
| 126 | + lo = mid + 1; | |
| 127 | + else | |
| 128 | + hi = mid; | |
| 129 | + } | |
| 130 | + return lo; | |
| 131 | +} | |
| 132 | + | |
| 133 | +static PyObject * | |
| 134 | +bisect_left(PyObject *self, PyObject *args, PyObject *kw) | |
| 135 | +{ | |
| 136 | + PyObject *list, *item; | |
| 137 | + int lo = 0; | |
| 138 | + int hi = -1; | |
| 139 | + int index; | |
| 140 | + static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | |
| 141 | + | |
| 142 | + if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|ii:bisect_left", | |
| 143 | + keywords, &list, &item, &lo, &hi)) | |
| 144 | + return NULL; | |
| 145 | + index = internal_bisect_left(list, item, lo, hi); | |
| 146 | + if (index < 0) | |
| 147 | + return NULL; | |
| 148 | + return PyInt_FromLong(index); | |
| 149 | +} | |
| 150 | + | |
| 151 | +PyDoc_STRVAR(bisect_left_doc, | |
| 152 | +"bisect_left(a, x[, lo[, hi]]) -> index\n\ | |
| 153 | +\n\ | |
| 154 | +Return the index where to insert item x in list a, assuming a is sorted.\n\ | |
| 155 | +\n\ | |
| 156 | +The return value i is such that all e in a[:i] have e < x, and all e in\n\ | |
| 157 | +a[i:] have e >= x. So if x already appears in the list, i points just\n\ | |
| 158 | +before the leftmost x already there.\n\ | |
| 159 | +\n\ | |
| 160 | +Optional args lo (default 0) and hi (default len(a)) bound the\n\ | |
| 161 | +slice of a to be searched.\n"); | |
| 162 | + | |
| 163 | +static PyObject * | |
| 164 | +insort_left(PyObject *self, PyObject *args, PyObject *kw) | |
| 165 | +{ | |
| 166 | + PyObject *list, *item, *result; | |
| 167 | + int lo = 0; | |
| 168 | + int hi = -1; | |
| 169 | + int index; | |
| 170 | + static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | |
| 171 | + | |
| 172 | + if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|ii:insort_left", | |
| 173 | + keywords, &list, &item, &lo, &hi)) | |
| 174 | + return NULL; | |
| 175 | + index = internal_bisect_left(list, item, lo, hi); | |
| 176 | + if (index < 0) | |
| 177 | + return NULL; | |
| 178 | + if (PyList_Check(list)) { | |
| 179 | + if (PyList_Insert(list, index, item) < 0) | |
| 180 | + return NULL; | |
| 181 | + } else { | |
| 182 | + result = PyObject_CallMethod(list, "insert", "iO", | |
| 183 | + index, item); | |
| 184 | + if (result == NULL) | |
| 185 | + return NULL; | |
| 186 | + Py_DECREF(result); | |
| 187 | + } | |
| 188 | + | |
| 189 | + Py_RETURN_NONE; | |
| 190 | +} | |
| 191 | + | |
| 192 | +PyDoc_STRVAR(insort_left_doc, | |
| 193 | +"insort_left(a, x[, lo[, hi]])\n\ | |
| 194 | +\n\ | |
| 195 | +Insert item x in list a, and keep it sorted assuming a is sorted.\n\ | |
| 196 | +\n\ | |
| 197 | +If x is already in a, insert it to the left of the leftmost x.\n\ | |
| 198 | +\n\ | |
| 199 | +Optional args lo (default 0) and hi (default len(a)) bound the\n\ | |
| 200 | +slice of a to be searched.\n"); | |
| 201 | + | |
| 202 | +PyDoc_STRVAR(bisect_doc, "Alias for bisect_right().\n"); | |
| 203 | +PyDoc_STRVAR(insort_doc, "Alias for insort_right().\n"); | |
| 204 | + | |
| 205 | +static PyMethodDef bisect_methods[] = { | |
| 206 | + {"bisect_right", (PyCFunction)bisect_right, | |
| 207 | + METH_VARARGS|METH_KEYWORDS, bisect_right_doc}, | |
| 208 | + {"bisect", (PyCFunction)bisect_right, | |
| 209 | + METH_VARARGS|METH_KEYWORDS, bisect_doc}, | |
| 210 | + {"insort_right", (PyCFunction)insort_right, | |
| 211 | + METH_VARARGS|METH_KEYWORDS, insort_right_doc}, | |
| 212 | + {"insort", (PyCFunction)insort_right, | |
| 213 | + METH_VARARGS|METH_KEYWORDS, insort_doc}, | |
| 214 | + {"bisect_left", (PyCFunction)bisect_left, | |
| 215 | + METH_VARARGS|METH_KEYWORDS, bisect_left_doc}, | |
| 216 | + {"insort_left", (PyCFunction)insort_left, | |
| 217 | + METH_VARARGS|METH_KEYWORDS, insort_left_doc}, | |
| 218 | + {NULL, NULL} /* sentinel */ | |
| 219 | +}; | |
| 220 | + | |
| 221 | +PyDoc_STRVAR(module_doc, | |
| 222 | +"Bisection algorithms.\n\ | |
| 223 | +\n\ | |
| 224 | +This module provides support for maintaining a list in sorted order without\n\ | |
| 225 | +having to sort the list after each insertion. For long lists of items with\n\ | |
| 226 | +expensive comparison operations, this can be an improvement over the more\n\ | |
| 227 | +common approach.\n"); | |
| 228 | + | |
| 229 | +PyMODINIT_FUNC | |
| 230 | +init_bisect(void) | |
| 231 | +{ | |
| 232 | + PyObject *m; | |
| 233 | + | |
| 234 | + m = Py_InitModule3("_bisect", bisect_methods, module_doc); | |
| 235 | +} | |
| @@ -0,0 +1,6047 @@ | ||
| 1 | +/*---------------------------------------------------------------------- | |
| 2 | + Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA | |
| 3 | + and Andrew Kuchling. All rights reserved. | |
| 4 | + | |
| 5 | + Redistribution and use in source and binary forms, with or without | |
| 6 | + modification, are permitted provided that the following conditions are | |
| 7 | + met: | |
| 8 | + | |
| 9 | + o Redistributions of source code must retain the above copyright | |
| 10 | + notice, this list of conditions, and the disclaimer that follows. | |
| 11 | + | |
| 12 | + o Redistributions in binary form must reproduce the above copyright | |
| 13 | + notice, this list of conditions, and the following disclaimer in | |
| 14 | + the documentation and/or other materials provided with the | |
| 15 | + distribution. | |
| 16 | + | |
| 17 | + o Neither the name of Digital Creations nor the names of its | |
| 18 | + contributors may be used to endorse or promote products derived | |
| 19 | + from this software without specific prior written permission. | |
| 20 | + | |
| 21 | + THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS | |
| 22 | + IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
| 23 | + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
| 24 | + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL | |
| 25 | + CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 26 | + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 27 | + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |
| 28 | + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 29 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
| 30 | + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
| 31 | + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
| 32 | + DAMAGE. | |
| 33 | +------------------------------------------------------------------------*/ | |
| 34 | + | |
| 35 | + | |
| 36 | +/* | |
| 37 | + * Handwritten code to wrap version 3.x of the Berkeley DB library, | |
| 38 | + * written to replace a SWIG-generated file. It has since been updated | |
| 39 | + * to compile with BerkeleyDB versions 3.2 through 4.2. | |
| 40 | + * | |
| 41 | + * This module was started by Andrew Kuchling to remove the dependency | |
| 42 | + * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who | |
| 43 | + * based his work on a similar package by Robin Dunn <robin@alldunn.com> | |
| 44 | + * which wrapped Berkeley DB 2.7.x. | |
| 45 | + * | |
| 46 | + * Development of this module then returned full circle back to Robin Dunn | |
| 47 | + * who worked on behalf of Digital Creations to complete the wrapping of | |
| 48 | + * the DB 3.x API and to build a solid unit test suite. Robin has | |
| 49 | + * since gone onto other projects (wxPython). | |
| 50 | + * | |
| 51 | + * Gregory P. Smith <greg@electricrain.com> is once again the maintainer. | |
| 52 | + * | |
| 53 | + * Use the pybsddb-users@lists.sf.net mailing list for all questions. | |
| 54 | + * Things can change faster than the header of this file is updated. This | |
| 55 | + * file is shared with the PyBSDDB project at SourceForge: | |
| 56 | + * | |
| 57 | + * http://pybsddb.sf.net | |
| 58 | + * | |
| 59 | + * This file should remain backward compatible with Python 2.1, but see PEP | |
| 60 | + * 291 for the most current backward compatibility requirements: | |
| 61 | + * | |
| 62 | + * http://www.python.org/peps/pep-0291.html | |
| 63 | + * | |
| 64 | + * This module contains 6 types: | |
| 65 | + * | |
| 66 | + * DB (Database) | |
| 67 | + * DBCursor (Database Cursor) | |
| 68 | + * DBEnv (database environment) | |
| 69 | + * DBTxn (An explicit database transaction) | |
| 70 | + * DBLock (A lock handle) | |
| 71 | + * DBSequence (Sequence) | |
| 72 | + * | |
| 73 | + */ | |
| 74 | + | |
| 75 | +/* --------------------------------------------------------------------- */ | |
| 76 | + | |
| 77 | +/* | |
| 78 | + * Portions of this module, associated unit tests and build scripts are the | |
| 79 | + * result of a contract with The Written Word (http://thewrittenword.com/) | |
| 80 | + * Many thanks go out to them for causing me to raise the bar on quality and | |
| 81 | + * functionality, resulting in a better bsddb3 package for all of us to use. | |
| 82 | + * | |
| 83 | + * --Robin | |
| 84 | + */ | |
| 85 | + | |
| 86 | +/* --------------------------------------------------------------------- */ | |
| 87 | + | |
| 88 | +#include <stddef.h> /* for offsetof() */ | |
| 89 | +#include <Python.h> | |
| 90 | +#include <db.h> | |
| 91 | + | |
| 92 | +/* --------------------------------------------------------------------- */ | |
| 93 | +/* Various macro definitions */ | |
| 94 | + | |
| 95 | +/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */ | |
| 96 | +#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR) | |
| 97 | +#if DB_VERSION_MINOR > 9 | |
| 98 | +#error "eek! DBVER can't handle minor versions > 9" | |
| 99 | +#endif | |
| 100 | + | |
| 101 | +#define PY_BSDDB_VERSION "4.4.5.2" | |
| 102 | +static char *rcs_id = "$Id: _bsddb.c 53254 2007-01-05 02:09:06Z gregory.p.smith $"; | |
| 103 | + | |
| 104 | + | |
| 105 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 106 | +typedef int Py_ssize_t; | |
| 107 | +#endif | |
| 108 | + | |
| 109 | +#ifdef WITH_THREAD | |
| 110 | + | |
| 111 | +/* These are for when calling Python --> C */ | |
| 112 | +#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS; | |
| 113 | +#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS; | |
| 114 | + | |
| 115 | +/* For 2.3, use the PyGILState_ calls */ | |
| 116 | +#if (PY_VERSION_HEX >= 0x02030000) | |
| 117 | +#define MYDB_USE_GILSTATE | |
| 118 | +#endif | |
| 119 | + | |
| 120 | +/* and these are for calling C --> Python */ | |
| 121 | +#if defined(MYDB_USE_GILSTATE) | |
| 122 | +#define MYDB_BEGIN_BLOCK_THREADS \ | |
| 123 | + PyGILState_STATE __savestate = PyGILState_Ensure(); | |
| 124 | +#define MYDB_END_BLOCK_THREADS \ | |
| 125 | + PyGILState_Release(__savestate); | |
| 126 | +#else /* MYDB_USE_GILSTATE */ | |
| 127 | +/* Pre GILState API - do it the long old way */ | |
| 128 | +static PyInterpreterState* _db_interpreterState = NULL; | |
| 129 | +#define MYDB_BEGIN_BLOCK_THREADS { \ | |
| 130 | + PyThreadState* prevState; \ | |
| 131 | + PyThreadState* newState; \ | |
| 132 | + PyEval_AcquireLock(); \ | |
| 133 | + newState = PyThreadState_New(_db_interpreterState); \ | |
| 134 | + prevState = PyThreadState_Swap(newState); | |
| 135 | + | |
| 136 | +#define MYDB_END_BLOCK_THREADS \ | |
| 137 | + newState = PyThreadState_Swap(prevState); \ | |
| 138 | + PyThreadState_Clear(newState); \ | |
| 139 | + PyEval_ReleaseLock(); \ | |
| 140 | + PyThreadState_Delete(newState); \ | |
| 141 | + } | |
| 142 | +#endif /* MYDB_USE_GILSTATE */ | |
| 143 | + | |
| 144 | +#else | |
| 145 | +/* Compiled without threads - avoid all this cruft */ | |
| 146 | +#define MYDB_BEGIN_ALLOW_THREADS | |
| 147 | +#define MYDB_END_ALLOW_THREADS | |
| 148 | +#define MYDB_BEGIN_BLOCK_THREADS | |
| 149 | +#define MYDB_END_BLOCK_THREADS | |
| 150 | + | |
| 151 | +#endif | |
| 152 | + | |
| 153 | +/* Should DB_INCOMPLETE be turned into a warning or an exception? */ | |
| 154 | +#define INCOMPLETE_IS_WARNING 1 | |
| 155 | + | |
| 156 | +/* --------------------------------------------------------------------- */ | |
| 157 | +/* Exceptions */ | |
| 158 | + | |
| 159 | +static PyObject* DBError; /* Base class, all others derive from this */ | |
| 160 | +static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */ | |
| 161 | +static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */ | |
| 162 | +static PyObject* DBKeyExistError; /* DB_KEYEXIST */ | |
| 163 | +static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */ | |
| 164 | +static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */ | |
| 165 | +static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */ | |
| 166 | +static PyObject* DBOldVersionError; /* DB_OLD_VERSION */ | |
| 167 | +static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */ | |
| 168 | +static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */ | |
| 169 | +static PyObject* DBNoServerError; /* DB_NOSERVER */ | |
| 170 | +static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */ | |
| 171 | +static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */ | |
| 172 | +#if (DBVER >= 33) | |
| 173 | +static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */ | |
| 174 | +static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */ | |
| 175 | +#endif | |
| 176 | + | |
| 177 | +#if !INCOMPLETE_IS_WARNING | |
| 178 | +static PyObject* DBIncompleteError; /* DB_INCOMPLETE */ | |
| 179 | +#endif | |
| 180 | + | |
| 181 | +static PyObject* DBInvalidArgError; /* EINVAL */ | |
| 182 | +static PyObject* DBAccessError; /* EACCES */ | |
| 183 | +static PyObject* DBNoSpaceError; /* ENOSPC */ | |
| 184 | +static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */ | |
| 185 | +static PyObject* DBAgainError; /* EAGAIN */ | |
| 186 | +static PyObject* DBBusyError; /* EBUSY */ | |
| 187 | +static PyObject* DBFileExistsError; /* EEXIST */ | |
| 188 | +static PyObject* DBNoSuchFileError; /* ENOENT */ | |
| 189 | +static PyObject* DBPermissionsError; /* EPERM */ | |
| 190 | + | |
| 191 | +#if (DBVER < 43) | |
| 192 | +#define DB_BUFFER_SMALL ENOMEM | |
| 193 | +#endif | |
| 194 | + | |
| 195 | + | |
| 196 | +/* --------------------------------------------------------------------- */ | |
| 197 | +/* Structure definitions */ | |
| 198 | + | |
| 199 | +#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */ | |
| 200 | +#define HAVE_WEAKREF | |
| 201 | +#else | |
| 202 | +#undef HAVE_WEAKREF | |
| 203 | +#endif | |
| 204 | + | |
| 205 | +/* if Python >= 2.1 better support warnings */ | |
| 206 | +#if PYTHON_API_VERSION >= 1010 | |
| 207 | +#define HAVE_WARNINGS | |
| 208 | +#else | |
| 209 | +#undef HAVE_WARNINGS | |
| 210 | +#endif | |
| 211 | + | |
| 212 | +#if PYTHON_API_VERSION <= 1007 | |
| 213 | + /* 1.5 compatibility */ | |
| 214 | +#define PyObject_New PyObject_NEW | |
| 215 | +#define PyObject_Del PyMem_DEL | |
| 216 | +#endif | |
| 217 | + | |
| 218 | +struct behaviourFlags { | |
| 219 | + /* What is the default behaviour when DB->get or DBCursor->get returns a | |
| 220 | + DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */ | |
| 221 | + unsigned int getReturnsNone : 1; | |
| 222 | + /* What is the default behaviour for DBCursor.set* methods when DBCursor->get | |
| 223 | + * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */ | |
| 224 | + unsigned int cursorSetReturnsNone : 1; | |
| 225 | +}; | |
| 226 | + | |
| 227 | +#define DEFAULT_GET_RETURNS_NONE 1 | |
| 228 | +#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */ | |
| 229 | + | |
| 230 | +typedef struct { | |
| 231 | + PyObject_HEAD | |
| 232 | + DB_ENV* db_env; | |
| 233 | + u_int32_t flags; /* saved flags from open() */ | |
| 234 | + int closed; | |
| 235 | + struct behaviourFlags moduleFlags; | |
| 236 | +#ifdef HAVE_WEAKREF | |
| 237 | + PyObject *in_weakreflist; /* List of weak references */ | |
| 238 | +#endif | |
| 239 | +} DBEnvObject; | |
| 240 | + | |
| 241 | + | |
| 242 | +typedef struct { | |
| 243 | + PyObject_HEAD | |
| 244 | + DB* db; | |
| 245 | + DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */ | |
| 246 | + u_int32_t flags; /* saved flags from open() */ | |
| 247 | + u_int32_t setflags; /* saved flags from set_flags() */ | |
| 248 | + int haveStat; | |
| 249 | + struct behaviourFlags moduleFlags; | |
| 250 | +#if (DBVER >= 33) | |
| 251 | + PyObject* associateCallback; | |
| 252 | + PyObject* btCompareCallback; | |
| 253 | + int primaryDBType; | |
| 254 | +#endif | |
| 255 | +#ifdef HAVE_WEAKREF | |
| 256 | + PyObject *in_weakreflist; /* List of weak references */ | |
| 257 | +#endif | |
| 258 | +} DBObject; | |
| 259 | + | |
| 260 | + | |
| 261 | +typedef struct { | |
| 262 | + PyObject_HEAD | |
| 263 | + DBC* dbc; | |
| 264 | + DBObject* mydb; | |
| 265 | +#ifdef HAVE_WEAKREF | |
| 266 | + PyObject *in_weakreflist; /* List of weak references */ | |
| 267 | +#endif | |
| 268 | +} DBCursorObject; | |
| 269 | + | |
| 270 | + | |
| 271 | +typedef struct { | |
| 272 | + PyObject_HEAD | |
| 273 | + DB_TXN* txn; | |
| 274 | + PyObject *env; | |
| 275 | +#ifdef HAVE_WEAKREF | |
| 276 | + PyObject *in_weakreflist; /* List of weak references */ | |
| 277 | +#endif | |
| 278 | +} DBTxnObject; | |
| 279 | + | |
| 280 | + | |
| 281 | +typedef struct { | |
| 282 | + PyObject_HEAD | |
| 283 | + DB_LOCK lock; | |
| 284 | +#ifdef HAVE_WEAKREF | |
| 285 | + PyObject *in_weakreflist; /* List of weak references */ | |
| 286 | +#endif | |
| 287 | +} DBLockObject; | |
| 288 | + | |
| 289 | +#if (DBVER >= 43) | |
| 290 | +typedef struct { | |
| 291 | + PyObject_HEAD | |
| 292 | + DB_SEQUENCE* sequence; | |
| 293 | + DBObject* mydb; | |
| 294 | +#ifdef HAVE_WEAKREF | |
| 295 | + PyObject *in_weakreflist; /* List of weak references */ | |
| 296 | +#endif | |
| 297 | +} DBSequenceObject; | |
| 298 | +staticforward PyTypeObject DBSequence_Type; | |
| 299 | +#endif | |
| 300 | + | |
| 301 | +staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type; | |
| 302 | + | |
| 303 | +#define DBObject_Check(v) ((v)->ob_type == &DB_Type) | |
| 304 | +#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type) | |
| 305 | +#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type) | |
| 306 | +#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type) | |
| 307 | +#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type) | |
| 308 | +#if (DBVER >= 43) | |
| 309 | +#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type) | |
| 310 | +#endif | |
| 311 | + | |
| 312 | + | |
| 313 | +/* --------------------------------------------------------------------- */ | |
| 314 | +/* Utility macros and functions */ | |
| 315 | + | |
| 316 | +#define RETURN_IF_ERR() \ | |
| 317 | + if (makeDBError(err)) { \ | |
| 318 | + return NULL; \ | |
| 319 | + } | |
| 320 | + | |
| 321 | +#define RETURN_NONE() Py_INCREF(Py_None); return Py_None; | |
| 322 | + | |
| 323 | +#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \ | |
| 324 | + if ((nonNull) == NULL) { \ | |
| 325 | + PyObject *errTuple = NULL; \ | |
| 326 | + errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \ | |
| 327 | + PyErr_SetObject((pyErrObj), errTuple); \ | |
| 328 | + Py_DECREF(errTuple); \ | |
| 329 | + return NULL; \ | |
| 330 | + } | |
| 331 | + | |
| 332 | +#define CHECK_DB_NOT_CLOSED(dbobj) \ | |
| 333 | + _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB) | |
| 334 | + | |
| 335 | +#define CHECK_ENV_NOT_CLOSED(env) \ | |
| 336 | + _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv) | |
| 337 | + | |
| 338 | +#define CHECK_CURSOR_NOT_CLOSED(curs) \ | |
| 339 | + _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor) | |
| 340 | + | |
| 341 | +#if (DBVER >= 43) | |
| 342 | +#define CHECK_SEQUENCE_NOT_CLOSED(curs) \ | |
| 343 | + _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence) | |
| 344 | +#endif | |
| 345 | + | |
| 346 | +#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \ | |
| 347 | + (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag)))) | |
| 348 | + | |
| 349 | +#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt))) | |
| 350 | + | |
| 351 | +#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \ | |
| 352 | + dbt.data != NULL) { free(dbt.data); dbt.data = NULL; } | |
| 353 | + | |
| 354 | + | |
| 355 | +static int makeDBError(int err); | |
| 356 | + | |
| 357 | + | |
| 358 | +/* Return the access method type of the DBObject */ | |
| 359 | +static int _DB_get_type(DBObject* self) | |
| 360 | +{ | |
| 361 | +#if (DBVER >= 33) | |
| 362 | + DBTYPE type; | |
| 363 | + int err; | |
| 364 | + err = self->db->get_type(self->db, &type); | |
| 365 | + if (makeDBError(err)) { | |
| 366 | + return -1; | |
| 367 | + } | |
| 368 | + return type; | |
| 369 | +#else | |
| 370 | + return self->db->get_type(self->db); | |
| 371 | +#endif | |
| 372 | +} | |
| 373 | + | |
| 374 | + | |
| 375 | +/* Create a DBT structure (containing key and data values) from Python | |
| 376 | + strings. Returns 1 on success, 0 on an error. */ | |
| 377 | +static int make_dbt(PyObject* obj, DBT* dbt) | |
| 378 | +{ | |
| 379 | + CLEAR_DBT(*dbt); | |
| 380 | + if (obj == Py_None) { | |
| 381 | + /* no need to do anything, the structure has already been zeroed */ | |
| 382 | + } | |
| 383 | + else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) { | |
| 384 | + PyErr_SetString(PyExc_TypeError, | |
| 385 | + "Data values must be of type string or None."); | |
| 386 | + return 0; | |
| 387 | + } | |
| 388 | + return 1; | |
| 389 | +} | |
| 390 | + | |
| 391 | + | |
| 392 | +/* Recno and Queue DBs can have integer keys. This function figures out | |
| 393 | + what's been given, verifies that it's allowed, and then makes the DBT. | |
| 394 | + | |
| 395 | + Caller MUST call FREE_DBT(key) when done. */ | |
| 396 | +static int | |
| 397 | +make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags) | |
| 398 | +{ | |
| 399 | + db_recno_t recno; | |
| 400 | + int type; | |
| 401 | + | |
| 402 | + CLEAR_DBT(*key); | |
| 403 | + if (keyobj == Py_None) { | |
| 404 | + type = _DB_get_type(self); | |
| 405 | + if (type == -1) | |
| 406 | + return 0; | |
| 407 | + if (type == DB_RECNO || type == DB_QUEUE) { | |
| 408 | + PyErr_SetString( | |
| 409 | + PyExc_TypeError, | |
| 410 | + "None keys not allowed for Recno and Queue DB's"); | |
| 411 | + return 0; | |
| 412 | + } | |
| 413 | + /* no need to do anything, the structure has already been zeroed */ | |
| 414 | + } | |
| 415 | + | |
| 416 | + else if (PyString_Check(keyobj)) { | |
| 417 | + /* verify access method type */ | |
| 418 | + type = _DB_get_type(self); | |
| 419 | + if (type == -1) | |
| 420 | + return 0; | |
| 421 | + if (type == DB_RECNO || type == DB_QUEUE) { | |
| 422 | + PyErr_SetString( | |
| 423 | + PyExc_TypeError, | |
| 424 | + "String keys not allowed for Recno and Queue DB's"); | |
| 425 | + return 0; | |
| 426 | + } | |
| 427 | + | |
| 428 | + key->data = PyString_AS_STRING(keyobj); | |
| 429 | + key->size = PyString_GET_SIZE(keyobj); | |
| 430 | + } | |
| 431 | + | |
| 432 | + else if (PyInt_Check(keyobj)) { | |
| 433 | + /* verify access method type */ | |
| 434 | + type = _DB_get_type(self); | |
| 435 | + if (type == -1) | |
| 436 | + return 0; | |
| 437 | + if (type == DB_BTREE && pflags != NULL) { | |
| 438 | + /* if BTREE then an Integer key is allowed with the | |
| 439 | + * DB_SET_RECNO flag */ | |
| 440 | + *pflags |= DB_SET_RECNO; | |
| 441 | + } | |
| 442 | + else if (type != DB_RECNO && type != DB_QUEUE) { | |
| 443 | + PyErr_SetString( | |
| 444 | + PyExc_TypeError, | |
| 445 | + "Integer keys only allowed for Recno and Queue DB's"); | |
| 446 | + return 0; | |
| 447 | + } | |
| 448 | + | |
| 449 | + /* Make a key out of the requested recno, use allocated space so DB | |
| 450 | + * will be able to realloc room for the real key if needed. */ | |
| 451 | + recno = PyInt_AS_LONG(keyobj); | |
| 452 | + key->data = malloc(sizeof(db_recno_t)); | |
| 453 | + if (key->data == NULL) { | |
| 454 | + PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); | |
| 455 | + return 0; | |
| 456 | + } | |
| 457 | + key->ulen = key->size = sizeof(db_recno_t); | |
| 458 | + memcpy(key->data, &recno, sizeof(db_recno_t)); | |
| 459 | + key->flags = DB_DBT_REALLOC; | |
| 460 | + } | |
| 461 | + else { | |
| 462 | + PyErr_Format(PyExc_TypeError, | |
| 463 | + "String or Integer object expected for key, %s found", | |
| 464 | + keyobj->ob_type->tp_name); | |
| 465 | + return 0; | |
| 466 | + } | |
| 467 | + | |
| 468 | + return 1; | |
| 469 | +} | |
| 470 | + | |
| 471 | + | |
| 472 | +/* Add partial record access to an existing DBT data struct. | |
| 473 | + If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set | |
| 474 | + and the data storage/retrieval will be done using dlen and doff. */ | |
| 475 | +static int add_partial_dbt(DBT* d, int dlen, int doff) { | |
| 476 | + /* if neither were set we do nothing (-1 is the default value) */ | |
| 477 | + if ((dlen == -1) && (doff == -1)) { | |
| 478 | + return 1; | |
| 479 | + } | |
| 480 | + | |
| 481 | + if ((dlen < 0) || (doff < 0)) { | |
| 482 | + PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0"); | |
| 483 | + return 0; | |
| 484 | + } | |
| 485 | + | |
| 486 | + d->flags = d->flags | DB_DBT_PARTIAL; | |
| 487 | + d->dlen = (unsigned int) dlen; | |
| 488 | + d->doff = (unsigned int) doff; | |
| 489 | + return 1; | |
| 490 | +} | |
| 491 | + | |
| 492 | +/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */ | |
| 493 | +/* TODO: make this use the native libc strlcpy() when available (BSD) */ | |
| 494 | +unsigned int our_strlcpy(char* dest, const char* src, unsigned int n) | |
| 495 | +{ | |
| 496 | + unsigned int srclen, copylen; | |
| 497 | + | |
| 498 | + srclen = strlen(src); | |
| 499 | + if (n <= 0) | |
| 500 | + return srclen; | |
| 501 | + copylen = (srclen > n-1) ? n-1 : srclen; | |
| 502 | + /* populate dest[0] thru dest[copylen-1] */ | |
| 503 | + memcpy(dest, src, copylen); | |
| 504 | + /* guarantee null termination */ | |
| 505 | + dest[copylen] = 0; | |
| 506 | + | |
| 507 | + return srclen; | |
| 508 | +} | |
| 509 | + | |
| 510 | +/* Callback used to save away more information about errors from the DB | |
| 511 | + * library. */ | |
| 512 | +static char _db_errmsg[1024]; | |
| 513 | +#if (DBVER <= 42) | |
| 514 | +static void _db_errorCallback(const char* prefix, char* msg) | |
| 515 | +#else | |
| 516 | +static void _db_errorCallback(const DB_ENV *db_env, | |
| 517 | + const char* prefix, const char* msg) | |
| 518 | +#endif | |
| 519 | +{ | |
| 520 | + our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg)); | |
| 521 | +} | |
| 522 | + | |
| 523 | + | |
| 524 | +/* make a nice exception object to raise for errors. */ | |
| 525 | +static int makeDBError(int err) | |
| 526 | +{ | |
| 527 | + char errTxt[2048]; /* really big, just in case... */ | |
| 528 | + PyObject *errObj = NULL; | |
| 529 | + PyObject *errTuple = NULL; | |
| 530 | + int exceptionRaised = 0; | |
| 531 | + unsigned int bytes_left; | |
| 532 | + | |
| 533 | + switch (err) { | |
| 534 | + case 0: /* successful, no error */ break; | |
| 535 | + | |
| 536 | +#if (DBVER < 41) | |
| 537 | + case DB_INCOMPLETE: | |
| 538 | +#if INCOMPLETE_IS_WARNING | |
| 539 | + bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt)); | |
| 540 | + /* Ensure that bytes_left never goes negative */ | |
| 541 | + if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) { | |
| 542 | + bytes_left = sizeof(errTxt) - bytes_left - 4 - 1; | |
| 543 | + assert(bytes_left >= 0); | |
| 544 | + strcat(errTxt, " -- "); | |
| 545 | + strncat(errTxt, _db_errmsg, bytes_left); | |
| 546 | + } | |
| 547 | + _db_errmsg[0] = 0; | |
| 548 | +#ifdef HAVE_WARNINGS | |
| 549 | + exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt); | |
| 550 | +#else | |
| 551 | + fprintf(stderr, errTxt); | |
| 552 | + fprintf(stderr, "\n"); | |
| 553 | +#endif | |
| 554 | + | |
| 555 | +#else /* do an exception instead */ | |
| 556 | + errObj = DBIncompleteError; | |
| 557 | +#endif | |
| 558 | + break; | |
| 559 | +#endif /* DBVER < 41 */ | |
| 560 | + | |
| 561 | + case DB_KEYEMPTY: errObj = DBKeyEmptyError; break; | |
| 562 | + case DB_KEYEXIST: errObj = DBKeyExistError; break; | |
| 563 | + case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break; | |
| 564 | + case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break; | |
| 565 | + case DB_NOTFOUND: errObj = DBNotFoundError; break; | |
| 566 | + case DB_OLD_VERSION: errObj = DBOldVersionError; break; | |
| 567 | + case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break; | |
| 568 | + case DB_VERIFY_BAD: errObj = DBVerifyBadError; break; | |
| 569 | + case DB_NOSERVER: errObj = DBNoServerError; break; | |
| 570 | + case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break; | |
| 571 | + case DB_NOSERVER_ID: errObj = DBNoServerIDError; break; | |
| 572 | +#if (DBVER >= 33) | |
| 573 | + case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break; | |
| 574 | + case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break; | |
| 575 | +#endif | |
| 576 | + case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break; | |
| 577 | + | |
| 578 | +#if (DBVER >= 43) | |
| 579 | + /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */ | |
| 580 | + case ENOMEM: errObj = PyExc_MemoryError; break; | |
| 581 | +#endif | |
| 582 | + case EINVAL: errObj = DBInvalidArgError; break; | |
| 583 | + case EACCES: errObj = DBAccessError; break; | |
| 584 | + case ENOSPC: errObj = DBNoSpaceError; break; | |
| 585 | + case EAGAIN: errObj = DBAgainError; break; | |
| 586 | + case EBUSY : errObj = DBBusyError; break; | |
| 587 | + case EEXIST: errObj = DBFileExistsError; break; | |
| 588 | + case ENOENT: errObj = DBNoSuchFileError; break; | |
| 589 | + case EPERM : errObj = DBPermissionsError; break; | |
| 590 | + | |
| 591 | + default: errObj = DBError; break; | |
| 592 | + } | |
| 593 | + | |
| 594 | + if (errObj != NULL) { | |
| 595 | + bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt)); | |
| 596 | + /* Ensure that bytes_left never goes negative */ | |
| 597 | + if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) { | |
| 598 | + bytes_left = sizeof(errTxt) - bytes_left - 4 - 1; | |
| 599 | + assert(bytes_left >= 0); | |
| 600 | + strcat(errTxt, " -- "); | |
| 601 | + strncat(errTxt, _db_errmsg, bytes_left); | |
| 602 | + } | |
| 603 | + _db_errmsg[0] = 0; | |
| 604 | + | |
| 605 | + errTuple = Py_BuildValue("(is)", err, errTxt); | |
| 606 | + PyErr_SetObject(errObj, errTuple); | |
| 607 | + Py_DECREF(errTuple); | |
| 608 | + } | |
| 609 | + | |
| 610 | + return ((errObj != NULL) || exceptionRaised); | |
| 611 | +} | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | +/* set a type exception */ | |
| 616 | +static void makeTypeError(char* expected, PyObject* found) | |
| 617 | +{ | |
| 618 | + PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.", | |
| 619 | + expected, found->ob_type->tp_name); | |
| 620 | +} | |
| 621 | + | |
| 622 | + | |
| 623 | +/* verify that an obj is either None or a DBTxn, and set the txn pointer */ | |
| 624 | +static int checkTxnObj(PyObject* txnobj, DB_TXN** txn) | |
| 625 | +{ | |
| 626 | + if (txnobj == Py_None || txnobj == NULL) { | |
| 627 | + *txn = NULL; | |
| 628 | + return 1; | |
| 629 | + } | |
| 630 | + if (DBTxnObject_Check(txnobj)) { | |
| 631 | + *txn = ((DBTxnObject*)txnobj)->txn; | |
| 632 | + return 1; | |
| 633 | + } | |
| 634 | + else | |
| 635 | + makeTypeError("DBTxn", txnobj); | |
| 636 | + return 0; | |
| 637 | +} | |
| 638 | + | |
| 639 | + | |
| 640 | +/* Delete a key from a database | |
| 641 | + Returns 0 on success, -1 on an error. */ | |
| 642 | +static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags) | |
| 643 | +{ | |
| 644 | + int err; | |
| 645 | + | |
| 646 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 647 | + err = self->db->del(self->db, txn, key, 0); | |
| 648 | + MYDB_END_ALLOW_THREADS; | |
| 649 | + if (makeDBError(err)) { | |
| 650 | + return -1; | |
| 651 | + } | |
| 652 | + self->haveStat = 0; | |
| 653 | + return 0; | |
| 654 | +} | |
| 655 | + | |
| 656 | + | |
| 657 | +/* Store a key into a database | |
| 658 | + Returns 0 on success, -1 on an error. */ | |
| 659 | +static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags) | |
| 660 | +{ | |
| 661 | + int err; | |
| 662 | + | |
| 663 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 664 | + err = self->db->put(self->db, txn, key, data, flags); | |
| 665 | + MYDB_END_ALLOW_THREADS; | |
| 666 | + if (makeDBError(err)) { | |
| 667 | + return -1; | |
| 668 | + } | |
| 669 | + self->haveStat = 0; | |
| 670 | + return 0; | |
| 671 | +} | |
| 672 | + | |
| 673 | +/* Get a key/data pair from a cursor */ | |
| 674 | +static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags, | |
| 675 | + PyObject *args, PyObject *kwargs, char *format) | |
| 676 | +{ | |
| 677 | + int err; | |
| 678 | + PyObject* retval = NULL; | |
| 679 | + DBT key, data; | |
| 680 | + int dlen = -1; | |
| 681 | + int doff = -1; | |
| 682 | + int flags = 0; | |
| 683 | + static char* kwnames[] = { "flags", "dlen", "doff", NULL }; | |
| 684 | + | |
| 685 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames, | |
| 686 | + &flags, &dlen, &doff)) | |
| 687 | + return NULL; | |
| 688 | + | |
| 689 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 690 | + | |
| 691 | + flags |= extra_flags; | |
| 692 | + CLEAR_DBT(key); | |
| 693 | + CLEAR_DBT(data); | |
| 694 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 695 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 696 | + data.flags = DB_DBT_MALLOC; | |
| 697 | + key.flags = DB_DBT_MALLOC; | |
| 698 | + } | |
| 699 | + if (!add_partial_dbt(&data, dlen, doff)) | |
| 700 | + return NULL; | |
| 701 | + | |
| 702 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 703 | + err = self->dbc->c_get(self->dbc, &key, &data, flags); | |
| 704 | + MYDB_END_ALLOW_THREADS; | |
| 705 | + | |
| 706 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 707 | + && self->mydb->moduleFlags.getReturnsNone) { | |
| 708 | + Py_INCREF(Py_None); | |
| 709 | + retval = Py_None; | |
| 710 | + } | |
| 711 | + else if (makeDBError(err)) { | |
| 712 | + retval = NULL; | |
| 713 | + } | |
| 714 | + else { /* otherwise, success! */ | |
| 715 | + | |
| 716 | + /* if Recno or Queue, return the key as an Int */ | |
| 717 | + switch (_DB_get_type(self->mydb)) { | |
| 718 | + case -1: | |
| 719 | + retval = NULL; | |
| 720 | + break; | |
| 721 | + | |
| 722 | + case DB_RECNO: | |
| 723 | + case DB_QUEUE: | |
| 724 | + retval = Py_BuildValue("is#", *((db_recno_t*)key.data), | |
| 725 | + data.data, data.size); | |
| 726 | + break; | |
| 727 | + case DB_HASH: | |
| 728 | + case DB_BTREE: | |
| 729 | + default: | |
| 730 | + retval = Py_BuildValue("s#s#", key.data, key.size, | |
| 731 | + data.data, data.size); | |
| 732 | + break; | |
| 733 | + } | |
| 734 | + } | |
| 735 | + if (!err) { | |
| 736 | + FREE_DBT(key); | |
| 737 | + FREE_DBT(data); | |
| 738 | + } | |
| 739 | + return retval; | |
| 740 | +} | |
| 741 | + | |
| 742 | + | |
| 743 | +/* add an integer to a dictionary using the given name as a key */ | |
| 744 | +static void _addIntToDict(PyObject* dict, char *name, int value) | |
| 745 | +{ | |
| 746 | + PyObject* v = PyInt_FromLong((long) value); | |
| 747 | + if (!v || PyDict_SetItemString(dict, name, v)) | |
| 748 | + PyErr_Clear(); | |
| 749 | + | |
| 750 | + Py_XDECREF(v); | |
| 751 | +} | |
| 752 | +#if (DBVER >= 43) | |
| 753 | +/* add an db_seq_t to a dictionary using the given name as a key */ | |
| 754 | +static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value) | |
| 755 | +{ | |
| 756 | + PyObject* v = PyLong_FromLongLong(value); | |
| 757 | + if (!v || PyDict_SetItemString(dict, name, v)) | |
| 758 | + PyErr_Clear(); | |
| 759 | + | |
| 760 | + Py_XDECREF(v); | |
| 761 | +} | |
| 762 | +#endif | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | +/* --------------------------------------------------------------------- */ | |
| 767 | +/* Allocators and deallocators */ | |
| 768 | + | |
| 769 | +static DBObject* | |
| 770 | +newDBObject(DBEnvObject* arg, int flags) | |
| 771 | +{ | |
| 772 | + DBObject* self; | |
| 773 | + DB_ENV* db_env = NULL; | |
| 774 | + int err; | |
| 775 | + | |
| 776 | + self = PyObject_New(DBObject, &DB_Type); | |
| 777 | + if (self == NULL) | |
| 778 | + return NULL; | |
| 779 | + | |
| 780 | + self->haveStat = 0; | |
| 781 | + self->flags = 0; | |
| 782 | + self->setflags = 0; | |
| 783 | + self->myenvobj = NULL; | |
| 784 | +#if (DBVER >= 33) | |
| 785 | + self->associateCallback = NULL; | |
| 786 | + self->btCompareCallback = NULL; | |
| 787 | + self->primaryDBType = 0; | |
| 788 | +#endif | |
| 789 | +#ifdef HAVE_WEAKREF | |
| 790 | + self->in_weakreflist = NULL; | |
| 791 | +#endif | |
| 792 | + | |
| 793 | + /* keep a reference to our python DBEnv object */ | |
| 794 | + if (arg) { | |
| 795 | + Py_INCREF(arg); | |
| 796 | + self->myenvobj = arg; | |
| 797 | + db_env = arg->db_env; | |
| 798 | + } | |
| 799 | + | |
| 800 | + if (self->myenvobj) | |
| 801 | + self->moduleFlags = self->myenvobj->moduleFlags; | |
| 802 | + else | |
| 803 | + self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; | |
| 804 | + self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; | |
| 805 | + | |
| 806 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 807 | + err = db_create(&self->db, db_env, flags); | |
| 808 | + if (self->db != NULL) { | |
| 809 | + self->db->set_errcall(self->db, _db_errorCallback); | |
| 810 | +#if (DBVER >= 33) | |
| 811 | + self->db->app_private = (void*)self; | |
| 812 | +#endif | |
| 813 | + } | |
| 814 | + MYDB_END_ALLOW_THREADS; | |
| 815 | + /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs | |
| 816 | + * list so that a DBEnv can refuse to close without aborting any open | |
| 817 | + * DBTxns and closing any open DBs first. */ | |
| 818 | + if (makeDBError(err)) { | |
| 819 | + if (self->myenvobj) { | |
| 820 | + Py_DECREF(self->myenvobj); | |
| 821 | + self->myenvobj = NULL; | |
| 822 | + } | |
| 823 | + PyObject_Del(self); | |
| 824 | + self = NULL; | |
| 825 | + } | |
| 826 | + return self; | |
| 827 | +} | |
| 828 | + | |
| 829 | + | |
| 830 | +static void | |
| 831 | +DB_dealloc(DBObject* self) | |
| 832 | +{ | |
| 833 | + if (self->db != NULL) { | |
| 834 | + /* avoid closing a DB when its DBEnv has been closed out from under | |
| 835 | + * it */ | |
| 836 | + if (!self->myenvobj || | |
| 837 | + (self->myenvobj && self->myenvobj->db_env)) | |
| 838 | + { | |
| 839 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 840 | + self->db->close(self->db, 0); | |
| 841 | + MYDB_END_ALLOW_THREADS; | |
| 842 | +#ifdef HAVE_WARNINGS | |
| 843 | + } else { | |
| 844 | + PyErr_Warn(PyExc_RuntimeWarning, | |
| 845 | + "DB could not be closed in destructor: DBEnv already closed"); | |
| 846 | +#endif | |
| 847 | + } | |
| 848 | + self->db = NULL; | |
| 849 | + } | |
| 850 | +#ifdef HAVE_WEAKREF | |
| 851 | + if (self->in_weakreflist != NULL) { | |
| 852 | + PyObject_ClearWeakRefs((PyObject *) self); | |
| 853 | + } | |
| 854 | +#endif | |
| 855 | + if (self->myenvobj) { | |
| 856 | + Py_DECREF(self->myenvobj); | |
| 857 | + self->myenvobj = NULL; | |
| 858 | + } | |
| 859 | +#if (DBVER >= 33) | |
| 860 | + if (self->associateCallback != NULL) { | |
| 861 | + Py_DECREF(self->associateCallback); | |
| 862 | + self->associateCallback = NULL; | |
| 863 | + } | |
| 864 | + if (self->btCompareCallback != NULL) { | |
| 865 | + Py_DECREF(self->btCompareCallback); | |
| 866 | + self->btCompareCallback = NULL; | |
| 867 | + } | |
| 868 | +#endif | |
| 869 | + PyObject_Del(self); | |
| 870 | +} | |
| 871 | + | |
| 872 | + | |
| 873 | +static DBCursorObject* | |
| 874 | +newDBCursorObject(DBC* dbc, DBObject* db) | |
| 875 | +{ | |
| 876 | + DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type); | |
| 877 | + if (self == NULL) | |
| 878 | + return NULL; | |
| 879 | + | |
| 880 | + self->dbc = dbc; | |
| 881 | + self->mydb = db; | |
| 882 | +#ifdef HAVE_WEAKREF | |
| 883 | + self->in_weakreflist = NULL; | |
| 884 | +#endif | |
| 885 | + Py_INCREF(self->mydb); | |
| 886 | + return self; | |
| 887 | +} | |
| 888 | + | |
| 889 | + | |
| 890 | +static void | |
| 891 | +DBCursor_dealloc(DBCursorObject* self) | |
| 892 | +{ | |
| 893 | + int err; | |
| 894 | + | |
| 895 | +#ifdef HAVE_WEAKREF | |
| 896 | + if (self->in_weakreflist != NULL) { | |
| 897 | + PyObject_ClearWeakRefs((PyObject *) self); | |
| 898 | + } | |
| 899 | +#endif | |
| 900 | + | |
| 901 | + if (self->dbc != NULL) { | |
| 902 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 903 | + /* If the underlying database has been closed, we don't | |
| 904 | + need to do anything. If the environment has been closed | |
| 905 | + we need to leak, as BerkeleyDB will crash trying to access | |
| 906 | + the environment. There was an exception when the | |
| 907 | + user closed the environment even though there still was | |
| 908 | + a database open. */ | |
| 909 | + if (self->mydb->db && self->mydb->myenvobj && | |
| 910 | + !self->mydb->myenvobj->closed) | |
| 911 | + err = self->dbc->c_close(self->dbc); | |
| 912 | + self->dbc = NULL; | |
| 913 | + MYDB_END_ALLOW_THREADS; | |
| 914 | + } | |
| 915 | + Py_XDECREF( self->mydb ); | |
| 916 | + PyObject_Del(self); | |
| 917 | +} | |
| 918 | + | |
| 919 | + | |
| 920 | +static DBEnvObject* | |
| 921 | +newDBEnvObject(int flags) | |
| 922 | +{ | |
| 923 | + int err; | |
| 924 | + DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type); | |
| 925 | + if (self == NULL) | |
| 926 | + return NULL; | |
| 927 | + | |
| 928 | + self->closed = 1; | |
| 929 | + self->flags = flags; | |
| 930 | + self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; | |
| 931 | + self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; | |
| 932 | +#ifdef HAVE_WEAKREF | |
| 933 | + self->in_weakreflist = NULL; | |
| 934 | +#endif | |
| 935 | + | |
| 936 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 937 | + err = db_env_create(&self->db_env, flags); | |
| 938 | + MYDB_END_ALLOW_THREADS; | |
| 939 | + if (makeDBError(err)) { | |
| 940 | + PyObject_Del(self); | |
| 941 | + self = NULL; | |
| 942 | + } | |
| 943 | + else { | |
| 944 | + self->db_env->set_errcall(self->db_env, _db_errorCallback); | |
| 945 | + } | |
| 946 | + return self; | |
| 947 | +} | |
| 948 | + | |
| 949 | + | |
| 950 | +static void | |
| 951 | +DBEnv_dealloc(DBEnvObject* self) | |
| 952 | +{ | |
| 953 | +#ifdef HAVE_WEAKREF | |
| 954 | + if (self->in_weakreflist != NULL) { | |
| 955 | + PyObject_ClearWeakRefs((PyObject *) self); | |
| 956 | + } | |
| 957 | +#endif | |
| 958 | + | |
| 959 | + if (self->db_env && !self->closed) { | |
| 960 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 961 | + self->db_env->close(self->db_env, 0); | |
| 962 | + MYDB_END_ALLOW_THREADS; | |
| 963 | + } | |
| 964 | + PyObject_Del(self); | |
| 965 | +} | |
| 966 | + | |
| 967 | + | |
| 968 | +static DBTxnObject* | |
| 969 | +newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags) | |
| 970 | +{ | |
| 971 | + int err; | |
| 972 | + DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type); | |
| 973 | + if (self == NULL) | |
| 974 | + return NULL; | |
| 975 | + Py_INCREF(myenv); | |
| 976 | + self->env = (PyObject*)myenv; | |
| 977 | +#ifdef HAVE_WEAKREF | |
| 978 | + self->in_weakreflist = NULL; | |
| 979 | +#endif | |
| 980 | + | |
| 981 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 982 | +#if (DBVER >= 40) | |
| 983 | + err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags); | |
| 984 | +#else | |
| 985 | + err = txn_begin(myenv->db_env, parent, &(self->txn), flags); | |
| 986 | +#endif | |
| 987 | + MYDB_END_ALLOW_THREADS; | |
| 988 | + if (makeDBError(err)) { | |
| 989 | + Py_DECREF(self->env); | |
| 990 | + PyObject_Del(self); | |
| 991 | + self = NULL; | |
| 992 | + } | |
| 993 | + return self; | |
| 994 | +} | |
| 995 | + | |
| 996 | + | |
| 997 | +static void | |
| 998 | +DBTxn_dealloc(DBTxnObject* self) | |
| 999 | +{ | |
| 1000 | +#ifdef HAVE_WEAKREF | |
| 1001 | + if (self->in_weakreflist != NULL) { | |
| 1002 | + PyObject_ClearWeakRefs((PyObject *) self); | |
| 1003 | + } | |
| 1004 | +#endif | |
| 1005 | + | |
| 1006 | +#ifdef HAVE_WARNINGS | |
| 1007 | + if (self->txn) { | |
| 1008 | + /* it hasn't been finalized, abort it! */ | |
| 1009 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1010 | +#if (DBVER >= 40) | |
| 1011 | + self->txn->abort(self->txn); | |
| 1012 | +#else | |
| 1013 | + txn_abort(self->txn); | |
| 1014 | +#endif | |
| 1015 | + MYDB_END_ALLOW_THREADS; | |
| 1016 | + PyErr_Warn(PyExc_RuntimeWarning, | |
| 1017 | + "DBTxn aborted in destructor. No prior commit() or abort()."); | |
| 1018 | + } | |
| 1019 | +#endif | |
| 1020 | + | |
| 1021 | + Py_DECREF(self->env); | |
| 1022 | + PyObject_Del(self); | |
| 1023 | +} | |
| 1024 | + | |
| 1025 | + | |
| 1026 | +static DBLockObject* | |
| 1027 | +newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj, | |
| 1028 | + db_lockmode_t lock_mode, int flags) | |
| 1029 | +{ | |
| 1030 | + int err; | |
| 1031 | + DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type); | |
| 1032 | + if (self == NULL) | |
| 1033 | + return NULL; | |
| 1034 | +#ifdef HAVE_WEAKREF | |
| 1035 | + self->in_weakreflist = NULL; | |
| 1036 | +#endif | |
| 1037 | + | |
| 1038 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1039 | +#if (DBVER >= 40) | |
| 1040 | + err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode, | |
| 1041 | + &self->lock); | |
| 1042 | +#else | |
| 1043 | + err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock); | |
| 1044 | +#endif | |
| 1045 | + MYDB_END_ALLOW_THREADS; | |
| 1046 | + if (makeDBError(err)) { | |
| 1047 | + PyObject_Del(self); | |
| 1048 | + self = NULL; | |
| 1049 | + } | |
| 1050 | + | |
| 1051 | + return self; | |
| 1052 | +} | |
| 1053 | + | |
| 1054 | + | |
| 1055 | +static void | |
| 1056 | +DBLock_dealloc(DBLockObject* self) | |
| 1057 | +{ | |
| 1058 | +#ifdef HAVE_WEAKREF | |
| 1059 | + if (self->in_weakreflist != NULL) { | |
| 1060 | + PyObject_ClearWeakRefs((PyObject *) self); | |
| 1061 | + } | |
| 1062 | +#endif | |
| 1063 | + /* TODO: is this lock held? should we release it? */ | |
| 1064 | + | |
| 1065 | + PyObject_Del(self); | |
| 1066 | +} | |
| 1067 | + | |
| 1068 | + | |
| 1069 | +#if (DBVER >= 43) | |
| 1070 | +static DBSequenceObject* | |
| 1071 | +newDBSequenceObject(DBObject* mydb, int flags) | |
| 1072 | +{ | |
| 1073 | + int err; | |
| 1074 | + DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type); | |
| 1075 | + if (self == NULL) | |
| 1076 | + return NULL; | |
| 1077 | + Py_INCREF(mydb); | |
| 1078 | + self->mydb = mydb; | |
| 1079 | +#ifdef HAVE_WEAKREF | |
| 1080 | + self->in_weakreflist = NULL; | |
| 1081 | +#endif | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1085 | + err = db_sequence_create(&self->sequence, self->mydb->db, flags); | |
| 1086 | + MYDB_END_ALLOW_THREADS; | |
| 1087 | + if (makeDBError(err)) { | |
| 1088 | + Py_DECREF(self->mydb); | |
| 1089 | + PyObject_Del(self); | |
| 1090 | + self = NULL; | |
| 1091 | + } | |
| 1092 | + | |
| 1093 | + return self; | |
| 1094 | +} | |
| 1095 | + | |
| 1096 | + | |
| 1097 | +static void | |
| 1098 | +DBSequence_dealloc(DBSequenceObject* self) | |
| 1099 | +{ | |
| 1100 | +#ifdef HAVE_WEAKREF | |
| 1101 | + if (self->in_weakreflist != NULL) { | |
| 1102 | + PyObject_ClearWeakRefs((PyObject *) self); | |
| 1103 | + } | |
| 1104 | +#endif | |
| 1105 | + | |
| 1106 | + Py_DECREF(self->mydb); | |
| 1107 | + PyObject_Del(self); | |
| 1108 | +} | |
| 1109 | +#endif | |
| 1110 | + | |
| 1111 | +/* --------------------------------------------------------------------- */ | |
| 1112 | +/* DB methods */ | |
| 1113 | + | |
| 1114 | +static PyObject* | |
| 1115 | +DB_append(DBObject* self, PyObject* args) | |
| 1116 | +{ | |
| 1117 | + PyObject* txnobj = NULL; | |
| 1118 | + PyObject* dataobj; | |
| 1119 | + db_recno_t recno; | |
| 1120 | + DBT key, data; | |
| 1121 | + DB_TXN *txn = NULL; | |
| 1122 | + | |
| 1123 | + if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj)) | |
| 1124 | + return NULL; | |
| 1125 | + | |
| 1126 | + CHECK_DB_NOT_CLOSED(self); | |
| 1127 | + | |
| 1128 | + /* make a dummy key out of a recno */ | |
| 1129 | + recno = 0; | |
| 1130 | + CLEAR_DBT(key); | |
| 1131 | + key.data = &recno; | |
| 1132 | + key.size = sizeof(recno); | |
| 1133 | + key.ulen = key.size; | |
| 1134 | + key.flags = DB_DBT_USERMEM; | |
| 1135 | + | |
| 1136 | + if (!make_dbt(dataobj, &data)) return NULL; | |
| 1137 | + if (!checkTxnObj(txnobj, &txn)) return NULL; | |
| 1138 | + | |
| 1139 | + if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) | |
| 1140 | + return NULL; | |
| 1141 | + | |
| 1142 | + return PyInt_FromLong(recno); | |
| 1143 | +} | |
| 1144 | + | |
| 1145 | + | |
| 1146 | +#if (DBVER >= 33) | |
| 1147 | + | |
| 1148 | +static int | |
| 1149 | +_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData, | |
| 1150 | + DBT* secKey) | |
| 1151 | +{ | |
| 1152 | + int retval = DB_DONOTINDEX; | |
| 1153 | + DBObject* secondaryDB = (DBObject*)db->app_private; | |
| 1154 | + PyObject* callback = secondaryDB->associateCallback; | |
| 1155 | + int type = secondaryDB->primaryDBType; | |
| 1156 | + PyObject* args; | |
| 1157 | + PyObject* result = NULL; | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + if (callback != NULL) { | |
| 1161 | + MYDB_BEGIN_BLOCK_THREADS; | |
| 1162 | + | |
| 1163 | + if (type == DB_RECNO || type == DB_QUEUE) | |
| 1164 | + args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data), | |
| 1165 | + priData->data, priData->size); | |
| 1166 | + else | |
| 1167 | + args = Py_BuildValue("(s#s#)", priKey->data, priKey->size, | |
| 1168 | + priData->data, priData->size); | |
| 1169 | + if (args != NULL) { | |
| 1170 | + result = PyEval_CallObject(callback, args); | |
| 1171 | + } | |
| 1172 | + if (args == NULL || result == NULL) { | |
| 1173 | + PyErr_Print(); | |
| 1174 | + } | |
| 1175 | + else if (result == Py_None) { | |
| 1176 | + retval = DB_DONOTINDEX; | |
| 1177 | + } | |
| 1178 | + else if (PyInt_Check(result)) { | |
| 1179 | + retval = PyInt_AsLong(result); | |
| 1180 | + } | |
| 1181 | + else if (PyString_Check(result)) { | |
| 1182 | + char* data; | |
| 1183 | + Py_ssize_t size; | |
| 1184 | + | |
| 1185 | + CLEAR_DBT(*secKey); | |
| 1186 | +#if PYTHON_API_VERSION <= 1007 | |
| 1187 | + /* 1.5 compatibility */ | |
| 1188 | + size = PyString_Size(result); | |
| 1189 | + data = PyString_AsString(result); | |
| 1190 | +#else | |
| 1191 | + PyString_AsStringAndSize(result, &data, &size); | |
| 1192 | +#endif | |
| 1193 | + secKey->flags = DB_DBT_APPMALLOC; /* DB will free */ | |
| 1194 | + secKey->data = malloc(size); /* TODO, check this */ | |
| 1195 | + if (secKey->data) { | |
| 1196 | + memcpy(secKey->data, data, size); | |
| 1197 | + secKey->size = size; | |
| 1198 | + retval = 0; | |
| 1199 | + } | |
| 1200 | + else { | |
| 1201 | + PyErr_SetString(PyExc_MemoryError, | |
| 1202 | + "malloc failed in _db_associateCallback"); | |
| 1203 | + PyErr_Print(); | |
| 1204 | + } | |
| 1205 | + } | |
| 1206 | + else { | |
| 1207 | + PyErr_SetString( | |
| 1208 | + PyExc_TypeError, | |
| 1209 | + "DB associate callback should return DB_DONOTINDEX or string."); | |
| 1210 | + PyErr_Print(); | |
| 1211 | + } | |
| 1212 | + | |
| 1213 | + Py_XDECREF(args); | |
| 1214 | + Py_XDECREF(result); | |
| 1215 | + | |
| 1216 | + MYDB_END_BLOCK_THREADS; | |
| 1217 | + } | |
| 1218 | + return retval; | |
| 1219 | +} | |
| 1220 | + | |
| 1221 | + | |
| 1222 | +static PyObject* | |
| 1223 | +DB_associate(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1224 | +{ | |
| 1225 | + int err, flags=0; | |
| 1226 | + DBObject* secondaryDB; | |
| 1227 | + PyObject* callback; | |
| 1228 | +#if (DBVER >= 41) | |
| 1229 | + PyObject *txnobj = NULL; | |
| 1230 | + DB_TXN *txn = NULL; | |
| 1231 | + static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", | |
| 1232 | + NULL}; | |
| 1233 | +#else | |
| 1234 | + static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL}; | |
| 1235 | +#endif | |
| 1236 | + | |
| 1237 | +#if (DBVER >= 41) | |
| 1238 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames, | |
| 1239 | + &secondaryDB, &callback, &flags, | |
| 1240 | + &txnobj)) { | |
| 1241 | +#else | |
| 1242 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames, | |
| 1243 | + &secondaryDB, &callback, &flags)) { | |
| 1244 | +#endif | |
| 1245 | + return NULL; | |
| 1246 | + } | |
| 1247 | + | |
| 1248 | +#if (DBVER >= 41) | |
| 1249 | + if (!checkTxnObj(txnobj, &txn)) return NULL; | |
| 1250 | +#endif | |
| 1251 | + | |
| 1252 | + CHECK_DB_NOT_CLOSED(self); | |
| 1253 | + if (!DBObject_Check(secondaryDB)) { | |
| 1254 | + makeTypeError("DB", (PyObject*)secondaryDB); | |
| 1255 | + return NULL; | |
| 1256 | + } | |
| 1257 | + CHECK_DB_NOT_CLOSED(secondaryDB); | |
| 1258 | + if (callback == Py_None) { | |
| 1259 | + callback = NULL; | |
| 1260 | + } | |
| 1261 | + else if (!PyCallable_Check(callback)) { | |
| 1262 | + makeTypeError("Callable", callback); | |
| 1263 | + return NULL; | |
| 1264 | + } | |
| 1265 | + | |
| 1266 | + /* Save a reference to the callback in the secondary DB. */ | |
| 1267 | + Py_XDECREF(secondaryDB->associateCallback); | |
| 1268 | + Py_XINCREF(callback); | |
| 1269 | + secondaryDB->associateCallback = callback; | |
| 1270 | + secondaryDB->primaryDBType = _DB_get_type(self); | |
| 1271 | + | |
| 1272 | + /* PyEval_InitThreads is called here due to a quirk in python 1.5 | |
| 1273 | + * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>: | |
| 1274 | + * The global interepreter lock is not initialized until the first | |
| 1275 | + * thread is created using thread.start_new_thread() or fork() is | |
| 1276 | + * called. that would cause the ALLOW_THREADS here to segfault due | |
| 1277 | + * to a null pointer reference if no threads or child processes | |
| 1278 | + * have been created. This works around that and is a no-op if | |
| 1279 | + * threads have already been initialized. | |
| 1280 | + * (see pybsddb-users mailing list post on 2002-08-07) | |
| 1281 | + */ | |
| 1282 | +#ifdef WITH_THREAD | |
| 1283 | + PyEval_InitThreads(); | |
| 1284 | +#endif | |
| 1285 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1286 | +#if (DBVER >= 41) | |
| 1287 | + err = self->db->associate(self->db, | |
| 1288 | + txn, | |
| 1289 | + secondaryDB->db, | |
| 1290 | + _db_associateCallback, | |
| 1291 | + flags); | |
| 1292 | +#else | |
| 1293 | + err = self->db->associate(self->db, | |
| 1294 | + secondaryDB->db, | |
| 1295 | + _db_associateCallback, | |
| 1296 | + flags); | |
| 1297 | +#endif | |
| 1298 | + MYDB_END_ALLOW_THREADS; | |
| 1299 | + | |
| 1300 | + if (err) { | |
| 1301 | + Py_XDECREF(secondaryDB->associateCallback); | |
| 1302 | + secondaryDB->associateCallback = NULL; | |
| 1303 | + secondaryDB->primaryDBType = 0; | |
| 1304 | + } | |
| 1305 | + | |
| 1306 | + RETURN_IF_ERR(); | |
| 1307 | + RETURN_NONE(); | |
| 1308 | +} | |
| 1309 | + | |
| 1310 | + | |
| 1311 | +#endif | |
| 1312 | + | |
| 1313 | + | |
| 1314 | +static PyObject* | |
| 1315 | +DB_close(DBObject* self, PyObject* args) | |
| 1316 | +{ | |
| 1317 | + int err, flags=0; | |
| 1318 | + if (!PyArg_ParseTuple(args,"|i:close", &flags)) | |
| 1319 | + return NULL; | |
| 1320 | + if (self->db != NULL) { | |
| 1321 | + if (self->myenvobj) | |
| 1322 | + CHECK_ENV_NOT_CLOSED(self->myenvobj); | |
| 1323 | + err = self->db->close(self->db, flags); | |
| 1324 | + self->db = NULL; | |
| 1325 | + RETURN_IF_ERR(); | |
| 1326 | + } | |
| 1327 | + RETURN_NONE(); | |
| 1328 | +} | |
| 1329 | + | |
| 1330 | + | |
| 1331 | +#if (DBVER >= 32) | |
| 1332 | +static PyObject* | |
| 1333 | +_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) | |
| 1334 | +{ | |
| 1335 | + int err, flags=0, type; | |
| 1336 | + PyObject* txnobj = NULL; | |
| 1337 | + PyObject* retval = NULL; | |
| 1338 | + DBT key, data; | |
| 1339 | + DB_TXN *txn = NULL; | |
| 1340 | + static char* kwnames[] = { "txn", "flags", NULL }; | |
| 1341 | + | |
| 1342 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames, | |
| 1343 | + &txnobj, &flags)) | |
| 1344 | + return NULL; | |
| 1345 | + | |
| 1346 | + CHECK_DB_NOT_CLOSED(self); | |
| 1347 | + type = _DB_get_type(self); | |
| 1348 | + if (type == -1) | |
| 1349 | + return NULL; | |
| 1350 | + if (type != DB_QUEUE) { | |
| 1351 | + PyErr_SetString(PyExc_TypeError, | |
| 1352 | + "Consume methods only allowed for Queue DB's"); | |
| 1353 | + return NULL; | |
| 1354 | + } | |
| 1355 | + if (!checkTxnObj(txnobj, &txn)) | |
| 1356 | + return NULL; | |
| 1357 | + | |
| 1358 | + CLEAR_DBT(key); | |
| 1359 | + CLEAR_DBT(data); | |
| 1360 | + if (CHECK_DBFLAG(self, DB_THREAD)) { | |
| 1361 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 1362 | + data.flags = DB_DBT_MALLOC; | |
| 1363 | + key.flags = DB_DBT_MALLOC; | |
| 1364 | + } | |
| 1365 | + | |
| 1366 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1367 | + err = self->db->get(self->db, txn, &key, &data, flags|consume_flag); | |
| 1368 | + MYDB_END_ALLOW_THREADS; | |
| 1369 | + | |
| 1370 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 1371 | + && self->moduleFlags.getReturnsNone) { | |
| 1372 | + err = 0; | |
| 1373 | + Py_INCREF(Py_None); | |
| 1374 | + retval = Py_None; | |
| 1375 | + } | |
| 1376 | + else if (!err) { | |
| 1377 | + retval = Py_BuildValue("s#s#", key.data, key.size, data.data, | |
| 1378 | + data.size); | |
| 1379 | + FREE_DBT(key); | |
| 1380 | + FREE_DBT(data); | |
| 1381 | + } | |
| 1382 | + | |
| 1383 | + RETURN_IF_ERR(); | |
| 1384 | + return retval; | |
| 1385 | +} | |
| 1386 | + | |
| 1387 | +static PyObject* | |
| 1388 | +DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) | |
| 1389 | +{ | |
| 1390 | + return _DB_consume(self, args, kwargs, DB_CONSUME); | |
| 1391 | +} | |
| 1392 | + | |
| 1393 | +static PyObject* | |
| 1394 | +DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs, | |
| 1395 | + int consume_flag) | |
| 1396 | +{ | |
| 1397 | + return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT); | |
| 1398 | +} | |
| 1399 | +#endif | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | +static PyObject* | |
| 1404 | +DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1405 | +{ | |
| 1406 | + int err, flags=0; | |
| 1407 | + DBC* dbc; | |
| 1408 | + PyObject* txnobj = NULL; | |
| 1409 | + DB_TXN *txn = NULL; | |
| 1410 | + static char* kwnames[] = { "txn", "flags", NULL }; | |
| 1411 | + | |
| 1412 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, | |
| 1413 | + &txnobj, &flags)) | |
| 1414 | + return NULL; | |
| 1415 | + CHECK_DB_NOT_CLOSED(self); | |
| 1416 | + if (!checkTxnObj(txnobj, &txn)) | |
| 1417 | + return NULL; | |
| 1418 | + | |
| 1419 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1420 | + err = self->db->cursor(self->db, txn, &dbc, flags); | |
| 1421 | + MYDB_END_ALLOW_THREADS; | |
| 1422 | + RETURN_IF_ERR(); | |
| 1423 | + return (PyObject*) newDBCursorObject(dbc, self); | |
| 1424 | +} | |
| 1425 | + | |
| 1426 | + | |
| 1427 | +static PyObject* | |
| 1428 | +DB_delete(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1429 | +{ | |
| 1430 | + PyObject* txnobj = NULL; | |
| 1431 | + int flags = 0; | |
| 1432 | + PyObject* keyobj; | |
| 1433 | + DBT key; | |
| 1434 | + DB_TXN *txn = NULL; | |
| 1435 | + static char* kwnames[] = { "key", "txn", "flags", NULL }; | |
| 1436 | + | |
| 1437 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames, | |
| 1438 | + &keyobj, &txnobj, &flags)) | |
| 1439 | + return NULL; | |
| 1440 | + CHECK_DB_NOT_CLOSED(self); | |
| 1441 | + if (!make_key_dbt(self, keyobj, &key, NULL)) | |
| 1442 | + return NULL; | |
| 1443 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 1444 | + FREE_DBT(key); | |
| 1445 | + return NULL; | |
| 1446 | + } | |
| 1447 | + | |
| 1448 | + if (-1 == _DB_delete(self, txn, &key, 0)) { | |
| 1449 | + FREE_DBT(key); | |
| 1450 | + return NULL; | |
| 1451 | + } | |
| 1452 | + | |
| 1453 | + FREE_DBT(key); | |
| 1454 | + RETURN_NONE(); | |
| 1455 | +} | |
| 1456 | + | |
| 1457 | + | |
| 1458 | +static PyObject* | |
| 1459 | +DB_fd(DBObject* self, PyObject* args) | |
| 1460 | +{ | |
| 1461 | + int err, the_fd; | |
| 1462 | + | |
| 1463 | + if (!PyArg_ParseTuple(args,":fd")) | |
| 1464 | + return NULL; | |
| 1465 | + CHECK_DB_NOT_CLOSED(self); | |
| 1466 | + | |
| 1467 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1468 | + err = self->db->fd(self->db, &the_fd); | |
| 1469 | + MYDB_END_ALLOW_THREADS; | |
| 1470 | + RETURN_IF_ERR(); | |
| 1471 | + return PyInt_FromLong(the_fd); | |
| 1472 | +} | |
| 1473 | + | |
| 1474 | + | |
| 1475 | +static PyObject* | |
| 1476 | +DB_get(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1477 | +{ | |
| 1478 | + int err, flags=0; | |
| 1479 | + PyObject* txnobj = NULL; | |
| 1480 | + PyObject* keyobj; | |
| 1481 | + PyObject* dfltobj = NULL; | |
| 1482 | + PyObject* retval = NULL; | |
| 1483 | + int dlen = -1; | |
| 1484 | + int doff = -1; | |
| 1485 | + DBT key, data; | |
| 1486 | + DB_TXN *txn = NULL; | |
| 1487 | + static char* kwnames[] = {"key", "default", "txn", "flags", "dlen", | |
| 1488 | + "doff", NULL}; | |
| 1489 | + | |
| 1490 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames, | |
| 1491 | + &keyobj, &dfltobj, &txnobj, &flags, &dlen, | |
| 1492 | + &doff)) | |
| 1493 | + return NULL; | |
| 1494 | + | |
| 1495 | + CHECK_DB_NOT_CLOSED(self); | |
| 1496 | + if (!make_key_dbt(self, keyobj, &key, &flags)) | |
| 1497 | + return NULL; | |
| 1498 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 1499 | + FREE_DBT(key); | |
| 1500 | + return NULL; | |
| 1501 | + } | |
| 1502 | + | |
| 1503 | + CLEAR_DBT(data); | |
| 1504 | + if (CHECK_DBFLAG(self, DB_THREAD)) { | |
| 1505 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 1506 | + data.flags = DB_DBT_MALLOC; | |
| 1507 | + } | |
| 1508 | + if (!add_partial_dbt(&data, dlen, doff)) { | |
| 1509 | + FREE_DBT(key); | |
| 1510 | + return NULL; | |
| 1511 | + } | |
| 1512 | + | |
| 1513 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1514 | + err = self->db->get(self->db, txn, &key, &data, flags); | |
| 1515 | + MYDB_END_ALLOW_THREADS; | |
| 1516 | + | |
| 1517 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) { | |
| 1518 | + err = 0; | |
| 1519 | + Py_INCREF(dfltobj); | |
| 1520 | + retval = dfltobj; | |
| 1521 | + } | |
| 1522 | + else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 1523 | + && self->moduleFlags.getReturnsNone) { | |
| 1524 | + err = 0; | |
| 1525 | + Py_INCREF(Py_None); | |
| 1526 | + retval = Py_None; | |
| 1527 | + } | |
| 1528 | + else if (!err) { | |
| 1529 | + if (flags & DB_SET_RECNO) /* return both key and data */ | |
| 1530 | + retval = Py_BuildValue("s#s#", key.data, key.size, data.data, | |
| 1531 | + data.size); | |
| 1532 | + else /* return just the data */ | |
| 1533 | + retval = PyString_FromStringAndSize((char*)data.data, data.size); | |
| 1534 | + FREE_DBT(data); | |
| 1535 | + } | |
| 1536 | + FREE_DBT(key); | |
| 1537 | + | |
| 1538 | + RETURN_IF_ERR(); | |
| 1539 | + return retval; | |
| 1540 | +} | |
| 1541 | + | |
| 1542 | +#if (DBVER >= 33) | |
| 1543 | +static PyObject* | |
| 1544 | +DB_pget(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1545 | +{ | |
| 1546 | + int err, flags=0; | |
| 1547 | + PyObject* txnobj = NULL; | |
| 1548 | + PyObject* keyobj; | |
| 1549 | + PyObject* dfltobj = NULL; | |
| 1550 | + PyObject* retval = NULL; | |
| 1551 | + int dlen = -1; | |
| 1552 | + int doff = -1; | |
| 1553 | + DBT key, pkey, data; | |
| 1554 | + DB_TXN *txn = NULL; | |
| 1555 | + static char* kwnames[] = {"key", "default", "txn", "flags", "dlen", | |
| 1556 | + "doff", NULL}; | |
| 1557 | + | |
| 1558 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames, | |
| 1559 | + &keyobj, &dfltobj, &txnobj, &flags, &dlen, | |
| 1560 | + &doff)) | |
| 1561 | + return NULL; | |
| 1562 | + | |
| 1563 | + CHECK_DB_NOT_CLOSED(self); | |
| 1564 | + if (!make_key_dbt(self, keyobj, &key, &flags)) | |
| 1565 | + return NULL; | |
| 1566 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 1567 | + FREE_DBT(key); | |
| 1568 | + return NULL; | |
| 1569 | + } | |
| 1570 | + | |
| 1571 | + CLEAR_DBT(data); | |
| 1572 | + if (CHECK_DBFLAG(self, DB_THREAD)) { | |
| 1573 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 1574 | + data.flags = DB_DBT_MALLOC; | |
| 1575 | + } | |
| 1576 | + if (!add_partial_dbt(&data, dlen, doff)) { | |
| 1577 | + FREE_DBT(key); | |
| 1578 | + return NULL; | |
| 1579 | + } | |
| 1580 | + | |
| 1581 | + CLEAR_DBT(pkey); | |
| 1582 | + pkey.flags = DB_DBT_MALLOC; | |
| 1583 | + | |
| 1584 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1585 | + err = self->db->pget(self->db, txn, &key, &pkey, &data, flags); | |
| 1586 | + MYDB_END_ALLOW_THREADS; | |
| 1587 | + | |
| 1588 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) { | |
| 1589 | + err = 0; | |
| 1590 | + Py_INCREF(dfltobj); | |
| 1591 | + retval = dfltobj; | |
| 1592 | + } | |
| 1593 | + else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 1594 | + && self->moduleFlags.getReturnsNone) { | |
| 1595 | + err = 0; | |
| 1596 | + Py_INCREF(Py_None); | |
| 1597 | + retval = Py_None; | |
| 1598 | + } | |
| 1599 | + else if (!err) { | |
| 1600 | + PyObject *pkeyObj; | |
| 1601 | + PyObject *dataObj; | |
| 1602 | + dataObj = PyString_FromStringAndSize(data.data, data.size); | |
| 1603 | + | |
| 1604 | + if (self->primaryDBType == DB_RECNO || | |
| 1605 | + self->primaryDBType == DB_QUEUE) | |
| 1606 | + pkeyObj = PyInt_FromLong(*(int *)pkey.data); | |
| 1607 | + else | |
| 1608 | + pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size); | |
| 1609 | + | |
| 1610 | + if (flags & DB_SET_RECNO) /* return key , pkey and data */ | |
| 1611 | + { | |
| 1612 | + PyObject *keyObj; | |
| 1613 | + int type = _DB_get_type(self); | |
| 1614 | + if (type == DB_RECNO || type == DB_QUEUE) | |
| 1615 | + keyObj = PyInt_FromLong(*(int *)key.data); | |
| 1616 | + else | |
| 1617 | + keyObj = PyString_FromStringAndSize(key.data, key.size); | |
| 1618 | +#if (PY_VERSION_HEX >= 0x02040000) | |
| 1619 | + retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); | |
| 1620 | +#else | |
| 1621 | + retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); | |
| 1622 | +#endif | |
| 1623 | + Py_DECREF(keyObj); | |
| 1624 | + } | |
| 1625 | + else /* return just the pkey and data */ | |
| 1626 | + { | |
| 1627 | +#if (PY_VERSION_HEX >= 0x02040000) | |
| 1628 | + retval = PyTuple_Pack(2, pkeyObj, dataObj); | |
| 1629 | +#else | |
| 1630 | + retval = Py_BuildValue("OO", pkeyObj, dataObj); | |
| 1631 | +#endif | |
| 1632 | + } | |
| 1633 | + Py_DECREF(dataObj); | |
| 1634 | + Py_DECREF(pkeyObj); | |
| 1635 | + FREE_DBT(pkey); | |
| 1636 | + FREE_DBT(data); | |
| 1637 | + } | |
| 1638 | + FREE_DBT(key); | |
| 1639 | + | |
| 1640 | + RETURN_IF_ERR(); | |
| 1641 | + return retval; | |
| 1642 | +} | |
| 1643 | +#endif | |
| 1644 | + | |
| 1645 | + | |
| 1646 | +/* Return size of entry */ | |
| 1647 | +static PyObject* | |
| 1648 | +DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1649 | +{ | |
| 1650 | + int err, flags=0; | |
| 1651 | + PyObject* txnobj = NULL; | |
| 1652 | + PyObject* keyobj; | |
| 1653 | + PyObject* retval = NULL; | |
| 1654 | + DBT key, data; | |
| 1655 | + DB_TXN *txn = NULL; | |
| 1656 | + static char* kwnames[] = { "key", "txn", NULL }; | |
| 1657 | + | |
| 1658 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames, | |
| 1659 | + &keyobj, &txnobj)) | |
| 1660 | + return NULL; | |
| 1661 | + CHECK_DB_NOT_CLOSED(self); | |
| 1662 | + if (!make_key_dbt(self, keyobj, &key, &flags)) | |
| 1663 | + return NULL; | |
| 1664 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 1665 | + FREE_DBT(key); | |
| 1666 | + return NULL; | |
| 1667 | + } | |
| 1668 | + CLEAR_DBT(data); | |
| 1669 | + | |
| 1670 | + /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and | |
| 1671 | + thus getting the record size. */ | |
| 1672 | + data.flags = DB_DBT_USERMEM; | |
| 1673 | + data.ulen = 0; | |
| 1674 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1675 | + err = self->db->get(self->db, txn, &key, &data, flags); | |
| 1676 | + MYDB_END_ALLOW_THREADS; | |
| 1677 | + if (err == DB_BUFFER_SMALL) { | |
| 1678 | + retval = PyInt_FromLong((long)data.size); | |
| 1679 | + err = 0; | |
| 1680 | + } | |
| 1681 | + | |
| 1682 | + FREE_DBT(key); | |
| 1683 | + FREE_DBT(data); | |
| 1684 | + RETURN_IF_ERR(); | |
| 1685 | + return retval; | |
| 1686 | +} | |
| 1687 | + | |
| 1688 | + | |
| 1689 | +static PyObject* | |
| 1690 | +DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1691 | +{ | |
| 1692 | + int err, flags=0; | |
| 1693 | + PyObject* txnobj = NULL; | |
| 1694 | + PyObject* keyobj; | |
| 1695 | + PyObject* dataobj; | |
| 1696 | + PyObject* retval = NULL; | |
| 1697 | + DBT key, data; | |
| 1698 | + DB_TXN *txn = NULL; | |
| 1699 | + static char* kwnames[] = { "key", "data", "txn", "flags", NULL }; | |
| 1700 | + | |
| 1701 | + | |
| 1702 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames, | |
| 1703 | + &keyobj, &dataobj, &txnobj, &flags)) | |
| 1704 | + return NULL; | |
| 1705 | + | |
| 1706 | + CHECK_DB_NOT_CLOSED(self); | |
| 1707 | + if (!make_key_dbt(self, keyobj, &key, NULL)) | |
| 1708 | + return NULL; | |
| 1709 | + if ( !make_dbt(dataobj, &data) || | |
| 1710 | + !checkTxnObj(txnobj, &txn) ) | |
| 1711 | + { | |
| 1712 | + FREE_DBT(key); | |
| 1713 | + return NULL; | |
| 1714 | + } | |
| 1715 | + | |
| 1716 | + flags |= DB_GET_BOTH; | |
| 1717 | + | |
| 1718 | + if (CHECK_DBFLAG(self, DB_THREAD)) { | |
| 1719 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 1720 | + data.flags = DB_DBT_MALLOC; | |
| 1721 | + /* TODO: Is this flag needed? We're passing a data object that should | |
| 1722 | + match what's in the DB, so there should be no need to malloc. | |
| 1723 | + We run the risk of freeing something twice! Check this. */ | |
| 1724 | + } | |
| 1725 | + | |
| 1726 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1727 | + err = self->db->get(self->db, txn, &key, &data, flags); | |
| 1728 | + MYDB_END_ALLOW_THREADS; | |
| 1729 | + | |
| 1730 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 1731 | + && self->moduleFlags.getReturnsNone) { | |
| 1732 | + err = 0; | |
| 1733 | + Py_INCREF(Py_None); | |
| 1734 | + retval = Py_None; | |
| 1735 | + } | |
| 1736 | + else if (!err) { | |
| 1737 | + retval = PyString_FromStringAndSize((char*)data.data, data.size); | |
| 1738 | + FREE_DBT(data); /* Only if retrieval was successful */ | |
| 1739 | + } | |
| 1740 | + | |
| 1741 | + FREE_DBT(key); | |
| 1742 | + RETURN_IF_ERR(); | |
| 1743 | + return retval; | |
| 1744 | +} | |
| 1745 | + | |
| 1746 | + | |
| 1747 | +static PyObject* | |
| 1748 | +DB_get_byteswapped(DBObject* self, PyObject* args) | |
| 1749 | +{ | |
| 1750 | +#if (DBVER >= 33) | |
| 1751 | + int err = 0; | |
| 1752 | +#endif | |
| 1753 | + int retval = -1; | |
| 1754 | + | |
| 1755 | + if (!PyArg_ParseTuple(args,":get_byteswapped")) | |
| 1756 | + return NULL; | |
| 1757 | + CHECK_DB_NOT_CLOSED(self); | |
| 1758 | + | |
| 1759 | +#if (DBVER >= 33) | |
| 1760 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1761 | + err = self->db->get_byteswapped(self->db, &retval); | |
| 1762 | + MYDB_END_ALLOW_THREADS; | |
| 1763 | + RETURN_IF_ERR(); | |
| 1764 | +#else | |
| 1765 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1766 | + retval = self->db->get_byteswapped(self->db); | |
| 1767 | + MYDB_END_ALLOW_THREADS; | |
| 1768 | +#endif | |
| 1769 | + return PyInt_FromLong(retval); | |
| 1770 | +} | |
| 1771 | + | |
| 1772 | + | |
| 1773 | +static PyObject* | |
| 1774 | +DB_get_type(DBObject* self, PyObject* args) | |
| 1775 | +{ | |
| 1776 | + int type; | |
| 1777 | + | |
| 1778 | + if (!PyArg_ParseTuple(args,":get_type")) | |
| 1779 | + return NULL; | |
| 1780 | + CHECK_DB_NOT_CLOSED(self); | |
| 1781 | + | |
| 1782 | + type = _DB_get_type(self); | |
| 1783 | + if (type == -1) | |
| 1784 | + return NULL; | |
| 1785 | + return PyInt_FromLong(type); | |
| 1786 | +} | |
| 1787 | + | |
| 1788 | + | |
| 1789 | +static PyObject* | |
| 1790 | +DB_join(DBObject* self, PyObject* args) | |
| 1791 | +{ | |
| 1792 | + int err, flags=0; | |
| 1793 | + int length, x; | |
| 1794 | + PyObject* cursorsObj; | |
| 1795 | + DBC** cursors; | |
| 1796 | + DBC* dbc; | |
| 1797 | + | |
| 1798 | + if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags)) | |
| 1799 | + return NULL; | |
| 1800 | + | |
| 1801 | + CHECK_DB_NOT_CLOSED(self); | |
| 1802 | + | |
| 1803 | + if (!PySequence_Check(cursorsObj)) { | |
| 1804 | + PyErr_SetString(PyExc_TypeError, | |
| 1805 | + "Sequence of DBCursor objects expected"); | |
| 1806 | + return NULL; | |
| 1807 | + } | |
| 1808 | + | |
| 1809 | + length = PyObject_Length(cursorsObj); | |
| 1810 | + cursors = malloc((length+1) * sizeof(DBC*)); | |
| 1811 | + if (!cursors) { | |
| 1812 | + PyErr_NoMemory(); | |
| 1813 | + return NULL; | |
| 1814 | + } | |
| 1815 | + | |
| 1816 | + cursors[length] = NULL; | |
| 1817 | + for (x=0; x<length; x++) { | |
| 1818 | + PyObject* item = PySequence_GetItem(cursorsObj, x); | |
| 1819 | + if (item == NULL) { | |
| 1820 | + free(cursors); | |
| 1821 | + return NULL; | |
| 1822 | + } | |
| 1823 | + if (!DBCursorObject_Check(item)) { | |
| 1824 | + PyErr_SetString(PyExc_TypeError, | |
| 1825 | + "Sequence of DBCursor objects expected"); | |
| 1826 | + free(cursors); | |
| 1827 | + return NULL; | |
| 1828 | + } | |
| 1829 | + cursors[x] = ((DBCursorObject*)item)->dbc; | |
| 1830 | + Py_DECREF(item); | |
| 1831 | + } | |
| 1832 | + | |
| 1833 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1834 | + err = self->db->join(self->db, cursors, &dbc, flags); | |
| 1835 | + MYDB_END_ALLOW_THREADS; | |
| 1836 | + free(cursors); | |
| 1837 | + RETURN_IF_ERR(); | |
| 1838 | + | |
| 1839 | + /* FIXME: this is a buggy interface. The returned cursor | |
| 1840 | + contains internal references to the passed in cursors | |
| 1841 | + but does not hold python references to them or prevent | |
| 1842 | + them from being closed prematurely. This can cause | |
| 1843 | + python to crash when things are done in the wrong order. */ | |
| 1844 | + return (PyObject*) newDBCursorObject(dbc, self); | |
| 1845 | +} | |
| 1846 | + | |
| 1847 | + | |
| 1848 | +static PyObject* | |
| 1849 | +DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1850 | +{ | |
| 1851 | + int err, flags=0; | |
| 1852 | + PyObject* txnobj = NULL; | |
| 1853 | + PyObject* keyobj; | |
| 1854 | + DBT key; | |
| 1855 | + DB_TXN *txn = NULL; | |
| 1856 | + DB_KEY_RANGE range; | |
| 1857 | + static char* kwnames[] = { "key", "txn", "flags", NULL }; | |
| 1858 | + | |
| 1859 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames, | |
| 1860 | + &keyobj, &txnobj, &flags)) | |
| 1861 | + return NULL; | |
| 1862 | + CHECK_DB_NOT_CLOSED(self); | |
| 1863 | + if (!make_dbt(keyobj, &key)) | |
| 1864 | + /* BTree only, don't need to allow for an int key */ | |
| 1865 | + return NULL; | |
| 1866 | + if (!checkTxnObj(txnobj, &txn)) | |
| 1867 | + return NULL; | |
| 1868 | + | |
| 1869 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1870 | + err = self->db->key_range(self->db, txn, &key, &range, flags); | |
| 1871 | + MYDB_END_ALLOW_THREADS; | |
| 1872 | + | |
| 1873 | + RETURN_IF_ERR(); | |
| 1874 | + return Py_BuildValue("ddd", range.less, range.equal, range.greater); | |
| 1875 | +} | |
| 1876 | + | |
| 1877 | + | |
| 1878 | +static PyObject* | |
| 1879 | +DB_open(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1880 | +{ | |
| 1881 | + int err, type = DB_UNKNOWN, flags=0, mode=0660; | |
| 1882 | + char* filename = NULL; | |
| 1883 | + char* dbname = NULL; | |
| 1884 | +#if (DBVER >= 41) | |
| 1885 | + PyObject *txnobj = NULL; | |
| 1886 | + DB_TXN *txn = NULL; | |
| 1887 | + /* with dbname */ | |
| 1888 | + static char* kwnames[] = { | |
| 1889 | + "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL}; | |
| 1890 | + /* without dbname */ | |
| 1891 | + static char* kwnames_basic[] = { | |
| 1892 | + "filename", "dbtype", "flags", "mode", "txn", NULL}; | |
| 1893 | +#else | |
| 1894 | + /* with dbname */ | |
| 1895 | + static char* kwnames[] = { | |
| 1896 | + "filename", "dbname", "dbtype", "flags", "mode", NULL}; | |
| 1897 | + /* without dbname */ | |
| 1898 | + static char* kwnames_basic[] = { | |
| 1899 | + "filename", "dbtype", "flags", "mode", NULL}; | |
| 1900 | +#endif | |
| 1901 | + | |
| 1902 | +#if (DBVER >= 41) | |
| 1903 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames, | |
| 1904 | + &filename, &dbname, &type, &flags, &mode, | |
| 1905 | + &txnobj)) | |
| 1906 | +#else | |
| 1907 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames, | |
| 1908 | + &filename, &dbname, &type, &flags, | |
| 1909 | + &mode)) | |
| 1910 | +#endif | |
| 1911 | + { | |
| 1912 | + PyErr_Clear(); | |
| 1913 | + type = DB_UNKNOWN; flags = 0; mode = 0660; | |
| 1914 | + filename = NULL; dbname = NULL; | |
| 1915 | +#if (DBVER >= 41) | |
| 1916 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open", | |
| 1917 | + kwnames_basic, | |
| 1918 | + &filename, &type, &flags, &mode, | |
| 1919 | + &txnobj)) | |
| 1920 | + return NULL; | |
| 1921 | +#else | |
| 1922 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open", | |
| 1923 | + kwnames_basic, | |
| 1924 | + &filename, &type, &flags, &mode)) | |
| 1925 | + return NULL; | |
| 1926 | +#endif | |
| 1927 | + } | |
| 1928 | + | |
| 1929 | +#if (DBVER >= 41) | |
| 1930 | + if (!checkTxnObj(txnobj, &txn)) return NULL; | |
| 1931 | +#endif | |
| 1932 | + | |
| 1933 | + if (NULL == self->db) { | |
| 1934 | + PyObject *t = Py_BuildValue("(is)", 0, | |
| 1935 | + "Cannot call open() twice for DB object"); | |
| 1936 | + PyErr_SetObject(DBError, t); | |
| 1937 | + Py_DECREF(t); | |
| 1938 | + return NULL; | |
| 1939 | + } | |
| 1940 | + | |
| 1941 | +#if 0 && (DBVER >= 41) | |
| 1942 | + if ((!txn) && (txnobj != Py_None) && self->myenvobj | |
| 1943 | + && (self->myenvobj->flags & DB_INIT_TXN)) | |
| 1944 | + { | |
| 1945 | + /* If no 'txn' parameter was supplied (no DbTxn object and None was not | |
| 1946 | + * explicitly passed) but we are in a transaction ready environment: | |
| 1947 | + * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions | |
| 1948 | + * to work on BerkeleyDB 4.1 without needing to modify their | |
| 1949 | + * DBEnv or DB open calls. | |
| 1950 | + * TODO make this behaviour of the library configurable. | |
| 1951 | + */ | |
| 1952 | + flags |= DB_AUTO_COMMIT; | |
| 1953 | + } | |
| 1954 | +#endif | |
| 1955 | + | |
| 1956 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 1957 | +#if (DBVER >= 41) | |
| 1958 | + err = self->db->open(self->db, txn, filename, dbname, type, flags, mode); | |
| 1959 | +#else | |
| 1960 | + err = self->db->open(self->db, filename, dbname, type, flags, mode); | |
| 1961 | +#endif | |
| 1962 | + MYDB_END_ALLOW_THREADS; | |
| 1963 | + if (makeDBError(err)) { | |
| 1964 | + self->db->close(self->db, 0); | |
| 1965 | + self->db = NULL; | |
| 1966 | + return NULL; | |
| 1967 | + } | |
| 1968 | + | |
| 1969 | + self->flags = flags; | |
| 1970 | + RETURN_NONE(); | |
| 1971 | +} | |
| 1972 | + | |
| 1973 | + | |
| 1974 | +static PyObject* | |
| 1975 | +DB_put(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 1976 | +{ | |
| 1977 | + int flags=0; | |
| 1978 | + PyObject* txnobj = NULL; | |
| 1979 | + int dlen = -1; | |
| 1980 | + int doff = -1; | |
| 1981 | + PyObject* keyobj, *dataobj, *retval; | |
| 1982 | + DBT key, data; | |
| 1983 | + DB_TXN *txn = NULL; | |
| 1984 | + static char* kwnames[] = { "key", "data", "txn", "flags", "dlen", | |
| 1985 | + "doff", NULL }; | |
| 1986 | + | |
| 1987 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames, | |
| 1988 | + &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff)) | |
| 1989 | + return NULL; | |
| 1990 | + | |
| 1991 | + CHECK_DB_NOT_CLOSED(self); | |
| 1992 | + if (!make_key_dbt(self, keyobj, &key, NULL)) | |
| 1993 | + return NULL; | |
| 1994 | + if ( !make_dbt(dataobj, &data) || | |
| 1995 | + !add_partial_dbt(&data, dlen, doff) || | |
| 1996 | + !checkTxnObj(txnobj, &txn) ) | |
| 1997 | + { | |
| 1998 | + FREE_DBT(key); | |
| 1999 | + return NULL; | |
| 2000 | + } | |
| 2001 | + | |
| 2002 | + if (-1 == _DB_put(self, txn, &key, &data, flags)) { | |
| 2003 | + FREE_DBT(key); | |
| 2004 | + return NULL; | |
| 2005 | + } | |
| 2006 | + | |
| 2007 | + if (flags & DB_APPEND) | |
| 2008 | + retval = PyInt_FromLong(*((db_recno_t*)key.data)); | |
| 2009 | + else { | |
| 2010 | + retval = Py_None; | |
| 2011 | + Py_INCREF(retval); | |
| 2012 | + } | |
| 2013 | + FREE_DBT(key); | |
| 2014 | + return retval; | |
| 2015 | +} | |
| 2016 | + | |
| 2017 | + | |
| 2018 | + | |
| 2019 | +static PyObject* | |
| 2020 | +DB_remove(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 2021 | +{ | |
| 2022 | + char* filename; | |
| 2023 | + char* database = NULL; | |
| 2024 | + int err, flags=0; | |
| 2025 | + static char* kwnames[] = { "filename", "dbname", "flags", NULL}; | |
| 2026 | + | |
| 2027 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames, | |
| 2028 | + &filename, &database, &flags)) | |
| 2029 | + return NULL; | |
| 2030 | + CHECK_DB_NOT_CLOSED(self); | |
| 2031 | + | |
| 2032 | + err = self->db->remove(self->db, filename, database, flags); | |
| 2033 | + self->db = NULL; | |
| 2034 | + RETURN_IF_ERR(); | |
| 2035 | + RETURN_NONE(); | |
| 2036 | +} | |
| 2037 | + | |
| 2038 | + | |
| 2039 | + | |
| 2040 | +static PyObject* | |
| 2041 | +DB_rename(DBObject* self, PyObject* args) | |
| 2042 | +{ | |
| 2043 | + char* filename; | |
| 2044 | + char* database; | |
| 2045 | + char* newname; | |
| 2046 | + int err, flags=0; | |
| 2047 | + | |
| 2048 | + if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname, | |
| 2049 | + &flags)) | |
| 2050 | + return NULL; | |
| 2051 | + CHECK_DB_NOT_CLOSED(self); | |
| 2052 | + | |
| 2053 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2054 | + err = self->db->rename(self->db, filename, database, newname, flags); | |
| 2055 | + MYDB_END_ALLOW_THREADS; | |
| 2056 | + RETURN_IF_ERR(); | |
| 2057 | + RETURN_NONE(); | |
| 2058 | +} | |
| 2059 | + | |
| 2060 | + | |
| 2061 | +static PyObject* | |
| 2062 | +DB_set_bt_minkey(DBObject* self, PyObject* args) | |
| 2063 | +{ | |
| 2064 | + int err, minkey; | |
| 2065 | + | |
| 2066 | + if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey )) | |
| 2067 | + return NULL; | |
| 2068 | + CHECK_DB_NOT_CLOSED(self); | |
| 2069 | + | |
| 2070 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2071 | + err = self->db->set_bt_minkey(self->db, minkey); | |
| 2072 | + MYDB_END_ALLOW_THREADS; | |
| 2073 | + RETURN_IF_ERR(); | |
| 2074 | + RETURN_NONE(); | |
| 2075 | +} | |
| 2076 | + | |
| 2077 | +#if (DBVER >= 33) | |
| 2078 | +static int | |
| 2079 | +_default_cmp(const DBT *leftKey, | |
| 2080 | + const DBT *rightKey) | |
| 2081 | +{ | |
| 2082 | + int res; | |
| 2083 | + int lsize = leftKey->size, rsize = rightKey->size; | |
| 2084 | + | |
| 2085 | + res = memcmp(leftKey->data, rightKey->data, | |
| 2086 | + lsize < rsize ? lsize : rsize); | |
| 2087 | + | |
| 2088 | + if (res == 0) { | |
| 2089 | + if (lsize < rsize) { | |
| 2090 | + res = -1; | |
| 2091 | + } | |
| 2092 | + else if (lsize > rsize) { | |
| 2093 | + res = 1; | |
| 2094 | + } | |
| 2095 | + } | |
| 2096 | + return res; | |
| 2097 | +} | |
| 2098 | + | |
| 2099 | +static int | |
| 2100 | +_db_compareCallback(DB* db, | |
| 2101 | + const DBT *leftKey, | |
| 2102 | + const DBT *rightKey) | |
| 2103 | +{ | |
| 2104 | + int res = 0; | |
| 2105 | + PyObject *args; | |
| 2106 | + PyObject *result = NULL; | |
| 2107 | + DBObject *self = (DBObject *)db->app_private; | |
| 2108 | + | |
| 2109 | + if (self == NULL || self->btCompareCallback == NULL) { | |
| 2110 | + MYDB_BEGIN_BLOCK_THREADS; | |
| 2111 | + PyErr_SetString(PyExc_TypeError, | |
| 2112 | + (self == 0 | |
| 2113 | + ? "DB_bt_compare db is NULL." | |
| 2114 | + : "DB_bt_compare callback is NULL.")); | |
| 2115 | + /* we're in a callback within the DB code, we can't raise */ | |
| 2116 | + PyErr_Print(); | |
| 2117 | + res = _default_cmp(leftKey, rightKey); | |
| 2118 | + MYDB_END_BLOCK_THREADS; | |
| 2119 | + } else { | |
| 2120 | + MYDB_BEGIN_BLOCK_THREADS; | |
| 2121 | + | |
| 2122 | + args = Py_BuildValue("s#s#", leftKey->data, leftKey->size, | |
| 2123 | + rightKey->data, rightKey->size); | |
| 2124 | + if (args != NULL) { | |
| 2125 | + /* XXX(twouters) I highly doubt this INCREF is correct */ | |
| 2126 | + Py_INCREF(self); | |
| 2127 | + result = PyEval_CallObject(self->btCompareCallback, args); | |
| 2128 | + } | |
| 2129 | + if (args == NULL || result == NULL) { | |
| 2130 | + /* we're in a callback within the DB code, we can't raise */ | |
| 2131 | + PyErr_Print(); | |
| 2132 | + res = _default_cmp(leftKey, rightKey); | |
| 2133 | + } else if (PyInt_Check(result)) { | |
| 2134 | + res = PyInt_AsLong(result); | |
| 2135 | + } else { | |
| 2136 | + PyErr_SetString(PyExc_TypeError, | |
| 2137 | + "DB_bt_compare callback MUST return an int."); | |
| 2138 | + /* we're in a callback within the DB code, we can't raise */ | |
| 2139 | + PyErr_Print(); | |
| 2140 | + res = _default_cmp(leftKey, rightKey); | |
| 2141 | + } | |
| 2142 | + | |
| 2143 | + Py_XDECREF(args); | |
| 2144 | + Py_XDECREF(result); | |
| 2145 | + | |
| 2146 | + MYDB_END_BLOCK_THREADS; | |
| 2147 | + } | |
| 2148 | + return res; | |
| 2149 | +} | |
| 2150 | + | |
| 2151 | +static PyObject* | |
| 2152 | +DB_set_bt_compare(DBObject* self, PyObject* args) | |
| 2153 | +{ | |
| 2154 | + int err; | |
| 2155 | + PyObject *comparator; | |
| 2156 | + PyObject *tuple, *result; | |
| 2157 | + | |
| 2158 | + if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator)) | |
| 2159 | + return NULL; | |
| 2160 | + | |
| 2161 | + CHECK_DB_NOT_CLOSED(self); | |
| 2162 | + | |
| 2163 | + if (!PyCallable_Check(comparator)) { | |
| 2164 | + makeTypeError("Callable", comparator); | |
| 2165 | + return NULL; | |
| 2166 | + } | |
| 2167 | + | |
| 2168 | + /* | |
| 2169 | + * Perform a test call of the comparator function with two empty | |
| 2170 | + * string objects here. verify that it returns an int (0). | |
| 2171 | + * err if not. | |
| 2172 | + */ | |
| 2173 | + tuple = Py_BuildValue("(ss)", "", ""); | |
| 2174 | + result = PyEval_CallObject(comparator, tuple); | |
| 2175 | + Py_DECREF(tuple); | |
| 2176 | + if (result == NULL) | |
| 2177 | + return NULL; | |
| 2178 | + if (!PyInt_Check(result)) { | |
| 2179 | + PyErr_SetString(PyExc_TypeError, | |
| 2180 | + "callback MUST return an int"); | |
| 2181 | + return NULL; | |
| 2182 | + } else if (PyInt_AsLong(result) != 0) { | |
| 2183 | + PyErr_SetString(PyExc_TypeError, | |
| 2184 | + "callback failed to return 0 on two empty strings"); | |
| 2185 | + return NULL; | |
| 2186 | + } | |
| 2187 | + Py_DECREF(result); | |
| 2188 | + | |
| 2189 | + /* We don't accept multiple set_bt_compare operations, in order to | |
| 2190 | + * simplify the code. This would have no real use, as one cannot | |
| 2191 | + * change the function once the db is opened anyway */ | |
| 2192 | + if (self->btCompareCallback != NULL) { | |
| 2193 | + PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once"); | |
| 2194 | + return NULL; | |
| 2195 | + } | |
| 2196 | + | |
| 2197 | + Py_INCREF(comparator); | |
| 2198 | + self->btCompareCallback = comparator; | |
| 2199 | + | |
| 2200 | + /* This is to workaround a problem with un-initialized threads (see | |
| 2201 | + comment in DB_associate) */ | |
| 2202 | +#ifdef WITH_THREAD | |
| 2203 | + PyEval_InitThreads(); | |
| 2204 | +#endif | |
| 2205 | + | |
| 2206 | + err = self->db->set_bt_compare(self->db, _db_compareCallback); | |
| 2207 | + | |
| 2208 | + if (err) { | |
| 2209 | + /* restore the old state in case of error */ | |
| 2210 | + Py_DECREF(comparator); | |
| 2211 | + self->btCompareCallback = NULL; | |
| 2212 | + } | |
| 2213 | + | |
| 2214 | + RETURN_IF_ERR(); | |
| 2215 | + RETURN_NONE(); | |
| 2216 | +} | |
| 2217 | +#endif /* DBVER >= 33 */ | |
| 2218 | + | |
| 2219 | + | |
| 2220 | +static PyObject* | |
| 2221 | +DB_set_cachesize(DBObject* self, PyObject* args) | |
| 2222 | +{ | |
| 2223 | + int err; | |
| 2224 | + int gbytes = 0, bytes = 0, ncache = 0; | |
| 2225 | + | |
| 2226 | + if (!PyArg_ParseTuple(args,"ii|i:set_cachesize", | |
| 2227 | + &gbytes,&bytes,&ncache)) | |
| 2228 | + return NULL; | |
| 2229 | + CHECK_DB_NOT_CLOSED(self); | |
| 2230 | + | |
| 2231 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2232 | + err = self->db->set_cachesize(self->db, gbytes, bytes, ncache); | |
| 2233 | + MYDB_END_ALLOW_THREADS; | |
| 2234 | + RETURN_IF_ERR(); | |
| 2235 | + RETURN_NONE(); | |
| 2236 | +} | |
| 2237 | + | |
| 2238 | + | |
| 2239 | +static PyObject* | |
| 2240 | +DB_set_flags(DBObject* self, PyObject* args) | |
| 2241 | +{ | |
| 2242 | + int err, flags; | |
| 2243 | + | |
| 2244 | + if (!PyArg_ParseTuple(args,"i:set_flags", &flags)) | |
| 2245 | + return NULL; | |
| 2246 | + CHECK_DB_NOT_CLOSED(self); | |
| 2247 | + | |
| 2248 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2249 | + err = self->db->set_flags(self->db, flags); | |
| 2250 | + MYDB_END_ALLOW_THREADS; | |
| 2251 | + RETURN_IF_ERR(); | |
| 2252 | + | |
| 2253 | + self->setflags |= flags; | |
| 2254 | + RETURN_NONE(); | |
| 2255 | +} | |
| 2256 | + | |
| 2257 | + | |
| 2258 | +static PyObject* | |
| 2259 | +DB_set_h_ffactor(DBObject* self, PyObject* args) | |
| 2260 | +{ | |
| 2261 | + int err, ffactor; | |
| 2262 | + | |
| 2263 | + if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor)) | |
| 2264 | + return NULL; | |
| 2265 | + CHECK_DB_NOT_CLOSED(self); | |
| 2266 | + | |
| 2267 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2268 | + err = self->db->set_h_ffactor(self->db, ffactor); | |
| 2269 | + MYDB_END_ALLOW_THREADS; | |
| 2270 | + RETURN_IF_ERR(); | |
| 2271 | + RETURN_NONE(); | |
| 2272 | +} | |
| 2273 | + | |
| 2274 | + | |
| 2275 | +static PyObject* | |
| 2276 | +DB_set_h_nelem(DBObject* self, PyObject* args) | |
| 2277 | +{ | |
| 2278 | + int err, nelem; | |
| 2279 | + | |
| 2280 | + if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem)) | |
| 2281 | + return NULL; | |
| 2282 | + CHECK_DB_NOT_CLOSED(self); | |
| 2283 | + | |
| 2284 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2285 | + err = self->db->set_h_nelem(self->db, nelem); | |
| 2286 | + MYDB_END_ALLOW_THREADS; | |
| 2287 | + RETURN_IF_ERR(); | |
| 2288 | + RETURN_NONE(); | |
| 2289 | +} | |
| 2290 | + | |
| 2291 | + | |
| 2292 | +static PyObject* | |
| 2293 | +DB_set_lorder(DBObject* self, PyObject* args) | |
| 2294 | +{ | |
| 2295 | + int err, lorder; | |
| 2296 | + | |
| 2297 | + if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder)) | |
| 2298 | + return NULL; | |
| 2299 | + CHECK_DB_NOT_CLOSED(self); | |
| 2300 | + | |
| 2301 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2302 | + err = self->db->set_lorder(self->db, lorder); | |
| 2303 | + MYDB_END_ALLOW_THREADS; | |
| 2304 | + RETURN_IF_ERR(); | |
| 2305 | + RETURN_NONE(); | |
| 2306 | +} | |
| 2307 | + | |
| 2308 | + | |
| 2309 | +static PyObject* | |
| 2310 | +DB_set_pagesize(DBObject* self, PyObject* args) | |
| 2311 | +{ | |
| 2312 | + int err, pagesize; | |
| 2313 | + | |
| 2314 | + if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize)) | |
| 2315 | + return NULL; | |
| 2316 | + CHECK_DB_NOT_CLOSED(self); | |
| 2317 | + | |
| 2318 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2319 | + err = self->db->set_pagesize(self->db, pagesize); | |
| 2320 | + MYDB_END_ALLOW_THREADS; | |
| 2321 | + RETURN_IF_ERR(); | |
| 2322 | + RETURN_NONE(); | |
| 2323 | +} | |
| 2324 | + | |
| 2325 | + | |
| 2326 | +static PyObject* | |
| 2327 | +DB_set_re_delim(DBObject* self, PyObject* args) | |
| 2328 | +{ | |
| 2329 | + int err; | |
| 2330 | + char delim; | |
| 2331 | + | |
| 2332 | + if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) { | |
| 2333 | + PyErr_Clear(); | |
| 2334 | + if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim)) | |
| 2335 | + return NULL; | |
| 2336 | + } | |
| 2337 | + | |
| 2338 | + CHECK_DB_NOT_CLOSED(self); | |
| 2339 | + | |
| 2340 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2341 | + err = self->db->set_re_delim(self->db, delim); | |
| 2342 | + MYDB_END_ALLOW_THREADS; | |
| 2343 | + RETURN_IF_ERR(); | |
| 2344 | + RETURN_NONE(); | |
| 2345 | +} | |
| 2346 | + | |
| 2347 | +static PyObject* | |
| 2348 | +DB_set_re_len(DBObject* self, PyObject* args) | |
| 2349 | +{ | |
| 2350 | + int err, len; | |
| 2351 | + | |
| 2352 | + if (!PyArg_ParseTuple(args,"i:set_re_len", &len)) | |
| 2353 | + return NULL; | |
| 2354 | + CHECK_DB_NOT_CLOSED(self); | |
| 2355 | + | |
| 2356 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2357 | + err = self->db->set_re_len(self->db, len); | |
| 2358 | + MYDB_END_ALLOW_THREADS; | |
| 2359 | + RETURN_IF_ERR(); | |
| 2360 | + RETURN_NONE(); | |
| 2361 | +} | |
| 2362 | + | |
| 2363 | + | |
| 2364 | +static PyObject* | |
| 2365 | +DB_set_re_pad(DBObject* self, PyObject* args) | |
| 2366 | +{ | |
| 2367 | + int err; | |
| 2368 | + char pad; | |
| 2369 | + | |
| 2370 | + if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) { | |
| 2371 | + PyErr_Clear(); | |
| 2372 | + if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad)) | |
| 2373 | + return NULL; | |
| 2374 | + } | |
| 2375 | + CHECK_DB_NOT_CLOSED(self); | |
| 2376 | + | |
| 2377 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2378 | + err = self->db->set_re_pad(self->db, pad); | |
| 2379 | + MYDB_END_ALLOW_THREADS; | |
| 2380 | + RETURN_IF_ERR(); | |
| 2381 | + RETURN_NONE(); | |
| 2382 | +} | |
| 2383 | + | |
| 2384 | + | |
| 2385 | +static PyObject* | |
| 2386 | +DB_set_re_source(DBObject* self, PyObject* args) | |
| 2387 | +{ | |
| 2388 | + int err; | |
| 2389 | + char *re_source; | |
| 2390 | + | |
| 2391 | + if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source)) | |
| 2392 | + return NULL; | |
| 2393 | + CHECK_DB_NOT_CLOSED(self); | |
| 2394 | + | |
| 2395 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2396 | + err = self->db->set_re_source(self->db, re_source); | |
| 2397 | + MYDB_END_ALLOW_THREADS; | |
| 2398 | + RETURN_IF_ERR(); | |
| 2399 | + RETURN_NONE(); | |
| 2400 | +} | |
| 2401 | + | |
| 2402 | + | |
| 2403 | +#if (DBVER >= 32) | |
| 2404 | +static PyObject* | |
| 2405 | +DB_set_q_extentsize(DBObject* self, PyObject* args) | |
| 2406 | +{ | |
| 2407 | + int err; | |
| 2408 | + int extentsize; | |
| 2409 | + | |
| 2410 | + if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize)) | |
| 2411 | + return NULL; | |
| 2412 | + CHECK_DB_NOT_CLOSED(self); | |
| 2413 | + | |
| 2414 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2415 | + err = self->db->set_q_extentsize(self->db, extentsize); | |
| 2416 | + MYDB_END_ALLOW_THREADS; | |
| 2417 | + RETURN_IF_ERR(); | |
| 2418 | + RETURN_NONE(); | |
| 2419 | +} | |
| 2420 | +#endif | |
| 2421 | + | |
| 2422 | +static PyObject* | |
| 2423 | +DB_stat(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 2424 | +{ | |
| 2425 | + int err, flags = 0, type; | |
| 2426 | + void* sp; | |
| 2427 | + PyObject* d; | |
| 2428 | +#if (DBVER >= 43) | |
| 2429 | + PyObject* txnobj = NULL; | |
| 2430 | + DB_TXN *txn = NULL; | |
| 2431 | + static char* kwnames[] = { "flags", "txn", NULL }; | |
| 2432 | +#else | |
| 2433 | + static char* kwnames[] = { "flags", NULL }; | |
| 2434 | +#endif | |
| 2435 | + | |
| 2436 | +#if (DBVER >= 43) | |
| 2437 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames, | |
| 2438 | + &flags, &txnobj)) | |
| 2439 | + return NULL; | |
| 2440 | + if (!checkTxnObj(txnobj, &txn)) | |
| 2441 | + return NULL; | |
| 2442 | +#else | |
| 2443 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags)) | |
| 2444 | + return NULL; | |
| 2445 | +#endif | |
| 2446 | + CHECK_DB_NOT_CLOSED(self); | |
| 2447 | + | |
| 2448 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2449 | +#if (DBVER >= 43) | |
| 2450 | + err = self->db->stat(self->db, txn, &sp, flags); | |
| 2451 | +#elif (DBVER >= 33) | |
| 2452 | + err = self->db->stat(self->db, &sp, flags); | |
| 2453 | +#else | |
| 2454 | + err = self->db->stat(self->db, &sp, NULL, flags); | |
| 2455 | +#endif | |
| 2456 | + MYDB_END_ALLOW_THREADS; | |
| 2457 | + RETURN_IF_ERR(); | |
| 2458 | + | |
| 2459 | + self->haveStat = 1; | |
| 2460 | + | |
| 2461 | + /* Turn the stat structure into a dictionary */ | |
| 2462 | + type = _DB_get_type(self); | |
| 2463 | + if ((type == -1) || ((d = PyDict_New()) == NULL)) { | |
| 2464 | + free(sp); | |
| 2465 | + return NULL; | |
| 2466 | + } | |
| 2467 | + | |
| 2468 | +#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name) | |
| 2469 | +#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name) | |
| 2470 | +#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name) | |
| 2471 | + | |
| 2472 | + switch (type) { | |
| 2473 | + case DB_HASH: | |
| 2474 | + MAKE_HASH_ENTRY(magic); | |
| 2475 | + MAKE_HASH_ENTRY(version); | |
| 2476 | + MAKE_HASH_ENTRY(nkeys); | |
| 2477 | + MAKE_HASH_ENTRY(ndata); | |
| 2478 | + MAKE_HASH_ENTRY(pagesize); | |
| 2479 | +#if (DBVER < 41) | |
| 2480 | + MAKE_HASH_ENTRY(nelem); | |
| 2481 | +#endif | |
| 2482 | + MAKE_HASH_ENTRY(ffactor); | |
| 2483 | + MAKE_HASH_ENTRY(buckets); | |
| 2484 | + MAKE_HASH_ENTRY(free); | |
| 2485 | + MAKE_HASH_ENTRY(bfree); | |
| 2486 | + MAKE_HASH_ENTRY(bigpages); | |
| 2487 | + MAKE_HASH_ENTRY(big_bfree); | |
| 2488 | + MAKE_HASH_ENTRY(overflows); | |
| 2489 | + MAKE_HASH_ENTRY(ovfl_free); | |
| 2490 | + MAKE_HASH_ENTRY(dup); | |
| 2491 | + MAKE_HASH_ENTRY(dup_free); | |
| 2492 | + break; | |
| 2493 | + | |
| 2494 | + case DB_BTREE: | |
| 2495 | + case DB_RECNO: | |
| 2496 | + MAKE_BT_ENTRY(magic); | |
| 2497 | + MAKE_BT_ENTRY(version); | |
| 2498 | + MAKE_BT_ENTRY(nkeys); | |
| 2499 | + MAKE_BT_ENTRY(ndata); | |
| 2500 | + MAKE_BT_ENTRY(pagesize); | |
| 2501 | + MAKE_BT_ENTRY(minkey); | |
| 2502 | + MAKE_BT_ENTRY(re_len); | |
| 2503 | + MAKE_BT_ENTRY(re_pad); | |
| 2504 | + MAKE_BT_ENTRY(levels); | |
| 2505 | + MAKE_BT_ENTRY(int_pg); | |
| 2506 | + MAKE_BT_ENTRY(leaf_pg); | |
| 2507 | + MAKE_BT_ENTRY(dup_pg); | |
| 2508 | + MAKE_BT_ENTRY(over_pg); | |
| 2509 | + MAKE_BT_ENTRY(free); | |
| 2510 | + MAKE_BT_ENTRY(int_pgfree); | |
| 2511 | + MAKE_BT_ENTRY(leaf_pgfree); | |
| 2512 | + MAKE_BT_ENTRY(dup_pgfree); | |
| 2513 | + MAKE_BT_ENTRY(over_pgfree); | |
| 2514 | + break; | |
| 2515 | + | |
| 2516 | + case DB_QUEUE: | |
| 2517 | + MAKE_QUEUE_ENTRY(magic); | |
| 2518 | + MAKE_QUEUE_ENTRY(version); | |
| 2519 | + MAKE_QUEUE_ENTRY(nkeys); | |
| 2520 | + MAKE_QUEUE_ENTRY(ndata); | |
| 2521 | + MAKE_QUEUE_ENTRY(pagesize); | |
| 2522 | + MAKE_QUEUE_ENTRY(pages); | |
| 2523 | + MAKE_QUEUE_ENTRY(re_len); | |
| 2524 | + MAKE_QUEUE_ENTRY(re_pad); | |
| 2525 | + MAKE_QUEUE_ENTRY(pgfree); | |
| 2526 | +#if (DBVER == 31) | |
| 2527 | + MAKE_QUEUE_ENTRY(start); | |
| 2528 | +#endif | |
| 2529 | + MAKE_QUEUE_ENTRY(first_recno); | |
| 2530 | + MAKE_QUEUE_ENTRY(cur_recno); | |
| 2531 | + break; | |
| 2532 | + | |
| 2533 | + default: | |
| 2534 | + PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat"); | |
| 2535 | + Py_DECREF(d); | |
| 2536 | + d = NULL; | |
| 2537 | + } | |
| 2538 | + | |
| 2539 | +#undef MAKE_HASH_ENTRY | |
| 2540 | +#undef MAKE_BT_ENTRY | |
| 2541 | +#undef MAKE_QUEUE_ENTRY | |
| 2542 | + | |
| 2543 | + free(sp); | |
| 2544 | + return d; | |
| 2545 | +} | |
| 2546 | + | |
| 2547 | +static PyObject* | |
| 2548 | +DB_sync(DBObject* self, PyObject* args) | |
| 2549 | +{ | |
| 2550 | + int err; | |
| 2551 | + int flags = 0; | |
| 2552 | + | |
| 2553 | + if (!PyArg_ParseTuple(args,"|i:sync", &flags )) | |
| 2554 | + return NULL; | |
| 2555 | + CHECK_DB_NOT_CLOSED(self); | |
| 2556 | + | |
| 2557 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2558 | + err = self->db->sync(self->db, flags); | |
| 2559 | + MYDB_END_ALLOW_THREADS; | |
| 2560 | + RETURN_IF_ERR(); | |
| 2561 | + RETURN_NONE(); | |
| 2562 | +} | |
| 2563 | + | |
| 2564 | + | |
| 2565 | +#if (DBVER >= 33) | |
| 2566 | +static PyObject* | |
| 2567 | +DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 2568 | +{ | |
| 2569 | + int err, flags=0; | |
| 2570 | + u_int32_t count=0; | |
| 2571 | + PyObject* txnobj = NULL; | |
| 2572 | + DB_TXN *txn = NULL; | |
| 2573 | + static char* kwnames[] = { "txn", "flags", NULL }; | |
| 2574 | + | |
| 2575 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, | |
| 2576 | + &txnobj, &flags)) | |
| 2577 | + return NULL; | |
| 2578 | + CHECK_DB_NOT_CLOSED(self); | |
| 2579 | + if (!checkTxnObj(txnobj, &txn)) | |
| 2580 | + return NULL; | |
| 2581 | + | |
| 2582 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2583 | + err = self->db->truncate(self->db, txn, &count, flags); | |
| 2584 | + MYDB_END_ALLOW_THREADS; | |
| 2585 | + RETURN_IF_ERR(); | |
| 2586 | + return PyInt_FromLong(count); | |
| 2587 | +} | |
| 2588 | +#endif | |
| 2589 | + | |
| 2590 | + | |
| 2591 | +static PyObject* | |
| 2592 | +DB_upgrade(DBObject* self, PyObject* args) | |
| 2593 | +{ | |
| 2594 | + int err, flags=0; | |
| 2595 | + char *filename; | |
| 2596 | + | |
| 2597 | + if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags)) | |
| 2598 | + return NULL; | |
| 2599 | + CHECK_DB_NOT_CLOSED(self); | |
| 2600 | + | |
| 2601 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2602 | + err = self->db->upgrade(self->db, filename, flags); | |
| 2603 | + MYDB_END_ALLOW_THREADS; | |
| 2604 | + RETURN_IF_ERR(); | |
| 2605 | + RETURN_NONE(); | |
| 2606 | +} | |
| 2607 | + | |
| 2608 | + | |
| 2609 | +static PyObject* | |
| 2610 | +DB_verify(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 2611 | +{ | |
| 2612 | + int err, flags=0; | |
| 2613 | + char* fileName; | |
| 2614 | + char* dbName=NULL; | |
| 2615 | + char* outFileName=NULL; | |
| 2616 | + FILE* outFile=NULL; | |
| 2617 | + static char* kwnames[] = { "filename", "dbname", "outfile", "flags", | |
| 2618 | + NULL }; | |
| 2619 | + | |
| 2620 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames, | |
| 2621 | + &fileName, &dbName, &outFileName, &flags)) | |
| 2622 | + return NULL; | |
| 2623 | + | |
| 2624 | + CHECK_DB_NOT_CLOSED(self); | |
| 2625 | + if (outFileName) | |
| 2626 | + outFile = fopen(outFileName, "w"); | |
| 2627 | + /* XXX(nnorwitz): it should probably be an exception if outFile | |
| 2628 | + can't be opened. */ | |
| 2629 | + | |
| 2630 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2631 | + err = self->db->verify(self->db, fileName, dbName, outFile, flags); | |
| 2632 | + MYDB_END_ALLOW_THREADS; | |
| 2633 | + if (outFile) | |
| 2634 | + fclose(outFile); | |
| 2635 | + | |
| 2636 | + /* DB.verify acts as a DB handle destructor (like close); this was | |
| 2637 | + * documented in BerkeleyDB 4.2 but had the undocumented effect | |
| 2638 | + * of not being safe in prior versions while still requiring an explicit | |
| 2639 | + * DB.close call afterwards. Lets call close for the user to emulate | |
| 2640 | + * the safe 4.2 behaviour. */ | |
| 2641 | +#if (DBVER <= 41) | |
| 2642 | + self->db->close(self->db, 0); | |
| 2643 | +#endif | |
| 2644 | + self->db = NULL; | |
| 2645 | + | |
| 2646 | + RETURN_IF_ERR(); | |
| 2647 | + RETURN_NONE(); | |
| 2648 | +} | |
| 2649 | + | |
| 2650 | + | |
| 2651 | +static PyObject* | |
| 2652 | +DB_set_get_returns_none(DBObject* self, PyObject* args) | |
| 2653 | +{ | |
| 2654 | + int flags=0; | |
| 2655 | + int oldValue=0; | |
| 2656 | + | |
| 2657 | + if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags)) | |
| 2658 | + return NULL; | |
| 2659 | + CHECK_DB_NOT_CLOSED(self); | |
| 2660 | + | |
| 2661 | + if (self->moduleFlags.getReturnsNone) | |
| 2662 | + ++oldValue; | |
| 2663 | + if (self->moduleFlags.cursorSetReturnsNone) | |
| 2664 | + ++oldValue; | |
| 2665 | + self->moduleFlags.getReturnsNone = (flags >= 1); | |
| 2666 | + self->moduleFlags.cursorSetReturnsNone = (flags >= 2); | |
| 2667 | + return PyInt_FromLong(oldValue); | |
| 2668 | +} | |
| 2669 | + | |
| 2670 | +#if (DBVER >= 41) | |
| 2671 | +static PyObject* | |
| 2672 | +DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs) | |
| 2673 | +{ | |
| 2674 | + int err; | |
| 2675 | + u_int32_t flags=0; | |
| 2676 | + char *passwd = NULL; | |
| 2677 | + static char* kwnames[] = { "passwd", "flags", NULL }; | |
| 2678 | + | |
| 2679 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, | |
| 2680 | + &passwd, &flags)) { | |
| 2681 | + return NULL; | |
| 2682 | + } | |
| 2683 | + | |
| 2684 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2685 | + err = self->db->set_encrypt(self->db, passwd, flags); | |
| 2686 | + MYDB_END_ALLOW_THREADS; | |
| 2687 | + | |
| 2688 | + RETURN_IF_ERR(); | |
| 2689 | + RETURN_NONE(); | |
| 2690 | +} | |
| 2691 | +#endif /* DBVER >= 41 */ | |
| 2692 | + | |
| 2693 | + | |
| 2694 | +/*-------------------------------------------------------------- */ | |
| 2695 | +/* Mapping and Dictionary-like access routines */ | |
| 2696 | + | |
| 2697 | +Py_ssize_t DB_length(PyObject* _self) | |
| 2698 | +{ | |
| 2699 | + int err; | |
| 2700 | + Py_ssize_t size = 0; | |
| 2701 | + int flags = 0; | |
| 2702 | + void* sp; | |
| 2703 | + DBObject* self = (DBObject*)_self; | |
| 2704 | + | |
| 2705 | + if (self->db == NULL) { | |
| 2706 | + PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); | |
| 2707 | + PyErr_SetObject(DBError, t); | |
| 2708 | + Py_DECREF(t); | |
| 2709 | + return -1; | |
| 2710 | + } | |
| 2711 | + | |
| 2712 | + if (self->haveStat) { /* Has the stat function been called recently? If | |
| 2713 | + so, we can use the cached value. */ | |
| 2714 | + flags = DB_FAST_STAT; | |
| 2715 | + } | |
| 2716 | + | |
| 2717 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2718 | +redo_stat_for_length: | |
| 2719 | +#if (DBVER >= 43) | |
| 2720 | + err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags); | |
| 2721 | +#elif (DBVER >= 33) | |
| 2722 | + err = self->db->stat(self->db, &sp, flags); | |
| 2723 | +#else | |
| 2724 | + err = self->db->stat(self->db, &sp, NULL, flags); | |
| 2725 | +#endif | |
| 2726 | + | |
| 2727 | + /* All the stat structures have matching fields upto the ndata field, | |
| 2728 | + so we can use any of them for the type cast */ | |
| 2729 | + size = ((DB_BTREE_STAT*)sp)->bt_ndata; | |
| 2730 | + | |
| 2731 | + /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached. | |
| 2732 | + * redo a full stat to make sure. | |
| 2733 | + * Fixes SF python bug 1493322, pybsddb bug 1184012 | |
| 2734 | + */ | |
| 2735 | + if (size == 0 && (flags & DB_FAST_STAT)) { | |
| 2736 | + flags = 0; | |
| 2737 | + if (!err) | |
| 2738 | + free(sp); | |
| 2739 | + goto redo_stat_for_length; | |
| 2740 | + } | |
| 2741 | + | |
| 2742 | + MYDB_END_ALLOW_THREADS; | |
| 2743 | + | |
| 2744 | + if (err) | |
| 2745 | + return -1; | |
| 2746 | + | |
| 2747 | + self->haveStat = 1; | |
| 2748 | + | |
| 2749 | + free(sp); | |
| 2750 | + return size; | |
| 2751 | +} | |
| 2752 | + | |
| 2753 | + | |
| 2754 | +PyObject* DB_subscript(DBObject* self, PyObject* keyobj) | |
| 2755 | +{ | |
| 2756 | + int err; | |
| 2757 | + PyObject* retval; | |
| 2758 | + DBT key; | |
| 2759 | + DBT data; | |
| 2760 | + | |
| 2761 | + CHECK_DB_NOT_CLOSED(self); | |
| 2762 | + if (!make_key_dbt(self, keyobj, &key, NULL)) | |
| 2763 | + return NULL; | |
| 2764 | + | |
| 2765 | + CLEAR_DBT(data); | |
| 2766 | + if (CHECK_DBFLAG(self, DB_THREAD)) { | |
| 2767 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 2768 | + data.flags = DB_DBT_MALLOC; | |
| 2769 | + } | |
| 2770 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2771 | + err = self->db->get(self->db, NULL, &key, &data, 0); | |
| 2772 | + MYDB_END_ALLOW_THREADS; | |
| 2773 | + if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { | |
| 2774 | + PyErr_SetObject(PyExc_KeyError, keyobj); | |
| 2775 | + retval = NULL; | |
| 2776 | + } | |
| 2777 | + else if (makeDBError(err)) { | |
| 2778 | + retval = NULL; | |
| 2779 | + } | |
| 2780 | + else { | |
| 2781 | + retval = PyString_FromStringAndSize((char*)data.data, data.size); | |
| 2782 | + FREE_DBT(data); | |
| 2783 | + } | |
| 2784 | + | |
| 2785 | + FREE_DBT(key); | |
| 2786 | + return retval; | |
| 2787 | +} | |
| 2788 | + | |
| 2789 | + | |
| 2790 | +static int | |
| 2791 | +DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj) | |
| 2792 | +{ | |
| 2793 | + DBT key, data; | |
| 2794 | + int retval; | |
| 2795 | + int flags = 0; | |
| 2796 | + | |
| 2797 | + if (self->db == NULL) { | |
| 2798 | + PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); | |
| 2799 | + PyErr_SetObject(DBError, t); | |
| 2800 | + Py_DECREF(t); | |
| 2801 | + return -1; | |
| 2802 | + } | |
| 2803 | + | |
| 2804 | + if (!make_key_dbt(self, keyobj, &key, NULL)) | |
| 2805 | + return -1; | |
| 2806 | + | |
| 2807 | + if (dataobj != NULL) { | |
| 2808 | + if (!make_dbt(dataobj, &data)) | |
| 2809 | + retval = -1; | |
| 2810 | + else { | |
| 2811 | + if (self->setflags & (DB_DUP|DB_DUPSORT)) | |
| 2812 | + /* dictionaries shouldn't have duplicate keys */ | |
| 2813 | + flags = DB_NOOVERWRITE; | |
| 2814 | + retval = _DB_put(self, NULL, &key, &data, flags); | |
| 2815 | + | |
| 2816 | + if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) { | |
| 2817 | + /* try deleting any old record that matches and then PUT it | |
| 2818 | + * again... */ | |
| 2819 | + _DB_delete(self, NULL, &key, 0); | |
| 2820 | + PyErr_Clear(); | |
| 2821 | + retval = _DB_put(self, NULL, &key, &data, flags); | |
| 2822 | + } | |
| 2823 | + } | |
| 2824 | + } | |
| 2825 | + else { | |
| 2826 | + /* dataobj == NULL, so delete the key */ | |
| 2827 | + retval = _DB_delete(self, NULL, &key, 0); | |
| 2828 | + } | |
| 2829 | + FREE_DBT(key); | |
| 2830 | + return retval; | |
| 2831 | +} | |
| 2832 | + | |
| 2833 | + | |
| 2834 | +static PyObject* | |
| 2835 | +DB_has_key(DBObject* self, PyObject* args) | |
| 2836 | +{ | |
| 2837 | + int err; | |
| 2838 | + PyObject* keyobj; | |
| 2839 | + DBT key, data; | |
| 2840 | + PyObject* txnobj = NULL; | |
| 2841 | + DB_TXN *txn = NULL; | |
| 2842 | + | |
| 2843 | + if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj)) | |
| 2844 | + return NULL; | |
| 2845 | + CHECK_DB_NOT_CLOSED(self); | |
| 2846 | + if (!make_key_dbt(self, keyobj, &key, NULL)) | |
| 2847 | + return NULL; | |
| 2848 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 2849 | + FREE_DBT(key); | |
| 2850 | + return NULL; | |
| 2851 | + } | |
| 2852 | + | |
| 2853 | + /* This causes DB_BUFFER_SMALL to be returned when the db has the key because | |
| 2854 | + it has a record but can't allocate a buffer for the data. This saves | |
| 2855 | + having to deal with data we won't be using. | |
| 2856 | + */ | |
| 2857 | + CLEAR_DBT(data); | |
| 2858 | + data.flags = DB_DBT_USERMEM; | |
| 2859 | + | |
| 2860 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2861 | + err = self->db->get(self->db, txn, &key, &data, 0); | |
| 2862 | + MYDB_END_ALLOW_THREADS; | |
| 2863 | + FREE_DBT(key); | |
| 2864 | + | |
| 2865 | + if (err == DB_BUFFER_SMALL || err == 0) { | |
| 2866 | + return PyInt_FromLong(1); | |
| 2867 | + } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { | |
| 2868 | + return PyInt_FromLong(0); | |
| 2869 | + } | |
| 2870 | + | |
| 2871 | + makeDBError(err); | |
| 2872 | + return NULL; | |
| 2873 | +} | |
| 2874 | + | |
| 2875 | + | |
| 2876 | +#define _KEYS_LIST 1 | |
| 2877 | +#define _VALUES_LIST 2 | |
| 2878 | +#define _ITEMS_LIST 3 | |
| 2879 | + | |
| 2880 | +static PyObject* | |
| 2881 | +_DB_make_list(DBObject* self, DB_TXN* txn, int type) | |
| 2882 | +{ | |
| 2883 | + int err, dbtype; | |
| 2884 | + DBT key; | |
| 2885 | + DBT data; | |
| 2886 | + DBC *cursor; | |
| 2887 | + PyObject* list; | |
| 2888 | + PyObject* item = NULL; | |
| 2889 | + | |
| 2890 | + CHECK_DB_NOT_CLOSED(self); | |
| 2891 | + CLEAR_DBT(key); | |
| 2892 | + CLEAR_DBT(data); | |
| 2893 | + | |
| 2894 | + dbtype = _DB_get_type(self); | |
| 2895 | + if (dbtype == -1) | |
| 2896 | + return NULL; | |
| 2897 | + | |
| 2898 | + list = PyList_New(0); | |
| 2899 | + if (list == NULL) | |
| 2900 | + return NULL; | |
| 2901 | + | |
| 2902 | + /* get a cursor */ | |
| 2903 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2904 | + err = self->db->cursor(self->db, txn, &cursor, 0); | |
| 2905 | + MYDB_END_ALLOW_THREADS; | |
| 2906 | + if (makeDBError(err)) { | |
| 2907 | + Py_DECREF(list); | |
| 2908 | + return NULL; | |
| 2909 | + } | |
| 2910 | + | |
| 2911 | + if (CHECK_DBFLAG(self, DB_THREAD)) { | |
| 2912 | + key.flags = DB_DBT_REALLOC; | |
| 2913 | + data.flags = DB_DBT_REALLOC; | |
| 2914 | + } | |
| 2915 | + | |
| 2916 | + while (1) { /* use the cursor to traverse the DB, collecting items */ | |
| 2917 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2918 | + err = cursor->c_get(cursor, &key, &data, DB_NEXT); | |
| 2919 | + MYDB_END_ALLOW_THREADS; | |
| 2920 | + | |
| 2921 | + if (err) { | |
| 2922 | + /* for any error, break out of the loop */ | |
| 2923 | + break; | |
| 2924 | + } | |
| 2925 | + | |
| 2926 | + switch (type) { | |
| 2927 | + case _KEYS_LIST: | |
| 2928 | + switch(dbtype) { | |
| 2929 | + case DB_BTREE: | |
| 2930 | + case DB_HASH: | |
| 2931 | + default: | |
| 2932 | + item = PyString_FromStringAndSize((char*)key.data, key.size); | |
| 2933 | + break; | |
| 2934 | + case DB_RECNO: | |
| 2935 | + case DB_QUEUE: | |
| 2936 | + item = PyInt_FromLong(*((db_recno_t*)key.data)); | |
| 2937 | + break; | |
| 2938 | + } | |
| 2939 | + break; | |
| 2940 | + | |
| 2941 | + case _VALUES_LIST: | |
| 2942 | + item = PyString_FromStringAndSize((char*)data.data, data.size); | |
| 2943 | + break; | |
| 2944 | + | |
| 2945 | + case _ITEMS_LIST: | |
| 2946 | + switch(dbtype) { | |
| 2947 | + case DB_BTREE: | |
| 2948 | + case DB_HASH: | |
| 2949 | + default: | |
| 2950 | + item = Py_BuildValue("s#s#", key.data, key.size, data.data, | |
| 2951 | + data.size); | |
| 2952 | + break; | |
| 2953 | + case DB_RECNO: | |
| 2954 | + case DB_QUEUE: | |
| 2955 | + item = Py_BuildValue("is#", *((db_recno_t*)key.data), | |
| 2956 | + data.data, data.size); | |
| 2957 | + break; | |
| 2958 | + } | |
| 2959 | + break; | |
| 2960 | + default: | |
| 2961 | + PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type); | |
| 2962 | + item = NULL; | |
| 2963 | + break; | |
| 2964 | + } | |
| 2965 | + if (item == NULL) { | |
| 2966 | + Py_DECREF(list); | |
| 2967 | + list = NULL; | |
| 2968 | + goto done; | |
| 2969 | + } | |
| 2970 | + PyList_Append(list, item); | |
| 2971 | + Py_DECREF(item); | |
| 2972 | + } | |
| 2973 | + | |
| 2974 | + /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */ | |
| 2975 | + if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) { | |
| 2976 | + Py_DECREF(list); | |
| 2977 | + list = NULL; | |
| 2978 | + } | |
| 2979 | + | |
| 2980 | + done: | |
| 2981 | + FREE_DBT(key); | |
| 2982 | + FREE_DBT(data); | |
| 2983 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 2984 | + cursor->c_close(cursor); | |
| 2985 | + MYDB_END_ALLOW_THREADS; | |
| 2986 | + return list; | |
| 2987 | +} | |
| 2988 | + | |
| 2989 | + | |
| 2990 | +static PyObject* | |
| 2991 | +DB_keys(DBObject* self, PyObject* args) | |
| 2992 | +{ | |
| 2993 | + PyObject* txnobj = NULL; | |
| 2994 | + DB_TXN *txn = NULL; | |
| 2995 | + | |
| 2996 | + if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj)) | |
| 2997 | + return NULL; | |
| 2998 | + if (!checkTxnObj(txnobj, &txn)) | |
| 2999 | + return NULL; | |
| 3000 | + return _DB_make_list(self, txn, _KEYS_LIST); | |
| 3001 | +} | |
| 3002 | + | |
| 3003 | + | |
| 3004 | +static PyObject* | |
| 3005 | +DB_items(DBObject* self, PyObject* args) | |
| 3006 | +{ | |
| 3007 | + PyObject* txnobj = NULL; | |
| 3008 | + DB_TXN *txn = NULL; | |
| 3009 | + | |
| 3010 | + if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj)) | |
| 3011 | + return NULL; | |
| 3012 | + if (!checkTxnObj(txnobj, &txn)) | |
| 3013 | + return NULL; | |
| 3014 | + return _DB_make_list(self, txn, _ITEMS_LIST); | |
| 3015 | +} | |
| 3016 | + | |
| 3017 | + | |
| 3018 | +static PyObject* | |
| 3019 | +DB_values(DBObject* self, PyObject* args) | |
| 3020 | +{ | |
| 3021 | + PyObject* txnobj = NULL; | |
| 3022 | + DB_TXN *txn = NULL; | |
| 3023 | + | |
| 3024 | + if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj)) | |
| 3025 | + return NULL; | |
| 3026 | + if (!checkTxnObj(txnobj, &txn)) | |
| 3027 | + return NULL; | |
| 3028 | + return _DB_make_list(self, txn, _VALUES_LIST); | |
| 3029 | +} | |
| 3030 | + | |
| 3031 | +/* --------------------------------------------------------------------- */ | |
| 3032 | +/* DBCursor methods */ | |
| 3033 | + | |
| 3034 | + | |
| 3035 | +static PyObject* | |
| 3036 | +DBC_close(DBCursorObject* self, PyObject* args) | |
| 3037 | +{ | |
| 3038 | + int err = 0; | |
| 3039 | + | |
| 3040 | + if (!PyArg_ParseTuple(args, ":close")) | |
| 3041 | + return NULL; | |
| 3042 | + | |
| 3043 | + if (self->dbc != NULL) { | |
| 3044 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3045 | + err = self->dbc->c_close(self->dbc); | |
| 3046 | + self->dbc = NULL; | |
| 3047 | + MYDB_END_ALLOW_THREADS; | |
| 3048 | + } | |
| 3049 | + RETURN_IF_ERR(); | |
| 3050 | + RETURN_NONE(); | |
| 3051 | +} | |
| 3052 | + | |
| 3053 | + | |
| 3054 | +static PyObject* | |
| 3055 | +DBC_count(DBCursorObject* self, PyObject* args) | |
| 3056 | +{ | |
| 3057 | + int err = 0; | |
| 3058 | + db_recno_t count; | |
| 3059 | + int flags = 0; | |
| 3060 | + | |
| 3061 | + if (!PyArg_ParseTuple(args, "|i:count", &flags)) | |
| 3062 | + return NULL; | |
| 3063 | + | |
| 3064 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3065 | + | |
| 3066 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3067 | + err = self->dbc->c_count(self->dbc, &count, flags); | |
| 3068 | + MYDB_END_ALLOW_THREADS; | |
| 3069 | + RETURN_IF_ERR(); | |
| 3070 | + | |
| 3071 | + return PyInt_FromLong(count); | |
| 3072 | +} | |
| 3073 | + | |
| 3074 | + | |
| 3075 | +static PyObject* | |
| 3076 | +DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3077 | +{ | |
| 3078 | + return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current"); | |
| 3079 | +} | |
| 3080 | + | |
| 3081 | + | |
| 3082 | +static PyObject* | |
| 3083 | +DBC_delete(DBCursorObject* self, PyObject* args) | |
| 3084 | +{ | |
| 3085 | + int err, flags=0; | |
| 3086 | + | |
| 3087 | + if (!PyArg_ParseTuple(args, "|i:delete", &flags)) | |
| 3088 | + return NULL; | |
| 3089 | + | |
| 3090 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3091 | + | |
| 3092 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3093 | + err = self->dbc->c_del(self->dbc, flags); | |
| 3094 | + MYDB_END_ALLOW_THREADS; | |
| 3095 | + RETURN_IF_ERR(); | |
| 3096 | + | |
| 3097 | + self->mydb->haveStat = 0; | |
| 3098 | + RETURN_NONE(); | |
| 3099 | +} | |
| 3100 | + | |
| 3101 | + | |
| 3102 | +static PyObject* | |
| 3103 | +DBC_dup(DBCursorObject* self, PyObject* args) | |
| 3104 | +{ | |
| 3105 | + int err, flags =0; | |
| 3106 | + DBC* dbc = NULL; | |
| 3107 | + | |
| 3108 | + if (!PyArg_ParseTuple(args, "|i:dup", &flags)) | |
| 3109 | + return NULL; | |
| 3110 | + | |
| 3111 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3112 | + | |
| 3113 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3114 | + err = self->dbc->c_dup(self->dbc, &dbc, flags); | |
| 3115 | + MYDB_END_ALLOW_THREADS; | |
| 3116 | + RETURN_IF_ERR(); | |
| 3117 | + | |
| 3118 | + return (PyObject*) newDBCursorObject(dbc, self->mydb); | |
| 3119 | +} | |
| 3120 | + | |
| 3121 | +static PyObject* | |
| 3122 | +DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs) | |
| 3123 | +{ | |
| 3124 | + return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first"); | |
| 3125 | +} | |
| 3126 | + | |
| 3127 | + | |
| 3128 | +static PyObject* | |
| 3129 | +DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3130 | +{ | |
| 3131 | + int err, flags=0; | |
| 3132 | + PyObject* keyobj = NULL; | |
| 3133 | + PyObject* dataobj = NULL; | |
| 3134 | + PyObject* retval = NULL; | |
| 3135 | + int dlen = -1; | |
| 3136 | + int doff = -1; | |
| 3137 | + DBT key, data; | |
| 3138 | + static char* kwnames[] = { "key","data", "flags", "dlen", "doff", | |
| 3139 | + NULL }; | |
| 3140 | + | |
| 3141 | + CLEAR_DBT(key); | |
| 3142 | + CLEAR_DBT(data); | |
| 3143 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2], | |
| 3144 | + &flags, &dlen, &doff)) | |
| 3145 | + { | |
| 3146 | + PyErr_Clear(); | |
| 3147 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", | |
| 3148 | + &kwnames[1], | |
| 3149 | + &keyobj, &flags, &dlen, &doff)) | |
| 3150 | + { | |
| 3151 | + PyErr_Clear(); | |
| 3152 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get", | |
| 3153 | + kwnames, &keyobj, &dataobj, | |
| 3154 | + &flags, &dlen, &doff)) | |
| 3155 | + { | |
| 3156 | + return NULL; | |
| 3157 | + } | |
| 3158 | + } | |
| 3159 | + } | |
| 3160 | + | |
| 3161 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3162 | + | |
| 3163 | + if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 3164 | + return NULL; | |
| 3165 | + if ( (dataobj && !make_dbt(dataobj, &data)) || | |
| 3166 | + (!add_partial_dbt(&data, dlen, doff)) ) | |
| 3167 | + { | |
| 3168 | + FREE_DBT(key); | |
| 3169 | + return NULL; | |
| 3170 | + } | |
| 3171 | + | |
| 3172 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3173 | + data.flags = DB_DBT_MALLOC; | |
| 3174 | + if (!(key.flags & DB_DBT_REALLOC)) { | |
| 3175 | + key.flags |= DB_DBT_MALLOC; | |
| 3176 | + } | |
| 3177 | + } | |
| 3178 | + | |
| 3179 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3180 | + err = self->dbc->c_get(self->dbc, &key, &data, flags); | |
| 3181 | + MYDB_END_ALLOW_THREADS; | |
| 3182 | + | |
| 3183 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 3184 | + && self->mydb->moduleFlags.getReturnsNone) { | |
| 3185 | + Py_INCREF(Py_None); | |
| 3186 | + retval = Py_None; | |
| 3187 | + } | |
| 3188 | + else if (makeDBError(err)) { | |
| 3189 | + retval = NULL; | |
| 3190 | + } | |
| 3191 | + else { | |
| 3192 | + switch (_DB_get_type(self->mydb)) { | |
| 3193 | + case -1: | |
| 3194 | + retval = NULL; | |
| 3195 | + break; | |
| 3196 | + case DB_BTREE: | |
| 3197 | + case DB_HASH: | |
| 3198 | + default: | |
| 3199 | + retval = Py_BuildValue("s#s#", key.data, key.size, | |
| 3200 | + data.data, data.size); | |
| 3201 | + break; | |
| 3202 | + case DB_RECNO: | |
| 3203 | + case DB_QUEUE: | |
| 3204 | + retval = Py_BuildValue("is#", *((db_recno_t*)key.data), | |
| 3205 | + data.data, data.size); | |
| 3206 | + break; | |
| 3207 | + } | |
| 3208 | + FREE_DBT(data); | |
| 3209 | + } | |
| 3210 | + FREE_DBT(key); | |
| 3211 | + return retval; | |
| 3212 | +} | |
| 3213 | + | |
| 3214 | +#if (DBVER >= 33) | |
| 3215 | +static PyObject* | |
| 3216 | +DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3217 | +{ | |
| 3218 | + int err, flags=0; | |
| 3219 | + PyObject* keyobj = NULL; | |
| 3220 | + PyObject* dataobj = NULL; | |
| 3221 | + PyObject* retval = NULL; | |
| 3222 | + int dlen = -1; | |
| 3223 | + int doff = -1; | |
| 3224 | + DBT key, pkey, data; | |
| 3225 | + static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL }; | |
| 3226 | + static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL }; | |
| 3227 | + | |
| 3228 | + CLEAR_DBT(key); | |
| 3229 | + CLEAR_DBT(data); | |
| 3230 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2], | |
| 3231 | + &flags, &dlen, &doff)) | |
| 3232 | + { | |
| 3233 | + PyErr_Clear(); | |
| 3234 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget", | |
| 3235 | + kwnames_keyOnly, | |
| 3236 | + &keyobj, &flags, &dlen, &doff)) | |
| 3237 | + { | |
| 3238 | + PyErr_Clear(); | |
| 3239 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget", | |
| 3240 | + kwnames, &keyobj, &dataobj, | |
| 3241 | + &flags, &dlen, &doff)) | |
| 3242 | + { | |
| 3243 | + return NULL; | |
| 3244 | + } | |
| 3245 | + } | |
| 3246 | + } | |
| 3247 | + | |
| 3248 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3249 | + | |
| 3250 | + if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 3251 | + return NULL; | |
| 3252 | + if ( (dataobj && !make_dbt(dataobj, &data)) || | |
| 3253 | + (!add_partial_dbt(&data, dlen, doff)) ) { | |
| 3254 | + FREE_DBT(key); | |
| 3255 | + return NULL; | |
| 3256 | + } | |
| 3257 | + | |
| 3258 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3259 | + data.flags = DB_DBT_MALLOC; | |
| 3260 | + if (!(key.flags & DB_DBT_REALLOC)) { | |
| 3261 | + key.flags |= DB_DBT_MALLOC; | |
| 3262 | + } | |
| 3263 | + } | |
| 3264 | + | |
| 3265 | + CLEAR_DBT(pkey); | |
| 3266 | + pkey.flags = DB_DBT_MALLOC; | |
| 3267 | + | |
| 3268 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3269 | + err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags); | |
| 3270 | + MYDB_END_ALLOW_THREADS; | |
| 3271 | + | |
| 3272 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 3273 | + && self->mydb->moduleFlags.getReturnsNone) { | |
| 3274 | + Py_INCREF(Py_None); | |
| 3275 | + retval = Py_None; | |
| 3276 | + } | |
| 3277 | + else if (makeDBError(err)) { | |
| 3278 | + retval = NULL; | |
| 3279 | + } | |
| 3280 | + else { | |
| 3281 | + PyObject *pkeyObj; | |
| 3282 | + PyObject *dataObj; | |
| 3283 | + dataObj = PyString_FromStringAndSize(data.data, data.size); | |
| 3284 | + | |
| 3285 | + if (self->mydb->primaryDBType == DB_RECNO || | |
| 3286 | + self->mydb->primaryDBType == DB_QUEUE) | |
| 3287 | + pkeyObj = PyInt_FromLong(*(int *)pkey.data); | |
| 3288 | + else | |
| 3289 | + pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size); | |
| 3290 | + | |
| 3291 | + if (key.data && key.size) /* return key, pkey and data */ | |
| 3292 | + { | |
| 3293 | + PyObject *keyObj; | |
| 3294 | + int type = _DB_get_type(self->mydb); | |
| 3295 | + if (type == DB_RECNO || type == DB_QUEUE) | |
| 3296 | + keyObj = PyInt_FromLong(*(int *)key.data); | |
| 3297 | + else | |
| 3298 | + keyObj = PyString_FromStringAndSize(key.data, key.size); | |
| 3299 | +#if (PY_VERSION_HEX >= 0x02040000) | |
| 3300 | + retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); | |
| 3301 | +#else | |
| 3302 | + retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); | |
| 3303 | +#endif | |
| 3304 | + Py_DECREF(keyObj); | |
| 3305 | + FREE_DBT(key); | |
| 3306 | + } | |
| 3307 | + else /* return just the pkey and data */ | |
| 3308 | + { | |
| 3309 | +#if (PY_VERSION_HEX >= 0x02040000) | |
| 3310 | + retval = PyTuple_Pack(2, pkeyObj, dataObj); | |
| 3311 | +#else | |
| 3312 | + retval = Py_BuildValue("OO", pkeyObj, dataObj); | |
| 3313 | +#endif | |
| 3314 | + } | |
| 3315 | + Py_DECREF(dataObj); | |
| 3316 | + Py_DECREF(pkeyObj); | |
| 3317 | + FREE_DBT(pkey); | |
| 3318 | + FREE_DBT(data); | |
| 3319 | + } | |
| 3320 | + /* the only time REALLOC should be set is if we used an integer | |
| 3321 | + * key that make_key_dbt malloc'd for us. always free these. */ | |
| 3322 | + if (key.flags & DB_DBT_REALLOC) { | |
| 3323 | + FREE_DBT(key); | |
| 3324 | + } | |
| 3325 | + return retval; | |
| 3326 | +} | |
| 3327 | +#endif | |
| 3328 | + | |
| 3329 | + | |
| 3330 | +static PyObject* | |
| 3331 | +DBC_get_recno(DBCursorObject* self, PyObject* args) | |
| 3332 | +{ | |
| 3333 | + int err; | |
| 3334 | + db_recno_t recno; | |
| 3335 | + DBT key; | |
| 3336 | + DBT data; | |
| 3337 | + | |
| 3338 | + if (!PyArg_ParseTuple(args, ":get_recno")) | |
| 3339 | + return NULL; | |
| 3340 | + | |
| 3341 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3342 | + | |
| 3343 | + CLEAR_DBT(key); | |
| 3344 | + CLEAR_DBT(data); | |
| 3345 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3346 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 3347 | + data.flags = DB_DBT_MALLOC; | |
| 3348 | + key.flags = DB_DBT_MALLOC; | |
| 3349 | + } | |
| 3350 | + | |
| 3351 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3352 | + err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO); | |
| 3353 | + MYDB_END_ALLOW_THREADS; | |
| 3354 | + RETURN_IF_ERR(); | |
| 3355 | + | |
| 3356 | + recno = *((db_recno_t*)data.data); | |
| 3357 | + FREE_DBT(key); | |
| 3358 | + FREE_DBT(data); | |
| 3359 | + return PyInt_FromLong(recno); | |
| 3360 | +} | |
| 3361 | + | |
| 3362 | + | |
| 3363 | +static PyObject* | |
| 3364 | +DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3365 | +{ | |
| 3366 | + return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last"); | |
| 3367 | +} | |
| 3368 | + | |
| 3369 | + | |
| 3370 | +static PyObject* | |
| 3371 | +DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3372 | +{ | |
| 3373 | + return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next"); | |
| 3374 | +} | |
| 3375 | + | |
| 3376 | + | |
| 3377 | +static PyObject* | |
| 3378 | +DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3379 | +{ | |
| 3380 | + return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev"); | |
| 3381 | +} | |
| 3382 | + | |
| 3383 | + | |
| 3384 | +static PyObject* | |
| 3385 | +DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs) | |
| 3386 | +{ | |
| 3387 | + int err, flags = 0; | |
| 3388 | + PyObject* keyobj, *dataobj; | |
| 3389 | + DBT key, data; | |
| 3390 | + static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", | |
| 3391 | + NULL }; | |
| 3392 | + int dlen = -1; | |
| 3393 | + int doff = -1; | |
| 3394 | + | |
| 3395 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames, | |
| 3396 | + &keyobj, &dataobj, &flags, &dlen, &doff)) | |
| 3397 | + return NULL; | |
| 3398 | + | |
| 3399 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3400 | + | |
| 3401 | + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 3402 | + return NULL; | |
| 3403 | + if (!make_dbt(dataobj, &data) || | |
| 3404 | + !add_partial_dbt(&data, dlen, doff) ) | |
| 3405 | + { | |
| 3406 | + FREE_DBT(key); | |
| 3407 | + return NULL; | |
| 3408 | + } | |
| 3409 | + | |
| 3410 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3411 | + err = self->dbc->c_put(self->dbc, &key, &data, flags); | |
| 3412 | + MYDB_END_ALLOW_THREADS; | |
| 3413 | + FREE_DBT(key); | |
| 3414 | + RETURN_IF_ERR(); | |
| 3415 | + self->mydb->haveStat = 0; | |
| 3416 | + RETURN_NONE(); | |
| 3417 | +} | |
| 3418 | + | |
| 3419 | + | |
| 3420 | +static PyObject* | |
| 3421 | +DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3422 | +{ | |
| 3423 | + int err, flags = 0; | |
| 3424 | + DBT key, data; | |
| 3425 | + PyObject* retval, *keyobj; | |
| 3426 | + static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; | |
| 3427 | + int dlen = -1; | |
| 3428 | + int doff = -1; | |
| 3429 | + | |
| 3430 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames, | |
| 3431 | + &keyobj, &flags, &dlen, &doff)) | |
| 3432 | + return NULL; | |
| 3433 | + | |
| 3434 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3435 | + | |
| 3436 | + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 3437 | + return NULL; | |
| 3438 | + | |
| 3439 | + CLEAR_DBT(data); | |
| 3440 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3441 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 3442 | + data.flags = DB_DBT_MALLOC; | |
| 3443 | + } | |
| 3444 | + if (!add_partial_dbt(&data, dlen, doff)) { | |
| 3445 | + FREE_DBT(key); | |
| 3446 | + return NULL; | |
| 3447 | + } | |
| 3448 | + | |
| 3449 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3450 | + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET); | |
| 3451 | + MYDB_END_ALLOW_THREADS; | |
| 3452 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 3453 | + && self->mydb->moduleFlags.cursorSetReturnsNone) { | |
| 3454 | + Py_INCREF(Py_None); | |
| 3455 | + retval = Py_None; | |
| 3456 | + } | |
| 3457 | + else if (makeDBError(err)) { | |
| 3458 | + retval = NULL; | |
| 3459 | + } | |
| 3460 | + else { | |
| 3461 | + switch (_DB_get_type(self->mydb)) { | |
| 3462 | + case -1: | |
| 3463 | + retval = NULL; | |
| 3464 | + break; | |
| 3465 | + case DB_BTREE: | |
| 3466 | + case DB_HASH: | |
| 3467 | + default: | |
| 3468 | + retval = Py_BuildValue("s#s#", key.data, key.size, | |
| 3469 | + data.data, data.size); | |
| 3470 | + break; | |
| 3471 | + case DB_RECNO: | |
| 3472 | + case DB_QUEUE: | |
| 3473 | + retval = Py_BuildValue("is#", *((db_recno_t*)key.data), | |
| 3474 | + data.data, data.size); | |
| 3475 | + break; | |
| 3476 | + } | |
| 3477 | + FREE_DBT(data); | |
| 3478 | + FREE_DBT(key); | |
| 3479 | + } | |
| 3480 | + /* the only time REALLOC should be set is if we used an integer | |
| 3481 | + * key that make_key_dbt malloc'd for us. always free these. */ | |
| 3482 | + if (key.flags & DB_DBT_REALLOC) { | |
| 3483 | + FREE_DBT(key); | |
| 3484 | + } | |
| 3485 | + | |
| 3486 | + return retval; | |
| 3487 | +} | |
| 3488 | + | |
| 3489 | + | |
| 3490 | +static PyObject* | |
| 3491 | +DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs) | |
| 3492 | +{ | |
| 3493 | + int err, flags = 0; | |
| 3494 | + DBT key, data; | |
| 3495 | + PyObject* retval, *keyobj; | |
| 3496 | + static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; | |
| 3497 | + int dlen = -1; | |
| 3498 | + int doff = -1; | |
| 3499 | + | |
| 3500 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames, | |
| 3501 | + &keyobj, &flags, &dlen, &doff)) | |
| 3502 | + return NULL; | |
| 3503 | + | |
| 3504 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3505 | + | |
| 3506 | + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 3507 | + return NULL; | |
| 3508 | + | |
| 3509 | + CLEAR_DBT(data); | |
| 3510 | + if (!add_partial_dbt(&data, dlen, doff)) { | |
| 3511 | + FREE_DBT(key); | |
| 3512 | + return NULL; | |
| 3513 | + } | |
| 3514 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3515 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 3516 | + data.flags |= DB_DBT_MALLOC; | |
| 3517 | + /* only BTREE databases will return anything in the key */ | |
| 3518 | + if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) { | |
| 3519 | + key.flags |= DB_DBT_MALLOC; | |
| 3520 | + } | |
| 3521 | + } | |
| 3522 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3523 | + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE); | |
| 3524 | + MYDB_END_ALLOW_THREADS; | |
| 3525 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 3526 | + && self->mydb->moduleFlags.cursorSetReturnsNone) { | |
| 3527 | + Py_INCREF(Py_None); | |
| 3528 | + retval = Py_None; | |
| 3529 | + } | |
| 3530 | + else if (makeDBError(err)) { | |
| 3531 | + retval = NULL; | |
| 3532 | + } | |
| 3533 | + else { | |
| 3534 | + switch (_DB_get_type(self->mydb)) { | |
| 3535 | + case -1: | |
| 3536 | + retval = NULL; | |
| 3537 | + break; | |
| 3538 | + case DB_BTREE: | |
| 3539 | + case DB_HASH: | |
| 3540 | + default: | |
| 3541 | + retval = Py_BuildValue("s#s#", key.data, key.size, | |
| 3542 | + data.data, data.size); | |
| 3543 | + break; | |
| 3544 | + case DB_RECNO: | |
| 3545 | + case DB_QUEUE: | |
| 3546 | + retval = Py_BuildValue("is#", *((db_recno_t*)key.data), | |
| 3547 | + data.data, data.size); | |
| 3548 | + break; | |
| 3549 | + } | |
| 3550 | + FREE_DBT(key); | |
| 3551 | + FREE_DBT(data); | |
| 3552 | + } | |
| 3553 | + /* the only time REALLOC should be set is if we used an integer | |
| 3554 | + * key that make_key_dbt malloc'd for us. always free these. */ | |
| 3555 | + if (key.flags & DB_DBT_REALLOC) { | |
| 3556 | + FREE_DBT(key); | |
| 3557 | + } | |
| 3558 | + | |
| 3559 | + return retval; | |
| 3560 | +} | |
| 3561 | + | |
| 3562 | +static PyObject* | |
| 3563 | +_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj, | |
| 3564 | + int flags, unsigned int returnsNone) | |
| 3565 | +{ | |
| 3566 | + int err; | |
| 3567 | + DBT key, data; | |
| 3568 | + PyObject* retval; | |
| 3569 | + | |
| 3570 | + /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */ | |
| 3571 | + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 3572 | + return NULL; | |
| 3573 | + if (!make_dbt(dataobj, &data)) { | |
| 3574 | + FREE_DBT(key); | |
| 3575 | + return NULL; | |
| 3576 | + } | |
| 3577 | + | |
| 3578 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3579 | + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH); | |
| 3580 | + MYDB_END_ALLOW_THREADS; | |
| 3581 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) { | |
| 3582 | + Py_INCREF(Py_None); | |
| 3583 | + retval = Py_None; | |
| 3584 | + } | |
| 3585 | + else if (makeDBError(err)) { | |
| 3586 | + retval = NULL; | |
| 3587 | + } | |
| 3588 | + else { | |
| 3589 | + switch (_DB_get_type(self->mydb)) { | |
| 3590 | + case -1: | |
| 3591 | + retval = NULL; | |
| 3592 | + break; | |
| 3593 | + case DB_BTREE: | |
| 3594 | + case DB_HASH: | |
| 3595 | + default: | |
| 3596 | + retval = Py_BuildValue("s#s#", key.data, key.size, | |
| 3597 | + data.data, data.size); | |
| 3598 | + break; | |
| 3599 | + case DB_RECNO: | |
| 3600 | + case DB_QUEUE: | |
| 3601 | + retval = Py_BuildValue("is#", *((db_recno_t*)key.data), | |
| 3602 | + data.data, data.size); | |
| 3603 | + break; | |
| 3604 | + } | |
| 3605 | + } | |
| 3606 | + | |
| 3607 | + FREE_DBT(key); | |
| 3608 | + return retval; | |
| 3609 | +} | |
| 3610 | + | |
| 3611 | +static PyObject* | |
| 3612 | +DBC_get_both(DBCursorObject* self, PyObject* args) | |
| 3613 | +{ | |
| 3614 | + int flags=0; | |
| 3615 | + PyObject *keyobj, *dataobj; | |
| 3616 | + | |
| 3617 | + if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags)) | |
| 3618 | + return NULL; | |
| 3619 | + | |
| 3620 | + /* if the cursor is closed, self->mydb may be invalid */ | |
| 3621 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3622 | + | |
| 3623 | + return _DBC_get_set_both(self, keyobj, dataobj, flags, | |
| 3624 | + self->mydb->moduleFlags.getReturnsNone); | |
| 3625 | +} | |
| 3626 | + | |
| 3627 | +/* Return size of entry */ | |
| 3628 | +static PyObject* | |
| 3629 | +DBC_get_current_size(DBCursorObject* self, PyObject* args) | |
| 3630 | +{ | |
| 3631 | + int err, flags=DB_CURRENT; | |
| 3632 | + PyObject* retval = NULL; | |
| 3633 | + DBT key, data; | |
| 3634 | + | |
| 3635 | + if (!PyArg_ParseTuple(args, ":get_current_size")) | |
| 3636 | + return NULL; | |
| 3637 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3638 | + CLEAR_DBT(key); | |
| 3639 | + CLEAR_DBT(data); | |
| 3640 | + | |
| 3641 | + /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus | |
| 3642 | + getting the record size. */ | |
| 3643 | + data.flags = DB_DBT_USERMEM; | |
| 3644 | + data.ulen = 0; | |
| 3645 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3646 | + err = self->dbc->c_get(self->dbc, &key, &data, flags); | |
| 3647 | + MYDB_END_ALLOW_THREADS; | |
| 3648 | + if (err == DB_BUFFER_SMALL || !err) { | |
| 3649 | + /* DB_BUFFER_SMALL means positive size, !err means zero length value */ | |
| 3650 | + retval = PyInt_FromLong((long)data.size); | |
| 3651 | + err = 0; | |
| 3652 | + } | |
| 3653 | + | |
| 3654 | + FREE_DBT(key); | |
| 3655 | + FREE_DBT(data); | |
| 3656 | + RETURN_IF_ERR(); | |
| 3657 | + return retval; | |
| 3658 | +} | |
| 3659 | + | |
| 3660 | +static PyObject* | |
| 3661 | +DBC_set_both(DBCursorObject* self, PyObject* args) | |
| 3662 | +{ | |
| 3663 | + int flags=0; | |
| 3664 | + PyObject *keyobj, *dataobj; | |
| 3665 | + | |
| 3666 | + if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags)) | |
| 3667 | + return NULL; | |
| 3668 | + | |
| 3669 | + /* if the cursor is closed, self->mydb may be invalid */ | |
| 3670 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3671 | + | |
| 3672 | + return _DBC_get_set_both(self, keyobj, dataobj, flags, | |
| 3673 | + self->mydb->moduleFlags.cursorSetReturnsNone); | |
| 3674 | +} | |
| 3675 | + | |
| 3676 | + | |
| 3677 | +static PyObject* | |
| 3678 | +DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3679 | +{ | |
| 3680 | + int err, irecno, flags=0; | |
| 3681 | + db_recno_t recno; | |
| 3682 | + DBT key, data; | |
| 3683 | + PyObject* retval; | |
| 3684 | + int dlen = -1; | |
| 3685 | + int doff = -1; | |
| 3686 | + static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL }; | |
| 3687 | + | |
| 3688 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames, | |
| 3689 | + &irecno, &flags, &dlen, &doff)) | |
| 3690 | + return NULL; | |
| 3691 | + | |
| 3692 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3693 | + | |
| 3694 | + CLEAR_DBT(key); | |
| 3695 | + recno = (db_recno_t) irecno; | |
| 3696 | + /* use allocated space so DB will be able to realloc room for the real | |
| 3697 | + * key */ | |
| 3698 | + key.data = malloc(sizeof(db_recno_t)); | |
| 3699 | + if (key.data == NULL) { | |
| 3700 | + PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); | |
| 3701 | + return NULL; | |
| 3702 | + } | |
| 3703 | + key.size = sizeof(db_recno_t); | |
| 3704 | + key.ulen = key.size; | |
| 3705 | + memcpy(key.data, &recno, sizeof(db_recno_t)); | |
| 3706 | + key.flags = DB_DBT_REALLOC; | |
| 3707 | + | |
| 3708 | + CLEAR_DBT(data); | |
| 3709 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3710 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 3711 | + data.flags = DB_DBT_MALLOC; | |
| 3712 | + } | |
| 3713 | + if (!add_partial_dbt(&data, dlen, doff)) { | |
| 3714 | + FREE_DBT(key); | |
| 3715 | + return NULL; | |
| 3716 | + } | |
| 3717 | + | |
| 3718 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3719 | + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO); | |
| 3720 | + MYDB_END_ALLOW_THREADS; | |
| 3721 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 3722 | + && self->mydb->moduleFlags.cursorSetReturnsNone) { | |
| 3723 | + Py_INCREF(Py_None); | |
| 3724 | + retval = Py_None; | |
| 3725 | + } | |
| 3726 | + else if (makeDBError(err)) { | |
| 3727 | + retval = NULL; | |
| 3728 | + } | |
| 3729 | + else { /* Can only be used for BTrees, so no need to return int key */ | |
| 3730 | + retval = Py_BuildValue("s#s#", key.data, key.size, | |
| 3731 | + data.data, data.size); | |
| 3732 | + FREE_DBT(data); | |
| 3733 | + } | |
| 3734 | + FREE_DBT(key); | |
| 3735 | + | |
| 3736 | + return retval; | |
| 3737 | +} | |
| 3738 | + | |
| 3739 | + | |
| 3740 | +static PyObject* | |
| 3741 | +DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3742 | +{ | |
| 3743 | + return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume"); | |
| 3744 | +} | |
| 3745 | + | |
| 3746 | + | |
| 3747 | +static PyObject* | |
| 3748 | +DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3749 | +{ | |
| 3750 | + return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup"); | |
| 3751 | +} | |
| 3752 | + | |
| 3753 | + | |
| 3754 | +static PyObject* | |
| 3755 | +DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3756 | +{ | |
| 3757 | + return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup"); | |
| 3758 | +} | |
| 3759 | + | |
| 3760 | + | |
| 3761 | +static PyObject* | |
| 3762 | +DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) | |
| 3763 | +{ | |
| 3764 | + return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup"); | |
| 3765 | +} | |
| 3766 | + | |
| 3767 | + | |
| 3768 | +static PyObject* | |
| 3769 | +DBC_join_item(DBCursorObject* self, PyObject* args) | |
| 3770 | +{ | |
| 3771 | + int err, flags=0; | |
| 3772 | + DBT key, data; | |
| 3773 | + PyObject* retval; | |
| 3774 | + | |
| 3775 | + if (!PyArg_ParseTuple(args, "|i:join_item", &flags)) | |
| 3776 | + return NULL; | |
| 3777 | + | |
| 3778 | + CHECK_CURSOR_NOT_CLOSED(self); | |
| 3779 | + | |
| 3780 | + CLEAR_DBT(key); | |
| 3781 | + CLEAR_DBT(data); | |
| 3782 | + if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { | |
| 3783 | + /* Tell BerkeleyDB to malloc the return value (thread safe) */ | |
| 3784 | + key.flags = DB_DBT_MALLOC; | |
| 3785 | + } | |
| 3786 | + | |
| 3787 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3788 | + err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); | |
| 3789 | + MYDB_END_ALLOW_THREADS; | |
| 3790 | + if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) | |
| 3791 | + && self->mydb->moduleFlags.getReturnsNone) { | |
| 3792 | + Py_INCREF(Py_None); | |
| 3793 | + retval = Py_None; | |
| 3794 | + } | |
| 3795 | + else if (makeDBError(err)) { | |
| 3796 | + retval = NULL; | |
| 3797 | + } | |
| 3798 | + else { | |
| 3799 | + retval = Py_BuildValue("s#", key.data, key.size); | |
| 3800 | + FREE_DBT(key); | |
| 3801 | + } | |
| 3802 | + | |
| 3803 | + return retval; | |
| 3804 | +} | |
| 3805 | + | |
| 3806 | + | |
| 3807 | + | |
| 3808 | +/* --------------------------------------------------------------------- */ | |
| 3809 | +/* DBEnv methods */ | |
| 3810 | + | |
| 3811 | + | |
| 3812 | +static PyObject* | |
| 3813 | +DBEnv_close(DBEnvObject* self, PyObject* args) | |
| 3814 | +{ | |
| 3815 | + int err, flags = 0; | |
| 3816 | + | |
| 3817 | + if (!PyArg_ParseTuple(args, "|i:close", &flags)) | |
| 3818 | + return NULL; | |
| 3819 | + if (!self->closed) { /* Don't close more than once */ | |
| 3820 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3821 | + err = self->db_env->close(self->db_env, flags); | |
| 3822 | + MYDB_END_ALLOW_THREADS; | |
| 3823 | + /* after calling DBEnv->close, regardless of error, this DBEnv | |
| 3824 | + * may not be accessed again (BerkeleyDB docs). */ | |
| 3825 | + self->closed = 1; | |
| 3826 | + self->db_env = NULL; | |
| 3827 | + RETURN_IF_ERR(); | |
| 3828 | + } | |
| 3829 | + RETURN_NONE(); | |
| 3830 | +} | |
| 3831 | + | |
| 3832 | + | |
| 3833 | +static PyObject* | |
| 3834 | +DBEnv_open(DBEnvObject* self, PyObject* args) | |
| 3835 | +{ | |
| 3836 | + int err, flags=0, mode=0660; | |
| 3837 | + char *db_home; | |
| 3838 | + | |
| 3839 | + if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode)) | |
| 3840 | + return NULL; | |
| 3841 | + | |
| 3842 | + CHECK_ENV_NOT_CLOSED(self); | |
| 3843 | + | |
| 3844 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3845 | + err = self->db_env->open(self->db_env, db_home, flags, mode); | |
| 3846 | + MYDB_END_ALLOW_THREADS; | |
| 3847 | + RETURN_IF_ERR(); | |
| 3848 | + self->closed = 0; | |
| 3849 | + self->flags = flags; | |
| 3850 | + RETURN_NONE(); | |
| 3851 | +} | |
| 3852 | + | |
| 3853 | + | |
| 3854 | +static PyObject* | |
| 3855 | +DBEnv_remove(DBEnvObject* self, PyObject* args) | |
| 3856 | +{ | |
| 3857 | + int err, flags=0; | |
| 3858 | + char *db_home; | |
| 3859 | + | |
| 3860 | + if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags)) | |
| 3861 | + return NULL; | |
| 3862 | + CHECK_ENV_NOT_CLOSED(self); | |
| 3863 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3864 | + err = self->db_env->remove(self->db_env, db_home, flags); | |
| 3865 | + MYDB_END_ALLOW_THREADS; | |
| 3866 | + RETURN_IF_ERR(); | |
| 3867 | + RETURN_NONE(); | |
| 3868 | +} | |
| 3869 | + | |
| 3870 | +#if (DBVER >= 41) | |
| 3871 | +static PyObject* | |
| 3872 | +DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs) | |
| 3873 | +{ | |
| 3874 | + int err; | |
| 3875 | + u_int32_t flags=0; | |
| 3876 | + char *file = NULL; | |
| 3877 | + char *database = NULL; | |
| 3878 | + PyObject *txnobj = NULL; | |
| 3879 | + DB_TXN *txn = NULL; | |
| 3880 | + static char* kwnames[] = { "file", "database", "txn", "flags", | |
| 3881 | + NULL }; | |
| 3882 | + | |
| 3883 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames, | |
| 3884 | + &file, &database, &txnobj, &flags)) { | |
| 3885 | + return NULL; | |
| 3886 | + } | |
| 3887 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 3888 | + return NULL; | |
| 3889 | + } | |
| 3890 | + CHECK_ENV_NOT_CLOSED(self); | |
| 3891 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3892 | + err = self->db_env->dbremove(self->db_env, txn, file, database, flags); | |
| 3893 | + MYDB_END_ALLOW_THREADS; | |
| 3894 | + RETURN_IF_ERR(); | |
| 3895 | + RETURN_NONE(); | |
| 3896 | +} | |
| 3897 | + | |
| 3898 | +static PyObject* | |
| 3899 | +DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs) | |
| 3900 | +{ | |
| 3901 | + int err; | |
| 3902 | + u_int32_t flags=0; | |
| 3903 | + char *file = NULL; | |
| 3904 | + char *database = NULL; | |
| 3905 | + char *newname = NULL; | |
| 3906 | + PyObject *txnobj = NULL; | |
| 3907 | + DB_TXN *txn = NULL; | |
| 3908 | + static char* kwnames[] = { "file", "database", "newname", "txn", | |
| 3909 | + "flags", NULL }; | |
| 3910 | + | |
| 3911 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames, | |
| 3912 | + &file, &database, &newname, &txnobj, &flags)) { | |
| 3913 | + return NULL; | |
| 3914 | + } | |
| 3915 | + if (!checkTxnObj(txnobj, &txn)) { | |
| 3916 | + return NULL; | |
| 3917 | + } | |
| 3918 | + CHECK_ENV_NOT_CLOSED(self); | |
| 3919 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3920 | + err = self->db_env->dbrename(self->db_env, txn, file, database, newname, | |
| 3921 | + flags); | |
| 3922 | + MYDB_END_ALLOW_THREADS; | |
| 3923 | + RETURN_IF_ERR(); | |
| 3924 | + RETURN_NONE(); | |
| 3925 | +} | |
| 3926 | + | |
| 3927 | +static PyObject* | |
| 3928 | +DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs) | |
| 3929 | +{ | |
| 3930 | + int err; | |
| 3931 | + u_int32_t flags=0; | |
| 3932 | + char *passwd = NULL; | |
| 3933 | + static char* kwnames[] = { "passwd", "flags", NULL }; | |
| 3934 | + | |
| 3935 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, | |
| 3936 | + &passwd, &flags)) { | |
| 3937 | + return NULL; | |
| 3938 | + } | |
| 3939 | + | |
| 3940 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3941 | + err = self->db_env->set_encrypt(self->db_env, passwd, flags); | |
| 3942 | + MYDB_END_ALLOW_THREADS; | |
| 3943 | + | |
| 3944 | + RETURN_IF_ERR(); | |
| 3945 | + RETURN_NONE(); | |
| 3946 | +} | |
| 3947 | +#endif /* DBVER >= 41 */ | |
| 3948 | + | |
| 3949 | +#if (DBVER >= 40) | |
| 3950 | +static PyObject* | |
| 3951 | +DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs) | |
| 3952 | +{ | |
| 3953 | + int err; | |
| 3954 | + u_int32_t flags=0; | |
| 3955 | + u_int32_t timeout = 0; | |
| 3956 | + static char* kwnames[] = { "timeout", "flags", NULL }; | |
| 3957 | + | |
| 3958 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames, | |
| 3959 | + &timeout, &flags)) { | |
| 3960 | + return NULL; | |
| 3961 | + } | |
| 3962 | + | |
| 3963 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3964 | + err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags); | |
| 3965 | + MYDB_END_ALLOW_THREADS; | |
| 3966 | + | |
| 3967 | + RETURN_IF_ERR(); | |
| 3968 | + RETURN_NONE(); | |
| 3969 | +} | |
| 3970 | +#endif /* DBVER >= 40 */ | |
| 3971 | + | |
| 3972 | +static PyObject* | |
| 3973 | +DBEnv_set_shm_key(DBEnvObject* self, PyObject* args) | |
| 3974 | +{ | |
| 3975 | + int err; | |
| 3976 | + long shm_key = 0; | |
| 3977 | + | |
| 3978 | + if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key)) | |
| 3979 | + return NULL; | |
| 3980 | + CHECK_ENV_NOT_CLOSED(self); | |
| 3981 | + | |
| 3982 | + err = self->db_env->set_shm_key(self->db_env, shm_key); | |
| 3983 | + RETURN_IF_ERR(); | |
| 3984 | + RETURN_NONE(); | |
| 3985 | +} | |
| 3986 | + | |
| 3987 | +static PyObject* | |
| 3988 | +DBEnv_set_cachesize(DBEnvObject* self, PyObject* args) | |
| 3989 | +{ | |
| 3990 | + int err, gbytes=0, bytes=0, ncache=0; | |
| 3991 | + | |
| 3992 | + if (!PyArg_ParseTuple(args, "ii|i:set_cachesize", | |
| 3993 | + &gbytes, &bytes, &ncache)) | |
| 3994 | + return NULL; | |
| 3995 | + CHECK_ENV_NOT_CLOSED(self); | |
| 3996 | + | |
| 3997 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 3998 | + err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache); | |
| 3999 | + MYDB_END_ALLOW_THREADS; | |
| 4000 | + RETURN_IF_ERR(); | |
| 4001 | + RETURN_NONE(); | |
| 4002 | +} | |
| 4003 | + | |
| 4004 | + | |
| 4005 | +#if (DBVER >= 32) | |
| 4006 | +static PyObject* | |
| 4007 | +DBEnv_set_flags(DBEnvObject* self, PyObject* args) | |
| 4008 | +{ | |
| 4009 | + int err, flags=0, onoff=0; | |
| 4010 | + | |
| 4011 | + if (!PyArg_ParseTuple(args, "ii:set_flags", | |
| 4012 | + &flags, &onoff)) | |
| 4013 | + return NULL; | |
| 4014 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4015 | + | |
| 4016 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4017 | + err = self->db_env->set_flags(self->db_env, flags, onoff); | |
| 4018 | + MYDB_END_ALLOW_THREADS; | |
| 4019 | + RETURN_IF_ERR(); | |
| 4020 | + RETURN_NONE(); | |
| 4021 | +} | |
| 4022 | +#endif | |
| 4023 | + | |
| 4024 | + | |
| 4025 | +static PyObject* | |
| 4026 | +DBEnv_set_data_dir(DBEnvObject* self, PyObject* args) | |
| 4027 | +{ | |
| 4028 | + int err; | |
| 4029 | + char *dir; | |
| 4030 | + | |
| 4031 | + if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir)) | |
| 4032 | + return NULL; | |
| 4033 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4034 | + | |
| 4035 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4036 | + err = self->db_env->set_data_dir(self->db_env, dir); | |
| 4037 | + MYDB_END_ALLOW_THREADS; | |
| 4038 | + RETURN_IF_ERR(); | |
| 4039 | + RETURN_NONE(); | |
| 4040 | +} | |
| 4041 | + | |
| 4042 | + | |
| 4043 | +static PyObject* | |
| 4044 | +DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args) | |
| 4045 | +{ | |
| 4046 | + int err, lg_bsize; | |
| 4047 | + | |
| 4048 | + if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize)) | |
| 4049 | + return NULL; | |
| 4050 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4051 | + | |
| 4052 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4053 | + err = self->db_env->set_lg_bsize(self->db_env, lg_bsize); | |
| 4054 | + MYDB_END_ALLOW_THREADS; | |
| 4055 | + RETURN_IF_ERR(); | |
| 4056 | + RETURN_NONE(); | |
| 4057 | +} | |
| 4058 | + | |
| 4059 | + | |
| 4060 | +static PyObject* | |
| 4061 | +DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args) | |
| 4062 | +{ | |
| 4063 | + int err; | |
| 4064 | + char *dir; | |
| 4065 | + | |
| 4066 | + if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir)) | |
| 4067 | + return NULL; | |
| 4068 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4069 | + | |
| 4070 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4071 | + err = self->db_env->set_lg_dir(self->db_env, dir); | |
| 4072 | + MYDB_END_ALLOW_THREADS; | |
| 4073 | + RETURN_IF_ERR(); | |
| 4074 | + RETURN_NONE(); | |
| 4075 | +} | |
| 4076 | + | |
| 4077 | +static PyObject* | |
| 4078 | +DBEnv_set_lg_max(DBEnvObject* self, PyObject* args) | |
| 4079 | +{ | |
| 4080 | + int err, lg_max; | |
| 4081 | + | |
| 4082 | + if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max)) | |
| 4083 | + return NULL; | |
| 4084 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4085 | + | |
| 4086 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4087 | + err = self->db_env->set_lg_max(self->db_env, lg_max); | |
| 4088 | + MYDB_END_ALLOW_THREADS; | |
| 4089 | + RETURN_IF_ERR(); | |
| 4090 | + RETURN_NONE(); | |
| 4091 | +} | |
| 4092 | + | |
| 4093 | + | |
| 4094 | +#if (DBVER >= 33) | |
| 4095 | +static PyObject* | |
| 4096 | +DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args) | |
| 4097 | +{ | |
| 4098 | + int err, lg_max; | |
| 4099 | + | |
| 4100 | + if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max)) | |
| 4101 | + return NULL; | |
| 4102 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4103 | + | |
| 4104 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4105 | + err = self->db_env->set_lg_regionmax(self->db_env, lg_max); | |
| 4106 | + MYDB_END_ALLOW_THREADS; | |
| 4107 | + RETURN_IF_ERR(); | |
| 4108 | + RETURN_NONE(); | |
| 4109 | +} | |
| 4110 | +#endif | |
| 4111 | + | |
| 4112 | + | |
| 4113 | +static PyObject* | |
| 4114 | +DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args) | |
| 4115 | +{ | |
| 4116 | + int err, lk_detect; | |
| 4117 | + | |
| 4118 | + if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect)) | |
| 4119 | + return NULL; | |
| 4120 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4121 | + | |
| 4122 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4123 | + err = self->db_env->set_lk_detect(self->db_env, lk_detect); | |
| 4124 | + MYDB_END_ALLOW_THREADS; | |
| 4125 | + RETURN_IF_ERR(); | |
| 4126 | + RETURN_NONE(); | |
| 4127 | +} | |
| 4128 | + | |
| 4129 | + | |
| 4130 | +#if (DBVER < 45) | |
| 4131 | +static PyObject* | |
| 4132 | +DBEnv_set_lk_max(DBEnvObject* self, PyObject* args) | |
| 4133 | +{ | |
| 4134 | + int err, max; | |
| 4135 | + | |
| 4136 | + if (!PyArg_ParseTuple(args, "i:set_lk_max", &max)) | |
| 4137 | + return NULL; | |
| 4138 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4139 | + | |
| 4140 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4141 | + err = self->db_env->set_lk_max(self->db_env, max); | |
| 4142 | + MYDB_END_ALLOW_THREADS; | |
| 4143 | + RETURN_IF_ERR(); | |
| 4144 | + RETURN_NONE(); | |
| 4145 | +} | |
| 4146 | +#endif | |
| 4147 | + | |
| 4148 | + | |
| 4149 | +#if (DBVER >= 32) | |
| 4150 | + | |
| 4151 | +static PyObject* | |
| 4152 | +DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args) | |
| 4153 | +{ | |
| 4154 | + int err, max; | |
| 4155 | + | |
| 4156 | + if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max)) | |
| 4157 | + return NULL; | |
| 4158 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4159 | + | |
| 4160 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4161 | + err = self->db_env->set_lk_max_locks(self->db_env, max); | |
| 4162 | + MYDB_END_ALLOW_THREADS; | |
| 4163 | + RETURN_IF_ERR(); | |
| 4164 | + RETURN_NONE(); | |
| 4165 | +} | |
| 4166 | + | |
| 4167 | + | |
| 4168 | +static PyObject* | |
| 4169 | +DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args) | |
| 4170 | +{ | |
| 4171 | + int err, max; | |
| 4172 | + | |
| 4173 | + if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max)) | |
| 4174 | + return NULL; | |
| 4175 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4176 | + | |
| 4177 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4178 | + err = self->db_env->set_lk_max_lockers(self->db_env, max); | |
| 4179 | + MYDB_END_ALLOW_THREADS; | |
| 4180 | + RETURN_IF_ERR(); | |
| 4181 | + RETURN_NONE(); | |
| 4182 | +} | |
| 4183 | + | |
| 4184 | + | |
| 4185 | +static PyObject* | |
| 4186 | +DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args) | |
| 4187 | +{ | |
| 4188 | + int err, max; | |
| 4189 | + | |
| 4190 | + if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max)) | |
| 4191 | + return NULL; | |
| 4192 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4193 | + | |
| 4194 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4195 | + err = self->db_env->set_lk_max_objects(self->db_env, max); | |
| 4196 | + MYDB_END_ALLOW_THREADS; | |
| 4197 | + RETURN_IF_ERR(); | |
| 4198 | + RETURN_NONE(); | |
| 4199 | +} | |
| 4200 | + | |
| 4201 | +#endif | |
| 4202 | + | |
| 4203 | + | |
| 4204 | +static PyObject* | |
| 4205 | +DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args) | |
| 4206 | +{ | |
| 4207 | + int err, mp_mmapsize; | |
| 4208 | + | |
| 4209 | + if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize)) | |
| 4210 | + return NULL; | |
| 4211 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4212 | + | |
| 4213 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4214 | + err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize); | |
| 4215 | + MYDB_END_ALLOW_THREADS; | |
| 4216 | + RETURN_IF_ERR(); | |
| 4217 | + RETURN_NONE(); | |
| 4218 | +} | |
| 4219 | + | |
| 4220 | + | |
| 4221 | +static PyObject* | |
| 4222 | +DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args) | |
| 4223 | +{ | |
| 4224 | + int err; | |
| 4225 | + char *dir; | |
| 4226 | + | |
| 4227 | + if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir)) | |
| 4228 | + return NULL; | |
| 4229 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4230 | + | |
| 4231 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4232 | + err = self->db_env->set_tmp_dir(self->db_env, dir); | |
| 4233 | + MYDB_END_ALLOW_THREADS; | |
| 4234 | + RETURN_IF_ERR(); | |
| 4235 | + RETURN_NONE(); | |
| 4236 | +} | |
| 4237 | + | |
| 4238 | + | |
| 4239 | +static PyObject* | |
| 4240 | +DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs) | |
| 4241 | +{ | |
| 4242 | + int flags = 0; | |
| 4243 | + PyObject* txnobj = NULL; | |
| 4244 | + DB_TXN *txn = NULL; | |
| 4245 | + static char* kwnames[] = { "parent", "flags", NULL }; | |
| 4246 | + | |
| 4247 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames, | |
| 4248 | + &txnobj, &flags)) | |
| 4249 | + return NULL; | |
| 4250 | + | |
| 4251 | + if (!checkTxnObj(txnobj, &txn)) | |
| 4252 | + return NULL; | |
| 4253 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4254 | + | |
| 4255 | + return (PyObject*)newDBTxnObject(self, txn, flags); | |
| 4256 | +} | |
| 4257 | + | |
| 4258 | + | |
| 4259 | +static PyObject* | |
| 4260 | +DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args) | |
| 4261 | +{ | |
| 4262 | + int err, kbyte=0, min=0, flags=0; | |
| 4263 | + | |
| 4264 | + if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags)) | |
| 4265 | + return NULL; | |
| 4266 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4267 | + | |
| 4268 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4269 | +#if (DBVER >= 40) | |
| 4270 | + err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags); | |
| 4271 | +#else | |
| 4272 | + err = txn_checkpoint(self->db_env, kbyte, min, flags); | |
| 4273 | +#endif | |
| 4274 | + MYDB_END_ALLOW_THREADS; | |
| 4275 | + RETURN_IF_ERR(); | |
| 4276 | + RETURN_NONE(); | |
| 4277 | +} | |
| 4278 | + | |
| 4279 | + | |
| 4280 | +static PyObject* | |
| 4281 | +DBEnv_set_tx_max(DBEnvObject* self, PyObject* args) | |
| 4282 | +{ | |
| 4283 | + int err, max; | |
| 4284 | + | |
| 4285 | + if (!PyArg_ParseTuple(args, "i:set_tx_max", &max)) | |
| 4286 | + return NULL; | |
| 4287 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4288 | + | |
| 4289 | + err = self->db_env->set_tx_max(self->db_env, max); | |
| 4290 | + RETURN_IF_ERR(); | |
| 4291 | + RETURN_NONE(); | |
| 4292 | +} | |
| 4293 | + | |
| 4294 | + | |
| 4295 | +static PyObject* | |
| 4296 | +DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args) | |
| 4297 | +{ | |
| 4298 | + int err; | |
| 4299 | + long stamp; | |
| 4300 | + time_t timestamp; | |
| 4301 | + | |
| 4302 | + if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp)) | |
| 4303 | + return NULL; | |
| 4304 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4305 | + timestamp = (time_t)stamp; | |
| 4306 | + err = self->db_env->set_tx_timestamp(self->db_env, ×tamp); | |
| 4307 | + RETURN_IF_ERR(); | |
| 4308 | + RETURN_NONE(); | |
| 4309 | +} | |
| 4310 | + | |
| 4311 | + | |
| 4312 | +static PyObject* | |
| 4313 | +DBEnv_lock_detect(DBEnvObject* self, PyObject* args) | |
| 4314 | +{ | |
| 4315 | + int err, atype, flags=0; | |
| 4316 | + int aborted = 0; | |
| 4317 | + | |
| 4318 | + if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags)) | |
| 4319 | + return NULL; | |
| 4320 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4321 | + | |
| 4322 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4323 | +#if (DBVER >= 40) | |
| 4324 | + err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted); | |
| 4325 | +#else | |
| 4326 | + err = lock_detect(self->db_env, flags, atype, &aborted); | |
| 4327 | +#endif | |
| 4328 | + MYDB_END_ALLOW_THREADS; | |
| 4329 | + RETURN_IF_ERR(); | |
| 4330 | + return PyInt_FromLong(aborted); | |
| 4331 | +} | |
| 4332 | + | |
| 4333 | + | |
| 4334 | +static PyObject* | |
| 4335 | +DBEnv_lock_get(DBEnvObject* self, PyObject* args) | |
| 4336 | +{ | |
| 4337 | + int flags=0; | |
| 4338 | + int locker, lock_mode; | |
| 4339 | + DBT obj; | |
| 4340 | + PyObject* objobj; | |
| 4341 | + | |
| 4342 | + if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags)) | |
| 4343 | + return NULL; | |
| 4344 | + | |
| 4345 | + | |
| 4346 | + if (!make_dbt(objobj, &obj)) | |
| 4347 | + return NULL; | |
| 4348 | + | |
| 4349 | + return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags); | |
| 4350 | +} | |
| 4351 | + | |
| 4352 | + | |
| 4353 | +static PyObject* | |
| 4354 | +DBEnv_lock_id(DBEnvObject* self, PyObject* args) | |
| 4355 | +{ | |
| 4356 | + int err; | |
| 4357 | + u_int32_t theID; | |
| 4358 | + | |
| 4359 | + if (!PyArg_ParseTuple(args, ":lock_id")) | |
| 4360 | + return NULL; | |
| 4361 | + | |
| 4362 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4363 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4364 | +#if (DBVER >= 40) | |
| 4365 | + err = self->db_env->lock_id(self->db_env, &theID); | |
| 4366 | +#else | |
| 4367 | + err = lock_id(self->db_env, &theID); | |
| 4368 | +#endif | |
| 4369 | + MYDB_END_ALLOW_THREADS; | |
| 4370 | + RETURN_IF_ERR(); | |
| 4371 | + | |
| 4372 | + return PyInt_FromLong((long)theID); | |
| 4373 | +} | |
| 4374 | + | |
| 4375 | + | |
| 4376 | +static PyObject* | |
| 4377 | +DBEnv_lock_put(DBEnvObject* self, PyObject* args) | |
| 4378 | +{ | |
| 4379 | + int err; | |
| 4380 | + DBLockObject* dblockobj; | |
| 4381 | + | |
| 4382 | + if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj)) | |
| 4383 | + return NULL; | |
| 4384 | + | |
| 4385 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4386 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4387 | +#if (DBVER >= 40) | |
| 4388 | + err = self->db_env->lock_put(self->db_env, &dblockobj->lock); | |
| 4389 | +#else | |
| 4390 | + err = lock_put(self->db_env, &dblockobj->lock); | |
| 4391 | +#endif | |
| 4392 | + MYDB_END_ALLOW_THREADS; | |
| 4393 | + RETURN_IF_ERR(); | |
| 4394 | + RETURN_NONE(); | |
| 4395 | +} | |
| 4396 | + | |
| 4397 | +#if (DBVER >= 44) | |
| 4398 | +static PyObject* | |
| 4399 | +DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs) | |
| 4400 | +{ | |
| 4401 | + int err; | |
| 4402 | + char *file; | |
| 4403 | + u_int32_t flags = 0; | |
| 4404 | + static char* kwnames[] = { "file", "flags", NULL}; | |
| 4405 | + | |
| 4406 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames, | |
| 4407 | + &file, &flags)) | |
| 4408 | + return NULL; | |
| 4409 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4410 | + | |
| 4411 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4412 | + err = self->db_env->lsn_reset(self->db_env, file, flags); | |
| 4413 | + MYDB_END_ALLOW_THREADS; | |
| 4414 | + RETURN_IF_ERR(); | |
| 4415 | + RETURN_NONE(); | |
| 4416 | +} | |
| 4417 | +#endif /* DBVER >= 4.4 */ | |
| 4418 | + | |
| 4419 | +#if (DBVER >= 40) | |
| 4420 | +static PyObject* | |
| 4421 | +DBEnv_log_stat(DBEnvObject* self, PyObject* args) | |
| 4422 | +{ | |
| 4423 | + int err; | |
| 4424 | + DB_LOG_STAT* statp = NULL; | |
| 4425 | + PyObject* d = NULL; | |
| 4426 | + u_int32_t flags = 0; | |
| 4427 | + | |
| 4428 | + if (!PyArg_ParseTuple(args, "|i:log_stat", &flags)) | |
| 4429 | + return NULL; | |
| 4430 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4431 | + | |
| 4432 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4433 | + err = self->db_env->log_stat(self->db_env, &statp, flags); | |
| 4434 | + MYDB_END_ALLOW_THREADS; | |
| 4435 | + RETURN_IF_ERR(); | |
| 4436 | + | |
| 4437 | + /* Turn the stat structure into a dictionary */ | |
| 4438 | + d = PyDict_New(); | |
| 4439 | + if (d == NULL) { | |
| 4440 | + if (statp) | |
| 4441 | + free(statp); | |
| 4442 | + return NULL; | |
| 4443 | + } | |
| 4444 | + | |
| 4445 | +#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name) | |
| 4446 | + | |
| 4447 | + MAKE_ENTRY(magic); | |
| 4448 | + MAKE_ENTRY(version); | |
| 4449 | + MAKE_ENTRY(mode); | |
| 4450 | + MAKE_ENTRY(lg_bsize); | |
| 4451 | +#if (DBVER >= 44) | |
| 4452 | + MAKE_ENTRY(lg_size); | |
| 4453 | + MAKE_ENTRY(record); | |
| 4454 | +#endif | |
| 4455 | +#if (DBVER <= 40) | |
| 4456 | + MAKE_ENTRY(lg_max); | |
| 4457 | +#endif | |
| 4458 | + MAKE_ENTRY(w_mbytes); | |
| 4459 | + MAKE_ENTRY(w_bytes); | |
| 4460 | + MAKE_ENTRY(wc_mbytes); | |
| 4461 | + MAKE_ENTRY(wc_bytes); | |
| 4462 | + MAKE_ENTRY(wcount); | |
| 4463 | + MAKE_ENTRY(wcount_fill); | |
| 4464 | +#if (DBVER >= 44) | |
| 4465 | + MAKE_ENTRY(rcount); | |
| 4466 | +#endif | |
| 4467 | + MAKE_ENTRY(scount); | |
| 4468 | + MAKE_ENTRY(cur_file); | |
| 4469 | + MAKE_ENTRY(cur_offset); | |
| 4470 | + MAKE_ENTRY(disk_file); | |
| 4471 | + MAKE_ENTRY(disk_offset); | |
| 4472 | + MAKE_ENTRY(maxcommitperflush); | |
| 4473 | + MAKE_ENTRY(mincommitperflush); | |
| 4474 | + MAKE_ENTRY(regsize); | |
| 4475 | + MAKE_ENTRY(region_wait); | |
| 4476 | + MAKE_ENTRY(region_nowait); | |
| 4477 | + | |
| 4478 | +#undef MAKE_ENTRY | |
| 4479 | + free(statp); | |
| 4480 | + return d; | |
| 4481 | +} /* DBEnv_log_stat */ | |
| 4482 | +#endif /* DBVER >= 4.0 for log_stat method */ | |
| 4483 | + | |
| 4484 | + | |
| 4485 | +static PyObject* | |
| 4486 | +DBEnv_lock_stat(DBEnvObject* self, PyObject* args) | |
| 4487 | +{ | |
| 4488 | + int err; | |
| 4489 | + DB_LOCK_STAT* sp; | |
| 4490 | + PyObject* d = NULL; | |
| 4491 | + u_int32_t flags = 0; | |
| 4492 | + | |
| 4493 | + if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags)) | |
| 4494 | + return NULL; | |
| 4495 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4496 | + | |
| 4497 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4498 | +#if (DBVER >= 40) | |
| 4499 | + err = self->db_env->lock_stat(self->db_env, &sp, flags); | |
| 4500 | +#else | |
| 4501 | +#if (DBVER >= 33) | |
| 4502 | + err = lock_stat(self->db_env, &sp); | |
| 4503 | +#else | |
| 4504 | + err = lock_stat(self->db_env, &sp, NULL); | |
| 4505 | +#endif | |
| 4506 | +#endif | |
| 4507 | + MYDB_END_ALLOW_THREADS; | |
| 4508 | + RETURN_IF_ERR(); | |
| 4509 | + | |
| 4510 | + /* Turn the stat structure into a dictionary */ | |
| 4511 | + d = PyDict_New(); | |
| 4512 | + if (d == NULL) { | |
| 4513 | + free(sp); | |
| 4514 | + return NULL; | |
| 4515 | + } | |
| 4516 | + | |
| 4517 | +#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) | |
| 4518 | + | |
| 4519 | +#if (DBVER < 41) | |
| 4520 | + MAKE_ENTRY(lastid); | |
| 4521 | +#endif | |
| 4522 | + MAKE_ENTRY(nmodes); | |
| 4523 | +#if (DBVER >= 32) | |
| 4524 | + MAKE_ENTRY(maxlocks); | |
| 4525 | + MAKE_ENTRY(maxlockers); | |
| 4526 | + MAKE_ENTRY(maxobjects); | |
| 4527 | + MAKE_ENTRY(nlocks); | |
| 4528 | + MAKE_ENTRY(maxnlocks); | |
| 4529 | +#endif | |
| 4530 | + MAKE_ENTRY(nlockers); | |
| 4531 | + MAKE_ENTRY(maxnlockers); | |
| 4532 | +#if (DBVER >= 32) | |
| 4533 | + MAKE_ENTRY(nobjects); | |
| 4534 | + MAKE_ENTRY(maxnobjects); | |
| 4535 | +#endif | |
| 4536 | + MAKE_ENTRY(nrequests); | |
| 4537 | + MAKE_ENTRY(nreleases); | |
| 4538 | +#if (DBVER < 44) | |
| 4539 | + MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */ | |
| 4540 | + MAKE_ENTRY(nconflicts); | |
| 4541 | +#else | |
| 4542 | + MAKE_ENTRY(lock_nowait); | |
| 4543 | + MAKE_ENTRY(lock_wait); | |
| 4544 | +#endif | |
| 4545 | + MAKE_ENTRY(ndeadlocks); | |
| 4546 | + MAKE_ENTRY(regsize); | |
| 4547 | + MAKE_ENTRY(region_wait); | |
| 4548 | + MAKE_ENTRY(region_nowait); | |
| 4549 | + | |
| 4550 | +#undef MAKE_ENTRY | |
| 4551 | + free(sp); | |
| 4552 | + return d; | |
| 4553 | +} | |
| 4554 | + | |
| 4555 | + | |
| 4556 | +static PyObject* | |
| 4557 | +DBEnv_log_archive(DBEnvObject* self, PyObject* args) | |
| 4558 | +{ | |
| 4559 | + int flags=0; | |
| 4560 | + int err; | |
| 4561 | + char **log_list = NULL; | |
| 4562 | + PyObject* list; | |
| 4563 | + PyObject* item = NULL; | |
| 4564 | + | |
| 4565 | + if (!PyArg_ParseTuple(args, "|i:log_archive", &flags)) | |
| 4566 | + return NULL; | |
| 4567 | + | |
| 4568 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4569 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4570 | +#if (DBVER >= 40) | |
| 4571 | + err = self->db_env->log_archive(self->db_env, &log_list, flags); | |
| 4572 | +#elif (DBVER == 33) | |
| 4573 | + err = log_archive(self->db_env, &log_list, flags); | |
| 4574 | +#else | |
| 4575 | + err = log_archive(self->db_env, &log_list, flags, NULL); | |
| 4576 | +#endif | |
| 4577 | + MYDB_END_ALLOW_THREADS; | |
| 4578 | + RETURN_IF_ERR(); | |
| 4579 | + | |
| 4580 | + list = PyList_New(0); | |
| 4581 | + if (list == NULL) { | |
| 4582 | + if (log_list) | |
| 4583 | + free(log_list); | |
| 4584 | + return NULL; | |
| 4585 | + } | |
| 4586 | + | |
| 4587 | + if (log_list) { | |
| 4588 | + char **log_list_start; | |
| 4589 | + for (log_list_start = log_list; *log_list != NULL; ++log_list) { | |
| 4590 | + item = PyString_FromString (*log_list); | |
| 4591 | + if (item == NULL) { | |
| 4592 | + Py_DECREF(list); | |
| 4593 | + list = NULL; | |
| 4594 | + break; | |
| 4595 | + } | |
| 4596 | + PyList_Append(list, item); | |
| 4597 | + Py_DECREF(item); | |
| 4598 | + } | |
| 4599 | + free(log_list_start); | |
| 4600 | + } | |
| 4601 | + return list; | |
| 4602 | +} | |
| 4603 | + | |
| 4604 | + | |
| 4605 | +static PyObject* | |
| 4606 | +DBEnv_txn_stat(DBEnvObject* self, PyObject* args) | |
| 4607 | +{ | |
| 4608 | + int err; | |
| 4609 | + DB_TXN_STAT* sp; | |
| 4610 | + PyObject* d = NULL; | |
| 4611 | + u_int32_t flags=0; | |
| 4612 | + | |
| 4613 | + if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags)) | |
| 4614 | + return NULL; | |
| 4615 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4616 | + | |
| 4617 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4618 | +#if (DBVER >= 40) | |
| 4619 | + err = self->db_env->txn_stat(self->db_env, &sp, flags); | |
| 4620 | +#elif (DBVER == 33) | |
| 4621 | + err = txn_stat(self->db_env, &sp); | |
| 4622 | +#else | |
| 4623 | + err = txn_stat(self->db_env, &sp, NULL); | |
| 4624 | +#endif | |
| 4625 | + MYDB_END_ALLOW_THREADS; | |
| 4626 | + RETURN_IF_ERR(); | |
| 4627 | + | |
| 4628 | + /* Turn the stat structure into a dictionary */ | |
| 4629 | + d = PyDict_New(); | |
| 4630 | + if (d == NULL) { | |
| 4631 | + free(sp); | |
| 4632 | + return NULL; | |
| 4633 | + } | |
| 4634 | + | |
| 4635 | +#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) | |
| 4636 | + | |
| 4637 | + MAKE_ENTRY(time_ckp); | |
| 4638 | + MAKE_ENTRY(last_txnid); | |
| 4639 | + MAKE_ENTRY(maxtxns); | |
| 4640 | + MAKE_ENTRY(nactive); | |
| 4641 | + MAKE_ENTRY(maxnactive); | |
| 4642 | + MAKE_ENTRY(nbegins); | |
| 4643 | + MAKE_ENTRY(naborts); | |
| 4644 | + MAKE_ENTRY(ncommits); | |
| 4645 | + MAKE_ENTRY(regsize); | |
| 4646 | + MAKE_ENTRY(region_wait); | |
| 4647 | + MAKE_ENTRY(region_nowait); | |
| 4648 | + | |
| 4649 | +#undef MAKE_ENTRY | |
| 4650 | + free(sp); | |
| 4651 | + return d; | |
| 4652 | +} | |
| 4653 | + | |
| 4654 | + | |
| 4655 | +static PyObject* | |
| 4656 | +DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args) | |
| 4657 | +{ | |
| 4658 | + int flags=0; | |
| 4659 | + int oldValue=0; | |
| 4660 | + | |
| 4661 | + if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags)) | |
| 4662 | + return NULL; | |
| 4663 | + CHECK_ENV_NOT_CLOSED(self); | |
| 4664 | + | |
| 4665 | + if (self->moduleFlags.getReturnsNone) | |
| 4666 | + ++oldValue; | |
| 4667 | + if (self->moduleFlags.cursorSetReturnsNone) | |
| 4668 | + ++oldValue; | |
| 4669 | + self->moduleFlags.getReturnsNone = (flags >= 1); | |
| 4670 | + self->moduleFlags.cursorSetReturnsNone = (flags >= 2); | |
| 4671 | + return PyInt_FromLong(oldValue); | |
| 4672 | +} | |
| 4673 | + | |
| 4674 | + | |
| 4675 | +/* --------------------------------------------------------------------- */ | |
| 4676 | +/* DBTxn methods */ | |
| 4677 | + | |
| 4678 | + | |
| 4679 | +static PyObject* | |
| 4680 | +DBTxn_commit(DBTxnObject* self, PyObject* args) | |
| 4681 | +{ | |
| 4682 | + int flags=0, err; | |
| 4683 | + DB_TXN *txn; | |
| 4684 | + | |
| 4685 | + if (!PyArg_ParseTuple(args, "|i:commit", &flags)) | |
| 4686 | + return NULL; | |
| 4687 | + | |
| 4688 | + if (!self->txn) { | |
| 4689 | + PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " | |
| 4690 | + "after txn_commit or txn_abort"); | |
| 4691 | + PyErr_SetObject(DBError, t); | |
| 4692 | + Py_DECREF(t); | |
| 4693 | + return NULL; | |
| 4694 | + } | |
| 4695 | + txn = self->txn; | |
| 4696 | + self->txn = NULL; /* this DB_TXN is no longer valid after this call */ | |
| 4697 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4698 | +#if (DBVER >= 40) | |
| 4699 | + err = txn->commit(txn, flags); | |
| 4700 | +#else | |
| 4701 | + err = txn_commit(txn, flags); | |
| 4702 | +#endif | |
| 4703 | + MYDB_END_ALLOW_THREADS; | |
| 4704 | + RETURN_IF_ERR(); | |
| 4705 | + RETURN_NONE(); | |
| 4706 | +} | |
| 4707 | + | |
| 4708 | +static PyObject* | |
| 4709 | +DBTxn_prepare(DBTxnObject* self, PyObject* args) | |
| 4710 | +{ | |
| 4711 | +#if (DBVER >= 33) | |
| 4712 | + int err; | |
| 4713 | + char* gid=NULL; | |
| 4714 | + int gid_size=0; | |
| 4715 | + | |
| 4716 | + if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size)) | |
| 4717 | + return NULL; | |
| 4718 | + | |
| 4719 | + if (gid_size != DB_XIDDATASIZE) { | |
| 4720 | + PyErr_SetString(PyExc_TypeError, | |
| 4721 | + "gid must be DB_XIDDATASIZE bytes long"); | |
| 4722 | + return NULL; | |
| 4723 | + } | |
| 4724 | + | |
| 4725 | + if (!self->txn) { | |
| 4726 | + PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used " | |
| 4727 | + "after txn_commit or txn_abort"); | |
| 4728 | + PyErr_SetObject(DBError, t); | |
| 4729 | + Py_DECREF(t); | |
| 4730 | + return NULL; | |
| 4731 | + } | |
| 4732 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4733 | +#if (DBVER >= 40) | |
| 4734 | + err = self->txn->prepare(self->txn, (u_int8_t*)gid); | |
| 4735 | +#else | |
| 4736 | + err = txn_prepare(self->txn, (u_int8_t*)gid); | |
| 4737 | +#endif | |
| 4738 | + MYDB_END_ALLOW_THREADS; | |
| 4739 | + RETURN_IF_ERR(); | |
| 4740 | + RETURN_NONE(); | |
| 4741 | +#else | |
| 4742 | + int err; | |
| 4743 | + | |
| 4744 | + if (!PyArg_ParseTuple(args, ":prepare")) | |
| 4745 | + return NULL; | |
| 4746 | + | |
| 4747 | + if (!self->txn) { | |
| 4748 | + PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " | |
| 4749 | + "after txn_commit or txn_abort"); | |
| 4750 | + PyErr_SetObject(DBError, t); | |
| 4751 | + Py_DECREF(t); | |
| 4752 | + return NULL; | |
| 4753 | + } | |
| 4754 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4755 | + err = txn_prepare(self->txn); | |
| 4756 | + MYDB_END_ALLOW_THREADS; | |
| 4757 | + RETURN_IF_ERR(); | |
| 4758 | + RETURN_NONE(); | |
| 4759 | +#endif | |
| 4760 | +} | |
| 4761 | + | |
| 4762 | + | |
| 4763 | +static PyObject* | |
| 4764 | +DBTxn_abort(DBTxnObject* self, PyObject* args) | |
| 4765 | +{ | |
| 4766 | + int err; | |
| 4767 | + DB_TXN *txn; | |
| 4768 | + | |
| 4769 | + if (!PyArg_ParseTuple(args, ":abort")) | |
| 4770 | + return NULL; | |
| 4771 | + | |
| 4772 | + if (!self->txn) { | |
| 4773 | + PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " | |
| 4774 | + "after txn_commit or txn_abort"); | |
| 4775 | + PyErr_SetObject(DBError, t); | |
| 4776 | + Py_DECREF(t); | |
| 4777 | + return NULL; | |
| 4778 | + } | |
| 4779 | + txn = self->txn; | |
| 4780 | + self->txn = NULL; /* this DB_TXN is no longer valid after this call */ | |
| 4781 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4782 | +#if (DBVER >= 40) | |
| 4783 | + err = txn->abort(txn); | |
| 4784 | +#else | |
| 4785 | + err = txn_abort(txn); | |
| 4786 | +#endif | |
| 4787 | + MYDB_END_ALLOW_THREADS; | |
| 4788 | + RETURN_IF_ERR(); | |
| 4789 | + RETURN_NONE(); | |
| 4790 | +} | |
| 4791 | + | |
| 4792 | + | |
| 4793 | +static PyObject* | |
| 4794 | +DBTxn_id(DBTxnObject* self, PyObject* args) | |
| 4795 | +{ | |
| 4796 | + int id; | |
| 4797 | + | |
| 4798 | + if (!PyArg_ParseTuple(args, ":id")) | |
| 4799 | + return NULL; | |
| 4800 | + | |
| 4801 | + if (!self->txn) { | |
| 4802 | + PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " | |
| 4803 | + "after txn_commit or txn_abort"); | |
| 4804 | + PyErr_SetObject(DBError, t); | |
| 4805 | + Py_DECREF(t); | |
| 4806 | + return NULL; | |
| 4807 | + } | |
| 4808 | + MYDB_BEGIN_ALLOW_THREADS; | |
| 4809 | +#if (DBVER >= 40) | |
| 4810 | + id = self->txn->id(self->txn); | |
| 4811 | +#else | |
| 4812 | + id = txn_id(self->txn); | |
| 4813 | +#endif | |
| 4814 | + MYDB_END_ALLOW_THREADS; | |
| 4815 | + return PyInt_FromLong(id); | |
| 4816 | +} | |
| 4817 | + | |
| 4818 | +#if (DBVER >= 43) | |
| 4819 | +/* --------------------------------------------------------------------- */ | |
| 4820 | +/* DBSequence methods */ | |
| 4821 | + | |
| 4822 | + | |
| 4823 | +static PyObject* | |
| 4824 | +DBSequence_close(DBSequenceObject* self, PyObject* args) | |
| 4825 | +{ | |
| 4826 | + int err, flags=0; | |
| 4827 | + if (!PyArg_ParseTuple(args,"|i:close", &flags)) | |
| 4828 | + return NULL; | |
| 4829 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4830 | + | |
| 4831 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4832 | + err = self->sequence->close(self->sequence, flags); | |
| 4833 | + self->sequence = NULL; | |
| 4834 | + MYDB_END_ALLOW_THREADS | |
| 4835 | + | |
| 4836 | + RETURN_IF_ERR(); | |
| 4837 | + | |
| 4838 | + RETURN_NONE(); | |
| 4839 | +} | |
| 4840 | + | |
| 4841 | +static PyObject* | |
| 4842 | +DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs) | |
| 4843 | +{ | |
| 4844 | + int err, flags = 0; | |
| 4845 | + int delta = 1; | |
| 4846 | + db_seq_t value; | |
| 4847 | + PyObject *txnobj = NULL; | |
| 4848 | + DB_TXN *txn = NULL; | |
| 4849 | + static char* kwnames[] = {"delta", "txn", "flags", NULL }; | |
| 4850 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags)) | |
| 4851 | + return NULL; | |
| 4852 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4853 | + | |
| 4854 | + if (!checkTxnObj(txnobj, &txn)) | |
| 4855 | + return NULL; | |
| 4856 | + | |
| 4857 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4858 | + err = self->sequence->get(self->sequence, txn, delta, &value, flags); | |
| 4859 | + MYDB_END_ALLOW_THREADS | |
| 4860 | + | |
| 4861 | + RETURN_IF_ERR(); | |
| 4862 | + return PyLong_FromLongLong(value); | |
| 4863 | + | |
| 4864 | +} | |
| 4865 | + | |
| 4866 | +static PyObject* | |
| 4867 | +DBSequence_get_dbp(DBSequenceObject* self, PyObject* args) | |
| 4868 | +{ | |
| 4869 | + if (!PyArg_ParseTuple(args,":get_dbp")) | |
| 4870 | + return NULL; | |
| 4871 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4872 | + Py_INCREF(self->mydb); | |
| 4873 | + return (PyObject* )self->mydb; | |
| 4874 | +} | |
| 4875 | + | |
| 4876 | +static PyObject* | |
| 4877 | +DBSequence_get_key(DBSequenceObject* self, PyObject* args) | |
| 4878 | +{ | |
| 4879 | + int err; | |
| 4880 | + DBT key; | |
| 4881 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4882 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4883 | + err = self->sequence->get_key(self->sequence, &key); | |
| 4884 | + MYDB_END_ALLOW_THREADS | |
| 4885 | + | |
| 4886 | + RETURN_IF_ERR(); | |
| 4887 | + | |
| 4888 | + return PyString_FromStringAndSize(key.data, key.size); | |
| 4889 | +} | |
| 4890 | + | |
| 4891 | +static PyObject* | |
| 4892 | +DBSequence_init_value(DBSequenceObject* self, PyObject* args) | |
| 4893 | +{ | |
| 4894 | + int err; | |
| 4895 | + db_seq_t value; | |
| 4896 | + if (!PyArg_ParseTuple(args,"L:init_value", &value)) | |
| 4897 | + return NULL; | |
| 4898 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4899 | + | |
| 4900 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4901 | + err = self->sequence->initial_value(self->sequence, value); | |
| 4902 | + MYDB_END_ALLOW_THREADS | |
| 4903 | + | |
| 4904 | + RETURN_IF_ERR(); | |
| 4905 | + | |
| 4906 | + RETURN_NONE(); | |
| 4907 | +} | |
| 4908 | + | |
| 4909 | +static PyObject* | |
| 4910 | +DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs) | |
| 4911 | +{ | |
| 4912 | + int err, flags = 0; | |
| 4913 | + PyObject* keyobj; | |
| 4914 | + PyObject *txnobj = NULL; | |
| 4915 | + DB_TXN *txn = NULL; | |
| 4916 | + DBT key; | |
| 4917 | + | |
| 4918 | + static char* kwnames[] = {"key", "txn", "flags", NULL }; | |
| 4919 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags)) | |
| 4920 | + return NULL; | |
| 4921 | + | |
| 4922 | + if (!checkTxnObj(txnobj, &txn)) | |
| 4923 | + return NULL; | |
| 4924 | + | |
| 4925 | + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) | |
| 4926 | + return NULL; | |
| 4927 | + | |
| 4928 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4929 | + err = self->sequence->open(self->sequence, txn, &key, flags); | |
| 4930 | + MYDB_END_ALLOW_THREADS | |
| 4931 | + | |
| 4932 | + CLEAR_DBT(key); | |
| 4933 | + RETURN_IF_ERR(); | |
| 4934 | + | |
| 4935 | + RETURN_NONE(); | |
| 4936 | +} | |
| 4937 | + | |
| 4938 | +static PyObject* | |
| 4939 | +DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs) | |
| 4940 | +{ | |
| 4941 | + int err, flags = 0; | |
| 4942 | + PyObject *txnobj = NULL; | |
| 4943 | + DB_TXN *txn = NULL; | |
| 4944 | + | |
| 4945 | + static char* kwnames[] = {"txn", "flags", NULL }; | |
| 4946 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags)) | |
| 4947 | + return NULL; | |
| 4948 | + | |
| 4949 | + if (!checkTxnObj(txnobj, &txn)) | |
| 4950 | + return NULL; | |
| 4951 | + | |
| 4952 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4953 | + | |
| 4954 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4955 | + err = self->sequence->remove(self->sequence, txn, flags); | |
| 4956 | + MYDB_END_ALLOW_THREADS | |
| 4957 | + | |
| 4958 | + RETURN_IF_ERR(); | |
| 4959 | + RETURN_NONE(); | |
| 4960 | +} | |
| 4961 | + | |
| 4962 | +static PyObject* | |
| 4963 | +DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args) | |
| 4964 | +{ | |
| 4965 | + int err, size; | |
| 4966 | + if (!PyArg_ParseTuple(args,"i:set_cachesize", &size)) | |
| 4967 | + return NULL; | |
| 4968 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4969 | + | |
| 4970 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4971 | + err = self->sequence->set_cachesize(self->sequence, size); | |
| 4972 | + MYDB_END_ALLOW_THREADS | |
| 4973 | + | |
| 4974 | + RETURN_IF_ERR(); | |
| 4975 | + RETURN_NONE(); | |
| 4976 | +} | |
| 4977 | + | |
| 4978 | +static PyObject* | |
| 4979 | +DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args) | |
| 4980 | +{ | |
| 4981 | + int err, size; | |
| 4982 | + if (!PyArg_ParseTuple(args,":get_cachesize")) | |
| 4983 | + return NULL; | |
| 4984 | + CHECK_SEQUENCE_NOT_CLOSED(self) | |
| 4985 | + | |
| 4986 | + MYDB_BEGIN_ALLOW_THREADS | |
| 4987 | + err = self->sequence->get_cachesize(self->sequence, &size); | |
| 4988 | + MYDB_END_ALLOW_THREADS | |
| 4989 | + | |
| 4990 | + RETURN_IF_ERR(); | |
| 4991 | + return PyInt_FromLong(size); | |
| 4992 | +} | |
| 4993 | + | |
| 4994 | +static PyObject* | |
| 4995 | +DBSequence_set_flags(DBSequenceObject* self, PyObject* args) | |
| 4996 | +{ | |
| 4997 | + int err, flags = 0; | |
| 4998 | + if (!PyArg_ParseTuple(args,"i:set_flags", &flags)) | |
| 4999 | + return NULL; | |
1048 more lines aren’t shown here.
| @@ -0,0 +1,934 @@ | ||
| 1 | +/* ------------------------------------------------------------------------ | |
| 2 | + | |
| 3 | + _codecs -- Provides access to the codec registry and the builtin | |
| 4 | + codecs. | |
| 5 | + | |
| 6 | + This module should never be imported directly. The standard library | |
| 7 | + module "codecs" wraps this builtin module for use within Python. | |
| 8 | + | |
| 9 | + The codec registry is accessible via: | |
| 10 | + | |
| 11 | + register(search_function) -> None | |
| 12 | + | |
| 13 | + lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer) | |
| 14 | + | |
| 15 | + The builtin Unicode codecs use the following interface: | |
| 16 | + | |
| 17 | + <encoding>_encode(Unicode_object[,errors='strict']) -> | |
| 18 | + (string object, bytes consumed) | |
| 19 | + | |
| 20 | + <encoding>_decode(char_buffer_obj[,errors='strict']) -> | |
| 21 | + (Unicode object, bytes consumed) | |
| 22 | + | |
| 23 | + <encoding>_encode() interfaces also accept non-Unicode object as | |
| 24 | + input. The objects are then converted to Unicode using | |
| 25 | + PyUnicode_FromObject() prior to applying the conversion. | |
| 26 | + | |
| 27 | + These <encoding>s are available: utf_8, unicode_escape, | |
| 28 | + raw_unicode_escape, unicode_internal, latin_1, ascii (7-bit), | |
| 29 | + mbcs (on win32). | |
| 30 | + | |
| 31 | + | |
| 32 | +Written by Marc-Andre Lemburg (mal@lemburg.com). | |
| 33 | + | |
| 34 | +Copyright (c) Corporation for National Research Initiatives. | |
| 35 | + | |
| 36 | + ------------------------------------------------------------------------ */ | |
| 37 | + | |
| 38 | +#define PY_SSIZE_T_CLEAN | |
| 39 | +#include "Python.h" | |
| 40 | + | |
| 41 | +/* --- Registry ----------------------------------------------------------- */ | |
| 42 | + | |
| 43 | +PyDoc_STRVAR(register__doc__, | |
| 44 | +"register(search_function)\n\ | |
| 45 | +\n\ | |
| 46 | +Register a codec search function. Search functions are expected to take\n\ | |
| 47 | +one argument, the encoding name in all lower case letters, and return\n\ | |
| 48 | +a tuple of functions (encoder, decoder, stream_reader, stream_writer)."); | |
| 49 | + | |
| 50 | +static | |
| 51 | +PyObject *codec_register(PyObject *self, PyObject *search_function) | |
| 52 | +{ | |
| 53 | + if (PyCodec_Register(search_function)) | |
| 54 | + return NULL; | |
| 55 | + | |
| 56 | + Py_RETURN_NONE; | |
| 57 | +} | |
| 58 | + | |
| 59 | +PyDoc_STRVAR(lookup__doc__, | |
| 60 | +"lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer)\n\ | |
| 61 | +\n\ | |
| 62 | +Looks up a codec tuple in the Python codec registry and returns\n\ | |
| 63 | +a tuple of functions."); | |
| 64 | + | |
| 65 | +static | |
| 66 | +PyObject *codec_lookup(PyObject *self, PyObject *args) | |
| 67 | +{ | |
| 68 | + char *encoding; | |
| 69 | + | |
| 70 | + if (!PyArg_ParseTuple(args, "s:lookup", &encoding)) | |
| 71 | + return NULL; | |
| 72 | + | |
| 73 | + return _PyCodec_Lookup(encoding); | |
| 74 | +} | |
| 75 | + | |
| 76 | +PyDoc_STRVAR(encode__doc__, | |
| 77 | +"encode(obj, [encoding[,errors]]) -> object\n\ | |
| 78 | +\n\ | |
| 79 | +Encodes obj using the codec registered for encoding. encoding defaults\n\ | |
| 80 | +to the default encoding. errors may be given to set a different error\n\ | |
| 81 | +handling scheme. Default is 'strict' meaning that encoding errors raise\n\ | |
| 82 | +a ValueError. Other possible values are 'ignore', 'replace' and\n\ | |
| 83 | +'xmlcharrefreplace' as well as any other name registered with\n\ | |
| 84 | +codecs.register_error that can handle ValueErrors."); | |
| 85 | + | |
| 86 | +static PyObject * | |
| 87 | +codec_encode(PyObject *self, PyObject *args) | |
| 88 | +{ | |
| 89 | + const char *encoding = NULL; | |
| 90 | + const char *errors = NULL; | |
| 91 | + PyObject *v; | |
| 92 | + | |
| 93 | + if (!PyArg_ParseTuple(args, "O|ss:encode", &v, &encoding, &errors)) | |
| 94 | + return NULL; | |
| 95 | + | |
| 96 | +#ifdef Py_USING_UNICODE | |
| 97 | + if (encoding == NULL) | |
| 98 | + encoding = PyUnicode_GetDefaultEncoding(); | |
| 99 | +#else | |
| 100 | + if (encoding == NULL) { | |
| 101 | + PyErr_SetString(PyExc_ValueError, "no encoding specified"); | |
| 102 | + return NULL; | |
| 103 | + } | |
| 104 | +#endif | |
| 105 | + | |
| 106 | + /* Encode via the codec registry */ | |
| 107 | + return PyCodec_Encode(v, encoding, errors); | |
| 108 | +} | |
| 109 | + | |
| 110 | +PyDoc_STRVAR(decode__doc__, | |
| 111 | +"decode(obj, [encoding[,errors]]) -> object\n\ | |
| 112 | +\n\ | |
| 113 | +Decodes obj using the codec registered for encoding. encoding defaults\n\ | |
| 114 | +to the default encoding. errors may be given to set a different error\n\ | |
| 115 | +handling scheme. Default is 'strict' meaning that encoding errors raise\n\ | |
| 116 | +a ValueError. Other possible values are 'ignore' and 'replace'\n\ | |
| 117 | +as well as any other name registerd with codecs.register_error that is\n\ | |
| 118 | +able to handle ValueErrors."); | |
| 119 | + | |
| 120 | +static PyObject * | |
| 121 | +codec_decode(PyObject *self, PyObject *args) | |
| 122 | +{ | |
| 123 | + const char *encoding = NULL; | |
| 124 | + const char *errors = NULL; | |
| 125 | + PyObject *v; | |
| 126 | + | |
| 127 | + if (!PyArg_ParseTuple(args, "O|ss:decode", &v, &encoding, &errors)) | |
| 128 | + return NULL; | |
| 129 | + | |
| 130 | +#ifdef Py_USING_UNICODE | |
| 131 | + if (encoding == NULL) | |
| 132 | + encoding = PyUnicode_GetDefaultEncoding(); | |
| 133 | +#else | |
| 134 | + if (encoding == NULL) { | |
| 135 | + PyErr_SetString(PyExc_ValueError, "no encoding specified"); | |
| 136 | + return NULL; | |
| 137 | + } | |
| 138 | +#endif | |
| 139 | + | |
| 140 | + /* Decode via the codec registry */ | |
| 141 | + return PyCodec_Decode(v, encoding, errors); | |
| 142 | +} | |
| 143 | + | |
| 144 | +/* --- Helpers ------------------------------------------------------------ */ | |
| 145 | + | |
| 146 | +static | |
| 147 | +PyObject *codec_tuple(PyObject *unicode, | |
| 148 | + Py_ssize_t len) | |
| 149 | +{ | |
| 150 | + PyObject *v; | |
| 151 | + if (unicode == NULL) | |
| 152 | + return NULL; | |
| 153 | + v = Py_BuildValue("On", unicode, len); | |
| 154 | + Py_DECREF(unicode); | |
| 155 | + return v; | |
| 156 | +} | |
| 157 | + | |
| 158 | +/* --- String codecs ------------------------------------------------------ */ | |
| 159 | +static PyObject * | |
| 160 | +escape_decode(PyObject *self, | |
| 161 | + PyObject *args) | |
| 162 | +{ | |
| 163 | + const char *errors = NULL; | |
| 164 | + const char *data; | |
| 165 | + Py_ssize_t size; | |
| 166 | + | |
| 167 | + if (!PyArg_ParseTuple(args, "s#|z:escape_decode", | |
| 168 | + &data, &size, &errors)) | |
| 169 | + return NULL; | |
| 170 | + return codec_tuple(PyString_DecodeEscape(data, size, errors, 0, NULL), | |
| 171 | + size); | |
| 172 | +} | |
| 173 | + | |
| 174 | +static PyObject * | |
| 175 | +escape_encode(PyObject *self, | |
| 176 | + PyObject *args) | |
| 177 | +{ | |
| 178 | + PyObject *str; | |
| 179 | + const char *errors = NULL; | |
| 180 | + char *buf; | |
| 181 | + Py_ssize_t len; | |
| 182 | + | |
| 183 | + if (!PyArg_ParseTuple(args, "O!|z:escape_encode", | |
| 184 | + &PyString_Type, &str, &errors)) | |
| 185 | + return NULL; | |
| 186 | + | |
| 187 | + str = PyString_Repr(str, 0); | |
| 188 | + if (!str) | |
| 189 | + return NULL; | |
| 190 | + | |
| 191 | + /* The string will be quoted. Unquote, similar to unicode-escape. */ | |
| 192 | + buf = PyString_AS_STRING (str); | |
| 193 | + len = PyString_GET_SIZE (str); | |
| 194 | + memmove(buf, buf+1, len-2); | |
| 195 | + if (_PyString_Resize(&str, len-2) < 0) | |
| 196 | + return NULL; | |
| 197 | + | |
| 198 | + return codec_tuple(str, PyString_Size(str)); | |
| 199 | +} | |
| 200 | + | |
| 201 | +#ifdef Py_USING_UNICODE | |
| 202 | +/* --- Decoder ------------------------------------------------------------ */ | |
| 203 | + | |
| 204 | +static PyObject * | |
| 205 | +unicode_internal_decode(PyObject *self, | |
| 206 | + PyObject *args) | |
| 207 | +{ | |
| 208 | + PyObject *obj; | |
| 209 | + const char *errors = NULL; | |
| 210 | + const char *data; | |
| 211 | + Py_ssize_t size; | |
| 212 | + | |
| 213 | + if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode", | |
| 214 | + &obj, &errors)) | |
| 215 | + return NULL; | |
| 216 | + | |
| 217 | + if (PyUnicode_Check(obj)) { | |
| 218 | + Py_INCREF(obj); | |
| 219 | + return codec_tuple(obj, PyUnicode_GET_SIZE(obj)); | |
| 220 | + } | |
| 221 | + else { | |
| 222 | + if (PyObject_AsReadBuffer(obj, (const void **)&data, &size)) | |
| 223 | + return NULL; | |
| 224 | + | |
| 225 | + return codec_tuple(_PyUnicode_DecodeUnicodeInternal(data, size, errors), | |
| 226 | + size); | |
| 227 | + } | |
| 228 | +} | |
| 229 | + | |
| 230 | +static PyObject * | |
| 231 | +utf_7_decode(PyObject *self, | |
| 232 | + PyObject *args) | |
| 233 | +{ | |
| 234 | + const char *data; | |
| 235 | + Py_ssize_t size; | |
| 236 | + const char *errors = NULL; | |
| 237 | + | |
| 238 | + if (!PyArg_ParseTuple(args, "t#|z:utf_7_decode", | |
| 239 | + &data, &size, &errors)) | |
| 240 | + return NULL; | |
| 241 | + | |
| 242 | + return codec_tuple(PyUnicode_DecodeUTF7(data, size, errors), | |
| 243 | + size); | |
| 244 | +} | |
| 245 | + | |
| 246 | +static PyObject * | |
| 247 | +utf_8_decode(PyObject *self, | |
| 248 | + PyObject *args) | |
| 249 | +{ | |
| 250 | + const char *data; | |
| 251 | + Py_ssize_t size; | |
| 252 | + const char *errors = NULL; | |
| 253 | + int final = 0; | |
| 254 | + Py_ssize_t consumed; | |
| 255 | + PyObject *decoded = NULL; | |
| 256 | + | |
| 257 | + if (!PyArg_ParseTuple(args, "t#|zi:utf_8_decode", | |
| 258 | + &data, &size, &errors, &final)) | |
| 259 | + return NULL; | |
| 260 | + if (size < 0) { | |
| 261 | + PyErr_SetString(PyExc_ValueError, "negative argument"); | |
| 262 | + return 0; | |
| 263 | + } | |
| 264 | + consumed = size; | |
| 265 | + | |
| 266 | + decoded = PyUnicode_DecodeUTF8Stateful(data, size, errors, | |
| 267 | + final ? NULL : &consumed); | |
| 268 | + if (decoded == NULL) | |
| 269 | + return NULL; | |
| 270 | + return codec_tuple(decoded, consumed); | |
| 271 | +} | |
| 272 | + | |
| 273 | +static PyObject * | |
| 274 | +utf_16_decode(PyObject *self, | |
| 275 | + PyObject *args) | |
| 276 | +{ | |
| 277 | + const char *data; | |
| 278 | + Py_ssize_t size; | |
| 279 | + const char *errors = NULL; | |
| 280 | + int byteorder = 0; | |
| 281 | + int final = 0; | |
| 282 | + Py_ssize_t consumed; | |
| 283 | + PyObject *decoded; | |
| 284 | + | |
| 285 | + if (!PyArg_ParseTuple(args, "t#|zi:utf_16_decode", | |
| 286 | + &data, &size, &errors, &final)) | |
| 287 | + return NULL; | |
| 288 | + if (size < 0) { | |
| 289 | + PyErr_SetString(PyExc_ValueError, "negative argument"); | |
| 290 | + return 0; | |
| 291 | + } | |
| 292 | + consumed = size; /* This is overwritten unless final is true. */ | |
| 293 | + decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, | |
| 294 | + final ? NULL : &consumed); | |
| 295 | + if (decoded == NULL) | |
| 296 | + return NULL; | |
| 297 | + return codec_tuple(decoded, consumed); | |
| 298 | +} | |
| 299 | + | |
| 300 | +static PyObject * | |
| 301 | +utf_16_le_decode(PyObject *self, | |
| 302 | + PyObject *args) | |
| 303 | +{ | |
| 304 | + const char *data; | |
| 305 | + Py_ssize_t size; | |
| 306 | + const char *errors = NULL; | |
| 307 | + int byteorder = -1; | |
| 308 | + int final = 0; | |
| 309 | + Py_ssize_t consumed; | |
| 310 | + PyObject *decoded = NULL; | |
| 311 | + | |
| 312 | + if (!PyArg_ParseTuple(args, "t#|zi:utf_16_le_decode", | |
| 313 | + &data, &size, &errors, &final)) | |
| 314 | + return NULL; | |
| 315 | + | |
| 316 | + if (size < 0) { | |
| 317 | + PyErr_SetString(PyExc_ValueError, "negative argument"); | |
| 318 | + return 0; | |
| 319 | + } | |
| 320 | + consumed = size; /* This is overwritten unless final is true. */ | |
| 321 | + decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, | |
| 322 | + &byteorder, final ? NULL : &consumed); | |
| 323 | + if (decoded == NULL) | |
| 324 | + return NULL; | |
| 325 | + return codec_tuple(decoded, consumed); | |
| 326 | + | |
| 327 | +} | |
| 328 | + | |
| 329 | +static PyObject * | |
| 330 | +utf_16_be_decode(PyObject *self, | |
| 331 | + PyObject *args) | |
| 332 | +{ | |
| 333 | + const char *data; | |
| 334 | + Py_ssize_t size; | |
| 335 | + const char *errors = NULL; | |
| 336 | + int byteorder = 1; | |
| 337 | + int final = 0; | |
| 338 | + Py_ssize_t consumed; | |
| 339 | + PyObject *decoded = NULL; | |
| 340 | + | |
| 341 | + if (!PyArg_ParseTuple(args, "t#|zi:utf_16_be_decode", | |
| 342 | + &data, &size, &errors, &final)) | |
| 343 | + return NULL; | |
| 344 | + if (size < 0) { | |
| 345 | + PyErr_SetString(PyExc_ValueError, "negative argument"); | |
| 346 | + return 0; | |
| 347 | + } | |
| 348 | + consumed = size; /* This is overwritten unless final is true. */ | |
| 349 | + decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, | |
| 350 | + &byteorder, final ? NULL : &consumed); | |
| 351 | + if (decoded == NULL) | |
| 352 | + return NULL; | |
| 353 | + return codec_tuple(decoded, consumed); | |
| 354 | +} | |
| 355 | + | |
| 356 | +/* This non-standard version also provides access to the byteorder | |
| 357 | + parameter of the builtin UTF-16 codec. | |
| 358 | + | |
| 359 | + It returns a tuple (unicode, bytesread, byteorder) with byteorder | |
| 360 | + being the value in effect at the end of data. | |
| 361 | + | |
| 362 | +*/ | |
| 363 | + | |
| 364 | +static PyObject * | |
| 365 | +utf_16_ex_decode(PyObject *self, | |
| 366 | + PyObject *args) | |
| 367 | +{ | |
| 368 | + const char *data; | |
| 369 | + Py_ssize_t size; | |
| 370 | + const char *errors = NULL; | |
| 371 | + int byteorder = 0; | |
| 372 | + PyObject *unicode, *tuple; | |
| 373 | + int final = 0; | |
| 374 | + Py_ssize_t consumed; | |
| 375 | + | |
| 376 | + if (!PyArg_ParseTuple(args, "t#|zii:utf_16_ex_decode", | |
| 377 | + &data, &size, &errors, &byteorder, &final)) | |
| 378 | + return NULL; | |
| 379 | + if (size < 0) { | |
| 380 | + PyErr_SetString(PyExc_ValueError, "negative argument"); | |
| 381 | + return 0; | |
| 382 | + } | |
| 383 | + consumed = size; /* This is overwritten unless final is true. */ | |
| 384 | + unicode = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, | |
| 385 | + final ? NULL : &consumed); | |
| 386 | + if (unicode == NULL) | |
| 387 | + return NULL; | |
| 388 | + tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); | |
| 389 | + Py_DECREF(unicode); | |
| 390 | + return tuple; | |
| 391 | +} | |
| 392 | + | |
| 393 | +static PyObject * | |
| 394 | +unicode_escape_decode(PyObject *self, | |
| 395 | + PyObject *args) | |
| 396 | +{ | |
| 397 | + const char *data; | |
| 398 | + Py_ssize_t size; | |
| 399 | + const char *errors = NULL; | |
| 400 | + | |
| 401 | + if (!PyArg_ParseTuple(args, "t#|z:unicode_escape_decode", | |
| 402 | + &data, &size, &errors)) | |
| 403 | + return NULL; | |
| 404 | + | |
| 405 | + return codec_tuple(PyUnicode_DecodeUnicodeEscape(data, size, errors), | |
| 406 | + size); | |
| 407 | +} | |
| 408 | + | |
| 409 | +static PyObject * | |
| 410 | +raw_unicode_escape_decode(PyObject *self, | |
| 411 | + PyObject *args) | |
| 412 | +{ | |
| 413 | + const char *data; | |
| 414 | + Py_ssize_t size; | |
| 415 | + const char *errors = NULL; | |
| 416 | + | |
| 417 | + if (!PyArg_ParseTuple(args, "t#|z:raw_unicode_escape_decode", | |
| 418 | + &data, &size, &errors)) | |
| 419 | + return NULL; | |
| 420 | + | |
| 421 | + return codec_tuple(PyUnicode_DecodeRawUnicodeEscape(data, size, errors), | |
| 422 | + size); | |
| 423 | +} | |
| 424 | + | |
| 425 | +static PyObject * | |
| 426 | +latin_1_decode(PyObject *self, | |
| 427 | + PyObject *args) | |
| 428 | +{ | |
| 429 | + const char *data; | |
| 430 | + Py_ssize_t size; | |
| 431 | + const char *errors = NULL; | |
| 432 | + | |
| 433 | + if (!PyArg_ParseTuple(args, "t#|z:latin_1_decode", | |
| 434 | + &data, &size, &errors)) | |
| 435 | + return NULL; | |
| 436 | + | |
| 437 | + return codec_tuple(PyUnicode_DecodeLatin1(data, size, errors), | |
| 438 | + size); | |
| 439 | +} | |
| 440 | + | |
| 441 | +static PyObject * | |
| 442 | +ascii_decode(PyObject *self, | |
| 443 | + PyObject *args) | |
| 444 | +{ | |
| 445 | + const char *data; | |
| 446 | + Py_ssize_t size; | |
| 447 | + const char *errors = NULL; | |
| 448 | + | |
| 449 | + if (!PyArg_ParseTuple(args, "t#|z:ascii_decode", | |
| 450 | + &data, &size, &errors)) | |
| 451 | + return NULL; | |
| 452 | + | |
| 453 | + return codec_tuple(PyUnicode_DecodeASCII(data, size, errors), | |
| 454 | + size); | |
| 455 | +} | |
| 456 | + | |
| 457 | +static PyObject * | |
| 458 | +charmap_decode(PyObject *self, | |
| 459 | + PyObject *args) | |
| 460 | +{ | |
| 461 | + const char *data; | |
| 462 | + Py_ssize_t size; | |
| 463 | + const char *errors = NULL; | |
| 464 | + PyObject *mapping = NULL; | |
| 465 | + | |
| 466 | + if (!PyArg_ParseTuple(args, "t#|zO:charmap_decode", | |
| 467 | + &data, &size, &errors, &mapping)) | |
| 468 | + return NULL; | |
| 469 | + if (mapping == Py_None) | |
| 470 | + mapping = NULL; | |
| 471 | + | |
| 472 | + return codec_tuple(PyUnicode_DecodeCharmap(data, size, mapping, errors), | |
| 473 | + size); | |
| 474 | +} | |
| 475 | + | |
| 476 | +#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) | |
| 477 | + | |
| 478 | +static PyObject * | |
| 479 | +mbcs_decode(PyObject *self, | |
| 480 | + PyObject *args) | |
| 481 | +{ | |
| 482 | + const char *data; | |
| 483 | + Py_ssize_t size, consumed; | |
| 484 | + const char *errors = NULL; | |
| 485 | + int final = 0; | |
| 486 | + PyObject *decoded; | |
| 487 | + | |
| 488 | + if (!PyArg_ParseTuple(args, "t#|zi:mbcs_decode", | |
| 489 | + &data, &size, &errors, &final)) | |
| 490 | + return NULL; | |
| 491 | + | |
| 492 | + decoded = PyUnicode_DecodeMBCSStateful( | |
| 493 | + data, size, errors, final ? NULL : &consumed); | |
| 494 | + if (!decoded) | |
| 495 | + return NULL; | |
| 496 | + return codec_tuple(decoded, final ? size : consumed); | |
| 497 | +} | |
| 498 | + | |
| 499 | +#endif /* MS_WINDOWS */ | |
| 500 | + | |
| 501 | +/* --- Encoder ------------------------------------------------------------ */ | |
| 502 | + | |
| 503 | +static PyObject * | |
| 504 | +readbuffer_encode(PyObject *self, | |
| 505 | + PyObject *args) | |
| 506 | +{ | |
| 507 | + const char *data; | |
| 508 | + Py_ssize_t size; | |
| 509 | + const char *errors = NULL; | |
| 510 | + | |
| 511 | + if (!PyArg_ParseTuple(args, "s#|z:readbuffer_encode", | |
| 512 | + &data, &size, &errors)) | |
| 513 | + return NULL; | |
| 514 | + | |
| 515 | + return codec_tuple(PyString_FromStringAndSize(data, size), | |
| 516 | + size); | |
| 517 | +} | |
| 518 | + | |
| 519 | +static PyObject * | |
| 520 | +charbuffer_encode(PyObject *self, | |
| 521 | + PyObject *args) | |
| 522 | +{ | |
| 523 | + const char *data; | |
| 524 | + Py_ssize_t size; | |
| 525 | + const char *errors = NULL; | |
| 526 | + | |
| 527 | + if (!PyArg_ParseTuple(args, "t#|z:charbuffer_encode", | |
| 528 | + &data, &size, &errors)) | |
| 529 | + return NULL; | |
| 530 | + | |
| 531 | + return codec_tuple(PyString_FromStringAndSize(data, size), | |
| 532 | + size); | |
| 533 | +} | |
| 534 | + | |
| 535 | +static PyObject * | |
| 536 | +unicode_internal_encode(PyObject *self, | |
| 537 | + PyObject *args) | |
| 538 | +{ | |
| 539 | + PyObject *obj; | |
| 540 | + const char *errors = NULL; | |
| 541 | + const char *data; | |
| 542 | + Py_ssize_t size; | |
| 543 | + | |
| 544 | + if (!PyArg_ParseTuple(args, "O|z:unicode_internal_encode", | |
| 545 | + &obj, &errors)) | |
| 546 | + return NULL; | |
| 547 | + | |
| 548 | + if (PyUnicode_Check(obj)) { | |
| 549 | + data = PyUnicode_AS_DATA(obj); | |
| 550 | + size = PyUnicode_GET_DATA_SIZE(obj); | |
| 551 | + return codec_tuple(PyString_FromStringAndSize(data, size), | |
| 552 | + size); | |
| 553 | + } | |
| 554 | + else { | |
| 555 | + if (PyObject_AsReadBuffer(obj, (const void **)&data, &size)) | |
| 556 | + return NULL; | |
| 557 | + return codec_tuple(PyString_FromStringAndSize(data, size), | |
| 558 | + size); | |
| 559 | + } | |
| 560 | +} | |
| 561 | + | |
| 562 | +static PyObject * | |
| 563 | +utf_7_encode(PyObject *self, | |
| 564 | + PyObject *args) | |
| 565 | +{ | |
| 566 | + PyObject *str, *v; | |
| 567 | + const char *errors = NULL; | |
| 568 | + | |
| 569 | + if (!PyArg_ParseTuple(args, "O|z:utf_7_encode", | |
| 570 | + &str, &errors)) | |
| 571 | + return NULL; | |
| 572 | + | |
| 573 | + str = PyUnicode_FromObject(str); | |
| 574 | + if (str == NULL) | |
| 575 | + return NULL; | |
| 576 | + v = codec_tuple(PyUnicode_EncodeUTF7(PyUnicode_AS_UNICODE(str), | |
| 577 | + PyUnicode_GET_SIZE(str), | |
| 578 | + 0, | |
| 579 | + 0, | |
| 580 | + errors), | |
| 581 | + PyUnicode_GET_SIZE(str)); | |
| 582 | + Py_DECREF(str); | |
| 583 | + return v; | |
| 584 | +} | |
| 585 | + | |
| 586 | +static PyObject * | |
| 587 | +utf_8_encode(PyObject *self, | |
| 588 | + PyObject *args) | |
| 589 | +{ | |
| 590 | + PyObject *str, *v; | |
| 591 | + const char *errors = NULL; | |
| 592 | + | |
| 593 | + if (!PyArg_ParseTuple(args, "O|z:utf_8_encode", | |
| 594 | + &str, &errors)) | |
| 595 | + return NULL; | |
| 596 | + | |
| 597 | + str = PyUnicode_FromObject(str); | |
| 598 | + if (str == NULL) | |
| 599 | + return NULL; | |
| 600 | + v = codec_tuple(PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(str), | |
| 601 | + PyUnicode_GET_SIZE(str), | |
| 602 | + errors), | |
| 603 | + PyUnicode_GET_SIZE(str)); | |
| 604 | + Py_DECREF(str); | |
| 605 | + return v; | |
| 606 | +} | |
| 607 | + | |
| 608 | +/* This version provides access to the byteorder parameter of the | |
| 609 | + builtin UTF-16 codecs as optional third argument. It defaults to 0 | |
| 610 | + which means: use the native byte order and prepend the data with a | |
| 611 | + BOM mark. | |
| 612 | + | |
| 613 | +*/ | |
| 614 | + | |
| 615 | +static PyObject * | |
| 616 | +utf_16_encode(PyObject *self, | |
| 617 | + PyObject *args) | |
| 618 | +{ | |
| 619 | + PyObject *str, *v; | |
| 620 | + const char *errors = NULL; | |
| 621 | + int byteorder = 0; | |
| 622 | + | |
| 623 | + if (!PyArg_ParseTuple(args, "O|zi:utf_16_encode", | |
| 624 | + &str, &errors, &byteorder)) | |
| 625 | + return NULL; | |
| 626 | + | |
| 627 | + str = PyUnicode_FromObject(str); | |
| 628 | + if (str == NULL) | |
| 629 | + return NULL; | |
| 630 | + v = codec_tuple(PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(str), | |
| 631 | + PyUnicode_GET_SIZE(str), | |
| 632 | + errors, | |
| 633 | + byteorder), | |
| 634 | + PyUnicode_GET_SIZE(str)); | |
| 635 | + Py_DECREF(str); | |
| 636 | + return v; | |
| 637 | +} | |
| 638 | + | |
| 639 | +static PyObject * | |
| 640 | +utf_16_le_encode(PyObject *self, | |
| 641 | + PyObject *args) | |
| 642 | +{ | |
| 643 | + PyObject *str, *v; | |
| 644 | + const char *errors = NULL; | |
| 645 | + | |
| 646 | + if (!PyArg_ParseTuple(args, "O|z:utf_16_le_encode", | |
| 647 | + &str, &errors)) | |
| 648 | + return NULL; | |
| 649 | + | |
| 650 | + str = PyUnicode_FromObject(str); | |
| 651 | + if (str == NULL) | |
| 652 | + return NULL; | |
| 653 | + v = codec_tuple(PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(str), | |
| 654 | + PyUnicode_GET_SIZE(str), | |
| 655 | + errors, | |
| 656 | + -1), | |
| 657 | + PyUnicode_GET_SIZE(str)); | |
| 658 | + Py_DECREF(str); | |
| 659 | + return v; | |
| 660 | +} | |
| 661 | + | |
| 662 | +static PyObject * | |
| 663 | +utf_16_be_encode(PyObject *self, | |
| 664 | + PyObject *args) | |
| 665 | +{ | |
| 666 | + PyObject *str, *v; | |
| 667 | + const char *errors = NULL; | |
| 668 | + | |
| 669 | + if (!PyArg_ParseTuple(args, "O|z:utf_16_be_encode", | |
| 670 | + &str, &errors)) | |
| 671 | + return NULL; | |
| 672 | + | |
| 673 | + str = PyUnicode_FromObject(str); | |
| 674 | + if (str == NULL) | |
| 675 | + return NULL; | |
| 676 | + v = codec_tuple(PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(str), | |
| 677 | + PyUnicode_GET_SIZE(str), | |
| 678 | + errors, | |
| 679 | + +1), | |
| 680 | + PyUnicode_GET_SIZE(str)); | |
| 681 | + Py_DECREF(str); | |
| 682 | + return v; | |
| 683 | +} | |
| 684 | + | |
| 685 | +static PyObject * | |
| 686 | +unicode_escape_encode(PyObject *self, | |
| 687 | + PyObject *args) | |
| 688 | +{ | |
| 689 | + PyObject *str, *v; | |
| 690 | + const char *errors = NULL; | |
| 691 | + | |
| 692 | + if (!PyArg_ParseTuple(args, "O|z:unicode_escape_encode", | |
| 693 | + &str, &errors)) | |
| 694 | + return NULL; | |
| 695 | + | |
| 696 | + str = PyUnicode_FromObject(str); | |
| 697 | + if (str == NULL) | |
| 698 | + return NULL; | |
| 699 | + v = codec_tuple(PyUnicode_EncodeUnicodeEscape(PyUnicode_AS_UNICODE(str), | |
| 700 | + PyUnicode_GET_SIZE(str)), | |
| 701 | + PyUnicode_GET_SIZE(str)); | |
| 702 | + Py_DECREF(str); | |
| 703 | + return v; | |
| 704 | +} | |
| 705 | + | |
| 706 | +static PyObject * | |
| 707 | +raw_unicode_escape_encode(PyObject *self, | |
| 708 | + PyObject *args) | |
| 709 | +{ | |
| 710 | + PyObject *str, *v; | |
| 711 | + const char *errors = NULL; | |
| 712 | + | |
| 713 | + if (!PyArg_ParseTuple(args, "O|z:raw_unicode_escape_encode", | |
| 714 | + &str, &errors)) | |
| 715 | + return NULL; | |
| 716 | + | |
| 717 | + str = PyUnicode_FromObject(str); | |
| 718 | + if (str == NULL) | |
| 719 | + return NULL; | |
| 720 | + v = codec_tuple(PyUnicode_EncodeRawUnicodeEscape( | |
| 721 | + PyUnicode_AS_UNICODE(str), | |
| 722 | + PyUnicode_GET_SIZE(str)), | |
| 723 | + PyUnicode_GET_SIZE(str)); | |
| 724 | + Py_DECREF(str); | |
| 725 | + return v; | |
| 726 | +} | |
| 727 | + | |
| 728 | +static PyObject * | |
| 729 | +latin_1_encode(PyObject *self, | |
| 730 | + PyObject *args) | |
| 731 | +{ | |
| 732 | + PyObject *str, *v; | |
| 733 | + const char *errors = NULL; | |
| 734 | + | |
| 735 | + if (!PyArg_ParseTuple(args, "O|z:latin_1_encode", | |
| 736 | + &str, &errors)) | |
| 737 | + return NULL; | |
| 738 | + | |
| 739 | + str = PyUnicode_FromObject(str); | |
| 740 | + if (str == NULL) | |
| 741 | + return NULL; | |
| 742 | + v = codec_tuple(PyUnicode_EncodeLatin1( | |
| 743 | + PyUnicode_AS_UNICODE(str), | |
| 744 | + PyUnicode_GET_SIZE(str), | |
| 745 | + errors), | |
| 746 | + PyUnicode_GET_SIZE(str)); | |
| 747 | + Py_DECREF(str); | |
| 748 | + return v; | |
| 749 | +} | |
| 750 | + | |
| 751 | +static PyObject * | |
| 752 | +ascii_encode(PyObject *self, | |
| 753 | + PyObject *args) | |
| 754 | +{ | |
| 755 | + PyObject *str, *v; | |
| 756 | + const char *errors = NULL; | |
| 757 | + | |
| 758 | + if (!PyArg_ParseTuple(args, "O|z:ascii_encode", | |
| 759 | + &str, &errors)) | |
| 760 | + return NULL; | |
| 761 | + | |
| 762 | + str = PyUnicode_FromObject(str); | |
| 763 | + if (str == NULL) | |
| 764 | + return NULL; | |
| 765 | + v = codec_tuple(PyUnicode_EncodeASCII( | |
| 766 | + PyUnicode_AS_UNICODE(str), | |
| 767 | + PyUnicode_GET_SIZE(str), | |
| 768 | + errors), | |
| 769 | + PyUnicode_GET_SIZE(str)); | |
| 770 | + Py_DECREF(str); | |
| 771 | + return v; | |
| 772 | +} | |
| 773 | + | |
| 774 | +static PyObject * | |
| 775 | +charmap_encode(PyObject *self, | |
| 776 | + PyObject *args) | |
| 777 | +{ | |
| 778 | + PyObject *str, *v; | |
| 779 | + const char *errors = NULL; | |
| 780 | + PyObject *mapping = NULL; | |
| 781 | + | |
| 782 | + if (!PyArg_ParseTuple(args, "O|zO:charmap_encode", | |
| 783 | + &str, &errors, &mapping)) | |
| 784 | + return NULL; | |
| 785 | + if (mapping == Py_None) | |
| 786 | + mapping = NULL; | |
| 787 | + | |
| 788 | + str = PyUnicode_FromObject(str); | |
| 789 | + if (str == NULL) | |
| 790 | + return NULL; | |
| 791 | + v = codec_tuple(PyUnicode_EncodeCharmap( | |
| 792 | + PyUnicode_AS_UNICODE(str), | |
| 793 | + PyUnicode_GET_SIZE(str), | |
| 794 | + mapping, | |
| 795 | + errors), | |
| 796 | + PyUnicode_GET_SIZE(str)); | |
| 797 | + Py_DECREF(str); | |
| 798 | + return v; | |
| 799 | +} | |
| 800 | + | |
| 801 | +static PyObject* | |
| 802 | +charmap_build(PyObject *self, PyObject *args) | |
| 803 | +{ | |
| 804 | + PyObject *map; | |
| 805 | + if (!PyArg_ParseTuple(args, "U:charmap_build", &map)) | |
| 806 | + return NULL; | |
| 807 | + return PyUnicode_BuildEncodingMap(map); | |
| 808 | +} | |
| 809 | + | |
| 810 | +#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) | |
| 811 | + | |
| 812 | +static PyObject * | |
| 813 | +mbcs_encode(PyObject *self, | |
| 814 | + PyObject *args) | |
| 815 | +{ | |
| 816 | + PyObject *str, *v; | |
| 817 | + const char *errors = NULL; | |
| 818 | + | |
| 819 | + if (!PyArg_ParseTuple(args, "O|z:mbcs_encode", | |
| 820 | + &str, &errors)) | |
| 821 | + return NULL; | |
| 822 | + | |
| 823 | + str = PyUnicode_FromObject(str); | |
| 824 | + if (str == NULL) | |
| 825 | + return NULL; | |
| 826 | + v = codec_tuple(PyUnicode_EncodeMBCS( | |
| 827 | + PyUnicode_AS_UNICODE(str), | |
| 828 | + PyUnicode_GET_SIZE(str), | |
| 829 | + errors), | |
| 830 | + PyUnicode_GET_SIZE(str)); | |
| 831 | + Py_DECREF(str); | |
| 832 | + return v; | |
| 833 | +} | |
| 834 | + | |
| 835 | +#endif /* MS_WINDOWS */ | |
| 836 | +#endif /* Py_USING_UNICODE */ | |
| 837 | + | |
| 838 | +/* --- Error handler registry --------------------------------------------- */ | |
| 839 | + | |
| 840 | +PyDoc_STRVAR(register_error__doc__, | |
| 841 | +"register_error(errors, handler)\n\ | |
| 842 | +\n\ | |
| 843 | +Register the specified error handler under the name\n\ | |
| 844 | +errors. handler must be a callable object, that\n\ | |
| 845 | +will be called with an exception instance containing\n\ | |
| 846 | +information about the location of the encoding/decoding\n\ | |
| 847 | +error and must return a (replacement, new position) tuple."); | |
| 848 | + | |
| 849 | +static PyObject *register_error(PyObject *self, PyObject *args) | |
| 850 | +{ | |
| 851 | + const char *name; | |
| 852 | + PyObject *handler; | |
| 853 | + | |
| 854 | + if (!PyArg_ParseTuple(args, "sO:register_error", | |
| 855 | + &name, &handler)) | |
| 856 | + return NULL; | |
| 857 | + if (PyCodec_RegisterError(name, handler)) | |
| 858 | + return NULL; | |
| 859 | + Py_RETURN_NONE; | |
| 860 | +} | |
| 861 | + | |
| 862 | +PyDoc_STRVAR(lookup_error__doc__, | |
| 863 | +"lookup_error(errors) -> handler\n\ | |
| 864 | +\n\ | |
| 865 | +Return the error handler for the specified error handling name\n\ | |
| 866 | +or raise a LookupError, if no handler exists under this name."); | |
| 867 | + | |
| 868 | +static PyObject *lookup_error(PyObject *self, PyObject *args) | |
| 869 | +{ | |
| 870 | + const char *name; | |
| 871 | + | |
| 872 | + if (!PyArg_ParseTuple(args, "s:lookup_error", | |
| 873 | + &name)) | |
| 874 | + return NULL; | |
| 875 | + return PyCodec_LookupError(name); | |
| 876 | +} | |
| 877 | + | |
| 878 | +/* --- Module API --------------------------------------------------------- */ | |
| 879 | + | |
| 880 | +static PyMethodDef _codecs_functions[] = { | |
| 881 | + {"register", codec_register, METH_O, | |
| 882 | + register__doc__}, | |
| 883 | + {"lookup", codec_lookup, METH_VARARGS, | |
| 884 | + lookup__doc__}, | |
| 885 | + {"encode", codec_encode, METH_VARARGS, | |
| 886 | + encode__doc__}, | |
| 887 | + {"decode", codec_decode, METH_VARARGS, | |
| 888 | + decode__doc__}, | |
| 889 | + {"escape_encode", escape_encode, METH_VARARGS}, | |
| 890 | + {"escape_decode", escape_decode, METH_VARARGS}, | |
| 891 | +#ifdef Py_USING_UNICODE | |
| 892 | + {"utf_8_encode", utf_8_encode, METH_VARARGS}, | |
| 893 | + {"utf_8_decode", utf_8_decode, METH_VARARGS}, | |
| 894 | + {"utf_7_encode", utf_7_encode, METH_VARARGS}, | |
| 895 | + {"utf_7_decode", utf_7_decode, METH_VARARGS}, | |
| 896 | + {"utf_16_encode", utf_16_encode, METH_VARARGS}, | |
| 897 | + {"utf_16_le_encode", utf_16_le_encode, METH_VARARGS}, | |
| 898 | + {"utf_16_be_encode", utf_16_be_encode, METH_VARARGS}, | |
| 899 | + {"utf_16_decode", utf_16_decode, METH_VARARGS}, | |
| 900 | + {"utf_16_le_decode", utf_16_le_decode, METH_VARARGS}, | |
| 901 | + {"utf_16_be_decode", utf_16_be_decode, METH_VARARGS}, | |
| 902 | + {"utf_16_ex_decode", utf_16_ex_decode, METH_VARARGS}, | |
| 903 | + {"unicode_escape_encode", unicode_escape_encode, METH_VARARGS}, | |
| 904 | + {"unicode_escape_decode", unicode_escape_decode, METH_VARARGS}, | |
| 905 | + {"unicode_internal_encode", unicode_internal_encode, METH_VARARGS}, | |
| 906 | + {"unicode_internal_decode", unicode_internal_decode, METH_VARARGS}, | |
| 907 | + {"raw_unicode_escape_encode", raw_unicode_escape_encode, METH_VARARGS}, | |
| 908 | + {"raw_unicode_escape_decode", raw_unicode_escape_decode, METH_VARARGS}, | |
| 909 | + {"latin_1_encode", latin_1_encode, METH_VARARGS}, | |
| 910 | + {"latin_1_decode", latin_1_decode, METH_VARARGS}, | |
| 911 | + {"ascii_encode", ascii_encode, METH_VARARGS}, | |
| 912 | + {"ascii_decode", ascii_decode, METH_VARARGS}, | |
| 913 | + {"charmap_encode", charmap_encode, METH_VARARGS}, | |
| 914 | + {"charmap_decode", charmap_decode, METH_VARARGS}, | |
| 915 | + {"charmap_build", charmap_build, METH_VARARGS}, | |
| 916 | + {"readbuffer_encode", readbuffer_encode, METH_VARARGS}, | |
| 917 | + {"charbuffer_encode", charbuffer_encode, METH_VARARGS}, | |
| 918 | +#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) | |
| 919 | + {"mbcs_encode", mbcs_encode, METH_VARARGS}, | |
| 920 | + {"mbcs_decode", mbcs_decode, METH_VARARGS}, | |
| 921 | +#endif | |
| 922 | +#endif /* Py_USING_UNICODE */ | |
| 923 | + {"register_error", register_error, METH_VARARGS, | |
| 924 | + register_error__doc__}, | |
| 925 | + {"lookup_error", lookup_error, METH_VARARGS, | |
| 926 | + lookup_error__doc__}, | |
| 927 | + {NULL, NULL} /* sentinel */ | |
| 928 | +}; | |
| 929 | + | |
| 930 | +PyMODINIT_FUNC | |
| 931 | +init_codecs(void) | |
| 932 | +{ | |
| 933 | + Py_InitModule("_codecs", _codecs_functions); | |
| 934 | +} | |
| @@ -0,0 +1,1604 @@ | ||
| 1 | +/* csv module */ | |
| 2 | + | |
| 3 | +/* | |
| 4 | + | |
| 5 | +This module provides the low-level underpinnings of a CSV reading/writing | |
| 6 | +module. Users should not use this module directly, but import the csv.py | |
| 7 | +module instead. | |
| 8 | + | |
| 9 | +**** For people modifying this code, please note that as of this writing | |
| 10 | +**** (2003-03-23), it is intended that this code should work with Python | |
| 11 | +**** 2.2. | |
| 12 | + | |
| 13 | +*/ | |
| 14 | + | |
| 15 | +#define MODULE_VERSION "1.0" | |
| 16 | + | |
| 17 | +#include "Python.h" | |
| 18 | +#include "structmember.h" | |
| 19 | + | |
| 20 | + | |
| 21 | +/* begin 2.2 compatibility macros */ | |
| 22 | +#ifndef PyDoc_STRVAR | |
| 23 | +/* Define macros for inline documentation. */ | |
| 24 | +#define PyDoc_VAR(name) static char name[] | |
| 25 | +#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) | |
| 26 | +#ifdef WITH_DOC_STRINGS | |
| 27 | +#define PyDoc_STR(str) str | |
| 28 | +#else | |
| 29 | +#define PyDoc_STR(str) "" | |
| 30 | +#endif | |
| 31 | +#endif /* ifndef PyDoc_STRVAR */ | |
| 32 | + | |
| 33 | +#ifndef PyMODINIT_FUNC | |
| 34 | +# if defined(__cplusplus) | |
| 35 | +# define PyMODINIT_FUNC extern "C" void | |
| 36 | +# else /* __cplusplus */ | |
| 37 | +# define PyMODINIT_FUNC void | |
| 38 | +# endif /* __cplusplus */ | |
| 39 | +#endif | |
| 40 | + | |
| 41 | +#ifndef Py_CLEAR | |
| 42 | +#define Py_CLEAR(op) \ | |
| 43 | + do { \ | |
| 44 | + if (op) { \ | |
| 45 | + PyObject *tmp = (PyObject *)(op); \ | |
| 46 | + (op) = NULL; \ | |
| 47 | + Py_DECREF(tmp); \ | |
| 48 | + } \ | |
| 49 | + } while (0) | |
| 50 | +#endif | |
| 51 | +#ifndef Py_VISIT | |
| 52 | +#define Py_VISIT(op) \ | |
| 53 | + do { \ | |
| 54 | + if (op) { \ | |
| 55 | + int vret = visit((PyObject *)(op), arg); \ | |
| 56 | + if (vret) \ | |
| 57 | + return vret; \ | |
| 58 | + } \ | |
| 59 | + } while (0) | |
| 60 | +#endif | |
| 61 | + | |
| 62 | +/* end 2.2 compatibility macros */ | |
| 63 | + | |
| 64 | +#define IS_BASESTRING(o) \ | |
| 65 | + PyObject_TypeCheck(o, &PyBaseString_Type) | |
| 66 | + | |
| 67 | +static PyObject *error_obj; /* CSV exception */ | |
| 68 | +static PyObject *dialects; /* Dialect registry */ | |
| 69 | +static long field_limit = 128 * 1024; /* max parsed field size */ | |
| 70 | + | |
| 71 | +typedef enum { | |
| 72 | + START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, | |
| 73 | + IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD, | |
| 74 | + EAT_CRNL | |
| 75 | +} ParserState; | |
| 76 | + | |
| 77 | +typedef enum { | |
| 78 | + QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE | |
| 79 | +} QuoteStyle; | |
| 80 | + | |
| 81 | +typedef struct { | |
| 82 | + QuoteStyle style; | |
| 83 | + char *name; | |
| 84 | +} StyleDesc; | |
| 85 | + | |
| 86 | +static StyleDesc quote_styles[] = { | |
| 87 | + { QUOTE_MINIMAL, "QUOTE_MINIMAL" }, | |
| 88 | + { QUOTE_ALL, "QUOTE_ALL" }, | |
| 89 | + { QUOTE_NONNUMERIC, "QUOTE_NONNUMERIC" }, | |
| 90 | + { QUOTE_NONE, "QUOTE_NONE" }, | |
| 91 | + { 0 } | |
| 92 | +}; | |
| 93 | + | |
| 94 | +typedef struct { | |
| 95 | + PyObject_HEAD | |
| 96 | + | |
| 97 | + int doublequote; /* is " represented by ""? */ | |
| 98 | + char delimiter; /* field separator */ | |
| 99 | + char quotechar; /* quote character */ | |
| 100 | + char escapechar; /* escape character */ | |
| 101 | + int skipinitialspace; /* ignore spaces following delimiter? */ | |
| 102 | + PyObject *lineterminator; /* string to write between records */ | |
| 103 | + int quoting; /* style of quoting to write */ | |
| 104 | + | |
| 105 | + int strict; /* raise exception on bad CSV */ | |
| 106 | +} DialectObj; | |
| 107 | + | |
| 108 | +staticforward PyTypeObject Dialect_Type; | |
| 109 | + | |
| 110 | +typedef struct { | |
| 111 | + PyObject_HEAD | |
| 112 | + | |
| 113 | + PyObject *input_iter; /* iterate over this for input lines */ | |
| 114 | + | |
| 115 | + DialectObj *dialect; /* parsing dialect */ | |
| 116 | + | |
| 117 | + PyObject *fields; /* field list for current record */ | |
| 118 | + ParserState state; /* current CSV parse state */ | |
| 119 | + char *field; /* build current field in here */ | |
| 120 | + int field_size; /* size of allocated buffer */ | |
| 121 | + int field_len; /* length of current field */ | |
| 122 | + int numeric_field; /* treat field as numeric */ | |
| 123 | + unsigned long line_num; /* Source-file line number */ | |
| 124 | +} ReaderObj; | |
| 125 | + | |
| 126 | +staticforward PyTypeObject Reader_Type; | |
| 127 | + | |
| 128 | +#define ReaderObject_Check(v) ((v)->ob_type == &Reader_Type) | |
| 129 | + | |
| 130 | +typedef struct { | |
| 131 | + PyObject_HEAD | |
| 132 | + | |
| 133 | + PyObject *writeline; /* write output lines to this file */ | |
| 134 | + | |
| 135 | + DialectObj *dialect; /* parsing dialect */ | |
| 136 | + | |
| 137 | + char *rec; /* buffer for parser.join */ | |
| 138 | + int rec_size; /* size of allocated record */ | |
| 139 | + int rec_len; /* length of record */ | |
| 140 | + int num_fields; /* number of fields in record */ | |
| 141 | +} WriterObj; | |
| 142 | + | |
| 143 | +staticforward PyTypeObject Writer_Type; | |
| 144 | + | |
| 145 | +/* | |
| 146 | + * DIALECT class | |
| 147 | + */ | |
| 148 | + | |
| 149 | +static PyObject * | |
| 150 | +get_dialect_from_registry(PyObject * name_obj) | |
| 151 | +{ | |
| 152 | + PyObject *dialect_obj; | |
| 153 | + | |
| 154 | + dialect_obj = PyDict_GetItem(dialects, name_obj); | |
| 155 | + if (dialect_obj == NULL) { | |
| 156 | + if (!PyErr_Occurred()) | |
| 157 | + PyErr_Format(error_obj, "unknown dialect"); | |
| 158 | + } | |
| 159 | + else | |
| 160 | + Py_INCREF(dialect_obj); | |
| 161 | + return dialect_obj; | |
| 162 | +} | |
| 163 | + | |
| 164 | +static PyObject * | |
| 165 | +get_string(PyObject *str) | |
| 166 | +{ | |
| 167 | + Py_XINCREF(str); | |
| 168 | + return str; | |
| 169 | +} | |
| 170 | + | |
| 171 | +static PyObject * | |
| 172 | +get_nullchar_as_None(char c) | |
| 173 | +{ | |
| 174 | + if (c == '\0') { | |
| 175 | + Py_INCREF(Py_None); | |
| 176 | + return Py_None; | |
| 177 | + } | |
| 178 | + else | |
| 179 | + return PyString_FromStringAndSize((char*)&c, 1); | |
| 180 | +} | |
| 181 | + | |
| 182 | +static PyObject * | |
| 183 | +Dialect_get_lineterminator(DialectObj *self) | |
| 184 | +{ | |
| 185 | + return get_string(self->lineterminator); | |
| 186 | +} | |
| 187 | + | |
| 188 | +static PyObject * | |
| 189 | +Dialect_get_escapechar(DialectObj *self) | |
| 190 | +{ | |
| 191 | + return get_nullchar_as_None(self->escapechar); | |
| 192 | +} | |
| 193 | + | |
| 194 | +static PyObject * | |
| 195 | +Dialect_get_quotechar(DialectObj *self) | |
| 196 | +{ | |
| 197 | + return get_nullchar_as_None(self->quotechar); | |
| 198 | +} | |
| 199 | + | |
| 200 | +static PyObject * | |
| 201 | +Dialect_get_quoting(DialectObj *self) | |
| 202 | +{ | |
| 203 | + return PyInt_FromLong(self->quoting); | |
| 204 | +} | |
| 205 | + | |
| 206 | +static int | |
| 207 | +_set_bool(const char *name, int *target, PyObject *src, int dflt) | |
| 208 | +{ | |
| 209 | + if (src == NULL) | |
| 210 | + *target = dflt; | |
| 211 | + else | |
| 212 | + *target = PyObject_IsTrue(src); | |
| 213 | + return 0; | |
| 214 | +} | |
| 215 | + | |
| 216 | +static int | |
| 217 | +_set_int(const char *name, int *target, PyObject *src, int dflt) | |
| 218 | +{ | |
| 219 | + if (src == NULL) | |
| 220 | + *target = dflt; | |
| 221 | + else { | |
| 222 | + if (!PyInt_Check(src)) { | |
| 223 | + PyErr_Format(PyExc_TypeError, | |
| 224 | + "\"%s\" must be an integer", name); | |
| 225 | + return -1; | |
| 226 | + } | |
| 227 | + *target = PyInt_AsLong(src); | |
| 228 | + } | |
| 229 | + return 0; | |
| 230 | +} | |
| 231 | + | |
| 232 | +static int | |
| 233 | +_set_char(const char *name, char *target, PyObject *src, char dflt) | |
| 234 | +{ | |
| 235 | + if (src == NULL) | |
| 236 | + *target = dflt; | |
| 237 | + else { | |
| 238 | + if (src == Py_None || PyString_Size(src) == 0) | |
| 239 | + *target = '\0'; | |
| 240 | + else if (!PyString_Check(src) || PyString_Size(src) != 1) { | |
| 241 | + PyErr_Format(PyExc_TypeError, | |
| 242 | + "\"%s\" must be an 1-character string", | |
| 243 | + name); | |
| 244 | + return -1; | |
| 245 | + } | |
| 246 | + else { | |
| 247 | + char *s = PyString_AsString(src); | |
| 248 | + if (s == NULL) | |
| 249 | + return -1; | |
| 250 | + *target = s[0]; | |
| 251 | + } | |
| 252 | + } | |
| 253 | + return 0; | |
| 254 | +} | |
| 255 | + | |
| 256 | +static int | |
| 257 | +_set_str(const char *name, PyObject **target, PyObject *src, const char *dflt) | |
| 258 | +{ | |
| 259 | + if (src == NULL) | |
| 260 | + *target = PyString_FromString(dflt); | |
| 261 | + else { | |
| 262 | + if (src == Py_None) | |
| 263 | + *target = NULL; | |
| 264 | + else if (!IS_BASESTRING(src)) { | |
| 265 | + PyErr_Format(PyExc_TypeError, | |
| 266 | + "\"%s\" must be an string", name); | |
| 267 | + return -1; | |
| 268 | + } | |
| 269 | + else { | |
| 270 | + Py_XDECREF(*target); | |
| 271 | + Py_INCREF(src); | |
| 272 | + *target = src; | |
| 273 | + } | |
| 274 | + } | |
| 275 | + return 0; | |
| 276 | +} | |
| 277 | + | |
| 278 | +static int | |
| 279 | +dialect_check_quoting(int quoting) | |
| 280 | +{ | |
| 281 | + StyleDesc *qs = quote_styles; | |
| 282 | + | |
| 283 | + for (qs = quote_styles; qs->name; qs++) { | |
| 284 | + if (qs->style == quoting) | |
| 285 | + return 0; | |
| 286 | + } | |
| 287 | + PyErr_Format(PyExc_TypeError, "bad \"quoting\" value"); | |
| 288 | + return -1; | |
| 289 | +} | |
| 290 | + | |
| 291 | +#define D_OFF(x) offsetof(DialectObj, x) | |
| 292 | + | |
| 293 | +static struct PyMemberDef Dialect_memberlist[] = { | |
| 294 | + { "delimiter", T_CHAR, D_OFF(delimiter), READONLY }, | |
| 295 | + { "skipinitialspace", T_INT, D_OFF(skipinitialspace), READONLY }, | |
| 296 | + { "doublequote", T_INT, D_OFF(doublequote), READONLY }, | |
| 297 | + { "strict", T_INT, D_OFF(strict), READONLY }, | |
| 298 | + { NULL } | |
| 299 | +}; | |
| 300 | + | |
| 301 | +static PyGetSetDef Dialect_getsetlist[] = { | |
| 302 | + { "escapechar", (getter)Dialect_get_escapechar}, | |
| 303 | + { "lineterminator", (getter)Dialect_get_lineterminator}, | |
| 304 | + { "quotechar", (getter)Dialect_get_quotechar}, | |
| 305 | + { "quoting", (getter)Dialect_get_quoting}, | |
| 306 | + {NULL}, | |
| 307 | +}; | |
| 308 | + | |
| 309 | +static void | |
| 310 | +Dialect_dealloc(DialectObj *self) | |
| 311 | +{ | |
| 312 | + Py_XDECREF(self->lineterminator); | |
| 313 | + self->ob_type->tp_free((PyObject *)self); | |
| 314 | +} | |
| 315 | + | |
| 316 | +static char *dialect_kws[] = { | |
| 317 | + "dialect", | |
| 318 | + "delimiter", | |
| 319 | + "doublequote", | |
| 320 | + "escapechar", | |
| 321 | + "lineterminator", | |
| 322 | + "quotechar", | |
| 323 | + "quoting", | |
| 324 | + "skipinitialspace", | |
| 325 | + "strict", | |
| 326 | + NULL | |
| 327 | +}; | |
| 328 | + | |
| 329 | +static PyObject * | |
| 330 | +dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) | |
| 331 | +{ | |
| 332 | + DialectObj *self; | |
| 333 | + PyObject *ret = NULL; | |
| 334 | + PyObject *dialect = NULL; | |
| 335 | + PyObject *delimiter = NULL; | |
| 336 | + PyObject *doublequote = NULL; | |
| 337 | + PyObject *escapechar = NULL; | |
| 338 | + PyObject *lineterminator = NULL; | |
| 339 | + PyObject *quotechar = NULL; | |
| 340 | + PyObject *quoting = NULL; | |
| 341 | + PyObject *skipinitialspace = NULL; | |
| 342 | + PyObject *strict = NULL; | |
| 343 | + | |
| 344 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, | |
| 345 | + "|OOOOOOOOO", dialect_kws, | |
| 346 | + &dialect, | |
| 347 | + &delimiter, | |
| 348 | + &doublequote, | |
| 349 | + &escapechar, | |
| 350 | + &lineterminator, | |
| 351 | + "echar, | |
| 352 | + "ing, | |
| 353 | + &skipinitialspace, | |
| 354 | + &strict)) | |
| 355 | + return NULL; | |
| 356 | + | |
| 357 | + if (dialect != NULL) { | |
| 358 | + if (IS_BASESTRING(dialect)) { | |
| 359 | + dialect = get_dialect_from_registry(dialect); | |
| 360 | + if (dialect == NULL) | |
| 361 | + return NULL; | |
| 362 | + } | |
| 363 | + else | |
| 364 | + Py_INCREF(dialect); | |
| 365 | + /* Can we reuse this instance? */ | |
| 366 | + if (PyObject_TypeCheck(dialect, &Dialect_Type) && | |
| 367 | + delimiter == 0 && | |
| 368 | + doublequote == 0 && | |
| 369 | + escapechar == 0 && | |
| 370 | + lineterminator == 0 && | |
| 371 | + quotechar == 0 && | |
| 372 | + quoting == 0 && | |
| 373 | + skipinitialspace == 0 && | |
| 374 | + strict == 0) | |
| 375 | + return dialect; | |
| 376 | + } | |
| 377 | + | |
| 378 | + self = (DialectObj *)type->tp_alloc(type, 0); | |
| 379 | + if (self == NULL) { | |
| 380 | + Py_XDECREF(dialect); | |
| 381 | + return NULL; | |
| 382 | + } | |
| 383 | + self->lineterminator = NULL; | |
| 384 | + | |
| 385 | + Py_XINCREF(delimiter); | |
| 386 | + Py_XINCREF(doublequote); | |
| 387 | + Py_XINCREF(escapechar); | |
| 388 | + Py_XINCREF(lineterminator); | |
| 389 | + Py_XINCREF(quotechar); | |
| 390 | + Py_XINCREF(quoting); | |
| 391 | + Py_XINCREF(skipinitialspace); | |
| 392 | + Py_XINCREF(strict); | |
| 393 | + if (dialect != NULL) { | |
| 394 | +#define DIALECT_GETATTR(v, n) \ | |
| 395 | + if (v == NULL) \ | |
| 396 | + v = PyObject_GetAttrString(dialect, n) | |
| 397 | + DIALECT_GETATTR(delimiter, "delimiter"); | |
| 398 | + DIALECT_GETATTR(doublequote, "doublequote"); | |
| 399 | + DIALECT_GETATTR(escapechar, "escapechar"); | |
| 400 | + DIALECT_GETATTR(lineterminator, "lineterminator"); | |
| 401 | + DIALECT_GETATTR(quotechar, "quotechar"); | |
| 402 | + DIALECT_GETATTR(quoting, "quoting"); | |
| 403 | + DIALECT_GETATTR(skipinitialspace, "skipinitialspace"); | |
| 404 | + DIALECT_GETATTR(strict, "strict"); | |
| 405 | + PyErr_Clear(); | |
| 406 | + } | |
| 407 | + | |
| 408 | + /* check types and convert to C values */ | |
| 409 | +#define DIASET(meth, name, target, src, dflt) \ | |
| 410 | + if (meth(name, target, src, dflt)) \ | |
| 411 | + goto err | |
| 412 | + DIASET(_set_char, "delimiter", &self->delimiter, delimiter, ','); | |
| 413 | + DIASET(_set_bool, "doublequote", &self->doublequote, doublequote, 1); | |
| 414 | + DIASET(_set_char, "escapechar", &self->escapechar, escapechar, 0); | |
| 415 | + DIASET(_set_str, "lineterminator", &self->lineterminator, lineterminator, "\r\n"); | |
| 416 | + DIASET(_set_char, "quotechar", &self->quotechar, quotechar, '"'); | |
| 417 | + DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL); | |
| 418 | + DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, 0); | |
| 419 | + DIASET(_set_bool, "strict", &self->strict, strict, 0); | |
| 420 | + | |
| 421 | + /* validate options */ | |
| 422 | + if (dialect_check_quoting(self->quoting)) | |
| 423 | + goto err; | |
| 424 | + if (self->delimiter == 0) { | |
| 425 | + PyErr_SetString(PyExc_TypeError, "delimiter must be set"); | |
| 426 | + goto err; | |
| 427 | + } | |
| 428 | + if (quotechar == Py_None && quoting == NULL) | |
| 429 | + self->quoting = QUOTE_NONE; | |
| 430 | + if (self->quoting != QUOTE_NONE && self->quotechar == 0) { | |
| 431 | + PyErr_SetString(PyExc_TypeError, | |
| 432 | + "quotechar must be set if quoting enabled"); | |
| 433 | + goto err; | |
| 434 | + } | |
| 435 | + if (self->lineterminator == 0) { | |
| 436 | + PyErr_SetString(PyExc_TypeError, "lineterminator must be set"); | |
| 437 | + goto err; | |
| 438 | + } | |
| 439 | + | |
| 440 | + ret = (PyObject *)self; | |
| 441 | + Py_INCREF(self); | |
| 442 | +err: | |
| 443 | + Py_XDECREF(self); | |
| 444 | + Py_XDECREF(dialect); | |
| 445 | + Py_XDECREF(delimiter); | |
| 446 | + Py_XDECREF(doublequote); | |
| 447 | + Py_XDECREF(escapechar); | |
| 448 | + Py_XDECREF(lineterminator); | |
| 449 | + Py_XDECREF(quotechar); | |
| 450 | + Py_XDECREF(quoting); | |
| 451 | + Py_XDECREF(skipinitialspace); | |
| 452 | + Py_XDECREF(strict); | |
| 453 | + return ret; | |
| 454 | +} | |
| 455 | + | |
| 456 | + | |
| 457 | +PyDoc_STRVAR(Dialect_Type_doc, | |
| 458 | +"CSV dialect\n" | |
| 459 | +"\n" | |
| 460 | +"The Dialect type records CSV parsing and generation options.\n"); | |
| 461 | + | |
| 462 | +static PyTypeObject Dialect_Type = { | |
| 463 | + PyObject_HEAD_INIT(NULL) | |
| 464 | + 0, /* ob_size */ | |
| 465 | + "_csv.Dialect", /* tp_name */ | |
| 466 | + sizeof(DialectObj), /* tp_basicsize */ | |
| 467 | + 0, /* tp_itemsize */ | |
| 468 | + /* methods */ | |
| 469 | + (destructor)Dialect_dealloc, /* tp_dealloc */ | |
| 470 | + (printfunc)0, /* tp_print */ | |
| 471 | + (getattrfunc)0, /* tp_getattr */ | |
| 472 | + (setattrfunc)0, /* tp_setattr */ | |
| 473 | + (cmpfunc)0, /* tp_compare */ | |
| 474 | + (reprfunc)0, /* tp_repr */ | |
| 475 | + 0, /* tp_as_number */ | |
| 476 | + 0, /* tp_as_sequence */ | |
| 477 | + 0, /* tp_as_mapping */ | |
| 478 | + (hashfunc)0, /* tp_hash */ | |
| 479 | + (ternaryfunc)0, /* tp_call */ | |
| 480 | + (reprfunc)0, /* tp_str */ | |
| 481 | + 0, /* tp_getattro */ | |
| 482 | + 0, /* tp_setattro */ | |
| 483 | + 0, /* tp_as_buffer */ | |
| 484 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 485 | + Dialect_Type_doc, /* tp_doc */ | |
| 486 | + 0, /* tp_traverse */ | |
| 487 | + 0, /* tp_clear */ | |
| 488 | + 0, /* tp_richcompare */ | |
| 489 | + 0, /* tp_weaklistoffset */ | |
| 490 | + 0, /* tp_iter */ | |
| 491 | + 0, /* tp_iternext */ | |
| 492 | + 0, /* tp_methods */ | |
| 493 | + Dialect_memberlist, /* tp_members */ | |
| 494 | + Dialect_getsetlist, /* tp_getset */ | |
| 495 | + 0, /* tp_base */ | |
| 496 | + 0, /* tp_dict */ | |
| 497 | + 0, /* tp_descr_get */ | |
| 498 | + 0, /* tp_descr_set */ | |
| 499 | + 0, /* tp_dictoffset */ | |
| 500 | + 0, /* tp_init */ | |
| 501 | + 0, /* tp_alloc */ | |
| 502 | + dialect_new, /* tp_new */ | |
| 503 | + 0, /* tp_free */ | |
| 504 | +}; | |
| 505 | + | |
| 506 | +/* | |
| 507 | + * Return an instance of the dialect type, given a Python instance or kwarg | |
| 508 | + * description of the dialect | |
| 509 | + */ | |
| 510 | +static PyObject * | |
| 511 | +_call_dialect(PyObject *dialect_inst, PyObject *kwargs) | |
| 512 | +{ | |
| 513 | + PyObject *ctor_args; | |
| 514 | + PyObject *dialect; | |
| 515 | + | |
| 516 | + ctor_args = Py_BuildValue(dialect_inst ? "(O)" : "()", dialect_inst); | |
| 517 | + if (ctor_args == NULL) | |
| 518 | + return NULL; | |
| 519 | + dialect = PyObject_Call((PyObject *)&Dialect_Type, ctor_args, kwargs); | |
| 520 | + Py_DECREF(ctor_args); | |
| 521 | + return dialect; | |
| 522 | +} | |
| 523 | + | |
| 524 | +/* | |
| 525 | + * READER | |
| 526 | + */ | |
| 527 | +static int | |
| 528 | +parse_save_field(ReaderObj *self) | |
| 529 | +{ | |
| 530 | + PyObject *field; | |
| 531 | + | |
| 532 | + field = PyString_FromStringAndSize(self->field, self->field_len); | |
| 533 | + if (field == NULL) | |
| 534 | + return -1; | |
| 535 | + self->field_len = 0; | |
| 536 | + if (self->numeric_field) { | |
| 537 | + PyObject *tmp; | |
| 538 | + | |
| 539 | + self->numeric_field = 0; | |
| 540 | + tmp = PyNumber_Float(field); | |
| 541 | + if (tmp == NULL) { | |
| 542 | + Py_DECREF(field); | |
| 543 | + return -1; | |
| 544 | + } | |
| 545 | + Py_DECREF(field); | |
| 546 | + field = tmp; | |
| 547 | + } | |
| 548 | + PyList_Append(self->fields, field); | |
| 549 | + Py_DECREF(field); | |
| 550 | + return 0; | |
| 551 | +} | |
| 552 | + | |
| 553 | +static int | |
| 554 | +parse_grow_buff(ReaderObj *self) | |
| 555 | +{ | |
| 556 | + if (self->field_size == 0) { | |
| 557 | + self->field_size = 4096; | |
| 558 | + if (self->field != NULL) | |
| 559 | + PyMem_Free(self->field); | |
| 560 | + self->field = PyMem_Malloc(self->field_size); | |
| 561 | + } | |
| 562 | + else { | |
| 563 | + self->field_size *= 2; | |
| 564 | + self->field = PyMem_Realloc(self->field, self->field_size); | |
| 565 | + } | |
| 566 | + if (self->field == NULL) { | |
| 567 | + PyErr_NoMemory(); | |
| 568 | + return 0; | |
| 569 | + } | |
| 570 | + return 1; | |
| 571 | +} | |
| 572 | + | |
| 573 | +static int | |
| 574 | +parse_add_char(ReaderObj *self, char c) | |
| 575 | +{ | |
| 576 | + if (self->field_len >= field_limit) { | |
| 577 | + PyErr_Format(error_obj, "field larger than field limit (%ld)", | |
| 578 | + field_limit); | |
| 579 | + return -1; | |
| 580 | + } | |
| 581 | + if (self->field_len == self->field_size && !parse_grow_buff(self)) | |
| 582 | + return -1; | |
| 583 | + self->field[self->field_len++] = c; | |
| 584 | + return 0; | |
| 585 | +} | |
| 586 | + | |
| 587 | +static int | |
| 588 | +parse_process_char(ReaderObj *self, char c) | |
| 589 | +{ | |
| 590 | + DialectObj *dialect = self->dialect; | |
| 591 | + | |
| 592 | + switch (self->state) { | |
| 593 | + case START_RECORD: | |
| 594 | + /* start of record */ | |
| 595 | + if (c == '\0') | |
| 596 | + /* empty line - return [] */ | |
| 597 | + break; | |
| 598 | + else if (c == '\n' || c == '\r') { | |
| 599 | + self->state = EAT_CRNL; | |
| 600 | + break; | |
| 601 | + } | |
| 602 | + /* normal character - handle as START_FIELD */ | |
| 603 | + self->state = START_FIELD; | |
| 604 | + /* fallthru */ | |
| 605 | + case START_FIELD: | |
| 606 | + /* expecting field */ | |
| 607 | + if (c == '\n' || c == '\r' || c == '\0') { | |
| 608 | + /* save empty field - return [fields] */ | |
| 609 | + if (parse_save_field(self) < 0) | |
| 610 | + return -1; | |
| 611 | + self->state = (c == '\0' ? START_RECORD : EAT_CRNL); | |
| 612 | + } | |
| 613 | + else if (c == dialect->quotechar && | |
| 614 | + dialect->quoting != QUOTE_NONE) { | |
| 615 | + /* start quoted field */ | |
| 616 | + self->state = IN_QUOTED_FIELD; | |
| 617 | + } | |
| 618 | + else if (c == dialect->escapechar) { | |
| 619 | + /* possible escaped character */ | |
| 620 | + self->state = ESCAPED_CHAR; | |
| 621 | + } | |
| 622 | + else if (c == ' ' && dialect->skipinitialspace) | |
| 623 | + /* ignore space at start of field */ | |
| 624 | + ; | |
| 625 | + else if (c == dialect->delimiter) { | |
| 626 | + /* save empty field */ | |
| 627 | + if (parse_save_field(self) < 0) | |
| 628 | + return -1; | |
| 629 | + } | |
| 630 | + else { | |
| 631 | + /* begin new unquoted field */ | |
| 632 | + if (dialect->quoting == QUOTE_NONNUMERIC) | |
| 633 | + self->numeric_field = 1; | |
| 634 | + if (parse_add_char(self, c) < 0) | |
| 635 | + return -1; | |
| 636 | + self->state = IN_FIELD; | |
| 637 | + } | |
| 638 | + break; | |
| 639 | + | |
| 640 | + case ESCAPED_CHAR: | |
| 641 | + if (c == '\0') | |
| 642 | + c = '\n'; | |
| 643 | + if (parse_add_char(self, c) < 0) | |
| 644 | + return -1; | |
| 645 | + self->state = IN_FIELD; | |
| 646 | + break; | |
| 647 | + | |
| 648 | + case IN_FIELD: | |
| 649 | + /* in unquoted field */ | |
| 650 | + if (c == '\n' || c == '\r' || c == '\0') { | |
| 651 | + /* end of line - return [fields] */ | |
| 652 | + if (parse_save_field(self) < 0) | |
| 653 | + return -1; | |
| 654 | + self->state = (c == '\0' ? START_RECORD : EAT_CRNL); | |
| 655 | + } | |
| 656 | + else if (c == dialect->escapechar) { | |
| 657 | + /* possible escaped character */ | |
| 658 | + self->state = ESCAPED_CHAR; | |
| 659 | + } | |
| 660 | + else if (c == dialect->delimiter) { | |
| 661 | + /* save field - wait for new field */ | |
| 662 | + if (parse_save_field(self) < 0) | |
| 663 | + return -1; | |
| 664 | + self->state = START_FIELD; | |
| 665 | + } | |
| 666 | + else { | |
| 667 | + /* normal character - save in field */ | |
| 668 | + if (parse_add_char(self, c) < 0) | |
| 669 | + return -1; | |
| 670 | + } | |
| 671 | + break; | |
| 672 | + | |
| 673 | + case IN_QUOTED_FIELD: | |
| 674 | + /* in quoted field */ | |
| 675 | + if (c == '\0') | |
| 676 | + ; | |
| 677 | + else if (c == dialect->escapechar) { | |
| 678 | + /* Possible escape character */ | |
| 679 | + self->state = ESCAPE_IN_QUOTED_FIELD; | |
| 680 | + } | |
| 681 | + else if (c == dialect->quotechar && | |
| 682 | + dialect->quoting != QUOTE_NONE) { | |
| 683 | + if (dialect->doublequote) { | |
| 684 | + /* doublequote; " represented by "" */ | |
| 685 | + self->state = QUOTE_IN_QUOTED_FIELD; | |
| 686 | + } | |
| 687 | + else { | |
| 688 | + /* end of quote part of field */ | |
| 689 | + self->state = IN_FIELD; | |
| 690 | + } | |
| 691 | + } | |
| 692 | + else { | |
| 693 | + /* normal character - save in field */ | |
| 694 | + if (parse_add_char(self, c) < 0) | |
| 695 | + return -1; | |
| 696 | + } | |
| 697 | + break; | |
| 698 | + | |
| 699 | + case ESCAPE_IN_QUOTED_FIELD: | |
| 700 | + if (c == '\0') | |
| 701 | + c = '\n'; | |
| 702 | + if (parse_add_char(self, c) < 0) | |
| 703 | + return -1; | |
| 704 | + self->state = IN_QUOTED_FIELD; | |
| 705 | + break; | |
| 706 | + | |
| 707 | + case QUOTE_IN_QUOTED_FIELD: | |
| 708 | + /* doublequote - seen a quote in an quoted field */ | |
| 709 | + if (dialect->quoting != QUOTE_NONE && | |
| 710 | + c == dialect->quotechar) { | |
| 711 | + /* save "" as " */ | |
| 712 | + if (parse_add_char(self, c) < 0) | |
| 713 | + return -1; | |
| 714 | + self->state = IN_QUOTED_FIELD; | |
| 715 | + } | |
| 716 | + else if (c == dialect->delimiter) { | |
| 717 | + /* save field - wait for new field */ | |
| 718 | + if (parse_save_field(self) < 0) | |
| 719 | + return -1; | |
| 720 | + self->state = START_FIELD; | |
| 721 | + } | |
| 722 | + else if (c == '\n' || c == '\r' || c == '\0') { | |
| 723 | + /* end of line - return [fields] */ | |
| 724 | + if (parse_save_field(self) < 0) | |
| 725 | + return -1; | |
| 726 | + self->state = (c == '\0' ? START_RECORD : EAT_CRNL); | |
| 727 | + } | |
| 728 | + else if (!dialect->strict) { | |
| 729 | + if (parse_add_char(self, c) < 0) | |
| 730 | + return -1; | |
| 731 | + self->state = IN_FIELD; | |
| 732 | + } | |
| 733 | + else { | |
| 734 | + /* illegal */ | |
| 735 | + PyErr_Format(error_obj, "'%c' expected after '%c'", | |
| 736 | + dialect->delimiter, | |
| 737 | + dialect->quotechar); | |
| 738 | + return -1; | |
| 739 | + } | |
| 740 | + break; | |
| 741 | + | |
| 742 | + case EAT_CRNL: | |
| 743 | + if (c == '\n' || c == '\r') | |
| 744 | + ; | |
| 745 | + else if (c == '\0') | |
| 746 | + self->state = START_RECORD; | |
| 747 | + else { | |
| 748 | + PyErr_Format(error_obj, "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?"); | |
| 749 | + return -1; | |
| 750 | + } | |
| 751 | + break; | |
| 752 | + | |
| 753 | + } | |
| 754 | + return 0; | |
| 755 | +} | |
| 756 | + | |
| 757 | +static int | |
| 758 | +parse_reset(ReaderObj *self) | |
| 759 | +{ | |
| 760 | + Py_XDECREF(self->fields); | |
| 761 | + self->fields = PyList_New(0); | |
| 762 | + if (self->fields == NULL) | |
| 763 | + return -1; | |
| 764 | + self->field_len = 0; | |
| 765 | + self->state = START_RECORD; | |
| 766 | + self->numeric_field = 0; | |
| 767 | + return 0; | |
| 768 | +} | |
| 769 | + | |
| 770 | +static PyObject * | |
| 771 | +Reader_iternext(ReaderObj *self) | |
| 772 | +{ | |
| 773 | + PyObject *lineobj; | |
| 774 | + PyObject *fields = NULL; | |
| 775 | + char *line, c; | |
| 776 | + int linelen; | |
| 777 | + | |
| 778 | + if (parse_reset(self) < 0) | |
| 779 | + return NULL; | |
| 780 | + do { | |
| 781 | + lineobj = PyIter_Next(self->input_iter); | |
| 782 | + if (lineobj == NULL) { | |
| 783 | + /* End of input OR exception */ | |
| 784 | + if (!PyErr_Occurred() && self->field_len != 0) | |
| 785 | + PyErr_Format(error_obj, | |
| 786 | + "newline inside string"); | |
| 787 | + return NULL; | |
| 788 | + } | |
| 789 | + ++self->line_num; | |
| 790 | + | |
| 791 | + line = PyString_AsString(lineobj); | |
| 792 | + linelen = PyString_Size(lineobj); | |
| 793 | + | |
| 794 | + if (line == NULL || linelen < 0) { | |
| 795 | + Py_DECREF(lineobj); | |
| 796 | + return NULL; | |
| 797 | + } | |
| 798 | + while (linelen--) { | |
| 799 | + c = *line++; | |
| 800 | + if (c == '\0') { | |
| 801 | + Py_DECREF(lineobj); | |
| 802 | + PyErr_Format(error_obj, | |
| 803 | + "line contains NULL byte"); | |
| 804 | + goto err; | |
| 805 | + } | |
| 806 | + if (parse_process_char(self, c) < 0) { | |
| 807 | + Py_DECREF(lineobj); | |
| 808 | + goto err; | |
| 809 | + } | |
| 810 | + } | |
| 811 | + Py_DECREF(lineobj); | |
| 812 | + if (parse_process_char(self, 0) < 0) | |
| 813 | + goto err; | |
| 814 | + } while (self->state != START_RECORD); | |
| 815 | + | |
| 816 | + fields = self->fields; | |
| 817 | + self->fields = NULL; | |
| 818 | +err: | |
| 819 | + return fields; | |
| 820 | +} | |
| 821 | + | |
| 822 | +static void | |
| 823 | +Reader_dealloc(ReaderObj *self) | |
| 824 | +{ | |
| 825 | + PyObject_GC_UnTrack(self); | |
| 826 | + Py_XDECREF(self->dialect); | |
| 827 | + Py_XDECREF(self->input_iter); | |
| 828 | + Py_XDECREF(self->fields); | |
| 829 | + if (self->field != NULL) | |
| 830 | + PyMem_Free(self->field); | |
| 831 | + PyObject_GC_Del(self); | |
| 832 | +} | |
| 833 | + | |
| 834 | +static int | |
| 835 | +Reader_traverse(ReaderObj *self, visitproc visit, void *arg) | |
| 836 | +{ | |
| 837 | + Py_VISIT(self->dialect); | |
| 838 | + Py_VISIT(self->input_iter); | |
| 839 | + Py_VISIT(self->fields); | |
| 840 | + return 0; | |
| 841 | +} | |
| 842 | + | |
| 843 | +static int | |
| 844 | +Reader_clear(ReaderObj *self) | |
| 845 | +{ | |
| 846 | + Py_CLEAR(self->dialect); | |
| 847 | + Py_CLEAR(self->input_iter); | |
| 848 | + Py_CLEAR(self->fields); | |
| 849 | + return 0; | |
| 850 | +} | |
| 851 | + | |
| 852 | +PyDoc_STRVAR(Reader_Type_doc, | |
| 853 | +"CSV reader\n" | |
| 854 | +"\n" | |
| 855 | +"Reader objects are responsible for reading and parsing tabular data\n" | |
| 856 | +"in CSV format.\n" | |
| 857 | +); | |
| 858 | + | |
| 859 | +static struct PyMethodDef Reader_methods[] = { | |
| 860 | + { NULL, NULL } | |
| 861 | +}; | |
| 862 | +#define R_OFF(x) offsetof(ReaderObj, x) | |
| 863 | + | |
| 864 | +static struct PyMemberDef Reader_memberlist[] = { | |
| 865 | + { "dialect", T_OBJECT, R_OFF(dialect), RO }, | |
| 866 | + { "line_num", T_ULONG, R_OFF(line_num), RO }, | |
| 867 | + { NULL } | |
| 868 | +}; | |
| 869 | + | |
| 870 | + | |
| 871 | +static PyTypeObject Reader_Type = { | |
| 872 | + PyObject_HEAD_INIT(NULL) | |
| 873 | + 0, /*ob_size*/ | |
| 874 | + "_csv.reader", /*tp_name*/ | |
| 875 | + sizeof(ReaderObj), /*tp_basicsize*/ | |
| 876 | + 0, /*tp_itemsize*/ | |
| 877 | + /* methods */ | |
| 878 | + (destructor)Reader_dealloc, /*tp_dealloc*/ | |
| 879 | + (printfunc)0, /*tp_print*/ | |
| 880 | + (getattrfunc)0, /*tp_getattr*/ | |
| 881 | + (setattrfunc)0, /*tp_setattr*/ | |
| 882 | + (cmpfunc)0, /*tp_compare*/ | |
| 883 | + (reprfunc)0, /*tp_repr*/ | |
| 884 | + 0, /*tp_as_number*/ | |
| 885 | + 0, /*tp_as_sequence*/ | |
| 886 | + 0, /*tp_as_mapping*/ | |
| 887 | + (hashfunc)0, /*tp_hash*/ | |
| 888 | + (ternaryfunc)0, /*tp_call*/ | |
| 889 | + (reprfunc)0, /*tp_str*/ | |
| 890 | + 0, /*tp_getattro*/ | |
| 891 | + 0, /*tp_setattro*/ | |
| 892 | + 0, /*tp_as_buffer*/ | |
| 893 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | |
| 894 | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ | |
| 895 | + Reader_Type_doc, /*tp_doc*/ | |
| 896 | + (traverseproc)Reader_traverse, /*tp_traverse*/ | |
| 897 | + (inquiry)Reader_clear, /*tp_clear*/ | |
| 898 | + 0, /*tp_richcompare*/ | |
| 899 | + 0, /*tp_weaklistoffset*/ | |
| 900 | + PyObject_SelfIter, /*tp_iter*/ | |
| 901 | + (getiterfunc)Reader_iternext, /*tp_iternext*/ | |
| 902 | + Reader_methods, /*tp_methods*/ | |
| 903 | + Reader_memberlist, /*tp_members*/ | |
| 904 | + 0, /*tp_getset*/ | |
| 905 | + | |
| 906 | +}; | |
| 907 | + | |
| 908 | +static PyObject * | |
| 909 | +csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args) | |
| 910 | +{ | |
| 911 | + PyObject * iterator, * dialect = NULL; | |
| 912 | + ReaderObj * self = PyObject_GC_New(ReaderObj, &Reader_Type); | |
| 913 | + | |
| 914 | + if (!self) | |
| 915 | + return NULL; | |
| 916 | + | |
| 917 | + self->dialect = NULL; | |
| 918 | + self->fields = NULL; | |
| 919 | + self->input_iter = NULL; | |
| 920 | + self->field = NULL; | |
| 921 | + self->field_size = 0; | |
| 922 | + self->line_num = 0; | |
| 923 | + | |
| 924 | + if (parse_reset(self) < 0) { | |
| 925 | + Py_DECREF(self); | |
| 926 | + return NULL; | |
| 927 | + } | |
| 928 | + | |
| 929 | + if (!PyArg_UnpackTuple(args, "", 1, 2, &iterator, &dialect)) { | |
| 930 | + Py_DECREF(self); | |
| 931 | + return NULL; | |
| 932 | + } | |
| 933 | + self->input_iter = PyObject_GetIter(iterator); | |
| 934 | + if (self->input_iter == NULL) { | |
| 935 | + PyErr_SetString(PyExc_TypeError, | |
| 936 | + "argument 1 must be an iterator"); | |
| 937 | + Py_DECREF(self); | |
| 938 | + return NULL; | |
| 939 | + } | |
| 940 | + self->dialect = (DialectObj *)_call_dialect(dialect, keyword_args); | |
| 941 | + if (self->dialect == NULL) { | |
| 942 | + Py_DECREF(self); | |
| 943 | + return NULL; | |
| 944 | + } | |
| 945 | + | |
| 946 | + PyObject_GC_Track(self); | |
| 947 | + return (PyObject *)self; | |
| 948 | +} | |
| 949 | + | |
| 950 | +/* | |
| 951 | + * WRITER | |
| 952 | + */ | |
| 953 | +/* ---------------------------------------------------------------- */ | |
| 954 | +static void | |
| 955 | +join_reset(WriterObj *self) | |
| 956 | +{ | |
| 957 | + self->rec_len = 0; | |
| 958 | + self->num_fields = 0; | |
| 959 | +} | |
| 960 | + | |
| 961 | +#define MEM_INCR 32768 | |
| 962 | + | |
| 963 | +/* Calculate new record length or append field to record. Return new | |
| 964 | + * record length. | |
| 965 | + */ | |
| 966 | +static int | |
| 967 | +join_append_data(WriterObj *self, char *field, int quote_empty, | |
| 968 | + int *quoted, int copy_phase) | |
| 969 | +{ | |
| 970 | + DialectObj *dialect = self->dialect; | |
| 971 | + int i, rec_len; | |
| 972 | + char *lineterm; | |
| 973 | + | |
| 974 | +#define ADDCH(c) \ | |
| 975 | + do {\ | |
| 976 | + if (copy_phase) \ | |
| 977 | + self->rec[rec_len] = c;\ | |
| 978 | + rec_len++;\ | |
| 979 | + } while(0) | |
| 980 | + | |
| 981 | + lineterm = PyString_AsString(dialect->lineterminator); | |
| 982 | + if (lineterm == NULL) | |
| 983 | + return -1; | |
| 984 | + | |
| 985 | + rec_len = self->rec_len; | |
| 986 | + | |
| 987 | + /* If this is not the first field we need a field separator */ | |
| 988 | + if (self->num_fields > 0) | |
| 989 | + ADDCH(dialect->delimiter); | |
| 990 | + | |
| 991 | + /* Handle preceding quote */ | |
| 992 | + if (copy_phase && *quoted) | |
| 993 | + ADDCH(dialect->quotechar); | |
| 994 | + | |
| 995 | + /* Copy/count field data */ | |
| 996 | + for (i = 0;; i++) { | |
| 997 | + char c = field[i]; | |
| 998 | + int want_escape = 0; | |
| 999 | + | |
| 1000 | + if (c == '\0') | |
| 1001 | + break; | |
| 1002 | + | |
| 1003 | + if (c == dialect->delimiter || | |
| 1004 | + c == dialect->escapechar || | |
| 1005 | + c == dialect->quotechar || | |
| 1006 | + strchr(lineterm, c)) { | |
| 1007 | + if (dialect->quoting == QUOTE_NONE) | |
| 1008 | + want_escape = 1; | |
| 1009 | + else { | |
| 1010 | + if (c == dialect->quotechar) { | |
| 1011 | + if (dialect->doublequote) | |
| 1012 | + ADDCH(dialect->quotechar); | |
| 1013 | + else | |
| 1014 | + want_escape = 1; | |
| 1015 | + } | |
| 1016 | + if (!want_escape) | |
| 1017 | + *quoted = 1; | |
| 1018 | + } | |
| 1019 | + if (want_escape) { | |
| 1020 | + if (!dialect->escapechar) { | |
| 1021 | + PyErr_Format(error_obj, | |
| 1022 | + "need to escape, but no escapechar set"); | |
| 1023 | + return -1; | |
| 1024 | + } | |
| 1025 | + ADDCH(dialect->escapechar); | |
| 1026 | + } | |
| 1027 | + } | |
| 1028 | + /* Copy field character into record buffer. | |
| 1029 | + */ | |
| 1030 | + ADDCH(c); | |
| 1031 | + } | |
| 1032 | + | |
| 1033 | + /* If field is empty check if it needs to be quoted. | |
| 1034 | + */ | |
| 1035 | + if (i == 0 && quote_empty) { | |
| 1036 | + if (dialect->quoting == QUOTE_NONE) { | |
| 1037 | + PyErr_Format(error_obj, | |
| 1038 | + "single empty field record must be quoted"); | |
| 1039 | + return -1; | |
| 1040 | + } | |
| 1041 | + else | |
| 1042 | + *quoted = 1; | |
| 1043 | + } | |
| 1044 | + | |
| 1045 | + if (*quoted) { | |
| 1046 | + if (copy_phase) | |
| 1047 | + ADDCH(dialect->quotechar); | |
| 1048 | + else | |
| 1049 | + rec_len += 2; | |
| 1050 | + } | |
| 1051 | + return rec_len; | |
| 1052 | +#undef ADDCH | |
| 1053 | +} | |
| 1054 | + | |
| 1055 | +static int | |
| 1056 | +join_check_rec_size(WriterObj *self, int rec_len) | |
| 1057 | +{ | |
| 1058 | + if (rec_len > self->rec_size) { | |
| 1059 | + if (self->rec_size == 0) { | |
| 1060 | + self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR; | |
| 1061 | + if (self->rec != NULL) | |
| 1062 | + PyMem_Free(self->rec); | |
| 1063 | + self->rec = PyMem_Malloc(self->rec_size); | |
| 1064 | + } | |
| 1065 | + else { | |
| 1066 | + char *old_rec = self->rec; | |
| 1067 | + | |
| 1068 | + self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR; | |
| 1069 | + self->rec = PyMem_Realloc(self->rec, self->rec_size); | |
| 1070 | + if (self->rec == NULL) | |
| 1071 | + PyMem_Free(old_rec); | |
| 1072 | + } | |
| 1073 | + if (self->rec == NULL) { | |
| 1074 | + PyErr_NoMemory(); | |
| 1075 | + return 0; | |
| 1076 | + } | |
| 1077 | + } | |
| 1078 | + return 1; | |
| 1079 | +} | |
| 1080 | + | |
| 1081 | +static int | |
| 1082 | +join_append(WriterObj *self, char *field, int *quoted, int quote_empty) | |
| 1083 | +{ | |
| 1084 | + int rec_len; | |
| 1085 | + | |
| 1086 | + rec_len = join_append_data(self, field, quote_empty, quoted, 0); | |
| 1087 | + if (rec_len < 0) | |
| 1088 | + return 0; | |
| 1089 | + | |
| 1090 | + /* grow record buffer if necessary */ | |
| 1091 | + if (!join_check_rec_size(self, rec_len)) | |
| 1092 | + return 0; | |
| 1093 | + | |
| 1094 | + self->rec_len = join_append_data(self, field, quote_empty, quoted, 1); | |
| 1095 | + self->num_fields++; | |
| 1096 | + | |
| 1097 | + return 1; | |
| 1098 | +} | |
| 1099 | + | |
| 1100 | +static int | |
| 1101 | +join_append_lineterminator(WriterObj *self) | |
| 1102 | +{ | |
| 1103 | + int terminator_len; | |
| 1104 | + char *terminator; | |
| 1105 | + | |
| 1106 | + terminator_len = PyString_Size(self->dialect->lineterminator); | |
| 1107 | + if (terminator_len == -1) | |
| 1108 | + return 0; | |
| 1109 | + | |
| 1110 | + /* grow record buffer if necessary */ | |
| 1111 | + if (!join_check_rec_size(self, self->rec_len + terminator_len)) | |
| 1112 | + return 0; | |
| 1113 | + | |
| 1114 | + terminator = PyString_AsString(self->dialect->lineterminator); | |
| 1115 | + if (terminator == NULL) | |
| 1116 | + return 0; | |
| 1117 | + memmove(self->rec + self->rec_len, terminator, terminator_len); | |
| 1118 | + self->rec_len += terminator_len; | |
| 1119 | + | |
| 1120 | + return 1; | |
| 1121 | +} | |
| 1122 | + | |
| 1123 | +PyDoc_STRVAR(csv_writerow_doc, | |
| 1124 | +"writerow(sequence)\n" | |
| 1125 | +"\n" | |
| 1126 | +"Construct and write a CSV record from a sequence of fields. Non-string\n" | |
| 1127 | +"elements will be converted to string."); | |
| 1128 | + | |
| 1129 | +static PyObject * | |
| 1130 | +csv_writerow(WriterObj *self, PyObject *seq) | |
| 1131 | +{ | |
| 1132 | + DialectObj *dialect = self->dialect; | |
| 1133 | + int len, i; | |
| 1134 | + | |
| 1135 | + if (!PySequence_Check(seq)) | |
| 1136 | + return PyErr_Format(error_obj, "sequence expected"); | |
| 1137 | + | |
| 1138 | + len = PySequence_Length(seq); | |
| 1139 | + if (len < 0) | |
| 1140 | + return NULL; | |
| 1141 | + | |
| 1142 | + /* Join all fields in internal buffer. | |
| 1143 | + */ | |
| 1144 | + join_reset(self); | |
| 1145 | + for (i = 0; i < len; i++) { | |
| 1146 | + PyObject *field; | |
| 1147 | + int append_ok; | |
| 1148 | + int quoted; | |
| 1149 | + | |
| 1150 | + field = PySequence_GetItem(seq, i); | |
| 1151 | + if (field == NULL) | |
| 1152 | + return NULL; | |
| 1153 | + | |
| 1154 | + switch (dialect->quoting) { | |
| 1155 | + case QUOTE_NONNUMERIC: | |
| 1156 | + quoted = !PyNumber_Check(field); | |
| 1157 | + break; | |
| 1158 | + case QUOTE_ALL: | |
| 1159 | + quoted = 1; | |
| 1160 | + break; | |
| 1161 | + default: | |
| 1162 | + quoted = 0; | |
| 1163 | + break; | |
| 1164 | + } | |
| 1165 | + | |
| 1166 | + if (PyString_Check(field)) { | |
| 1167 | + append_ok = join_append(self, | |
| 1168 | + PyString_AS_STRING(field), | |
| 1169 | + "ed, len == 1); | |
| 1170 | + Py_DECREF(field); | |
| 1171 | + } | |
| 1172 | + else if (field == Py_None) { | |
| 1173 | + append_ok = join_append(self, "", "ed, len == 1); | |
| 1174 | + Py_DECREF(field); | |
| 1175 | + } | |
| 1176 | + else { | |
| 1177 | + PyObject *str; | |
| 1178 | + | |
| 1179 | + str = PyObject_Str(field); | |
| 1180 | + Py_DECREF(field); | |
| 1181 | + if (str == NULL) | |
| 1182 | + return NULL; | |
| 1183 | + | |
| 1184 | + append_ok = join_append(self, PyString_AS_STRING(str), | |
| 1185 | + "ed, len == 1); | |
| 1186 | + Py_DECREF(str); | |
| 1187 | + } | |
| 1188 | + if (!append_ok) | |
| 1189 | + return NULL; | |
| 1190 | + } | |
| 1191 | + | |
| 1192 | + /* Add line terminator. | |
| 1193 | + */ | |
| 1194 | + if (!join_append_lineterminator(self)) | |
| 1195 | + return 0; | |
| 1196 | + | |
| 1197 | + return PyObject_CallFunction(self->writeline, | |
| 1198 | + "(s#)", self->rec, self->rec_len); | |
| 1199 | +} | |
| 1200 | + | |
| 1201 | +PyDoc_STRVAR(csv_writerows_doc, | |
| 1202 | +"writerows(sequence of sequences)\n" | |
| 1203 | +"\n" | |
| 1204 | +"Construct and write a series of sequences to a csv file. Non-string\n" | |
| 1205 | +"elements will be converted to string."); | |
| 1206 | + | |
| 1207 | +static PyObject * | |
| 1208 | +csv_writerows(WriterObj *self, PyObject *seqseq) | |
| 1209 | +{ | |
| 1210 | + PyObject *row_iter, *row_obj, *result; | |
| 1211 | + | |
| 1212 | + row_iter = PyObject_GetIter(seqseq); | |
| 1213 | + if (row_iter == NULL) { | |
| 1214 | + PyErr_SetString(PyExc_TypeError, | |
| 1215 | + "writerows() argument must be iterable"); | |
| 1216 | + return NULL; | |
| 1217 | + } | |
| 1218 | + while ((row_obj = PyIter_Next(row_iter))) { | |
| 1219 | + result = csv_writerow(self, row_obj); | |
| 1220 | + Py_DECREF(row_obj); | |
| 1221 | + if (!result) { | |
| 1222 | + Py_DECREF(row_iter); | |
| 1223 | + return NULL; | |
| 1224 | + } | |
| 1225 | + else | |
| 1226 | + Py_DECREF(result); | |
| 1227 | + } | |
| 1228 | + Py_DECREF(row_iter); | |
| 1229 | + if (PyErr_Occurred()) | |
| 1230 | + return NULL; | |
| 1231 | + Py_INCREF(Py_None); | |
| 1232 | + return Py_None; | |
| 1233 | +} | |
| 1234 | + | |
| 1235 | +static struct PyMethodDef Writer_methods[] = { | |
| 1236 | + { "writerow", (PyCFunction)csv_writerow, METH_O, csv_writerow_doc}, | |
| 1237 | + { "writerows", (PyCFunction)csv_writerows, METH_O, csv_writerows_doc}, | |
| 1238 | + { NULL, NULL } | |
| 1239 | +}; | |
| 1240 | + | |
| 1241 | +#define W_OFF(x) offsetof(WriterObj, x) | |
| 1242 | + | |
| 1243 | +static struct PyMemberDef Writer_memberlist[] = { | |
| 1244 | + { "dialect", T_OBJECT, W_OFF(dialect), RO }, | |
| 1245 | + { NULL } | |
| 1246 | +}; | |
| 1247 | + | |
| 1248 | +static void | |
| 1249 | +Writer_dealloc(WriterObj *self) | |
| 1250 | +{ | |
| 1251 | + PyObject_GC_UnTrack(self); | |
| 1252 | + Py_XDECREF(self->dialect); | |
| 1253 | + Py_XDECREF(self->writeline); | |
| 1254 | + if (self->rec != NULL) | |
| 1255 | + PyMem_Free(self->rec); | |
| 1256 | + PyObject_GC_Del(self); | |
| 1257 | +} | |
| 1258 | + | |
| 1259 | +static int | |
| 1260 | +Writer_traverse(WriterObj *self, visitproc visit, void *arg) | |
| 1261 | +{ | |
| 1262 | + Py_VISIT(self->dialect); | |
| 1263 | + Py_VISIT(self->writeline); | |
| 1264 | + return 0; | |
| 1265 | +} | |
| 1266 | + | |
| 1267 | +static int | |
| 1268 | +Writer_clear(WriterObj *self) | |
| 1269 | +{ | |
| 1270 | + Py_CLEAR(self->dialect); | |
| 1271 | + Py_CLEAR(self->writeline); | |
| 1272 | + return 0; | |
| 1273 | +} | |
| 1274 | + | |
| 1275 | +PyDoc_STRVAR(Writer_Type_doc, | |
| 1276 | +"CSV writer\n" | |
| 1277 | +"\n" | |
| 1278 | +"Writer objects are responsible for generating tabular data\n" | |
| 1279 | +"in CSV format from sequence input.\n" | |
| 1280 | +); | |
| 1281 | + | |
| 1282 | +static PyTypeObject Writer_Type = { | |
| 1283 | + PyObject_HEAD_INIT(NULL) | |
| 1284 | + 0, /*ob_size*/ | |
| 1285 | + "_csv.writer", /*tp_name*/ | |
| 1286 | + sizeof(WriterObj), /*tp_basicsize*/ | |
| 1287 | + 0, /*tp_itemsize*/ | |
| 1288 | + /* methods */ | |
| 1289 | + (destructor)Writer_dealloc, /*tp_dealloc*/ | |
| 1290 | + (printfunc)0, /*tp_print*/ | |
| 1291 | + (getattrfunc)0, /*tp_getattr*/ | |
| 1292 | + (setattrfunc)0, /*tp_setattr*/ | |
| 1293 | + (cmpfunc)0, /*tp_compare*/ | |
| 1294 | + (reprfunc)0, /*tp_repr*/ | |
| 1295 | + 0, /*tp_as_number*/ | |
| 1296 | + 0, /*tp_as_sequence*/ | |
| 1297 | + 0, /*tp_as_mapping*/ | |
| 1298 | + (hashfunc)0, /*tp_hash*/ | |
| 1299 | + (ternaryfunc)0, /*tp_call*/ | |
| 1300 | + (reprfunc)0, /*tp_str*/ | |
| 1301 | + 0, /*tp_getattro*/ | |
| 1302 | + 0, /*tp_setattro*/ | |
| 1303 | + 0, /*tp_as_buffer*/ | |
| 1304 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | |
| 1305 | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ | |
| 1306 | + Writer_Type_doc, | |
| 1307 | + (traverseproc)Writer_traverse, /*tp_traverse*/ | |
| 1308 | + (inquiry)Writer_clear, /*tp_clear*/ | |
| 1309 | + 0, /*tp_richcompare*/ | |
| 1310 | + 0, /*tp_weaklistoffset*/ | |
| 1311 | + (getiterfunc)0, /*tp_iter*/ | |
| 1312 | + (getiterfunc)0, /*tp_iternext*/ | |
| 1313 | + Writer_methods, /*tp_methods*/ | |
| 1314 | + Writer_memberlist, /*tp_members*/ | |
| 1315 | + 0, /*tp_getset*/ | |
| 1316 | +}; | |
| 1317 | + | |
| 1318 | +static PyObject * | |
| 1319 | +csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) | |
| 1320 | +{ | |
| 1321 | + PyObject * output_file, * dialect = NULL; | |
| 1322 | + WriterObj * self = PyObject_GC_New(WriterObj, &Writer_Type); | |
| 1323 | + | |
| 1324 | + if (!self) | |
| 1325 | + return NULL; | |
| 1326 | + | |
| 1327 | + self->dialect = NULL; | |
| 1328 | + self->writeline = NULL; | |
| 1329 | + | |
| 1330 | + self->rec = NULL; | |
| 1331 | + self->rec_size = 0; | |
| 1332 | + self->rec_len = 0; | |
| 1333 | + self->num_fields = 0; | |
| 1334 | + | |
| 1335 | + if (!PyArg_UnpackTuple(args, "", 1, 2, &output_file, &dialect)) { | |
| 1336 | + Py_DECREF(self); | |
| 1337 | + return NULL; | |
| 1338 | + } | |
| 1339 | + self->writeline = PyObject_GetAttrString(output_file, "write"); | |
| 1340 | + if (self->writeline == NULL || !PyCallable_Check(self->writeline)) { | |
| 1341 | + PyErr_SetString(PyExc_TypeError, | |
| 1342 | + "argument 1 must have a \"write\" method"); | |
| 1343 | + Py_DECREF(self); | |
| 1344 | + return NULL; | |
| 1345 | + } | |
| 1346 | + self->dialect = (DialectObj *)_call_dialect(dialect, keyword_args); | |
| 1347 | + if (self->dialect == NULL) { | |
| 1348 | + Py_DECREF(self); | |
| 1349 | + return NULL; | |
| 1350 | + } | |
| 1351 | + PyObject_GC_Track(self); | |
| 1352 | + return (PyObject *)self; | |
| 1353 | +} | |
| 1354 | + | |
| 1355 | +/* | |
| 1356 | + * DIALECT REGISTRY | |
| 1357 | + */ | |
| 1358 | +static PyObject * | |
| 1359 | +csv_list_dialects(PyObject *module, PyObject *args) | |
| 1360 | +{ | |
| 1361 | + return PyDict_Keys(dialects); | |
| 1362 | +} | |
| 1363 | + | |
| 1364 | +static PyObject * | |
| 1365 | +csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs) | |
| 1366 | +{ | |
| 1367 | + PyObject *name_obj, *dialect_obj = NULL; | |
| 1368 | + PyObject *dialect; | |
| 1369 | + | |
| 1370 | + if (!PyArg_UnpackTuple(args, "", 1, 2, &name_obj, &dialect_obj)) | |
| 1371 | + return NULL; | |
| 1372 | + if (!IS_BASESTRING(name_obj)) { | |
| 1373 | + PyErr_SetString(PyExc_TypeError, | |
| 1374 | + "dialect name must be a string or unicode"); | |
| 1375 | + return NULL; | |
| 1376 | + } | |
| 1377 | + dialect = _call_dialect(dialect_obj, kwargs); | |
| 1378 | + if (dialect == NULL) | |
| 1379 | + return NULL; | |
| 1380 | + if (PyDict_SetItem(dialects, name_obj, dialect) < 0) { | |
| 1381 | + Py_DECREF(dialect); | |
| 1382 | + return NULL; | |
| 1383 | + } | |
| 1384 | + Py_DECREF(dialect); | |
| 1385 | + Py_INCREF(Py_None); | |
| 1386 | + return Py_None; | |
| 1387 | +} | |
| 1388 | + | |
| 1389 | +static PyObject * | |
| 1390 | +csv_unregister_dialect(PyObject *module, PyObject *name_obj) | |
| 1391 | +{ | |
| 1392 | + if (PyDict_DelItem(dialects, name_obj) < 0) | |
| 1393 | + return PyErr_Format(error_obj, "unknown dialect"); | |
| 1394 | + Py_INCREF(Py_None); | |
| 1395 | + return Py_None; | |
| 1396 | +} | |
| 1397 | + | |
| 1398 | +static PyObject * | |
| 1399 | +csv_get_dialect(PyObject *module, PyObject *name_obj) | |
| 1400 | +{ | |
| 1401 | + return get_dialect_from_registry(name_obj); | |
| 1402 | +} | |
| 1403 | + | |
| 1404 | +static PyObject * | |
| 1405 | +csv_field_size_limit(PyObject *module, PyObject *args) | |
| 1406 | +{ | |
| 1407 | + PyObject *new_limit = NULL; | |
| 1408 | + long old_limit = field_limit; | |
| 1409 | + | |
| 1410 | + if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit)) | |
| 1411 | + return NULL; | |
| 1412 | + if (new_limit != NULL) { | |
| 1413 | + if (!PyInt_Check(new_limit)) { | |
| 1414 | + PyErr_Format(PyExc_TypeError, | |
| 1415 | + "limit must be an integer"); | |
| 1416 | + return NULL; | |
| 1417 | + } | |
| 1418 | + field_limit = PyInt_AsLong(new_limit); | |
| 1419 | + } | |
| 1420 | + return PyInt_FromLong(old_limit); | |
| 1421 | +} | |
| 1422 | + | |
| 1423 | +/* | |
| 1424 | + * MODULE | |
| 1425 | + */ | |
| 1426 | + | |
| 1427 | +PyDoc_STRVAR(csv_module_doc, | |
| 1428 | +"CSV parsing and writing.\n" | |
| 1429 | +"\n" | |
| 1430 | +"This module provides classes that assist in the reading and writing\n" | |
| 1431 | +"of Comma Separated Value (CSV) files, and implements the interface\n" | |
| 1432 | +"described by PEP 305. Although many CSV files are simple to parse,\n" | |
| 1433 | +"the format is not formally defined by a stable specification and\n" | |
| 1434 | +"is subtle enough that parsing lines of a CSV file with something\n" | |
| 1435 | +"like line.split(\",\") is bound to fail. The module supports three\n" | |
| 1436 | +"basic APIs: reading, writing, and registration of dialects.\n" | |
| 1437 | +"\n" | |
| 1438 | +"\n" | |
| 1439 | +"DIALECT REGISTRATION:\n" | |
| 1440 | +"\n" | |
| 1441 | +"Readers and writers support a dialect argument, which is a convenient\n" | |
| 1442 | +"handle on a group of settings. When the dialect argument is a string,\n" | |
| 1443 | +"it identifies one of the dialects previously registered with the module.\n" | |
| 1444 | +"If it is a class or instance, the attributes of the argument are used as\n" | |
| 1445 | +"the settings for the reader or writer:\n" | |
| 1446 | +"\n" | |
| 1447 | +" class excel:\n" | |
| 1448 | +" delimiter = ','\n" | |
| 1449 | +" quotechar = '\"'\n" | |
| 1450 | +" escapechar = None\n" | |
| 1451 | +" doublequote = True\n" | |
| 1452 | +" skipinitialspace = False\n" | |
| 1453 | +" lineterminator = '\\r\\n'\n" | |
| 1454 | +" quoting = QUOTE_MINIMAL\n" | |
| 1455 | +"\n" | |
| 1456 | +"SETTINGS:\n" | |
| 1457 | +"\n" | |
| 1458 | +" * quotechar - specifies a one-character string to use as the \n" | |
| 1459 | +" quoting character. It defaults to '\"'.\n" | |
| 1460 | +" * delimiter - specifies a one-character string to use as the \n" | |
| 1461 | +" field separator. It defaults to ','.\n" | |
| 1462 | +" * skipinitialspace - specifies how to interpret whitespace which\n" | |
| 1463 | +" immediately follows a delimiter. It defaults to False, which\n" | |
| 1464 | +" means that whitespace immediately following a delimiter is part\n" | |
| 1465 | +" of the following field.\n" | |
| 1466 | +" * lineterminator - specifies the character sequence which should \n" | |
| 1467 | +" terminate rows.\n" | |
| 1468 | +" * quoting - controls when quotes should be generated by the writer.\n" | |
| 1469 | +" It can take on any of the following module constants:\n" | |
| 1470 | +"\n" | |
| 1471 | +" csv.QUOTE_MINIMAL means only when required, for example, when a\n" | |
| 1472 | +" field contains either the quotechar or the delimiter\n" | |
| 1473 | +" csv.QUOTE_ALL means that quotes are always placed around fields.\n" | |
| 1474 | +" csv.QUOTE_NONNUMERIC means that quotes are always placed around\n" | |
| 1475 | +" fields which do not parse as integers or floating point\n" | |
| 1476 | +" numbers.\n" | |
| 1477 | +" csv.QUOTE_NONE means that quotes are never placed around fields.\n" | |
| 1478 | +" * escapechar - specifies a one-character string used to escape \n" | |
| 1479 | +" the delimiter when quoting is set to QUOTE_NONE.\n" | |
| 1480 | +" * doublequote - controls the handling of quotes inside fields. When\n" | |
| 1481 | +" True, two consecutive quotes are interpreted as one during read,\n" | |
| 1482 | +" and when writing, each quote character embedded in the data is\n" | |
| 1483 | +" written as two quotes\n"); | |
| 1484 | + | |
| 1485 | +PyDoc_STRVAR(csv_reader_doc, | |
| 1486 | +" csv_reader = reader(iterable [, dialect='excel']\n" | |
| 1487 | +" [optional keyword args])\n" | |
| 1488 | +" for row in csv_reader:\n" | |
| 1489 | +" process(row)\n" | |
| 1490 | +"\n" | |
| 1491 | +"The \"iterable\" argument can be any object that returns a line\n" | |
| 1492 | +"of input for each iteration, such as a file object or a list. The\n" | |
| 1493 | +"optional \"dialect\" parameter is discussed below. The function\n" | |
| 1494 | +"also accepts optional keyword arguments which override settings\n" | |
| 1495 | +"provided by the dialect.\n" | |
| 1496 | +"\n" | |
| 1497 | +"The returned object is an iterator. Each iteration returns a row\n" | |
| 1498 | +"of the CSV file (which can span multiple input lines):\n"); | |
| 1499 | + | |
| 1500 | +PyDoc_STRVAR(csv_writer_doc, | |
| 1501 | +" csv_writer = csv.writer(fileobj [, dialect='excel']\n" | |
| 1502 | +" [optional keyword args])\n" | |
| 1503 | +" for row in sequence:\n" | |
| 1504 | +" csv_writer.writerow(row)\n" | |
| 1505 | +"\n" | |
| 1506 | +" [or]\n" | |
| 1507 | +"\n" | |
| 1508 | +" csv_writer = csv.writer(fileobj [, dialect='excel']\n" | |
| 1509 | +" [optional keyword args])\n" | |
| 1510 | +" csv_writer.writerows(rows)\n" | |
| 1511 | +"\n" | |
| 1512 | +"The \"fileobj\" argument can be any object that supports the file API.\n"); | |
| 1513 | + | |
| 1514 | +PyDoc_STRVAR(csv_list_dialects_doc, | |
| 1515 | +"Return a list of all know dialect names.\n" | |
| 1516 | +" names = csv.list_dialects()"); | |
| 1517 | + | |
| 1518 | +PyDoc_STRVAR(csv_get_dialect_doc, | |
| 1519 | +"Return the dialect instance associated with name.\n" | |
| 1520 | +" dialect = csv.get_dialect(name)"); | |
| 1521 | + | |
| 1522 | +PyDoc_STRVAR(csv_register_dialect_doc, | |
| 1523 | +"Create a mapping from a string name to a dialect class.\n" | |
| 1524 | +" dialect = csv.register_dialect(name, dialect)"); | |
| 1525 | + | |
| 1526 | +PyDoc_STRVAR(csv_unregister_dialect_doc, | |
| 1527 | +"Delete the name/dialect mapping associated with a string name.\n" | |
| 1528 | +" csv.unregister_dialect(name)"); | |
| 1529 | + | |
| 1530 | +PyDoc_STRVAR(csv_field_size_limit_doc, | |
| 1531 | +"Sets an upper limit on parsed fields.\n" | |
| 1532 | +" csv.field_size_limit([limit])\n" | |
| 1533 | +"\n" | |
| 1534 | +"Returns old limit. If limit is not given, no new limit is set and\n" | |
| 1535 | +"the old limit is returned"); | |
| 1536 | + | |
| 1537 | +static struct PyMethodDef csv_methods[] = { | |
| 1538 | + { "reader", (PyCFunction)csv_reader, | |
| 1539 | + METH_VARARGS | METH_KEYWORDS, csv_reader_doc}, | |
| 1540 | + { "writer", (PyCFunction)csv_writer, | |
| 1541 | + METH_VARARGS | METH_KEYWORDS, csv_writer_doc}, | |
| 1542 | + { "list_dialects", (PyCFunction)csv_list_dialects, | |
| 1543 | + METH_NOARGS, csv_list_dialects_doc}, | |
| 1544 | + { "register_dialect", (PyCFunction)csv_register_dialect, | |
| 1545 | + METH_VARARGS | METH_KEYWORDS, csv_register_dialect_doc}, | |
| 1546 | + { "unregister_dialect", (PyCFunction)csv_unregister_dialect, | |
| 1547 | + METH_O, csv_unregister_dialect_doc}, | |
| 1548 | + { "get_dialect", (PyCFunction)csv_get_dialect, | |
| 1549 | + METH_O, csv_get_dialect_doc}, | |
| 1550 | + { "field_size_limit", (PyCFunction)csv_field_size_limit, | |
| 1551 | + METH_VARARGS, csv_field_size_limit_doc}, | |
| 1552 | + { NULL, NULL } | |
| 1553 | +}; | |
| 1554 | + | |
| 1555 | +PyMODINIT_FUNC | |
| 1556 | +init_csv(void) | |
| 1557 | +{ | |
| 1558 | + PyObject *module; | |
| 1559 | + StyleDesc *style; | |
| 1560 | + | |
| 1561 | + if (PyType_Ready(&Dialect_Type) < 0) | |
| 1562 | + return; | |
| 1563 | + | |
| 1564 | + if (PyType_Ready(&Reader_Type) < 0) | |
| 1565 | + return; | |
| 1566 | + | |
| 1567 | + if (PyType_Ready(&Writer_Type) < 0) | |
| 1568 | + return; | |
| 1569 | + | |
| 1570 | + /* Create the module and add the functions */ | |
| 1571 | + module = Py_InitModule3("_csv", csv_methods, csv_module_doc); | |
| 1572 | + if (module == NULL) | |
| 1573 | + return; | |
| 1574 | + | |
| 1575 | + /* Add version to the module. */ | |
| 1576 | + if (PyModule_AddStringConstant(module, "__version__", | |
| 1577 | + MODULE_VERSION) == -1) | |
| 1578 | + return; | |
| 1579 | + | |
| 1580 | + /* Add _dialects dictionary */ | |
| 1581 | + dialects = PyDict_New(); | |
| 1582 | + if (dialects == NULL) | |
| 1583 | + return; | |
| 1584 | + if (PyModule_AddObject(module, "_dialects", dialects)) | |
| 1585 | + return; | |
| 1586 | + | |
| 1587 | + /* Add quote styles into dictionary */ | |
| 1588 | + for (style = quote_styles; style->name; style++) { | |
| 1589 | + if (PyModule_AddIntConstant(module, style->name, | |
| 1590 | + style->style) == -1) | |
| 1591 | + return; | |
| 1592 | + } | |
| 1593 | + | |
| 1594 | + /* Add the Dialect type */ | |
| 1595 | + Py_INCREF(&Dialect_Type); | |
| 1596 | + if (PyModule_AddObject(module, "Dialect", (PyObject *)&Dialect_Type)) | |
| 1597 | + return; | |
| 1598 | + | |
| 1599 | + /* Add the CSV exception object to the module. */ | |
| 1600 | + error_obj = PyErr_NewException("_csv.Error", NULL, NULL); | |
| 1601 | + if (error_obj == NULL) | |
| 1602 | + return; | |
| 1603 | + PyModule_AddObject(module, "Error", error_obj); | |
| 1604 | +} | |
| @@ -0,0 +1,4859 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | + | |
| 6 | +/* | |
| 7 | + ToDo: | |
| 8 | + | |
| 9 | + Get rid of the checker (and also the converters) field in CFuncPtrObject and | |
| 10 | + StgDictObject, and replace them by slot functions in StgDictObject. | |
| 11 | + | |
| 12 | + think about a buffer-like object (memory? bytes?) | |
| 13 | + | |
| 14 | + Should POINTER(c_char) and POINTER(c_wchar) have a .value property? | |
| 15 | + What about c_char and c_wchar arrays then? | |
| 16 | + | |
| 17 | + Add from_mmap, from_file, from_string metaclass methods. | |
| 18 | + | |
| 19 | + Maybe we can get away with from_file (calls read) and with a from_buffer | |
| 20 | + method? | |
| 21 | + | |
| 22 | + And what about the to_mmap, to_file, to_str(?) methods? They would clobber | |
| 23 | + the namespace, probably. So, functions instead? And we already have memmove... | |
| 24 | +*/ | |
| 25 | + | |
| 26 | +/* | |
| 27 | + | |
| 28 | +Name methods, members, getsets | |
| 29 | +============================================================================== | |
| 30 | + | |
| 31 | +StructType_Type __new__(), from_address(), __mul__(), from_param() | |
| 32 | +UnionType_Type __new__(), from_address(), __mul__(), from_param() | |
| 33 | +PointerType_Type __new__(), from_address(), __mul__(), from_param(), set_type() | |
| 34 | +ArrayType_Type __new__(), from_address(), __mul__(), from_param() | |
| 35 | +SimpleType_Type __new__(), from_address(), __mul__(), from_param() | |
| 36 | + | |
| 37 | +CData_Type | |
| 38 | + Struct_Type __new__(), __init__() | |
| 39 | + Pointer_Type __new__(), __init__(), _as_parameter_, contents | |
| 40 | + Array_Type __new__(), __init__(), _as_parameter_, __get/setitem__(), __len__() | |
| 41 | + Simple_Type __new__(), __init__(), _as_parameter_ | |
| 42 | + | |
| 43 | +CField_Type | |
| 44 | +StgDict_Type | |
| 45 | + | |
| 46 | +============================================================================== | |
| 47 | + | |
| 48 | +class methods | |
| 49 | +------------- | |
| 50 | + | |
| 51 | +It has some similarity to the byref() construct compared to pointer() | |
| 52 | +from_address(addr) | |
| 53 | + - construct an instance from a given memory block (sharing this memory block) | |
| 54 | + | |
| 55 | +from_param(obj) | |
| 56 | + - typecheck and convert a Python object into a C function call parameter | |
| 57 | + the result may be an instance of the type, or an integer or tuple | |
| 58 | + (typecode, value[, obj]) | |
| 59 | + | |
| 60 | +instance methods/properties | |
| 61 | +--------------------------- | |
| 62 | + | |
| 63 | +_as_parameter_ | |
| 64 | + - convert self into a C function call parameter | |
| 65 | + This is either an integer, or a 3-tuple (typecode, value, obj) | |
| 66 | + | |
| 67 | +functions | |
| 68 | +--------- | |
| 69 | + | |
| 70 | +sizeof(cdata) | |
| 71 | + - return the number of bytes the buffer contains | |
| 72 | + | |
| 73 | +sizeof(ctype) | |
| 74 | + - return the number of bytes the buffer of an instance would contain | |
| 75 | + | |
| 76 | +byref(cdata) | |
| 77 | + | |
| 78 | +addressof(cdata) | |
| 79 | + | |
| 80 | +pointer(cdata) | |
| 81 | + | |
| 82 | +POINTER(ctype) | |
| 83 | + | |
| 84 | +bytes(cdata) | |
| 85 | + - return the buffer contents as a sequence of bytes (which is currently a string) | |
| 86 | + | |
| 87 | +*/ | |
| 88 | + | |
| 89 | +/* | |
| 90 | + * StgDict_Type | |
| 91 | + * StructType_Type | |
| 92 | + * UnionType_Type | |
| 93 | + * PointerType_Type | |
| 94 | + * ArrayType_Type | |
| 95 | + * SimpleType_Type | |
| 96 | + * | |
| 97 | + * CData_Type | |
| 98 | + * Struct_Type | |
| 99 | + * Union_Type | |
| 100 | + * Array_Type | |
| 101 | + * Simple_Type | |
| 102 | + * Pointer_Type | |
| 103 | + * CField_Type | |
| 104 | + * | |
| 105 | + */ | |
| 106 | + | |
| 107 | +#include "Python.h" | |
| 108 | +#include "structmember.h" | |
| 109 | + | |
| 110 | +#include <ffi.h> | |
| 111 | +#ifdef MS_WIN32 | |
| 112 | +#include <windows.h> | |
| 113 | +#include <malloc.h> | |
| 114 | +#ifndef IS_INTRESOURCE | |
| 115 | +#define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0) | |
| 116 | +#endif | |
| 117 | +# ifdef _WIN32_WCE | |
| 118 | +/* Unlike desktop Windows, WinCE has both W and A variants of | |
| 119 | + GetProcAddress, but the default W version is not what we want */ | |
| 120 | +# undef GetProcAddress | |
| 121 | +# define GetProcAddress GetProcAddressA | |
| 122 | +# endif | |
| 123 | +#else | |
| 124 | +#include "ctypes_dlfcn.h" | |
| 125 | +#endif | |
| 126 | +#include "ctypes.h" | |
| 127 | + | |
| 128 | +PyObject *PyExc_ArgError; | |
| 129 | +static PyTypeObject Simple_Type; | |
| 130 | + | |
| 131 | +char *conversion_mode_encoding = NULL; | |
| 132 | +char *conversion_mode_errors = NULL; | |
| 133 | + | |
| 134 | + | |
| 135 | +/******************************************************************/ | |
| 136 | +/* | |
| 137 | + StructType_Type - a meta type/class. Creating a new class using this one as | |
| 138 | + __metaclass__ will call the contructor StructUnionType_new. It replaces the | |
| 139 | + tp_dict member with a new instance of StgDict, and initializes the C | |
| 140 | + accessible fields somehow. | |
| 141 | +*/ | |
| 142 | + | |
| 143 | +static PyCArgObject * | |
| 144 | +StructUnionType_paramfunc(CDataObject *self) | |
| 145 | +{ | |
| 146 | + PyCArgObject *parg; | |
| 147 | + StgDictObject *stgdict; | |
| 148 | + | |
| 149 | + parg = new_CArgObject(); | |
| 150 | + if (parg == NULL) | |
| 151 | + return NULL; | |
| 152 | + | |
| 153 | + parg->tag = 'V'; | |
| 154 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 155 | + assert(stgdict); /* Cannot be NULL for structure/union instances */ | |
| 156 | + parg->pffi_type = &stgdict->ffi_type_pointer; | |
| 157 | + /* For structure parameters (by value), parg->value doesn't contain the structure | |
| 158 | + data itself, instead parg->value.p *points* to the structure's data | |
| 159 | + See also _ctypes.c, function _call_function_pointer(). | |
| 160 | + */ | |
| 161 | + parg->value.p = self->b_ptr; | |
| 162 | + parg->size = self->b_size; | |
| 163 | + Py_INCREF(self); | |
| 164 | + parg->obj = (PyObject *)self; | |
| 165 | + return parg; | |
| 166 | +} | |
| 167 | + | |
| 168 | +static PyObject * | |
| 169 | +StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isStruct) | |
| 170 | +{ | |
| 171 | + PyTypeObject *result; | |
| 172 | + PyObject *fields; | |
| 173 | + StgDictObject *dict; | |
| 174 | + | |
| 175 | + /* create the new instance (which is a class, | |
| 176 | + since we are a metatype!) */ | |
| 177 | + result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); | |
| 178 | + if (!result) | |
| 179 | + return NULL; | |
| 180 | + | |
| 181 | + /* keep this for bw compatibility */ | |
| 182 | + if (PyDict_GetItemString(result->tp_dict, "_abstract_")) | |
| 183 | + return (PyObject *)result; | |
| 184 | + | |
| 185 | + dict = (StgDictObject *)PyObject_CallObject((PyObject *)&StgDict_Type, NULL); | |
| 186 | + if (!dict) { | |
| 187 | + Py_DECREF(result); | |
| 188 | + return NULL; | |
| 189 | + } | |
| 190 | + /* replace the class dict by our updated stgdict, which holds info | |
| 191 | + about storage requirements of the instances */ | |
| 192 | + if (-1 == PyDict_Update((PyObject *)dict, result->tp_dict)) { | |
| 193 | + Py_DECREF(result); | |
| 194 | + Py_DECREF((PyObject *)dict); | |
| 195 | + return NULL; | |
| 196 | + } | |
| 197 | + Py_DECREF(result->tp_dict); | |
| 198 | + result->tp_dict = (PyObject *)dict; | |
| 199 | + | |
| 200 | + dict->paramfunc = StructUnionType_paramfunc; | |
| 201 | + | |
| 202 | + fields = PyDict_GetItemString((PyObject *)dict, "_fields_"); | |
| 203 | + if (!fields) { | |
| 204 | + StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base); | |
| 205 | + | |
| 206 | + if (basedict == NULL) | |
| 207 | + return (PyObject *)result; | |
| 208 | + /* copy base dict */ | |
| 209 | + if (-1 == StgDict_clone(dict, basedict)) { | |
| 210 | + Py_DECREF(result); | |
| 211 | + return NULL; | |
| 212 | + } | |
| 213 | + dict->flags &= ~DICTFLAG_FINAL; /* clear the 'final' flag in the subclass dict */ | |
| 214 | + basedict->flags |= DICTFLAG_FINAL; /* set the 'final' flag in the baseclass dict */ | |
| 215 | + return (PyObject *)result; | |
| 216 | + } | |
| 217 | + | |
| 218 | + if (-1 == PyObject_SetAttrString((PyObject *)result, "_fields_", fields)) { | |
| 219 | + Py_DECREF(result); | |
| 220 | + return NULL; | |
| 221 | + } | |
| 222 | + return (PyObject *)result; | |
| 223 | +} | |
| 224 | + | |
| 225 | +static PyObject * | |
| 226 | +StructType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 227 | +{ | |
| 228 | + return StructUnionType_new(type, args, kwds, 1); | |
| 229 | +} | |
| 230 | + | |
| 231 | +static PyObject * | |
| 232 | +UnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 233 | +{ | |
| 234 | + return StructUnionType_new(type, args, kwds, 0); | |
| 235 | +} | |
| 236 | + | |
| 237 | +static char from_address_doc[] = | |
| 238 | +"C.from_address(integer) -> C instance\naccess a C instance at the specified address"; | |
| 239 | + | |
| 240 | +static PyObject * | |
| 241 | +CDataType_from_address(PyObject *type, PyObject *value) | |
| 242 | +{ | |
| 243 | + void *buf; | |
| 244 | + if (!PyInt_Check(value) && !PyLong_Check(value)) { | |
| 245 | + PyErr_SetString(PyExc_TypeError, | |
| 246 | + "integer expected"); | |
| 247 | + return NULL; | |
| 248 | + } | |
| 249 | + buf = (void *)PyLong_AsVoidPtr(value); | |
| 250 | + if (PyErr_Occurred()) | |
| 251 | + return NULL; | |
| 252 | + return CData_AtAddress(type, buf); | |
| 253 | +} | |
| 254 | + | |
| 255 | +static char in_dll_doc[] = | |
| 256 | +"C.in_dll(dll, name) -> C instance\naccess a C instance in a dll"; | |
| 257 | + | |
| 258 | +static PyObject * | |
| 259 | +CDataType_in_dll(PyObject *type, PyObject *args) | |
| 260 | +{ | |
| 261 | + PyObject *dll; | |
| 262 | + char *name; | |
| 263 | + PyObject *obj; | |
| 264 | + void *handle; | |
| 265 | + void *address; | |
| 266 | + | |
| 267 | + if (!PyArg_ParseTuple(args, "Os:in_dll", &dll, &name)) | |
| 268 | + return NULL; | |
| 269 | + | |
| 270 | + obj = PyObject_GetAttrString(dll, "_handle"); | |
| 271 | + if (!obj) | |
| 272 | + return NULL; | |
| 273 | + if (!PyInt_Check(obj) && !PyLong_Check(obj)) { | |
| 274 | + PyErr_SetString(PyExc_TypeError, | |
| 275 | + "the _handle attribute of the second argument must be an integer"); | |
| 276 | + Py_DECREF(obj); | |
| 277 | + return NULL; | |
| 278 | + } | |
| 279 | + handle = (void *)PyLong_AsVoidPtr(obj); | |
| 280 | + Py_DECREF(obj); | |
| 281 | + if (PyErr_Occurred()) { | |
| 282 | + PyErr_SetString(PyExc_ValueError, | |
| 283 | + "could not convert the _handle attribute to a pointer"); | |
| 284 | + return NULL; | |
| 285 | + } | |
| 286 | + | |
| 287 | +#ifdef MS_WIN32 | |
| 288 | + address = (void *)GetProcAddress(handle, name); | |
| 289 | + if (!address) { | |
| 290 | + PyErr_Format(PyExc_ValueError, | |
| 291 | + "symbol '%s' not found", | |
| 292 | + name); | |
| 293 | + return NULL; | |
| 294 | + } | |
| 295 | +#else | |
| 296 | + address = (void *)ctypes_dlsym(handle, name); | |
| 297 | + if (!address) { | |
| 298 | + PyErr_Format(PyExc_ValueError, | |
| 299 | +#ifdef __CYGWIN__ | |
| 300 | +/* dlerror() isn't very helpful on cygwin */ | |
| 301 | + "symbol '%s' not found (%s) ", | |
| 302 | + name, | |
| 303 | +#endif | |
| 304 | + ctypes_dlerror()); | |
| 305 | + return NULL; | |
| 306 | + } | |
| 307 | +#endif | |
| 308 | + return CData_AtAddress(type, address); | |
| 309 | +} | |
| 310 | + | |
| 311 | +static char from_param_doc[] = | |
| 312 | +"Convert a Python object into a function call parameter."; | |
| 313 | + | |
| 314 | +static PyObject * | |
| 315 | +CDataType_from_param(PyObject *type, PyObject *value) | |
| 316 | +{ | |
| 317 | + PyObject *as_parameter; | |
| 318 | + if (1 == PyObject_IsInstance(value, type)) { | |
| 319 | + Py_INCREF(value); | |
| 320 | + return value; | |
| 321 | + } | |
| 322 | + if (PyCArg_CheckExact(value)) { | |
| 323 | + PyCArgObject *p = (PyCArgObject *)value; | |
| 324 | + PyObject *ob = p->obj; | |
| 325 | + const char *ob_name; | |
| 326 | + StgDictObject *dict; | |
| 327 | + dict = PyType_stgdict(type); | |
| 328 | + | |
| 329 | + /* If we got a PyCArgObject, we must check if the object packed in it | |
| 330 | + is an instance of the type's dict->proto */ | |
| 331 | + if(dict && ob | |
| 332 | + && PyObject_IsInstance(ob, dict->proto)) { | |
| 333 | + Py_INCREF(value); | |
| 334 | + return value; | |
| 335 | + } | |
| 336 | + ob_name = (ob) ? ob->ob_type->tp_name : "???"; | |
| 337 | + PyErr_Format(PyExc_TypeError, | |
| 338 | + "expected %s instance instead of pointer to %s", | |
| 339 | + ((PyTypeObject *)type)->tp_name, ob_name); | |
| 340 | + return NULL; | |
| 341 | + } | |
| 342 | + | |
| 343 | + as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); | |
| 344 | + if (as_parameter) { | |
| 345 | + value = CDataType_from_param(type, as_parameter); | |
| 346 | + Py_DECREF(as_parameter); | |
| 347 | + return value; | |
| 348 | + } | |
| 349 | + PyErr_Format(PyExc_TypeError, | |
| 350 | + "expected %s instance instead of %s", | |
| 351 | + ((PyTypeObject *)type)->tp_name, | |
| 352 | + value->ob_type->tp_name); | |
| 353 | + return NULL; | |
| 354 | +} | |
| 355 | + | |
| 356 | +static PyMethodDef CDataType_methods[] = { | |
| 357 | + { "from_param", CDataType_from_param, METH_O, from_param_doc }, | |
| 358 | + { "from_address", CDataType_from_address, METH_O, from_address_doc }, | |
| 359 | + { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc }, | |
| 360 | + { NULL, NULL }, | |
| 361 | +}; | |
| 362 | + | |
| 363 | +static PyObject * | |
| 364 | +CDataType_repeat(PyObject *self, Py_ssize_t length) | |
| 365 | +{ | |
| 366 | + if (length < 0) | |
| 367 | + return PyErr_Format(PyExc_ValueError, | |
| 368 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 369 | + "Array length must be >= 0, not %d", | |
| 370 | +#else | |
| 371 | + "Array length must be >= 0, not %zd", | |
| 372 | +#endif | |
| 373 | + length); | |
| 374 | + return CreateArrayType(self, length); | |
| 375 | +} | |
| 376 | + | |
| 377 | +static PySequenceMethods CDataType_as_sequence = { | |
| 378 | + 0, /* inquiry sq_length; */ | |
| 379 | + 0, /* binaryfunc sq_concat; */ | |
| 380 | + CDataType_repeat, /* intargfunc sq_repeat; */ | |
| 381 | + 0, /* intargfunc sq_item; */ | |
| 382 | + 0, /* intintargfunc sq_slice; */ | |
| 383 | + 0, /* intobjargproc sq_ass_item; */ | |
| 384 | + 0, /* intintobjargproc sq_ass_slice; */ | |
| 385 | + 0, /* objobjproc sq_contains; */ | |
| 386 | + | |
| 387 | + 0, /* binaryfunc sq_inplace_concat; */ | |
| 388 | + 0, /* intargfunc sq_inplace_repeat; */ | |
| 389 | +}; | |
| 390 | + | |
| 391 | +static int | |
| 392 | +CDataType_clear(PyTypeObject *self) | |
| 393 | +{ | |
| 394 | + StgDictObject *dict = PyType_stgdict((PyObject *)self); | |
| 395 | + if (dict) | |
| 396 | + Py_CLEAR(dict->proto); | |
| 397 | + return PyType_Type.tp_clear((PyObject *)self); | |
| 398 | +} | |
| 399 | + | |
| 400 | +static int | |
| 401 | +CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg) | |
| 402 | +{ | |
| 403 | + StgDictObject *dict = PyType_stgdict((PyObject *)self); | |
| 404 | + if (dict) | |
| 405 | + Py_VISIT(dict->proto); | |
| 406 | + return PyType_Type.tp_traverse((PyObject *)self, visit, arg); | |
| 407 | +} | |
| 408 | + | |
| 409 | +static int | |
| 410 | +StructType_setattro(PyObject *self, PyObject *key, PyObject *value) | |
| 411 | +{ | |
| 412 | + /* XXX Should we disallow deleting _fields_? */ | |
| 413 | + if (-1 == PyObject_GenericSetAttr(self, key, value)) | |
| 414 | + return -1; | |
| 415 | + | |
| 416 | + if (value && PyString_Check(key) && | |
| 417 | + 0 == strcmp(PyString_AS_STRING(key), "_fields_")) | |
| 418 | + return StructUnionType_update_stgdict(self, value, 1); | |
| 419 | + return 0; | |
| 420 | +} | |
| 421 | + | |
| 422 | + | |
| 423 | +static int | |
| 424 | +UnionType_setattro(PyObject *self, PyObject *key, PyObject *value) | |
| 425 | +{ | |
| 426 | + /* XXX Should we disallow deleting _fields_? */ | |
| 427 | + if (-1 == PyObject_GenericSetAttr(self, key, value)) | |
| 428 | + return -1; | |
| 429 | + | |
| 430 | + if (PyString_Check(key) && | |
| 431 | + 0 == strcmp(PyString_AS_STRING(key), "_fields_")) | |
| 432 | + return StructUnionType_update_stgdict(self, value, 0); | |
| 433 | + return 0; | |
| 434 | +} | |
| 435 | + | |
| 436 | + | |
| 437 | +PyTypeObject StructType_Type = { | |
| 438 | + PyObject_HEAD_INIT(NULL) | |
| 439 | + 0, /* ob_size */ | |
| 440 | + "_ctypes.StructType", /* tp_name */ | |
| 441 | + 0, /* tp_basicsize */ | |
| 442 | + 0, /* tp_itemsize */ | |
| 443 | + 0, /* tp_dealloc */ | |
| 444 | + 0, /* tp_print */ | |
| 445 | + 0, /* tp_getattr */ | |
| 446 | + 0, /* tp_setattr */ | |
| 447 | + 0, /* tp_compare */ | |
| 448 | + 0, /* tp_repr */ | |
| 449 | + 0, /* tp_as_number */ | |
| 450 | + &CDataType_as_sequence, /* tp_as_sequence */ | |
| 451 | + 0, /* tp_as_mapping */ | |
| 452 | + 0, /* tp_hash */ | |
| 453 | + 0, /* tp_call */ | |
| 454 | + 0, /* tp_str */ | |
| 455 | + 0, /* tp_getattro */ | |
| 456 | + StructType_setattro, /* tp_setattro */ | |
| 457 | + 0, /* tp_as_buffer */ | |
| 458 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ | |
| 459 | + "metatype for the CData Objects", /* tp_doc */ | |
| 460 | + (traverseproc)CDataType_traverse, /* tp_traverse */ | |
| 461 | + (inquiry)CDataType_clear, /* tp_clear */ | |
| 462 | + 0, /* tp_richcompare */ | |
| 463 | + 0, /* tp_weaklistoffset */ | |
| 464 | + 0, /* tp_iter */ | |
| 465 | + 0, /* tp_iternext */ | |
| 466 | + CDataType_methods, /* tp_methods */ | |
| 467 | + 0, /* tp_members */ | |
| 468 | + 0, /* tp_getset */ | |
| 469 | + 0, /* tp_base */ | |
| 470 | + 0, /* tp_dict */ | |
| 471 | + 0, /* tp_descr_get */ | |
| 472 | + 0, /* tp_descr_set */ | |
| 473 | + 0, /* tp_dictoffset */ | |
| 474 | + 0, /* tp_init */ | |
| 475 | + 0, /* tp_alloc */ | |
| 476 | + StructType_new, /* tp_new */ | |
| 477 | + 0, /* tp_free */ | |
| 478 | +}; | |
| 479 | + | |
| 480 | +static PyTypeObject UnionType_Type = { | |
| 481 | + PyObject_HEAD_INIT(NULL) | |
| 482 | + 0, /* ob_size */ | |
| 483 | + "_ctypes.UnionType", /* tp_name */ | |
| 484 | + 0, /* tp_basicsize */ | |
| 485 | + 0, /* tp_itemsize */ | |
| 486 | + 0, /* tp_dealloc */ | |
| 487 | + 0, /* tp_print */ | |
| 488 | + 0, /* tp_getattr */ | |
| 489 | + 0, /* tp_setattr */ | |
| 490 | + 0, /* tp_compare */ | |
| 491 | + 0, /* tp_repr */ | |
| 492 | + 0, /* tp_as_number */ | |
| 493 | + &CDataType_as_sequence, /* tp_as_sequence */ | |
| 494 | + 0, /* tp_as_mapping */ | |
| 495 | + 0, /* tp_hash */ | |
| 496 | + 0, /* tp_call */ | |
| 497 | + 0, /* tp_str */ | |
| 498 | + 0, /* tp_getattro */ | |
| 499 | + UnionType_setattro, /* tp_setattro */ | |
| 500 | + 0, /* tp_as_buffer */ | |
| 501 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ | |
| 502 | + "metatype for the CData Objects", /* tp_doc */ | |
| 503 | + (traverseproc)CDataType_traverse, /* tp_traverse */ | |
| 504 | + (inquiry)CDataType_clear, /* tp_clear */ | |
| 505 | + 0, /* tp_richcompare */ | |
| 506 | + 0, /* tp_weaklistoffset */ | |
| 507 | + 0, /* tp_iter */ | |
| 508 | + 0, /* tp_iternext */ | |
| 509 | + CDataType_methods, /* tp_methods */ | |
| 510 | + 0, /* tp_members */ | |
| 511 | + 0, /* tp_getset */ | |
| 512 | + 0, /* tp_base */ | |
| 513 | + 0, /* tp_dict */ | |
| 514 | + 0, /* tp_descr_get */ | |
| 515 | + 0, /* tp_descr_set */ | |
| 516 | + 0, /* tp_dictoffset */ | |
| 517 | + 0, /* tp_init */ | |
| 518 | + 0, /* tp_alloc */ | |
| 519 | + UnionType_new, /* tp_new */ | |
| 520 | + 0, /* tp_free */ | |
| 521 | +}; | |
| 522 | + | |
| 523 | + | |
| 524 | +/******************************************************************/ | |
| 525 | + | |
| 526 | +/* | |
| 527 | + | |
| 528 | +The PointerType_Type metaclass must ensure that the subclass of Pointer can be | |
| 529 | +created. It must check for a _type_ attribute in the class. Since are no | |
| 530 | +runtime created properties, a CField is probably *not* needed ? | |
| 531 | + | |
| 532 | +class IntPointer(Pointer): | |
| 533 | + _type_ = "i" | |
| 534 | + | |
| 535 | +The Pointer_Type provides the functionality: a contents method/property, a | |
| 536 | +size property/method, and the sequence protocol. | |
| 537 | + | |
| 538 | +*/ | |
| 539 | + | |
| 540 | +static int | |
| 541 | +PointerType_SetProto(StgDictObject *stgdict, PyObject *proto) | |
| 542 | +{ | |
| 543 | + if (!proto || !PyType_Check(proto)) { | |
| 544 | + PyErr_SetString(PyExc_TypeError, | |
| 545 | + "_type_ must be a type"); | |
| 546 | + return -1; | |
| 547 | + } | |
| 548 | + if (!PyType_stgdict(proto)) { | |
| 549 | + PyErr_SetString(PyExc_TypeError, | |
| 550 | + "_type_ must have storage info"); | |
| 551 | + return -1; | |
| 552 | + } | |
| 553 | + Py_INCREF(proto); | |
| 554 | + Py_XDECREF(stgdict->proto); | |
| 555 | + stgdict->proto = proto; | |
| 556 | + return 0; | |
| 557 | +} | |
| 558 | + | |
| 559 | +static PyCArgObject * | |
| 560 | +PointerType_paramfunc(CDataObject *self) | |
| 561 | +{ | |
| 562 | + PyCArgObject *parg; | |
| 563 | + | |
| 564 | + parg = new_CArgObject(); | |
| 565 | + if (parg == NULL) | |
| 566 | + return NULL; | |
| 567 | + | |
| 568 | + parg->tag = 'P'; | |
| 569 | + parg->pffi_type = &ffi_type_pointer; | |
| 570 | + Py_INCREF(self); | |
| 571 | + parg->obj = (PyObject *)self; | |
| 572 | + parg->value.p = *(void **)self->b_ptr; | |
| 573 | + return parg; | |
| 574 | +} | |
| 575 | + | |
| 576 | +static PyObject * | |
| 577 | +PointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 578 | +{ | |
| 579 | + PyTypeObject *result; | |
| 580 | + StgDictObject *stgdict; | |
| 581 | + PyObject *proto; | |
| 582 | + PyObject *typedict; | |
| 583 | + | |
| 584 | + typedict = PyTuple_GetItem(args, 2); | |
| 585 | + if (!typedict) | |
| 586 | + return NULL; | |
| 587 | +/* | |
| 588 | + stgdict items size, align, length contain info about pointers itself, | |
| 589 | + stgdict->proto has info about the pointed to type! | |
| 590 | +*/ | |
| 591 | + stgdict = (StgDictObject *)PyObject_CallObject( | |
| 592 | + (PyObject *)&StgDict_Type, NULL); | |
| 593 | + if (!stgdict) | |
| 594 | + return NULL; | |
| 595 | + stgdict->size = sizeof(void *); | |
| 596 | + stgdict->align = getentry("P")->pffi_type->alignment; | |
| 597 | + stgdict->length = 1; | |
| 598 | + stgdict->ffi_type_pointer = ffi_type_pointer; | |
| 599 | + stgdict->paramfunc = PointerType_paramfunc; | |
| 600 | + | |
| 601 | + proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */ | |
| 602 | + if (proto && -1 == PointerType_SetProto(stgdict, proto)) { | |
| 603 | + Py_DECREF((PyObject *)stgdict); | |
| 604 | + return NULL; | |
| 605 | + } | |
| 606 | + | |
| 607 | + /* create the new instance (which is a class, | |
| 608 | + since we are a metatype!) */ | |
| 609 | + result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); | |
| 610 | + if (result == NULL) { | |
| 611 | + Py_DECREF((PyObject *)stgdict); | |
| 612 | + return NULL; | |
| 613 | + } | |
| 614 | + | |
| 615 | + /* replace the class dict by our updated spam dict */ | |
| 616 | + if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { | |
| 617 | + Py_DECREF(result); | |
| 618 | + Py_DECREF((PyObject *)stgdict); | |
| 619 | + return NULL; | |
| 620 | + } | |
| 621 | + Py_DECREF(result->tp_dict); | |
| 622 | + result->tp_dict = (PyObject *)stgdict; | |
| 623 | + | |
| 624 | + return (PyObject *)result; | |
| 625 | +} | |
| 626 | + | |
| 627 | + | |
| 628 | +static PyObject * | |
| 629 | +PointerType_set_type(PyTypeObject *self, PyObject *type) | |
| 630 | +{ | |
| 631 | + StgDictObject *dict; | |
| 632 | + | |
| 633 | + dict = PyType_stgdict((PyObject *)self); | |
| 634 | + assert(dict); | |
| 635 | + | |
| 636 | + if (-1 == PointerType_SetProto(dict, type)) | |
| 637 | + return NULL; | |
| 638 | + | |
| 639 | + if (-1 == PyDict_SetItemString((PyObject *)dict, "_type_", type)) | |
| 640 | + return NULL; | |
| 641 | + | |
| 642 | + Py_INCREF(Py_None); | |
| 643 | + return Py_None; | |
| 644 | +} | |
| 645 | + | |
| 646 | +staticforward PyObject *_byref(PyObject *); | |
| 647 | + | |
| 648 | +static PyObject * | |
| 649 | +PointerType_from_param(PyObject *type, PyObject *value) | |
| 650 | +{ | |
| 651 | + StgDictObject *typedict; | |
| 652 | + | |
| 653 | + if (value == Py_None) | |
| 654 | + return PyInt_FromLong(0); /* NULL pointer */ | |
| 655 | + | |
| 656 | + typedict = PyType_stgdict(type); | |
| 657 | + assert(typedict); /* Cannot be NULL for pointer types */ | |
| 658 | + | |
| 659 | + /* If we expect POINTER(<type>), but receive a <type> instance, accept | |
| 660 | + it by calling byref(<type>). | |
| 661 | + */ | |
| 662 | + switch (PyObject_IsInstance(value, typedict->proto)) { | |
| 663 | + case 1: | |
| 664 | + Py_INCREF(value); /* _byref steals a refcount */ | |
| 665 | + return _byref(value); | |
| 666 | + case -1: | |
| 667 | + PyErr_Clear(); | |
| 668 | + break; | |
| 669 | + default: | |
| 670 | + break; | |
| 671 | + } | |
| 672 | + | |
| 673 | + if (PointerObject_Check(value) || ArrayObject_Check(value)) { | |
| 674 | + /* Array instances are also pointers when | |
| 675 | + the item types are the same. | |
| 676 | + */ | |
| 677 | + StgDictObject *v = PyObject_stgdict(value); | |
| 678 | + assert(v); /* Cannot be NULL for pointer or array objects */ | |
| 679 | + if (PyObject_IsSubclass(v->proto, typedict->proto)) { | |
| 680 | + Py_INCREF(value); | |
| 681 | + return value; | |
| 682 | + } | |
| 683 | + } | |
| 684 | + return CDataType_from_param(type, value); | |
| 685 | +} | |
| 686 | + | |
| 687 | +static PyMethodDef PointerType_methods[] = { | |
| 688 | + { "from_address", CDataType_from_address, METH_O, from_address_doc }, | |
| 689 | + { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, | |
| 690 | + { "from_param", (PyCFunction)PointerType_from_param, METH_O, from_param_doc}, | |
| 691 | + { "set_type", (PyCFunction)PointerType_set_type, METH_O }, | |
| 692 | + { NULL, NULL }, | |
| 693 | +}; | |
| 694 | + | |
| 695 | +PyTypeObject PointerType_Type = { | |
| 696 | + PyObject_HEAD_INIT(NULL) | |
| 697 | + 0, /* ob_size */ | |
| 698 | + "_ctypes.PointerType", /* tp_name */ | |
| 699 | + 0, /* tp_basicsize */ | |
| 700 | + 0, /* tp_itemsize */ | |
| 701 | + 0, /* tp_dealloc */ | |
| 702 | + 0, /* tp_print */ | |
| 703 | + 0, /* tp_getattr */ | |
| 704 | + 0, /* tp_setattr */ | |
| 705 | + 0, /* tp_compare */ | |
| 706 | + 0, /* tp_repr */ | |
| 707 | + 0, /* tp_as_number */ | |
| 708 | + &CDataType_as_sequence, /* tp_as_sequence */ | |
| 709 | + 0, /* tp_as_mapping */ | |
| 710 | + 0, /* tp_hash */ | |
| 711 | + 0, /* tp_call */ | |
| 712 | + 0, /* tp_str */ | |
| 713 | + 0, /* tp_getattro */ | |
| 714 | + 0, /* tp_setattro */ | |
| 715 | + 0, /* tp_as_buffer */ | |
| 716 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ | |
| 717 | + "metatype for the Pointer Objects", /* tp_doc */ | |
| 718 | + (traverseproc)CDataType_traverse, /* tp_traverse */ | |
| 719 | + (inquiry)CDataType_clear, /* tp_clear */ | |
| 720 | + 0, /* tp_richcompare */ | |
| 721 | + 0, /* tp_weaklistoffset */ | |
| 722 | + 0, /* tp_iter */ | |
| 723 | + 0, /* tp_iternext */ | |
| 724 | + PointerType_methods, /* tp_methods */ | |
| 725 | + 0, /* tp_members */ | |
| 726 | + 0, /* tp_getset */ | |
| 727 | + 0, /* tp_base */ | |
| 728 | + 0, /* tp_dict */ | |
| 729 | + 0, /* tp_descr_get */ | |
| 730 | + 0, /* tp_descr_set */ | |
| 731 | + 0, /* tp_dictoffset */ | |
| 732 | + 0, /* tp_init */ | |
| 733 | + 0, /* tp_alloc */ | |
| 734 | + PointerType_new, /* tp_new */ | |
| 735 | + 0, /* tp_free */ | |
| 736 | +}; | |
| 737 | + | |
| 738 | + | |
| 739 | +/******************************************************************/ | |
| 740 | +/* | |
| 741 | + ArrayType_Type | |
| 742 | +*/ | |
| 743 | +/* | |
| 744 | + ArrayType_new ensures that the new Array subclass created has a _length_ | |
| 745 | + attribute, and a _type_ attribute. | |
| 746 | +*/ | |
| 747 | + | |
| 748 | +static int | |
| 749 | +CharArray_set_raw(CDataObject *self, PyObject *value) | |
| 750 | +{ | |
| 751 | + char *ptr; | |
| 752 | + Py_ssize_t size; | |
| 753 | + if (PyBuffer_Check(value)) { | |
| 754 | + size = value->ob_type->tp_as_buffer->bf_getreadbuffer(value, 0, (void *)&ptr); | |
| 755 | + if (size < 0) | |
| 756 | + return -1; | |
| 757 | + } else if (-1 == PyString_AsStringAndSize(value, &ptr, &size)) { | |
| 758 | + return -1; | |
| 759 | + } | |
| 760 | + if (size > self->b_size) { | |
| 761 | + PyErr_SetString(PyExc_ValueError, | |
| 762 | + "string too long"); | |
| 763 | + return -1; | |
| 764 | + } | |
| 765 | + | |
| 766 | + memcpy(self->b_ptr, ptr, size); | |
| 767 | + | |
| 768 | + return 0; | |
| 769 | +} | |
| 770 | + | |
| 771 | +static PyObject * | |
| 772 | +CharArray_get_raw(CDataObject *self) | |
| 773 | +{ | |
| 774 | + return PyString_FromStringAndSize(self->b_ptr, self->b_size); | |
| 775 | +} | |
| 776 | + | |
| 777 | +static PyObject * | |
| 778 | +CharArray_get_value(CDataObject *self) | |
| 779 | +{ | |
| 780 | + int i; | |
| 781 | + char *ptr = self->b_ptr; | |
| 782 | + for (i = 0; i < self->b_size; ++i) | |
| 783 | + if (*ptr++ == '\0') | |
| 784 | + break; | |
| 785 | + return PyString_FromStringAndSize(self->b_ptr, i); | |
| 786 | +} | |
| 787 | + | |
| 788 | +static int | |
| 789 | +CharArray_set_value(CDataObject *self, PyObject *value) | |
| 790 | +{ | |
| 791 | + char *ptr; | |
| 792 | + int size; | |
| 793 | + | |
| 794 | + if (PyUnicode_Check(value)) { | |
| 795 | + value = PyUnicode_AsEncodedString(value, | |
| 796 | + conversion_mode_encoding, | |
| 797 | + conversion_mode_errors); | |
| 798 | + if (!value) | |
| 799 | + return -1; | |
| 800 | + } else if (!PyString_Check(value)) { | |
| 801 | + PyErr_Format(PyExc_TypeError, | |
| 802 | + "string expected instead of %s instance", | |
| 803 | + value->ob_type->tp_name); | |
| 804 | + return -1; | |
| 805 | + } else | |
| 806 | + Py_INCREF(value); | |
| 807 | + size = PyString_GET_SIZE(value); | |
| 808 | + if (size > self->b_size) { | |
| 809 | + PyErr_SetString(PyExc_ValueError, | |
| 810 | + "string too long"); | |
| 811 | + Py_DECREF(value); | |
| 812 | + return -1; | |
| 813 | + } | |
| 814 | + | |
| 815 | + ptr = PyString_AS_STRING(value); | |
| 816 | + memcpy(self->b_ptr, ptr, size); | |
| 817 | + if (size < self->b_size) | |
| 818 | + self->b_ptr[size] = '\0'; | |
| 819 | + Py_DECREF(value); | |
| 820 | + | |
| 821 | + return 0; | |
| 822 | +} | |
| 823 | + | |
| 824 | +static PyGetSetDef CharArray_getsets[] = { | |
| 825 | + { "raw", (getter)CharArray_get_raw, (setter)CharArray_set_raw, | |
| 826 | + "value", NULL }, | |
| 827 | + { "value", (getter)CharArray_get_value, (setter)CharArray_set_value, | |
| 828 | + "string value"}, | |
| 829 | + { NULL, NULL } | |
| 830 | +}; | |
| 831 | + | |
| 832 | +#ifdef CTYPES_UNICODE | |
| 833 | +static PyObject * | |
| 834 | +WCharArray_get_value(CDataObject *self) | |
| 835 | +{ | |
| 836 | + unsigned int i; | |
| 837 | + wchar_t *ptr = (wchar_t *)self->b_ptr; | |
| 838 | + for (i = 0; i < self->b_size/sizeof(wchar_t); ++i) | |
| 839 | + if (*ptr++ == (wchar_t)0) | |
| 840 | + break; | |
| 841 | + return PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i); | |
| 842 | +} | |
| 843 | + | |
| 844 | +static int | |
| 845 | +WCharArray_set_value(CDataObject *self, PyObject *value) | |
| 846 | +{ | |
| 847 | + int result = 0; | |
| 848 | + | |
| 849 | + if (PyString_Check(value)) { | |
| 850 | + value = PyUnicode_FromEncodedObject(value, | |
| 851 | + conversion_mode_encoding, | |
| 852 | + conversion_mode_errors); | |
| 853 | + if (!value) | |
| 854 | + return -1; | |
| 855 | + } else if (!PyUnicode_Check(value)) { | |
| 856 | + PyErr_Format(PyExc_TypeError, | |
| 857 | + "unicode string expected instead of %s instance", | |
| 858 | + value->ob_type->tp_name); | |
| 859 | + return -1; | |
| 860 | + } else | |
| 861 | + Py_INCREF(value); | |
| 862 | + if ((unsigned)PyUnicode_GET_SIZE(value) > self->b_size/sizeof(wchar_t)) { | |
| 863 | + PyErr_SetString(PyExc_ValueError, | |
| 864 | + "string too long"); | |
| 865 | + result = -1; | |
| 866 | + goto done; | |
| 867 | + } | |
| 868 | + result = PyUnicode_AsWideChar((PyUnicodeObject *)value, | |
| 869 | + (wchar_t *)self->b_ptr, | |
| 870 | + self->b_size/sizeof(wchar_t)); | |
| 871 | + if (result >= 0 && (unsigned)result < self->b_size/sizeof(wchar_t)) | |
| 872 | + ((wchar_t *)self->b_ptr)[result] = (wchar_t)0; | |
| 873 | + if (result > 0) | |
| 874 | + result = 0; | |
| 875 | + done: | |
| 876 | + Py_DECREF(value); | |
| 877 | + | |
| 878 | + return result; | |
| 879 | +} | |
| 880 | + | |
| 881 | +static PyGetSetDef WCharArray_getsets[] = { | |
| 882 | + { "value", (getter)WCharArray_get_value, (setter)WCharArray_set_value, | |
| 883 | + "string value"}, | |
| 884 | + { NULL, NULL } | |
| 885 | +}; | |
| 886 | +#endif | |
| 887 | + | |
| 888 | +/* | |
| 889 | + The next three functions copied from Python's typeobject.c. | |
| 890 | + | |
| 891 | + They are used to attach methods, members, or getsets to a type *after* it | |
| 892 | + has been created: Arrays of characters have additional getsets to treat them | |
| 893 | + as strings. | |
| 894 | + */ | |
| 895 | +/* | |
| 896 | +static int | |
| 897 | +add_methods(PyTypeObject *type, PyMethodDef *meth) | |
| 898 | +{ | |
| 899 | + PyObject *dict = type->tp_dict; | |
| 900 | + for (; meth->ml_name != NULL; meth++) { | |
| 901 | + PyObject *descr; | |
| 902 | + descr = PyDescr_NewMethod(type, meth); | |
| 903 | + if (descr == NULL) | |
| 904 | + return -1; | |
| 905 | + if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0) | |
| 906 | + return -1; | |
| 907 | + Py_DECREF(descr); | |
| 908 | + } | |
| 909 | + return 0; | |
| 910 | +} | |
| 911 | + | |
| 912 | +static int | |
| 913 | +add_members(PyTypeObject *type, PyMemberDef *memb) | |
| 914 | +{ | |
| 915 | + PyObject *dict = type->tp_dict; | |
| 916 | + for (; memb->name != NULL; memb++) { | |
| 917 | + PyObject *descr; | |
| 918 | + descr = PyDescr_NewMember(type, memb); | |
| 919 | + if (descr == NULL) | |
| 920 | + return -1; | |
| 921 | + if (PyDict_SetItemString(dict, memb->name, descr) < 0) | |
| 922 | + return -1; | |
| 923 | + Py_DECREF(descr); | |
| 924 | + } | |
| 925 | + return 0; | |
| 926 | +} | |
| 927 | +*/ | |
| 928 | + | |
| 929 | +static int | |
| 930 | +add_getset(PyTypeObject *type, PyGetSetDef *gsp) | |
| 931 | +{ | |
| 932 | + PyObject *dict = type->tp_dict; | |
| 933 | + for (; gsp->name != NULL; gsp++) { | |
| 934 | + PyObject *descr; | |
| 935 | + descr = PyDescr_NewGetSet(type, gsp); | |
| 936 | + if (descr == NULL) | |
| 937 | + return -1; | |
| 938 | + if (PyDict_SetItemString(dict, gsp->name, descr) < 0) | |
| 939 | + return -1; | |
| 940 | + Py_DECREF(descr); | |
| 941 | + } | |
| 942 | + return 0; | |
| 943 | +} | |
| 944 | + | |
| 945 | +static PyCArgObject * | |
| 946 | +ArrayType_paramfunc(CDataObject *self) | |
| 947 | +{ | |
| 948 | + PyCArgObject *p = new_CArgObject(); | |
| 949 | + if (p == NULL) | |
| 950 | + return NULL; | |
| 951 | + p->tag = 'P'; | |
| 952 | + p->pffi_type = &ffi_type_pointer; | |
| 953 | + p->value.p = (char *)self->b_ptr; | |
| 954 | + Py_INCREF(self); | |
| 955 | + p->obj = (PyObject *)self; | |
| 956 | + return p; | |
| 957 | +} | |
| 958 | + | |
| 959 | +static PyObject * | |
| 960 | +ArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 961 | +{ | |
| 962 | + PyTypeObject *result; | |
| 963 | + StgDictObject *stgdict; | |
| 964 | + StgDictObject *itemdict; | |
| 965 | + PyObject *proto; | |
| 966 | + PyObject *typedict; | |
| 967 | + int length; | |
| 968 | + | |
| 969 | + int itemsize, itemalign; | |
| 970 | + | |
| 971 | + typedict = PyTuple_GetItem(args, 2); | |
| 972 | + if (!typedict) | |
| 973 | + return NULL; | |
| 974 | + | |
| 975 | + proto = PyDict_GetItemString(typedict, "_length_"); /* Borrowed ref */ | |
| 976 | + if (!proto || !PyInt_Check(proto)) { | |
| 977 | + PyErr_SetString(PyExc_AttributeError, | |
| 978 | + "class must define a '_length_' attribute, " | |
| 979 | + "which must be a positive integer"); | |
| 980 | + return NULL; | |
| 981 | + } | |
| 982 | + length = PyInt_AS_LONG(proto); | |
| 983 | + | |
| 984 | + proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */ | |
| 985 | + if (!proto) { | |
| 986 | + PyErr_SetString(PyExc_AttributeError, | |
| 987 | + "class must define a '_type_' attribute"); | |
| 988 | + return NULL; | |
| 989 | + } | |
| 990 | + | |
| 991 | + stgdict = (StgDictObject *)PyObject_CallObject( | |
| 992 | + (PyObject *)&StgDict_Type, NULL); | |
| 993 | + if (!stgdict) | |
| 994 | + return NULL; | |
| 995 | + | |
| 996 | + itemdict = PyType_stgdict(proto); | |
| 997 | + if (!itemdict) { | |
| 998 | + PyErr_SetString(PyExc_TypeError, | |
| 999 | + "_type_ must have storage info"); | |
| 1000 | + Py_DECREF((PyObject *)stgdict); | |
| 1001 | + return NULL; | |
| 1002 | + } | |
| 1003 | + | |
| 1004 | + itemsize = itemdict->size; | |
| 1005 | + if (length * itemsize < 0) { | |
| 1006 | + PyErr_SetString(PyExc_OverflowError, | |
| 1007 | + "array too large"); | |
| 1008 | + return NULL; | |
| 1009 | + } | |
| 1010 | + | |
| 1011 | + itemalign = itemdict->align; | |
| 1012 | + | |
| 1013 | + stgdict->size = itemsize * length; | |
| 1014 | + stgdict->align = itemalign; | |
| 1015 | + stgdict->length = length; | |
| 1016 | + Py_INCREF(proto); | |
| 1017 | + stgdict->proto = proto; | |
| 1018 | + | |
| 1019 | + stgdict->paramfunc = &ArrayType_paramfunc; | |
| 1020 | + | |
| 1021 | + /* Arrays are passed as pointers to function calls. */ | |
| 1022 | + stgdict->ffi_type_pointer = ffi_type_pointer; | |
| 1023 | + | |
| 1024 | + /* create the new instance (which is a class, | |
| 1025 | + since we are a metatype!) */ | |
| 1026 | + result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); | |
| 1027 | + if (result == NULL) | |
| 1028 | + return NULL; | |
| 1029 | + | |
| 1030 | + /* replace the class dict by our updated spam dict */ | |
| 1031 | + if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { | |
| 1032 | + Py_DECREF(result); | |
| 1033 | + Py_DECREF((PyObject *)stgdict); | |
| 1034 | + return NULL; | |
| 1035 | + } | |
| 1036 | + Py_DECREF(result->tp_dict); | |
| 1037 | + result->tp_dict = (PyObject *)stgdict; | |
| 1038 | + | |
| 1039 | + /* Special case for character arrays. | |
| 1040 | + A permanent annoyance: char arrays are also strings! | |
| 1041 | + */ | |
| 1042 | + if (itemdict->getfunc == getentry("c")->getfunc) { | |
| 1043 | + if (-1 == add_getset(result, CharArray_getsets)) | |
| 1044 | + return NULL; | |
| 1045 | +#ifdef CTYPES_UNICODE | |
| 1046 | + } else if (itemdict->getfunc == getentry("u")->getfunc) { | |
| 1047 | + if (-1 == add_getset(result, WCharArray_getsets)) | |
| 1048 | + return NULL; | |
| 1049 | +#endif | |
| 1050 | + } | |
| 1051 | + | |
| 1052 | + return (PyObject *)result; | |
| 1053 | +} | |
| 1054 | + | |
| 1055 | +PyTypeObject ArrayType_Type = { | |
| 1056 | + PyObject_HEAD_INIT(NULL) | |
| 1057 | + 0, /* ob_size */ | |
| 1058 | + "_ctypes.ArrayType", /* tp_name */ | |
| 1059 | + 0, /* tp_basicsize */ | |
| 1060 | + 0, /* tp_itemsize */ | |
| 1061 | + 0, /* tp_dealloc */ | |
| 1062 | + 0, /* tp_print */ | |
| 1063 | + 0, /* tp_getattr */ | |
| 1064 | + 0, /* tp_setattr */ | |
| 1065 | + 0, /* tp_compare */ | |
| 1066 | + 0, /* tp_repr */ | |
| 1067 | + 0, /* tp_as_number */ | |
| 1068 | + &CDataType_as_sequence, /* tp_as_sequence */ | |
| 1069 | + 0, /* tp_as_mapping */ | |
| 1070 | + 0, /* tp_hash */ | |
| 1071 | + 0, /* tp_call */ | |
| 1072 | + 0, /* tp_str */ | |
| 1073 | + 0, /* tp_getattro */ | |
| 1074 | + 0, /* tp_setattro */ | |
| 1075 | + 0, /* tp_as_buffer */ | |
| 1076 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 1077 | + "metatype for the Array Objects", /* tp_doc */ | |
| 1078 | + 0, /* tp_traverse */ | |
| 1079 | + 0, /* tp_clear */ | |
| 1080 | + 0, /* tp_richcompare */ | |
| 1081 | + 0, /* tp_weaklistoffset */ | |
| 1082 | + 0, /* tp_iter */ | |
| 1083 | + 0, /* tp_iternext */ | |
| 1084 | + CDataType_methods, /* tp_methods */ | |
| 1085 | + 0, /* tp_members */ | |
| 1086 | + 0, /* tp_getset */ | |
| 1087 | + 0, /* tp_base */ | |
| 1088 | + 0, /* tp_dict */ | |
| 1089 | + 0, /* tp_descr_get */ | |
| 1090 | + 0, /* tp_descr_set */ | |
| 1091 | + 0, /* tp_dictoffset */ | |
| 1092 | + 0, /* tp_init */ | |
| 1093 | + 0, /* tp_alloc */ | |
| 1094 | + ArrayType_new, /* tp_new */ | |
| 1095 | + 0, /* tp_free */ | |
| 1096 | +}; | |
| 1097 | + | |
| 1098 | + | |
| 1099 | +/******************************************************************/ | |
| 1100 | +/* | |
| 1101 | + SimpleType_Type | |
| 1102 | +*/ | |
| 1103 | +/* | |
| 1104 | + | |
| 1105 | +SimpleType_new ensures that the new Simple_Type subclass created has a valid | |
| 1106 | +_type_ attribute. | |
| 1107 | + | |
| 1108 | +*/ | |
| 1109 | + | |
| 1110 | +static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv"; | |
| 1111 | + | |
| 1112 | +static PyObject * | |
| 1113 | +c_wchar_p_from_param(PyObject *type, PyObject *value) | |
| 1114 | +{ | |
| 1115 | + PyObject *as_parameter; | |
| 1116 | +#if (PYTHON_API_VERSION < 1012) | |
| 1117 | +# error not supported | |
| 1118 | +#endif | |
| 1119 | + if (value == Py_None) { | |
| 1120 | + Py_INCREF(Py_None); | |
| 1121 | + return Py_None; | |
| 1122 | + } | |
| 1123 | + if (PyUnicode_Check(value) || PyString_Check(value)) { | |
| 1124 | + PyCArgObject *parg; | |
| 1125 | + struct fielddesc *fd = getentry("Z"); | |
| 1126 | + | |
| 1127 | + parg = new_CArgObject(); | |
| 1128 | + if (parg == NULL) | |
| 1129 | + return NULL; | |
| 1130 | + parg->pffi_type = &ffi_type_pointer; | |
| 1131 | + parg->tag = 'Z'; | |
| 1132 | + parg->obj = fd->setfunc(&parg->value, value, 0); | |
| 1133 | + if (parg->obj == NULL) { | |
| 1134 | + Py_DECREF(parg); | |
| 1135 | + return NULL; | |
| 1136 | + } | |
| 1137 | + return (PyObject *)parg; | |
| 1138 | + } | |
| 1139 | + if (PyObject_IsInstance(value, type)) { | |
| 1140 | + Py_INCREF(value); | |
| 1141 | + return value; | |
| 1142 | + } | |
| 1143 | + if (ArrayObject_Check(value) || PointerObject_Check(value)) { | |
| 1144 | + /* c_wchar array instance or pointer(c_wchar(...)) */ | |
| 1145 | + StgDictObject *dt = PyObject_stgdict(value); | |
| 1146 | + StgDictObject *dict; | |
| 1147 | + assert(dt); /* Cannot be NULL for pointer or array objects */ | |
| 1148 | + dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL; | |
| 1149 | + if (dict && (dict->setfunc == getentry("u")->setfunc)) { | |
| 1150 | + Py_INCREF(value); | |
| 1151 | + return value; | |
| 1152 | + } | |
| 1153 | + } | |
| 1154 | + if (PyCArg_CheckExact(value)) { | |
| 1155 | + /* byref(c_char(...)) */ | |
| 1156 | + PyCArgObject *a = (PyCArgObject *)value; | |
| 1157 | + StgDictObject *dict = PyObject_stgdict(a->obj); | |
| 1158 | + if (dict && (dict->setfunc == getentry("u")->setfunc)) { | |
| 1159 | + Py_INCREF(value); | |
| 1160 | + return value; | |
| 1161 | + } | |
| 1162 | + } | |
| 1163 | + | |
| 1164 | + as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); | |
| 1165 | + if (as_parameter) { | |
| 1166 | + value = c_wchar_p_from_param(type, as_parameter); | |
| 1167 | + Py_DECREF(as_parameter); | |
| 1168 | + return value; | |
| 1169 | + } | |
| 1170 | + /* XXX better message */ | |
| 1171 | + PyErr_SetString(PyExc_TypeError, | |
| 1172 | + "wrong type"); | |
| 1173 | + return NULL; | |
| 1174 | +} | |
| 1175 | + | |
| 1176 | +static PyObject * | |
| 1177 | +c_char_p_from_param(PyObject *type, PyObject *value) | |
| 1178 | +{ | |
| 1179 | + PyObject *as_parameter; | |
| 1180 | +#if (PYTHON_API_VERSION < 1012) | |
| 1181 | +# error not supported | |
| 1182 | +#endif | |
| 1183 | + if (value == Py_None) { | |
| 1184 | + Py_INCREF(Py_None); | |
| 1185 | + return Py_None; | |
| 1186 | + } | |
| 1187 | + if (PyString_Check(value) || PyUnicode_Check(value)) { | |
| 1188 | + PyCArgObject *parg; | |
| 1189 | + struct fielddesc *fd = getentry("z"); | |
| 1190 | + | |
| 1191 | + parg = new_CArgObject(); | |
| 1192 | + if (parg == NULL) | |
| 1193 | + return NULL; | |
| 1194 | + parg->pffi_type = &ffi_type_pointer; | |
| 1195 | + parg->tag = 'z'; | |
| 1196 | + parg->obj = fd->setfunc(&parg->value, value, 0); | |
| 1197 | + if (parg->obj == NULL) { | |
| 1198 | + Py_DECREF(parg); | |
| 1199 | + return NULL; | |
| 1200 | + } | |
| 1201 | + return (PyObject *)parg; | |
| 1202 | + } | |
| 1203 | + if (PyObject_IsInstance(value, type)) { | |
| 1204 | + Py_INCREF(value); | |
| 1205 | + return value; | |
| 1206 | + } | |
| 1207 | + if (ArrayObject_Check(value) || PointerObject_Check(value)) { | |
| 1208 | + /* c_char array instance or pointer(c_char(...)) */ | |
| 1209 | + StgDictObject *dt = PyObject_stgdict(value); | |
| 1210 | + StgDictObject *dict; | |
| 1211 | + assert(dt); /* Cannot be NULL for pointer or array objects */ | |
| 1212 | + dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL; | |
| 1213 | + if (dict && (dict->setfunc == getentry("c")->setfunc)) { | |
| 1214 | + Py_INCREF(value); | |
| 1215 | + return value; | |
| 1216 | + } | |
| 1217 | + } | |
| 1218 | + if (PyCArg_CheckExact(value)) { | |
| 1219 | + /* byref(c_char(...)) */ | |
| 1220 | + PyCArgObject *a = (PyCArgObject *)value; | |
| 1221 | + StgDictObject *dict = PyObject_stgdict(a->obj); | |
| 1222 | + if (dict && (dict->setfunc == getentry("c")->setfunc)) { | |
| 1223 | + Py_INCREF(value); | |
| 1224 | + return value; | |
| 1225 | + } | |
| 1226 | + } | |
| 1227 | + | |
| 1228 | + as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); | |
| 1229 | + if (as_parameter) { | |
| 1230 | + value = c_char_p_from_param(type, as_parameter); | |
| 1231 | + Py_DECREF(as_parameter); | |
| 1232 | + return value; | |
| 1233 | + } | |
| 1234 | + /* XXX better message */ | |
| 1235 | + PyErr_SetString(PyExc_TypeError, | |
| 1236 | + "wrong type"); | |
| 1237 | + return NULL; | |
| 1238 | +} | |
| 1239 | + | |
| 1240 | +static PyObject * | |
| 1241 | +c_void_p_from_param(PyObject *type, PyObject *value) | |
| 1242 | +{ | |
| 1243 | + StgDictObject *stgd; | |
| 1244 | + PyObject *as_parameter; | |
| 1245 | +#if (PYTHON_API_VERSION < 1012) | |
| 1246 | +# error not supported | |
| 1247 | +#endif | |
| 1248 | + | |
| 1249 | +/* None */ | |
| 1250 | + if (value == Py_None) { | |
| 1251 | + Py_INCREF(Py_None); | |
| 1252 | + return Py_None; | |
| 1253 | + } | |
| 1254 | + /* Should probably allow buffer interface as well */ | |
| 1255 | +/* int, long */ | |
| 1256 | + if (PyInt_Check(value) || PyLong_Check(value)) { | |
| 1257 | + PyCArgObject *parg; | |
| 1258 | + struct fielddesc *fd = getentry("P"); | |
| 1259 | + | |
| 1260 | + parg = new_CArgObject(); | |
| 1261 | + if (parg == NULL) | |
| 1262 | + return NULL; | |
| 1263 | + parg->pffi_type = &ffi_type_pointer; | |
| 1264 | + parg->tag = 'P'; | |
| 1265 | + parg->obj = fd->setfunc(&parg->value, value, 0); | |
| 1266 | + if (parg->obj == NULL) { | |
| 1267 | + Py_DECREF(parg); | |
| 1268 | + return NULL; | |
| 1269 | + } | |
| 1270 | + return (PyObject *)parg; | |
| 1271 | + } | |
| 1272 | +/* string */ | |
| 1273 | + if (PyString_Check(value)) { | |
| 1274 | + PyCArgObject *parg; | |
| 1275 | + struct fielddesc *fd = getentry("z"); | |
| 1276 | + | |
| 1277 | + parg = new_CArgObject(); | |
| 1278 | + if (parg == NULL) | |
| 1279 | + return NULL; | |
| 1280 | + parg->pffi_type = &ffi_type_pointer; | |
| 1281 | + parg->tag = 'z'; | |
| 1282 | + parg->obj = fd->setfunc(&parg->value, value, 0); | |
| 1283 | + if (parg->obj == NULL) { | |
| 1284 | + Py_DECREF(parg); | |
| 1285 | + return NULL; | |
| 1286 | + } | |
| 1287 | + return (PyObject *)parg; | |
| 1288 | + } | |
| 1289 | +/* unicode */ | |
| 1290 | + if (PyUnicode_Check(value)) { | |
| 1291 | + PyCArgObject *parg; | |
| 1292 | + struct fielddesc *fd = getentry("Z"); | |
| 1293 | + | |
| 1294 | + parg = new_CArgObject(); | |
| 1295 | + if (parg == NULL) | |
| 1296 | + return NULL; | |
| 1297 | + parg->pffi_type = &ffi_type_pointer; | |
| 1298 | + parg->tag = 'Z'; | |
| 1299 | + parg->obj = fd->setfunc(&parg->value, value, 0); | |
| 1300 | + if (parg->obj == NULL) { | |
| 1301 | + Py_DECREF(parg); | |
| 1302 | + return NULL; | |
| 1303 | + } | |
| 1304 | + return (PyObject *)parg; | |
| 1305 | + } | |
| 1306 | +/* c_void_p instance (or subclass) */ | |
| 1307 | + if (PyObject_IsInstance(value, type)) { | |
| 1308 | + /* c_void_p instances */ | |
| 1309 | + Py_INCREF(value); | |
| 1310 | + return value; | |
| 1311 | + } | |
| 1312 | +/* ctypes array or pointer instance */ | |
| 1313 | + if (ArrayObject_Check(value) || PointerObject_Check(value)) { | |
| 1314 | + /* Any array or pointer is accepted */ | |
| 1315 | + Py_INCREF(value); | |
| 1316 | + return value; | |
| 1317 | + } | |
| 1318 | +/* byref(...) */ | |
| 1319 | + if (PyCArg_CheckExact(value)) { | |
| 1320 | + /* byref(c_xxx()) */ | |
| 1321 | + PyCArgObject *a = (PyCArgObject *)value; | |
| 1322 | + if (a->tag == 'P') { | |
| 1323 | + Py_INCREF(value); | |
| 1324 | + return value; | |
| 1325 | + } | |
| 1326 | + } | |
| 1327 | +/* function pointer */ | |
| 1328 | + if (CFuncPtrObject_Check(value)) { | |
| 1329 | + PyCArgObject *parg; | |
| 1330 | + CFuncPtrObject *func; | |
| 1331 | + func = (CFuncPtrObject *)value; | |
| 1332 | + parg = new_CArgObject(); | |
| 1333 | + if (parg == NULL) | |
| 1334 | + return NULL; | |
| 1335 | + parg->pffi_type = &ffi_type_pointer; | |
| 1336 | + parg->tag = 'P'; | |
| 1337 | + Py_INCREF(value); | |
| 1338 | + parg->value.p = *(void **)func->b_ptr; | |
| 1339 | + parg->obj = value; | |
| 1340 | + return (PyObject *)parg; | |
| 1341 | + } | |
| 1342 | +/* c_char_p, c_wchar_p */ | |
| 1343 | + stgd = PyObject_stgdict(value); | |
| 1344 | + if (stgd && CDataObject_Check(value) && stgd->proto && PyString_Check(stgd->proto)) { | |
| 1345 | + PyCArgObject *parg; | |
| 1346 | + | |
| 1347 | + switch (PyString_AS_STRING(stgd->proto)[0]) { | |
| 1348 | + case 'z': /* c_char_p */ | |
| 1349 | + case 'Z': /* c_wchar_p */ | |
| 1350 | + parg = new_CArgObject(); | |
| 1351 | + if (parg == NULL) | |
| 1352 | + return NULL; | |
| 1353 | + parg->pffi_type = &ffi_type_pointer; | |
| 1354 | + parg->tag = 'Z'; | |
| 1355 | + Py_INCREF(value); | |
| 1356 | + parg->obj = value; | |
| 1357 | + /* Remember: b_ptr points to where the pointer is stored! */ | |
| 1358 | + parg->value.p = *(void **)(((CDataObject *)value)->b_ptr); | |
| 1359 | + return (PyObject *)parg; | |
| 1360 | + } | |
| 1361 | + } | |
| 1362 | + | |
| 1363 | + as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); | |
| 1364 | + if (as_parameter) { | |
| 1365 | + value = c_void_p_from_param(type, as_parameter); | |
| 1366 | + Py_DECREF(as_parameter); | |
| 1367 | + return value; | |
| 1368 | + } | |
| 1369 | + /* XXX better message */ | |
| 1370 | + PyErr_SetString(PyExc_TypeError, | |
| 1371 | + "wrong type"); | |
| 1372 | + return NULL; | |
| 1373 | +} | |
| 1374 | +#if (PYTHON_API_VERSION >= 1012) | |
| 1375 | + | |
| 1376 | +static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_O }; | |
| 1377 | +static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_O }; | |
| 1378 | +static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_O }; | |
| 1379 | + | |
| 1380 | +#else | |
| 1381 | +#error | |
| 1382 | +static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_VARARGS }; | |
| 1383 | +static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_VARARGS }; | |
| 1384 | +static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_VARARGS }; | |
| 1385 | + | |
| 1386 | +#endif | |
| 1387 | + | |
| 1388 | +static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject *kwds, | |
| 1389 | + PyObject *proto, struct fielddesc *fmt) | |
| 1390 | +{ | |
| 1391 | + PyTypeObject *result; | |
| 1392 | + StgDictObject *stgdict; | |
| 1393 | + PyObject *name = PyTuple_GET_ITEM(args, 0); | |
| 1394 | + PyObject *swapped_args; | |
| 1395 | + static PyObject *suffix; | |
| 1396 | + Py_ssize_t i; | |
| 1397 | + | |
| 1398 | + swapped_args = PyTuple_New(PyTuple_GET_SIZE(args)); | |
| 1399 | + if (!swapped_args) | |
| 1400 | + return NULL; | |
| 1401 | + | |
| 1402 | + if (suffix == NULL) | |
| 1403 | +#ifdef WORDS_BIGENDIAN | |
| 1404 | + suffix = PyString_FromString("_le"); | |
| 1405 | +#else | |
| 1406 | + suffix = PyString_FromString("_be"); | |
| 1407 | +#endif | |
| 1408 | + | |
| 1409 | + Py_INCREF(name); | |
| 1410 | + PyString_Concat(&name, suffix); | |
| 1411 | + if (name == NULL) | |
| 1412 | + return NULL; | |
| 1413 | + | |
| 1414 | + PyTuple_SET_ITEM(swapped_args, 0, name); | |
| 1415 | + for (i=1; i<PyTuple_GET_SIZE(args); ++i) { | |
| 1416 | + PyObject *v = PyTuple_GET_ITEM(args, i); | |
| 1417 | + Py_INCREF(v); | |
| 1418 | + PyTuple_SET_ITEM(swapped_args, i, v); | |
| 1419 | + } | |
| 1420 | + | |
| 1421 | + /* create the new instance (which is a class, | |
| 1422 | + since we are a metatype!) */ | |
| 1423 | + result = (PyTypeObject *)PyType_Type.tp_new(type, swapped_args, kwds); | |
| 1424 | + Py_DECREF(swapped_args); | |
| 1425 | + if (result == NULL) | |
| 1426 | + return NULL; | |
| 1427 | + | |
| 1428 | + stgdict = (StgDictObject *)PyObject_CallObject( | |
| 1429 | + (PyObject *)&StgDict_Type, NULL); | |
| 1430 | + if (!stgdict) /* XXX leaks result! */ | |
| 1431 | + return NULL; | |
| 1432 | + | |
| 1433 | + stgdict->ffi_type_pointer = *fmt->pffi_type; | |
| 1434 | + stgdict->align = fmt->pffi_type->alignment; | |
| 1435 | + stgdict->length = 0; | |
| 1436 | + stgdict->size = fmt->pffi_type->size; | |
| 1437 | + stgdict->setfunc = fmt->setfunc_swapped; | |
| 1438 | + stgdict->getfunc = fmt->getfunc_swapped; | |
| 1439 | + | |
| 1440 | + Py_INCREF(proto); | |
| 1441 | + stgdict->proto = proto; | |
| 1442 | + | |
| 1443 | + /* replace the class dict by our updated spam dict */ | |
| 1444 | + if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { | |
| 1445 | + Py_DECREF(result); | |
| 1446 | + Py_DECREF((PyObject *)stgdict); | |
| 1447 | + return NULL; | |
| 1448 | + } | |
| 1449 | + Py_DECREF(result->tp_dict); | |
| 1450 | + result->tp_dict = (PyObject *)stgdict; | |
| 1451 | + | |
| 1452 | + return (PyObject *)result; | |
| 1453 | +} | |
| 1454 | + | |
| 1455 | +static PyCArgObject * | |
| 1456 | +SimpleType_paramfunc(CDataObject *self) | |
| 1457 | +{ | |
| 1458 | + StgDictObject *dict; | |
| 1459 | + char *fmt; | |
| 1460 | + PyCArgObject *parg; | |
| 1461 | + struct fielddesc *fd; | |
| 1462 | + | |
| 1463 | + dict = PyObject_stgdict((PyObject *)self); | |
| 1464 | + assert(dict); /* Cannot be NULL for CDataObject instances */ | |
| 1465 | + fmt = PyString_AsString(dict->proto); | |
| 1466 | + assert(fmt); | |
| 1467 | + | |
| 1468 | + fd = getentry(fmt); | |
| 1469 | + assert(fd); | |
| 1470 | + | |
| 1471 | + parg = new_CArgObject(); | |
| 1472 | + if (parg == NULL) | |
| 1473 | + return NULL; | |
| 1474 | + | |
| 1475 | + parg->tag = fmt[0]; | |
| 1476 | + parg->pffi_type = fd->pffi_type; | |
| 1477 | + Py_INCREF(self); | |
| 1478 | + parg->obj = (PyObject *)self; | |
| 1479 | + memcpy(&parg->value, self->b_ptr, self->b_size); | |
| 1480 | + return parg; | |
| 1481 | +} | |
| 1482 | + | |
| 1483 | +static PyObject * | |
| 1484 | +SimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 1485 | +{ | |
| 1486 | + PyTypeObject *result; | |
| 1487 | + StgDictObject *stgdict; | |
| 1488 | + PyObject *proto; | |
| 1489 | + PyMethodDef *ml; | |
| 1490 | + struct fielddesc *fmt; | |
| 1491 | + | |
| 1492 | + /* create the new instance (which is a class, | |
| 1493 | + since we are a metatype!) */ | |
| 1494 | + result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); | |
| 1495 | + if (result == NULL) | |
| 1496 | + return NULL; | |
| 1497 | + | |
| 1498 | + proto = PyObject_GetAttrString((PyObject *)result, "_type_"); /* new ref */ | |
| 1499 | + if (!proto | |
| 1500 | + || !PyString_Check(proto) | |
| 1501 | + || 1 != strlen(PyString_AS_STRING(proto)) | |
| 1502 | + || !strchr(SIMPLE_TYPE_CHARS, PyString_AS_STRING(proto)[0])) { | |
| 1503 | + PyErr_Format(PyExc_AttributeError, | |
| 1504 | + "class must define a '_type_' attribute which must be\n" | |
| 1505 | + "a single character string containing one of '%s'.", | |
| 1506 | + SIMPLE_TYPE_CHARS); | |
| 1507 | + Py_XDECREF(proto); | |
| 1508 | + Py_DECREF(result); | |
| 1509 | + return NULL; | |
| 1510 | + } | |
| 1511 | + fmt = getentry(PyString_AS_STRING(proto)); | |
| 1512 | + if (fmt == NULL) { | |
| 1513 | + Py_DECREF(result); | |
| 1514 | + PyErr_Format(PyExc_ValueError, | |
| 1515 | + "_type_ '%s' not supported", | |
| 1516 | + PyString_AS_STRING(proto)); | |
| 1517 | + return NULL; | |
| 1518 | + } | |
| 1519 | + | |
| 1520 | + stgdict = (StgDictObject *)PyObject_CallObject( | |
| 1521 | + (PyObject *)&StgDict_Type, NULL); | |
| 1522 | + if (!stgdict) | |
| 1523 | + return NULL; | |
| 1524 | + | |
| 1525 | + stgdict->ffi_type_pointer = *fmt->pffi_type; | |
| 1526 | + stgdict->align = fmt->pffi_type->alignment; | |
| 1527 | + stgdict->length = 0; | |
| 1528 | + stgdict->size = fmt->pffi_type->size; | |
| 1529 | + stgdict->setfunc = fmt->setfunc; | |
| 1530 | + stgdict->getfunc = fmt->getfunc; | |
| 1531 | + | |
| 1532 | + stgdict->paramfunc = SimpleType_paramfunc; | |
| 1533 | +/* | |
| 1534 | + if (result->tp_base != &Simple_Type) { | |
| 1535 | + stgdict->setfunc = NULL; | |
| 1536 | + stgdict->getfunc = NULL; | |
| 1537 | + } | |
| 1538 | +*/ | |
| 1539 | + | |
| 1540 | + /* This consumes the refcount on proto which we have */ | |
| 1541 | + stgdict->proto = proto; | |
| 1542 | + | |
| 1543 | + /* replace the class dict by our updated spam dict */ | |
| 1544 | + if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { | |
| 1545 | + Py_DECREF(result); | |
| 1546 | + Py_DECREF((PyObject *)stgdict); | |
| 1547 | + return NULL; | |
| 1548 | + } | |
| 1549 | + Py_DECREF(result->tp_dict); | |
| 1550 | + result->tp_dict = (PyObject *)stgdict; | |
| 1551 | + | |
| 1552 | + /* Install from_param class methods in ctypes base classes. | |
| 1553 | + Overrides the SimpleType_from_param generic method. | |
| 1554 | + */ | |
| 1555 | + if (result->tp_base == &Simple_Type) { | |
| 1556 | + switch (PyString_AS_STRING(proto)[0]) { | |
| 1557 | + case 'z': /* c_char_p */ | |
| 1558 | + ml = &c_char_p_method; | |
| 1559 | + break; | |
| 1560 | + case 'Z': /* c_wchar_p */ | |
| 1561 | + ml = &c_wchar_p_method; | |
| 1562 | + break; | |
| 1563 | + case 'P': /* c_void_p */ | |
| 1564 | + ml = &c_void_p_method; | |
| 1565 | + break; | |
| 1566 | + default: | |
| 1567 | + ml = NULL; | |
| 1568 | + break; | |
| 1569 | + } | |
| 1570 | + | |
| 1571 | + if (ml) { | |
| 1572 | +#if (PYTHON_API_VERSION >= 1012) | |
| 1573 | + PyObject *meth; | |
| 1574 | + int x; | |
| 1575 | + meth = PyDescr_NewClassMethod(result, ml); | |
| 1576 | + if (!meth) | |
| 1577 | + return NULL; | |
| 1578 | +#else | |
| 1579 | +#error | |
| 1580 | + PyObject *meth, *func; | |
| 1581 | + int x; | |
| 1582 | + func = PyCFunction_New(ml, NULL); | |
| 1583 | + if (!func) | |
| 1584 | + return NULL; | |
| 1585 | + meth = PyObject_CallFunctionObjArgs( | |
| 1586 | + (PyObject *)&PyClassMethod_Type, | |
| 1587 | + func, NULL); | |
| 1588 | + Py_DECREF(func); | |
| 1589 | + if (!meth) { | |
| 1590 | + return NULL; | |
| 1591 | + } | |
| 1592 | +#endif | |
| 1593 | + x = PyDict_SetItemString(result->tp_dict, | |
| 1594 | + ml->ml_name, | |
| 1595 | + meth); | |
| 1596 | + Py_DECREF(meth); | |
| 1597 | + if (x == -1) { | |
| 1598 | + Py_DECREF(result); | |
| 1599 | + return NULL; | |
| 1600 | + } | |
| 1601 | + } | |
| 1602 | + } | |
| 1603 | + | |
| 1604 | + if (type == &SimpleType_Type && fmt->setfunc_swapped && fmt->getfunc_swapped) { | |
| 1605 | + PyObject *swapped = CreateSwappedType(type, args, kwds, | |
| 1606 | + proto, fmt); | |
| 1607 | + if (swapped == NULL) { | |
| 1608 | + Py_DECREF(result); | |
| 1609 | + return NULL; | |
| 1610 | + } | |
| 1611 | +#ifdef WORDS_BIGENDIAN | |
| 1612 | + PyObject_SetAttrString((PyObject *)result, "__ctype_le__", swapped); | |
| 1613 | + PyObject_SetAttrString((PyObject *)result, "__ctype_be__", (PyObject *)result); | |
| 1614 | + PyObject_SetAttrString(swapped, "__ctype_be__", (PyObject *)result); | |
| 1615 | + PyObject_SetAttrString(swapped, "__ctype_le__", swapped); | |
| 1616 | +#else | |
| 1617 | + PyObject_SetAttrString((PyObject *)result, "__ctype_be__", swapped); | |
| 1618 | + PyObject_SetAttrString((PyObject *)result, "__ctype_le__", (PyObject *)result); | |
| 1619 | + PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result); | |
| 1620 | + PyObject_SetAttrString(swapped, "__ctype_be__", swapped); | |
| 1621 | +#endif | |
| 1622 | + Py_DECREF(swapped); | |
| 1623 | + }; | |
| 1624 | + | |
| 1625 | + return (PyObject *)result; | |
| 1626 | +} | |
| 1627 | + | |
| 1628 | +/* | |
| 1629 | + * This is a *class method*. | |
| 1630 | + * Convert a parameter into something that ConvParam can handle. | |
| 1631 | + */ | |
| 1632 | +static PyObject * | |
| 1633 | +SimpleType_from_param(PyObject *type, PyObject *value) | |
| 1634 | +{ | |
| 1635 | + StgDictObject *dict; | |
| 1636 | + char *fmt; | |
| 1637 | + PyCArgObject *parg; | |
| 1638 | + struct fielddesc *fd; | |
| 1639 | + PyObject *as_parameter; | |
| 1640 | + | |
| 1641 | + /* If the value is already an instance of the requested type, | |
| 1642 | + we can use it as is */ | |
| 1643 | + if (1 == PyObject_IsInstance(value, type)) { | |
| 1644 | + Py_INCREF(value); | |
| 1645 | + return value; | |
| 1646 | + } | |
| 1647 | + | |
| 1648 | + dict = PyType_stgdict(type); | |
| 1649 | + assert(dict); | |
| 1650 | + | |
| 1651 | + /* I think we can rely on this being a one-character string */ | |
| 1652 | + fmt = PyString_AsString(dict->proto); | |
| 1653 | + assert(fmt); | |
| 1654 | + | |
| 1655 | + fd = getentry(fmt); | |
| 1656 | + assert(fd); | |
| 1657 | + | |
| 1658 | + parg = new_CArgObject(); | |
| 1659 | + if (parg == NULL) | |
| 1660 | + return NULL; | |
| 1661 | + | |
| 1662 | + parg->tag = fmt[0]; | |
| 1663 | + parg->pffi_type = fd->pffi_type; | |
| 1664 | + parg->obj = fd->setfunc(&parg->value, value, 0); | |
| 1665 | + if (parg->obj) | |
| 1666 | + return (PyObject *)parg; | |
| 1667 | + PyErr_Clear(); | |
| 1668 | + Py_DECREF(parg); | |
| 1669 | + | |
| 1670 | + as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); | |
| 1671 | + if (as_parameter) { | |
| 1672 | + value = SimpleType_from_param(type, as_parameter); | |
| 1673 | + Py_DECREF(as_parameter); | |
| 1674 | + return value; | |
| 1675 | + } | |
| 1676 | + PyErr_SetString(PyExc_TypeError, | |
| 1677 | + "wrong type"); | |
| 1678 | + return NULL; | |
| 1679 | +} | |
| 1680 | + | |
| 1681 | +static PyMethodDef SimpleType_methods[] = { | |
| 1682 | + { "from_param", SimpleType_from_param, METH_O, from_param_doc }, | |
| 1683 | + { "from_address", CDataType_from_address, METH_O, from_address_doc }, | |
| 1684 | + { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, | |
| 1685 | + { NULL, NULL }, | |
| 1686 | +}; | |
| 1687 | + | |
| 1688 | +PyTypeObject SimpleType_Type = { | |
| 1689 | + PyObject_HEAD_INIT(NULL) | |
| 1690 | + 0, /* ob_size */ | |
| 1691 | + "_ctypes.SimpleType", /* tp_name */ | |
| 1692 | + 0, /* tp_basicsize */ | |
| 1693 | + 0, /* tp_itemsize */ | |
| 1694 | + 0, /* tp_dealloc */ | |
| 1695 | + 0, /* tp_print */ | |
| 1696 | + 0, /* tp_getattr */ | |
| 1697 | + 0, /* tp_setattr */ | |
| 1698 | + 0, /* tp_compare */ | |
| 1699 | + 0, /* tp_repr */ | |
| 1700 | + 0, /* tp_as_number */ | |
| 1701 | + &CDataType_as_sequence, /* tp_as_sequence */ | |
| 1702 | + 0, /* tp_as_mapping */ | |
| 1703 | + 0, /* tp_hash */ | |
| 1704 | + 0, /* tp_call */ | |
| 1705 | + 0, /* tp_str */ | |
| 1706 | + 0, /* tp_getattro */ | |
| 1707 | + 0, /* tp_setattro */ | |
| 1708 | + 0, /* tp_as_buffer */ | |
| 1709 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 1710 | + "metatype for the SimpleType Objects", /* tp_doc */ | |
| 1711 | + 0, /* tp_traverse */ | |
| 1712 | + 0, /* tp_clear */ | |
| 1713 | + 0, /* tp_richcompare */ | |
| 1714 | + 0, /* tp_weaklistoffset */ | |
| 1715 | + 0, /* tp_iter */ | |
| 1716 | + 0, /* tp_iternext */ | |
| 1717 | + SimpleType_methods, /* tp_methods */ | |
| 1718 | + 0, /* tp_members */ | |
| 1719 | + 0, /* tp_getset */ | |
| 1720 | + 0, /* tp_base */ | |
| 1721 | + 0, /* tp_dict */ | |
| 1722 | + 0, /* tp_descr_get */ | |
| 1723 | + 0, /* tp_descr_set */ | |
| 1724 | + 0, /* tp_dictoffset */ | |
| 1725 | + 0, /* tp_init */ | |
| 1726 | + 0, /* tp_alloc */ | |
| 1727 | + SimpleType_new, /* tp_new */ | |
| 1728 | + 0, /* tp_free */ | |
| 1729 | +}; | |
| 1730 | + | |
| 1731 | +/******************************************************************/ | |
| 1732 | +/* | |
| 1733 | + CFuncPtrType_Type | |
| 1734 | + */ | |
| 1735 | + | |
| 1736 | +static PyObject * | |
| 1737 | +converters_from_argtypes(PyObject *ob) | |
| 1738 | +{ | |
| 1739 | + PyObject *converters; | |
| 1740 | + int i; | |
| 1741 | + int nArgs; | |
| 1742 | + | |
| 1743 | + ob = PySequence_Tuple(ob); /* new reference */ | |
| 1744 | + if (!ob) { | |
| 1745 | + PyErr_SetString(PyExc_TypeError, | |
| 1746 | + "_argtypes_ must be a sequence of types"); | |
| 1747 | + return NULL; | |
| 1748 | + } | |
| 1749 | + | |
| 1750 | + nArgs = PyTuple_GET_SIZE(ob); | |
| 1751 | + converters = PyTuple_New(nArgs); | |
| 1752 | + if (!converters) | |
| 1753 | + return NULL; | |
| 1754 | + | |
| 1755 | + /* I have to check if this is correct. Using c_char, which has a size | |
| 1756 | + of 1, will be assumed to be pushed as only one byte! | |
| 1757 | + Aren't these promoted to integers by the C compiler and pushed as 4 bytes? | |
| 1758 | + */ | |
| 1759 | + | |
| 1760 | + for (i = 0; i < nArgs; ++i) { | |
| 1761 | + PyObject *tp = PyTuple_GET_ITEM(ob, i); | |
| 1762 | + PyObject *cnv = PyObject_GetAttrString(tp, "from_param"); | |
| 1763 | + if (!cnv) | |
| 1764 | + goto argtypes_error_1; | |
| 1765 | + PyTuple_SET_ITEM(converters, i, cnv); | |
| 1766 | + } | |
| 1767 | + Py_DECREF(ob); | |
| 1768 | + return converters; | |
| 1769 | + | |
| 1770 | + argtypes_error_1: | |
| 1771 | + Py_XDECREF(converters); | |
| 1772 | + Py_DECREF(ob); | |
| 1773 | + PyErr_Format(PyExc_TypeError, | |
| 1774 | + "item %d in _argtypes_ has no from_param method", i+1); | |
| 1775 | + return NULL; | |
| 1776 | +} | |
| 1777 | + | |
| 1778 | +static int | |
| 1779 | +make_funcptrtype_dict(StgDictObject *stgdict) | |
| 1780 | +{ | |
| 1781 | + PyObject *ob; | |
| 1782 | + PyObject *converters = NULL; | |
| 1783 | + | |
| 1784 | + stgdict->align = getentry("P")->pffi_type->alignment; | |
| 1785 | + stgdict->length = 1; | |
| 1786 | + stgdict->size = sizeof(void *); | |
| 1787 | + stgdict->setfunc = NULL; | |
| 1788 | + stgdict->getfunc = NULL; | |
| 1789 | + stgdict->ffi_type_pointer = ffi_type_pointer; | |
| 1790 | + | |
| 1791 | + ob = PyDict_GetItemString((PyObject *)stgdict, "_flags_"); | |
| 1792 | + if (!ob || !PyInt_Check(ob)) { | |
| 1793 | + PyErr_SetString(PyExc_TypeError, | |
| 1794 | + "class must define _flags_ which must be an integer"); | |
| 1795 | + return -1; | |
| 1796 | + } | |
| 1797 | + stgdict->flags = PyInt_AS_LONG(ob); | |
| 1798 | + | |
| 1799 | + /* _argtypes_ is optional... */ | |
| 1800 | + ob = PyDict_GetItemString((PyObject *)stgdict, "_argtypes_"); | |
| 1801 | + if (ob) { | |
| 1802 | + converters = converters_from_argtypes(ob); | |
| 1803 | + if (!converters) | |
| 1804 | + goto error; | |
| 1805 | + Py_INCREF(ob); | |
| 1806 | + stgdict->argtypes = ob; | |
| 1807 | + stgdict->converters = converters; | |
| 1808 | + } | |
| 1809 | + | |
| 1810 | + ob = PyDict_GetItemString((PyObject *)stgdict, "_restype_"); | |
| 1811 | + if (ob) { | |
| 1812 | + if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { | |
| 1813 | + PyErr_SetString(PyExc_TypeError, | |
| 1814 | + "_restype_ must be a type, a callable, or None"); | |
| 1815 | + return -1; | |
| 1816 | + } | |
| 1817 | + Py_INCREF(ob); | |
| 1818 | + stgdict->restype = ob; | |
| 1819 | + stgdict->checker = PyObject_GetAttrString(ob, "_check_retval_"); | |
| 1820 | + if (stgdict->checker == NULL) | |
| 1821 | + PyErr_Clear(); | |
| 1822 | + } | |
| 1823 | +/* XXX later, maybe. | |
| 1824 | + ob = PyDict_GetItemString((PyObject *)stgdict, "_errcheck_"); | |
| 1825 | + if (ob) { | |
| 1826 | + if (!PyCallable_Check(ob)) { | |
| 1827 | + PyErr_SetString(PyExc_TypeError, | |
| 1828 | + "_errcheck_ must be callable"); | |
| 1829 | + return -1; | |
| 1830 | + } | |
| 1831 | + Py_INCREF(ob); | |
| 1832 | + stgdict->errcheck = ob; | |
| 1833 | + } | |
| 1834 | +*/ | |
| 1835 | + return 0; | |
| 1836 | + | |
| 1837 | + error: | |
| 1838 | + Py_XDECREF(converters); | |
| 1839 | + return -1; | |
| 1840 | + | |
| 1841 | +} | |
| 1842 | + | |
| 1843 | +static PyCArgObject * | |
| 1844 | +CFuncPtrType_paramfunc(CDataObject *self) | |
| 1845 | +{ | |
| 1846 | + PyCArgObject *parg; | |
| 1847 | + | |
| 1848 | + parg = new_CArgObject(); | |
| 1849 | + if (parg == NULL) | |
| 1850 | + return NULL; | |
| 1851 | + | |
| 1852 | + parg->tag = 'P'; | |
| 1853 | + parg->pffi_type = &ffi_type_pointer; | |
| 1854 | + Py_INCREF(self); | |
| 1855 | + parg->obj = (PyObject *)self; | |
| 1856 | + parg->value.p = *(void **)self->b_ptr; | |
| 1857 | + return parg; | |
| 1858 | +} | |
| 1859 | + | |
| 1860 | +static PyObject * | |
| 1861 | +CFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 1862 | +{ | |
| 1863 | + PyTypeObject *result; | |
| 1864 | + StgDictObject *stgdict; | |
| 1865 | + | |
| 1866 | + stgdict = (StgDictObject *)PyObject_CallObject( | |
| 1867 | + (PyObject *)&StgDict_Type, NULL); | |
| 1868 | + if (!stgdict) | |
| 1869 | + return NULL; | |
| 1870 | + | |
| 1871 | + stgdict->paramfunc = CFuncPtrType_paramfunc; | |
| 1872 | + | |
| 1873 | + /* create the new instance (which is a class, | |
| 1874 | + since we are a metatype!) */ | |
| 1875 | + result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); | |
| 1876 | + if (result == NULL) { | |
| 1877 | + Py_DECREF((PyObject *)stgdict); | |
| 1878 | + return NULL; | |
| 1879 | + } | |
| 1880 | + | |
| 1881 | + /* replace the class dict by our updated storage dict */ | |
| 1882 | + if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) { | |
| 1883 | + Py_DECREF(result); | |
| 1884 | + Py_DECREF((PyObject *)stgdict); | |
| 1885 | + return NULL; | |
| 1886 | + } | |
| 1887 | + Py_DECREF(result->tp_dict); | |
| 1888 | + result->tp_dict = (PyObject *)stgdict; | |
| 1889 | + | |
| 1890 | + if (-1 == make_funcptrtype_dict(stgdict)) { | |
| 1891 | + Py_DECREF(result); | |
| 1892 | + return NULL; | |
| 1893 | + } | |
| 1894 | + | |
| 1895 | + return (PyObject *)result; | |
| 1896 | +} | |
| 1897 | + | |
| 1898 | +PyTypeObject CFuncPtrType_Type = { | |
| 1899 | + PyObject_HEAD_INIT(NULL) | |
| 1900 | + 0, /* ob_size */ | |
| 1901 | + "_ctypes.CFuncPtrType", /* tp_name */ | |
| 1902 | + 0, /* tp_basicsize */ | |
| 1903 | + 0, /* tp_itemsize */ | |
| 1904 | + 0, /* tp_dealloc */ | |
| 1905 | + 0, /* tp_print */ | |
| 1906 | + 0, /* tp_getattr */ | |
| 1907 | + 0, /* tp_setattr */ | |
| 1908 | + 0, /* tp_compare */ | |
| 1909 | + 0, /* tp_repr */ | |
| 1910 | + 0, /* tp_as_number */ | |
| 1911 | + &CDataType_as_sequence, /* tp_as_sequence */ | |
| 1912 | + 0, /* tp_as_mapping */ | |
| 1913 | + 0, /* tp_hash */ | |
| 1914 | + 0, /* tp_call */ | |
| 1915 | + 0, /* tp_str */ | |
| 1916 | + 0, /* tp_getattro */ | |
| 1917 | + 0, /* tp_setattro */ | |
| 1918 | + 0, /* tp_as_buffer */ | |
| 1919 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ | |
| 1920 | + "metatype for C function pointers", /* tp_doc */ | |
| 1921 | + (traverseproc)CDataType_traverse, /* tp_traverse */ | |
| 1922 | + (inquiry)CDataType_clear, /* tp_clear */ | |
| 1923 | + 0, /* tp_richcompare */ | |
| 1924 | + 0, /* tp_weaklistoffset */ | |
| 1925 | + 0, /* tp_iter */ | |
| 1926 | + 0, /* tp_iternext */ | |
| 1927 | + CDataType_methods, /* tp_methods */ | |
| 1928 | + 0, /* tp_members */ | |
| 1929 | + 0, /* tp_getset */ | |
| 1930 | + 0, /* tp_base */ | |
| 1931 | + 0, /* tp_dict */ | |
| 1932 | + 0, /* tp_descr_get */ | |
| 1933 | + 0, /* tp_descr_set */ | |
| 1934 | + 0, /* tp_dictoffset */ | |
| 1935 | + 0, /* tp_init */ | |
| 1936 | + 0, /* tp_alloc */ | |
| 1937 | + CFuncPtrType_new, /* tp_new */ | |
| 1938 | + 0, /* tp_free */ | |
| 1939 | +}; | |
| 1940 | + | |
| 1941 | + | |
| 1942 | +/***************************************************************** | |
| 1943 | + * Code to keep needed objects alive | |
| 1944 | + */ | |
| 1945 | + | |
| 1946 | +static CDataObject * | |
| 1947 | +CData_GetContainer(CDataObject *self) | |
| 1948 | +{ | |
| 1949 | + while (self->b_base) | |
| 1950 | + self = self->b_base; | |
| 1951 | + if (self->b_objects == NULL) { | |
| 1952 | + if (self->b_length) { | |
| 1953 | + self->b_objects = PyDict_New(); | |
| 1954 | + } else { | |
| 1955 | + Py_INCREF(Py_None); | |
| 1956 | + self->b_objects = Py_None; | |
| 1957 | + } | |
| 1958 | + } | |
| 1959 | + return self; | |
| 1960 | +} | |
| 1961 | + | |
| 1962 | +static PyObject * | |
| 1963 | +GetKeepedObjects(CDataObject *target) | |
| 1964 | +{ | |
| 1965 | + return CData_GetContainer(target)->b_objects; | |
| 1966 | +} | |
| 1967 | + | |
| 1968 | +static PyObject * | |
| 1969 | +unique_key(CDataObject *target, Py_ssize_t index) | |
| 1970 | +{ | |
| 1971 | + char string[256]; | |
| 1972 | + char *cp = string; | |
| 1973 | + size_t bytes_left; | |
| 1974 | + | |
| 1975 | + assert(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2); | |
| 1976 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 1977 | + cp += sprintf(cp, "%x", index); | |
| 1978 | +#else | |
| 1979 | + cp += sprintf(cp, "%x", Py_SAFE_DOWNCAST(index, Py_ssize_t, int)); | |
| 1980 | +#endif | |
| 1981 | + while (target->b_base) { | |
| 1982 | + bytes_left = sizeof(string) - (cp - string) - 1; | |
| 1983 | + /* Hex format needs 2 characters per byte */ | |
| 1984 | + if (bytes_left < sizeof(Py_ssize_t) * 2) { | |
| 1985 | + PyErr_SetString(PyExc_ValueError, | |
| 1986 | + "ctypes object structure too deep"); | |
| 1987 | + return NULL; | |
| 1988 | + } | |
| 1989 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 1990 | + cp += sprintf(cp, ":%x", (int)target->b_index); | |
| 1991 | +#else | |
| 1992 | + cp += sprintf(cp, ":%x", Py_SAFE_DOWNCAST(target->b_index, Py_ssize_t, int)); | |
| 1993 | +#endif | |
| 1994 | + target = target->b_base; | |
| 1995 | + } | |
| 1996 | + return PyString_FromStringAndSize(string, cp-string); | |
| 1997 | +} | |
| 1998 | + | |
| 1999 | +/* | |
| 2000 | + * Keep a reference to 'keep' in the 'target', at index 'index'. | |
| 2001 | + * | |
| 2002 | + * If 'keep' is None, do nothing. | |
| 2003 | + * | |
| 2004 | + * Otherwise create a dictionary (if it does not yet exist) id the root | |
| 2005 | + * objects 'b_objects' item, which will store the 'keep' object under a unique | |
| 2006 | + * key. | |
| 2007 | + * | |
| 2008 | + * The unique_key helper travels the target's b_base pointer down to the root, | |
| 2009 | + * building a string containing hex-formatted indexes found during traversal, | |
| 2010 | + * separated by colons. | |
| 2011 | + * | |
| 2012 | + * The index tuple is used as a key into the root object's b_objects dict. | |
| 2013 | + * | |
| 2014 | + * Note: This function steals a refcount of the third argument, even if it | |
| 2015 | + * fails! | |
| 2016 | + */ | |
| 2017 | +static int | |
| 2018 | +KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep) | |
| 2019 | +{ | |
| 2020 | + int result; | |
| 2021 | + CDataObject *ob; | |
| 2022 | + PyObject *key; | |
| 2023 | + | |
| 2024 | +/* Optimization: no need to store None */ | |
| 2025 | + if (keep == Py_None) { | |
| 2026 | + Py_DECREF(Py_None); | |
| 2027 | + return 0; | |
| 2028 | + } | |
| 2029 | + ob = CData_GetContainer(target); | |
| 2030 | + if (ob->b_objects == NULL || !PyDict_Check(ob->b_objects)) { | |
| 2031 | + Py_XDECREF(ob->b_objects); | |
| 2032 | + ob->b_objects = keep; /* refcount consumed */ | |
| 2033 | + return 0; | |
| 2034 | + } | |
| 2035 | + key = unique_key(target, index); | |
| 2036 | + if (key == NULL) { | |
| 2037 | + Py_DECREF(keep); | |
| 2038 | + return -1; | |
| 2039 | + } | |
| 2040 | + result = PyDict_SetItem(ob->b_objects, key, keep); | |
| 2041 | + Py_DECREF(key); | |
| 2042 | + Py_DECREF(keep); | |
| 2043 | + return result; | |
| 2044 | +} | |
| 2045 | + | |
| 2046 | +/******************************************************************/ | |
| 2047 | +/* | |
| 2048 | + CData_Type | |
| 2049 | + */ | |
| 2050 | +static int | |
| 2051 | +CData_traverse(CDataObject *self, visitproc visit, void *arg) | |
| 2052 | +{ | |
| 2053 | + Py_VISIT(self->b_objects); | |
| 2054 | + Py_VISIT((PyObject *)self->b_base); | |
| 2055 | + return 0; | |
| 2056 | +} | |
| 2057 | + | |
| 2058 | +static int | |
| 2059 | +CData_clear(CDataObject *self) | |
| 2060 | +{ | |
| 2061 | + StgDictObject *dict = PyObject_stgdict((PyObject *)self); | |
| 2062 | + assert(dict); /* Cannot be NULL for CDataObject instances */ | |
| 2063 | + Py_CLEAR(self->b_objects); | |
| 2064 | + if ((self->b_needsfree) | |
| 2065 | + && ((size_t)dict->size > sizeof(self->b_value))) | |
| 2066 | + PyMem_Free(self->b_ptr); | |
| 2067 | + self->b_ptr = NULL; | |
| 2068 | + Py_CLEAR(self->b_base); | |
| 2069 | + return 0; | |
| 2070 | +} | |
| 2071 | + | |
| 2072 | +static void | |
| 2073 | +CData_dealloc(PyObject *self) | |
| 2074 | +{ | |
| 2075 | + CData_clear((CDataObject *)self); | |
| 2076 | + self->ob_type->tp_free(self); | |
| 2077 | +} | |
| 2078 | + | |
| 2079 | +static PyMemberDef CData_members[] = { | |
| 2080 | + { "_b_base_", T_OBJECT, | |
| 2081 | + offsetof(CDataObject, b_base), READONLY, | |
| 2082 | + "the base object" }, | |
| 2083 | + { "_b_needsfree_", T_INT, | |
| 2084 | + offsetof(CDataObject, b_needsfree), READONLY, | |
| 2085 | + "whether the object owns the memory or not" }, | |
| 2086 | + { "_objects", T_OBJECT, | |
| 2087 | + offsetof(CDataObject, b_objects), READONLY, | |
| 2088 | + "internal objects tree (NEVER CHANGE THIS OBJECT!)"}, | |
| 2089 | + { NULL }, | |
| 2090 | +}; | |
| 2091 | + | |
| 2092 | +static Py_ssize_t CData_GetBuffer(PyObject *_self, Py_ssize_t seg, void **pptr) | |
| 2093 | +{ | |
| 2094 | + CDataObject *self = (CDataObject *)_self; | |
| 2095 | + if (seg != 0) { | |
| 2096 | + /* Hm. Must this set an exception? */ | |
| 2097 | + return -1; | |
| 2098 | + } | |
| 2099 | + *pptr = self->b_ptr; | |
| 2100 | + return self->b_size; | |
| 2101 | +} | |
| 2102 | + | |
| 2103 | +static Py_ssize_t CData_GetSegcount(PyObject *_self, Py_ssize_t *lenp) | |
| 2104 | +{ | |
| 2105 | + if (lenp) | |
| 2106 | + *lenp = 1; | |
| 2107 | + return 1; | |
| 2108 | +} | |
| 2109 | + | |
| 2110 | +static PyBufferProcs CData_as_buffer = { | |
| 2111 | + CData_GetBuffer, | |
| 2112 | + CData_GetBuffer, | |
| 2113 | + CData_GetSegcount, | |
| 2114 | + NULL, | |
| 2115 | +}; | |
| 2116 | + | |
| 2117 | +/* | |
| 2118 | + * CData objects are mutable, so they cannot be hashable! | |
| 2119 | + */ | |
| 2120 | +static long | |
| 2121 | +CData_nohash(PyObject *self) | |
| 2122 | +{ | |
| 2123 | + PyErr_SetString(PyExc_TypeError, "unhashable type"); | |
| 2124 | + return -1; | |
| 2125 | +} | |
| 2126 | + | |
| 2127 | +/* | |
| 2128 | + * default __ctypes_from_outparam__ method returns self. | |
| 2129 | + */ | |
| 2130 | +static PyObject * | |
| 2131 | +CData_from_outparam(PyObject *self, PyObject *args) | |
| 2132 | +{ | |
| 2133 | + Py_INCREF(self); | |
| 2134 | + return self; | |
| 2135 | +} | |
| 2136 | + | |
| 2137 | +static PyMethodDef CData_methods[] = { | |
| 2138 | + { "__ctypes_from_outparam__", CData_from_outparam, METH_NOARGS, }, | |
| 2139 | + { NULL, NULL }, | |
| 2140 | +}; | |
| 2141 | + | |
| 2142 | +PyTypeObject CData_Type = { | |
| 2143 | + PyObject_HEAD_INIT(NULL) | |
| 2144 | + 0, | |
| 2145 | + "_ctypes._CData", | |
| 2146 | + sizeof(CDataObject), /* tp_basicsize */ | |
| 2147 | + 0, /* tp_itemsize */ | |
| 2148 | + CData_dealloc, /* tp_dealloc */ | |
| 2149 | + 0, /* tp_print */ | |
| 2150 | + 0, /* tp_getattr */ | |
| 2151 | + 0, /* tp_setattr */ | |
| 2152 | + 0, /* tp_compare */ | |
| 2153 | + 0, /* tp_repr */ | |
| 2154 | + 0, /* tp_as_number */ | |
| 2155 | + 0, /* tp_as_sequence */ | |
| 2156 | + 0, /* tp_as_mapping */ | |
| 2157 | + CData_nohash, /* tp_hash */ | |
| 2158 | + 0, /* tp_call */ | |
| 2159 | + 0, /* tp_str */ | |
| 2160 | + 0, /* tp_getattro */ | |
| 2161 | + 0, /* tp_setattro */ | |
| 2162 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 2163 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 2164 | + "XXX to be provided", /* tp_doc */ | |
| 2165 | + (traverseproc)CData_traverse, /* tp_traverse */ | |
| 2166 | + (inquiry)CData_clear, /* tp_clear */ | |
| 2167 | + 0, /* tp_richcompare */ | |
| 2168 | + 0, /* tp_weaklistoffset */ | |
| 2169 | + 0, /* tp_iter */ | |
| 2170 | + 0, /* tp_iternext */ | |
| 2171 | + CData_methods, /* tp_methods */ | |
| 2172 | + CData_members, /* tp_members */ | |
| 2173 | + 0, /* tp_getset */ | |
| 2174 | + 0, /* tp_base */ | |
| 2175 | + 0, /* tp_dict */ | |
| 2176 | + 0, /* tp_descr_get */ | |
| 2177 | + 0, /* tp_descr_set */ | |
| 2178 | + 0, /* tp_dictoffset */ | |
| 2179 | + 0, /* tp_init */ | |
| 2180 | + 0, /* tp_alloc */ | |
| 2181 | + 0, /* tp_new */ | |
| 2182 | + 0, /* tp_free */ | |
| 2183 | +}; | |
| 2184 | + | |
| 2185 | +static int CData_MallocBuffer(CDataObject *obj, StgDictObject *dict) | |
| 2186 | +{ | |
| 2187 | + if ((size_t)dict->size <= sizeof(obj->b_value)) { | |
| 2188 | + /* No need to call malloc, can use the default buffer */ | |
| 2189 | + obj->b_ptr = (char *)&obj->b_value; | |
| 2190 | + /* The b_needsfree flag does not mean that we actually did | |
| 2191 | + call PyMem_Malloc to allocate the memory block; instead it | |
| 2192 | + means we are the *owner* of the memory and are responsible | |
| 2193 | + for freeing resources associated with the memory. This is | |
| 2194 | + also the reason that b_needsfree is exposed to Python. | |
| 2195 | + */ | |
| 2196 | + obj->b_needsfree = 1; | |
| 2197 | + } else { | |
| 2198 | + /* In python 2.4, and ctypes 0.9.6, the malloc call took about | |
| 2199 | + 33% of the creation time for c_int(). | |
| 2200 | + */ | |
| 2201 | + obj->b_ptr = (char *)PyMem_Malloc(dict->size); | |
| 2202 | + if (obj->b_ptr == NULL) { | |
| 2203 | + PyErr_NoMemory(); | |
| 2204 | + return -1; | |
| 2205 | + } | |
| 2206 | + obj->b_needsfree = 1; | |
| 2207 | + memset(obj->b_ptr, 0, dict->size); | |
| 2208 | + } | |
| 2209 | + obj->b_size = dict->size; | |
| 2210 | + return 0; | |
| 2211 | +} | |
| 2212 | + | |
| 2213 | +PyObject * | |
| 2214 | +CData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr) | |
| 2215 | +{ | |
| 2216 | + CDataObject *cmem; | |
| 2217 | + StgDictObject *dict; | |
| 2218 | + | |
| 2219 | + assert(PyType_Check(type)); | |
| 2220 | + dict = PyType_stgdict(type); | |
| 2221 | + if (!dict) { | |
| 2222 | + PyErr_SetString(PyExc_TypeError, | |
| 2223 | + "abstract class"); | |
| 2224 | + return NULL; | |
| 2225 | + } | |
| 2226 | + dict->flags |= DICTFLAG_FINAL; | |
| 2227 | + cmem = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0); | |
| 2228 | + if (cmem == NULL) | |
| 2229 | + return NULL; | |
| 2230 | + assert(CDataObject_Check(cmem)); | |
| 2231 | + | |
| 2232 | + cmem->b_length = dict->length; | |
| 2233 | + cmem->b_size = dict->size; | |
| 2234 | + if (base) { /* use base's buffer */ | |
| 2235 | + assert(CDataObject_Check(base)); | |
| 2236 | + cmem->b_ptr = adr; | |
| 2237 | + cmem->b_needsfree = 0; | |
| 2238 | + Py_INCREF(base); | |
| 2239 | + cmem->b_base = (CDataObject *)base; | |
| 2240 | + cmem->b_index = index; | |
| 2241 | + } else { /* copy contents of adr */ | |
| 2242 | + if (-1 == CData_MallocBuffer(cmem, dict)) { | |
| 2243 | + return NULL; | |
| 2244 | + Py_DECREF(cmem); | |
| 2245 | + } | |
| 2246 | + memcpy(cmem->b_ptr, adr, dict->size); | |
| 2247 | + cmem->b_index = index; | |
| 2248 | + } | |
| 2249 | + return (PyObject *)cmem; | |
| 2250 | +} | |
| 2251 | + | |
| 2252 | +/* | |
| 2253 | + Box a memory block into a CData instance. | |
| 2254 | +*/ | |
| 2255 | +PyObject * | |
| 2256 | +CData_AtAddress(PyObject *type, void *buf) | |
| 2257 | +{ | |
| 2258 | + CDataObject *pd; | |
| 2259 | + StgDictObject *dict; | |
| 2260 | + | |
| 2261 | + assert(PyType_Check(type)); | |
| 2262 | + dict = PyType_stgdict(type); | |
| 2263 | + if (!dict) { | |
| 2264 | + PyErr_SetString(PyExc_TypeError, | |
| 2265 | + "abstract class"); | |
| 2266 | + return NULL; | |
| 2267 | + } | |
| 2268 | + dict->flags |= DICTFLAG_FINAL; | |
| 2269 | + | |
| 2270 | + pd = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0); | |
| 2271 | + if (!pd) | |
| 2272 | + return NULL; | |
| 2273 | + assert(CDataObject_Check(pd)); | |
| 2274 | + pd->b_ptr = (char *)buf; | |
| 2275 | + pd->b_length = dict->length; | |
| 2276 | + pd->b_size = dict->size; | |
| 2277 | + return (PyObject *)pd; | |
| 2278 | +} | |
| 2279 | + | |
| 2280 | +/* | |
| 2281 | + This function returns TRUE for c_int, c_void_p, and these kind of | |
| 2282 | + classes. FALSE otherwise FALSE also for subclasses of c_int and | |
| 2283 | + such. | |
| 2284 | +*/ | |
| 2285 | +int IsSimpleSubType(PyObject *obj) | |
| 2286 | +{ | |
| 2287 | + PyTypeObject *type = (PyTypeObject *)obj; | |
| 2288 | + | |
| 2289 | + if (SimpleTypeObject_Check(type)) | |
| 2290 | + return type->tp_base != &Simple_Type; | |
| 2291 | + return 0; | |
| 2292 | +} | |
| 2293 | + | |
| 2294 | +PyObject * | |
| 2295 | +CData_get(PyObject *type, GETFUNC getfunc, PyObject *src, | |
| 2296 | + Py_ssize_t index, Py_ssize_t size, char *adr) | |
| 2297 | +{ | |
| 2298 | + StgDictObject *dict; | |
| 2299 | + if (getfunc) | |
| 2300 | + return getfunc(adr, size); | |
| 2301 | + assert(type); | |
| 2302 | + dict = PyType_stgdict(type); | |
| 2303 | + if (dict && dict->getfunc && !IsSimpleSubType(type)) | |
| 2304 | + return dict->getfunc(adr, size); | |
| 2305 | + return CData_FromBaseObj(type, src, index, adr); | |
| 2306 | +} | |
| 2307 | + | |
| 2308 | +/* | |
| 2309 | + Helper function for CData_set below. | |
| 2310 | +*/ | |
| 2311 | +static PyObject * | |
| 2312 | +_CData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, | |
| 2313 | + Py_ssize_t size, char *ptr) | |
| 2314 | +{ | |
| 2315 | + CDataObject *src; | |
| 2316 | + | |
| 2317 | + if (setfunc) | |
| 2318 | + return setfunc(ptr, value, size); | |
| 2319 | + | |
| 2320 | + if (!CDataObject_Check(value)) { | |
| 2321 | + StgDictObject *dict = PyType_stgdict(type); | |
| 2322 | + if (dict && dict->setfunc) | |
| 2323 | + return dict->setfunc(ptr, value, size); | |
| 2324 | + /* | |
| 2325 | + If value is a tuple, we try to call the type with the tuple | |
| 2326 | + and use the result! | |
| 2327 | + */ | |
| 2328 | + assert(PyType_Check(type)); | |
| 2329 | + if (PyTuple_Check(value)) { | |
| 2330 | + PyObject *ob; | |
| 2331 | + PyObject *result; | |
| 2332 | + ob = PyObject_CallObject(type, value); | |
| 2333 | + if (ob == NULL) { | |
| 2334 | + Extend_Error_Info(PyExc_RuntimeError, "(%s) ", | |
| 2335 | + ((PyTypeObject *)type)->tp_name); | |
| 2336 | + return NULL; | |
| 2337 | + } | |
| 2338 | + result = _CData_set(dst, type, setfunc, ob, | |
| 2339 | + size, ptr); | |
| 2340 | + Py_DECREF(ob); | |
| 2341 | + return result; | |
| 2342 | + } else if (value == Py_None && PointerTypeObject_Check(type)) { | |
| 2343 | + *(void **)ptr = NULL; | |
| 2344 | + Py_INCREF(Py_None); | |
| 2345 | + return Py_None; | |
| 2346 | + } else { | |
| 2347 | + PyErr_Format(PyExc_TypeError, | |
| 2348 | + "expected %s instance, got %s", | |
| 2349 | + ((PyTypeObject *)type)->tp_name, | |
| 2350 | + value->ob_type->tp_name); | |
| 2351 | + return NULL; | |
| 2352 | + } | |
| 2353 | + } | |
| 2354 | + src = (CDataObject *)value; | |
| 2355 | + | |
| 2356 | + if (PyObject_IsInstance(value, type)) { | |
| 2357 | + memcpy(ptr, | |
| 2358 | + src->b_ptr, | |
| 2359 | + size); | |
| 2360 | + | |
| 2361 | + if (PointerTypeObject_Check(type)) | |
| 2362 | + /* XXX */; | |
| 2363 | + | |
| 2364 | + value = GetKeepedObjects(src); | |
| 2365 | + Py_INCREF(value); | |
| 2366 | + return value; | |
| 2367 | + } | |
| 2368 | + | |
| 2369 | + if (PointerTypeObject_Check(type) | |
| 2370 | + && ArrayObject_Check(value)) { | |
| 2371 | + StgDictObject *p1, *p2; | |
| 2372 | + PyObject *keep; | |
| 2373 | + p1 = PyObject_stgdict(value); | |
| 2374 | + assert(p1); /* Cannot be NULL for array instances */ | |
| 2375 | + p2 = PyType_stgdict(type); | |
| 2376 | + assert(p2); /* Cannot be NULL for pointer types */ | |
| 2377 | + | |
| 2378 | + if (p1->proto != p2->proto) { | |
| 2379 | + PyErr_Format(PyExc_TypeError, | |
| 2380 | + "incompatible types, %s instance instead of %s instance", | |
| 2381 | + value->ob_type->tp_name, | |
| 2382 | + ((PyTypeObject *)type)->tp_name); | |
| 2383 | + return NULL; | |
| 2384 | + } | |
| 2385 | + *(void **)ptr = src->b_ptr; | |
| 2386 | + | |
| 2387 | + keep = GetKeepedObjects(src); | |
| 2388 | + /* | |
| 2389 | + We are assigning an array object to a field which represents | |
| 2390 | + a pointer. This has the same effect as converting an array | |
| 2391 | + into a pointer. So, again, we have to keep the whole object | |
| 2392 | + pointed to (which is the array in this case) alive, and not | |
| 2393 | + only it's object list. So we create a tuple, containing | |
| 2394 | + b_objects list PLUS the array itself, and return that! | |
| 2395 | + */ | |
| 2396 | + return Py_BuildValue("(OO)", keep, value); | |
| 2397 | + } | |
| 2398 | + PyErr_Format(PyExc_TypeError, | |
| 2399 | + "incompatible types, %s instance instead of %s instance", | |
| 2400 | + value->ob_type->tp_name, | |
| 2401 | + ((PyTypeObject *)type)->tp_name); | |
| 2402 | + return NULL; | |
| 2403 | +} | |
| 2404 | + | |
| 2405 | +/* | |
| 2406 | + * Set a slice in object 'dst', which has the type 'type', | |
| 2407 | + * to the value 'value'. | |
| 2408 | + */ | |
| 2409 | +int | |
| 2410 | +CData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, | |
| 2411 | + Py_ssize_t index, Py_ssize_t size, char *ptr) | |
| 2412 | +{ | |
| 2413 | + CDataObject *mem = (CDataObject *)dst; | |
| 2414 | + PyObject *result; | |
| 2415 | + | |
| 2416 | + if (!CDataObject_Check(dst)) { | |
| 2417 | + PyErr_SetString(PyExc_TypeError, | |
| 2418 | + "not a ctype instance"); | |
| 2419 | + return -1; | |
| 2420 | + } | |
| 2421 | + | |
| 2422 | + result = _CData_set(mem, type, setfunc, value, | |
| 2423 | + size, ptr); | |
| 2424 | + if (result == NULL) | |
| 2425 | + return -1; | |
| 2426 | + | |
| 2427 | + /* KeepRef steals a refcount from it's last argument */ | |
| 2428 | + /* If KeepRef fails, we are stumped. The dst memory block has already | |
| 2429 | + been changed */ | |
| 2430 | + return KeepRef(mem, index, result); | |
| 2431 | +} | |
| 2432 | + | |
| 2433 | + | |
| 2434 | +/******************************************************************/ | |
| 2435 | +static PyObject * | |
| 2436 | +GenericCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 2437 | +{ | |
| 2438 | + CDataObject *obj; | |
| 2439 | + StgDictObject *dict; | |
| 2440 | + | |
| 2441 | + dict = PyType_stgdict((PyObject *)type); | |
| 2442 | + if (!dict) { | |
| 2443 | + PyErr_SetString(PyExc_TypeError, | |
| 2444 | + "abstract class"); | |
| 2445 | + return NULL; | |
| 2446 | + } | |
| 2447 | + dict->flags |= DICTFLAG_FINAL; | |
| 2448 | + | |
| 2449 | + obj = (CDataObject *)type->tp_alloc(type, 0); | |
| 2450 | + if (!obj) | |
| 2451 | + return NULL; | |
| 2452 | + | |
| 2453 | + obj->b_base = NULL; | |
| 2454 | + obj->b_index = 0; | |
| 2455 | + obj->b_objects = NULL; | |
| 2456 | + obj->b_length = dict->length; | |
| 2457 | + | |
| 2458 | + if (-1 == CData_MallocBuffer(obj, dict)) { | |
| 2459 | + Py_DECREF(obj); | |
| 2460 | + return NULL; | |
| 2461 | + } | |
| 2462 | + return (PyObject *)obj; | |
| 2463 | +} | |
| 2464 | +/*****************************************************************/ | |
| 2465 | +/* | |
| 2466 | + CFuncPtr_Type | |
| 2467 | +*/ | |
| 2468 | + | |
| 2469 | +static int | |
| 2470 | +CFuncPtr_set_errcheck(CFuncPtrObject *self, PyObject *ob) | |
| 2471 | +{ | |
| 2472 | + if (ob && !PyCallable_Check(ob)) { | |
| 2473 | + PyErr_SetString(PyExc_TypeError, | |
| 2474 | + "the errcheck attribute must be callable"); | |
| 2475 | + return -1; | |
| 2476 | + } | |
| 2477 | + Py_XDECREF(self->errcheck); | |
| 2478 | + Py_XINCREF(ob); | |
| 2479 | + self->errcheck = ob; | |
| 2480 | + return 0; | |
| 2481 | +} | |
| 2482 | + | |
| 2483 | +static PyObject * | |
| 2484 | +CFuncPtr_get_errcheck(CFuncPtrObject *self) | |
| 2485 | +{ | |
| 2486 | + if (self->errcheck) { | |
| 2487 | + Py_INCREF(self->errcheck); | |
| 2488 | + return self->errcheck; | |
| 2489 | + } | |
| 2490 | + Py_INCREF(Py_None); | |
| 2491 | + return Py_None; | |
| 2492 | +} | |
| 2493 | + | |
| 2494 | +static int | |
| 2495 | +CFuncPtr_set_restype(CFuncPtrObject *self, PyObject *ob) | |
| 2496 | +{ | |
| 2497 | + if (ob == NULL) { | |
| 2498 | + Py_XDECREF(self->restype); | |
| 2499 | + self->restype = NULL; | |
| 2500 | + Py_XDECREF(self->checker); | |
| 2501 | + self->checker = NULL; | |
| 2502 | + return 0; | |
| 2503 | + } | |
| 2504 | + if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { | |
| 2505 | + PyErr_SetString(PyExc_TypeError, | |
| 2506 | + "restype must be a type, a callable, or None"); | |
| 2507 | + return -1; | |
| 2508 | + } | |
| 2509 | + Py_XDECREF(self->checker); | |
| 2510 | + Py_XDECREF(self->restype); | |
| 2511 | + Py_INCREF(ob); | |
| 2512 | + self->restype = ob; | |
| 2513 | + self->checker = PyObject_GetAttrString(ob, "_check_retval_"); | |
| 2514 | + if (self->checker == NULL) | |
| 2515 | + PyErr_Clear(); | |
| 2516 | + return 0; | |
| 2517 | +} | |
| 2518 | + | |
| 2519 | +static PyObject * | |
| 2520 | +CFuncPtr_get_restype(CFuncPtrObject *self) | |
| 2521 | +{ | |
| 2522 | + StgDictObject *dict; | |
| 2523 | + if (self->restype) { | |
| 2524 | + Py_INCREF(self->restype); | |
| 2525 | + return self->restype; | |
| 2526 | + } | |
| 2527 | + dict = PyObject_stgdict((PyObject *)self); | |
| 2528 | + assert(dict); /* Cannot be NULL for CFuncPtrObject instances */ | |
| 2529 | + if (dict->restype) { | |
| 2530 | + Py_INCREF(dict->restype); | |
| 2531 | + return dict->restype; | |
| 2532 | + } else { | |
| 2533 | + Py_INCREF(Py_None); | |
| 2534 | + return Py_None; | |
| 2535 | + } | |
| 2536 | +} | |
| 2537 | + | |
| 2538 | +static int | |
| 2539 | +CFuncPtr_set_argtypes(CFuncPtrObject *self, PyObject *ob) | |
| 2540 | +{ | |
| 2541 | + PyObject *converters; | |
| 2542 | + | |
| 2543 | + if (ob == NULL || ob == Py_None) { | |
| 2544 | + Py_XDECREF(self->converters); | |
| 2545 | + self->converters = NULL; | |
| 2546 | + Py_XDECREF(self->argtypes); | |
| 2547 | + self->argtypes = NULL; | |
| 2548 | + } else { | |
| 2549 | + converters = converters_from_argtypes(ob); | |
| 2550 | + if (!converters) | |
| 2551 | + return -1; | |
| 2552 | + Py_XDECREF(self->converters); | |
| 2553 | + self->converters = converters; | |
| 2554 | + Py_XDECREF(self->argtypes); | |
| 2555 | + Py_INCREF(ob); | |
| 2556 | + self->argtypes = ob; | |
| 2557 | + } | |
| 2558 | + return 0; | |
| 2559 | +} | |
| 2560 | + | |
| 2561 | +static PyObject * | |
| 2562 | +CFuncPtr_get_argtypes(CFuncPtrObject *self) | |
| 2563 | +{ | |
| 2564 | + StgDictObject *dict; | |
| 2565 | + if (self->argtypes) { | |
| 2566 | + Py_INCREF(self->argtypes); | |
| 2567 | + return self->argtypes; | |
| 2568 | + } | |
| 2569 | + dict = PyObject_stgdict((PyObject *)self); | |
| 2570 | + assert(dict); /* Cannot be NULL for CFuncPtrObject instances */ | |
| 2571 | + if (dict->argtypes) { | |
| 2572 | + Py_INCREF(dict->argtypes); | |
| 2573 | + return dict->argtypes; | |
| 2574 | + } else { | |
| 2575 | + Py_INCREF(Py_None); | |
| 2576 | + return Py_None; | |
| 2577 | + } | |
| 2578 | +} | |
| 2579 | + | |
| 2580 | +static PyGetSetDef CFuncPtr_getsets[] = { | |
| 2581 | + { "errcheck", (getter)CFuncPtr_get_errcheck, (setter)CFuncPtr_set_errcheck, | |
| 2582 | + "a function to check for errors", NULL }, | |
| 2583 | + { "restype", (getter)CFuncPtr_get_restype, (setter)CFuncPtr_set_restype, | |
| 2584 | + "specify the result type", NULL }, | |
| 2585 | + { "argtypes", (getter)CFuncPtr_get_argtypes, | |
| 2586 | + (setter)CFuncPtr_set_argtypes, | |
| 2587 | + "specify the argument types", NULL }, | |
| 2588 | + { NULL, NULL } | |
| 2589 | +}; | |
| 2590 | + | |
| 2591 | +#ifdef MS_WIN32 | |
| 2592 | +static PPROC FindAddress(void *handle, char *name, PyObject *type) | |
| 2593 | +{ | |
| 2594 | + PPROC address; | |
| 2595 | + char *mangled_name; | |
| 2596 | + int i; | |
| 2597 | + StgDictObject *dict = PyType_stgdict((PyObject *)type); | |
| 2598 | + | |
| 2599 | + address = (PPROC)GetProcAddress(handle, name); | |
| 2600 | + if (address) | |
| 2601 | + return address; | |
| 2602 | + | |
| 2603 | + if (((size_t)name & ~0xFFFF) == 0) { | |
| 2604 | + return NULL; | |
| 2605 | + } | |
| 2606 | + | |
| 2607 | + /* It should not happen that dict is NULL, but better be safe */ | |
| 2608 | + if (dict==NULL || dict->flags & FUNCFLAG_CDECL) | |
| 2609 | + return address; | |
| 2610 | + | |
| 2611 | + /* for stdcall, try mangled names: | |
| 2612 | + funcname -> _funcname@<n> | |
| 2613 | + where n is 0, 4, 8, 12, ..., 128 | |
| 2614 | + */ | |
| 2615 | + mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */ | |
| 2616 | + if (!mangled_name) | |
| 2617 | + return NULL; | |
| 2618 | + for (i = 0; i < 32; ++i) { | |
| 2619 | + sprintf(mangled_name, "_%s@%d", name, i*4); | |
| 2620 | + address = (PPROC)GetProcAddress(handle, mangled_name); | |
| 2621 | + if (address) | |
| 2622 | + return address; | |
| 2623 | + } | |
| 2624 | + return NULL; | |
| 2625 | +} | |
| 2626 | +#endif | |
| 2627 | + | |
| 2628 | +/* Return 1 if usable, 0 else and exception set. */ | |
| 2629 | +static int | |
| 2630 | +_check_outarg_type(PyObject *arg, int index) | |
| 2631 | +{ | |
| 2632 | + StgDictObject *dict; | |
| 2633 | + | |
| 2634 | + if (PointerTypeObject_Check(arg)) | |
| 2635 | + return 1; | |
| 2636 | + | |
| 2637 | + if (ArrayTypeObject_Check(arg)) | |
| 2638 | + return 1; | |
| 2639 | + | |
| 2640 | + dict = PyType_stgdict(arg); | |
| 2641 | + if (dict | |
| 2642 | + /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ | |
| 2643 | + && PyString_Check(dict->proto) | |
| 2644 | +/* We only allow c_void_p, c_char_p and c_wchar_p as a simple output parameter type */ | |
| 2645 | + && (strchr("PzZ", PyString_AS_STRING(dict->proto)[0]))) { | |
| 2646 | + return 1; | |
| 2647 | + } | |
| 2648 | + | |
| 2649 | + PyErr_Format(PyExc_TypeError, | |
| 2650 | + "'out' parameter %d must be a pointer type, not %s", | |
| 2651 | + index, | |
| 2652 | + PyType_Check(arg) ? | |
| 2653 | + ((PyTypeObject *)arg)->tp_name : | |
| 2654 | + arg->ob_type->tp_name); | |
| 2655 | + return 0; | |
| 2656 | +} | |
| 2657 | + | |
| 2658 | +/* Returns 1 on success, 0 on error */ | |
| 2659 | +static int | |
| 2660 | +_validate_paramflags(PyTypeObject *type, PyObject *paramflags) | |
| 2661 | +{ | |
| 2662 | + int i, len; | |
| 2663 | + StgDictObject *dict; | |
| 2664 | + PyObject *argtypes; | |
| 2665 | + | |
| 2666 | + dict = PyType_stgdict((PyObject *)type); | |
| 2667 | + assert(dict); /* Cannot be NULL. 'type' is a CFuncPtr type. */ | |
| 2668 | + argtypes = dict->argtypes; | |
| 2669 | + | |
| 2670 | + if (paramflags == NULL || dict->argtypes == NULL) | |
| 2671 | + return 1; | |
| 2672 | + | |
| 2673 | + if (!PyTuple_Check(paramflags)) { | |
| 2674 | + PyErr_SetString(PyExc_TypeError, | |
| 2675 | + "paramflags must be a tuple or None"); | |
| 2676 | + return 0; | |
| 2677 | + } | |
| 2678 | + | |
| 2679 | + len = PyTuple_GET_SIZE(paramflags); | |
| 2680 | + if (len != PyTuple_GET_SIZE(dict->argtypes)) { | |
| 2681 | + PyErr_SetString(PyExc_ValueError, | |
| 2682 | + "paramflags must have the same length as argtypes"); | |
| 2683 | + return 0; | |
| 2684 | + } | |
| 2685 | + | |
| 2686 | + for (i = 0; i < len; ++i) { | |
| 2687 | + PyObject *item = PyTuple_GET_ITEM(paramflags, i); | |
| 2688 | + int flag; | |
| 2689 | + char *name; | |
| 2690 | + PyObject *defval; | |
| 2691 | + PyObject *typ; | |
| 2692 | + if (!PyArg_ParseTuple(item, "i|zO", &flag, &name, &defval)) { | |
| 2693 | + PyErr_SetString(PyExc_TypeError, | |
| 2694 | + "paramflags must be a sequence of (int [,string [,value]]) tuples"); | |
| 2695 | + return 0; | |
| 2696 | + } | |
| 2697 | + typ = PyTuple_GET_ITEM(argtypes, i); | |
| 2698 | + switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) { | |
| 2699 | + case 0: | |
| 2700 | + case PARAMFLAG_FIN: | |
| 2701 | + case PARAMFLAG_FIN | PARAMFLAG_FLCID: | |
| 2702 | + case PARAMFLAG_FIN | PARAMFLAG_FOUT: | |
| 2703 | + break; | |
| 2704 | + case PARAMFLAG_FOUT: | |
| 2705 | + if (!_check_outarg_type(typ, i+1)) | |
| 2706 | + return 0; | |
| 2707 | + break; | |
| 2708 | + default: | |
| 2709 | + PyErr_Format(PyExc_TypeError, | |
| 2710 | + "paramflag value %d not supported", | |
| 2711 | + flag); | |
| 2712 | + return 0; | |
| 2713 | + } | |
| 2714 | + } | |
| 2715 | + return 1; | |
| 2716 | +} | |
| 2717 | + | |
| 2718 | +static int | |
| 2719 | +_get_name(PyObject *obj, char **pname) | |
| 2720 | +{ | |
| 2721 | +#ifdef MS_WIN32 | |
| 2722 | + if (PyInt_Check(obj) || PyLong_Check(obj)) { | |
| 2723 | + /* We have to use MAKEINTRESOURCEA for Windows CE. | |
| 2724 | + Works on Windows as well, of course. | |
| 2725 | + */ | |
| 2726 | + *pname = MAKEINTRESOURCEA(PyInt_AsUnsignedLongMask(obj) & 0xFFFF); | |
| 2727 | + return 1; | |
| 2728 | + } | |
| 2729 | +#endif | |
| 2730 | + if (PyString_Check(obj) || PyUnicode_Check(obj)) { | |
| 2731 | + *pname = PyString_AsString(obj); | |
| 2732 | + return *pname ? 1 : 0; | |
| 2733 | + } | |
| 2734 | + PyErr_SetString(PyExc_TypeError, | |
| 2735 | + "function name must be string or integer"); | |
| 2736 | + return 0; | |
| 2737 | +} | |
| 2738 | + | |
| 2739 | + | |
| 2740 | +static PyObject * | |
| 2741 | +CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 2742 | +{ | |
| 2743 | + char *name; | |
| 2744 | + int (* address)(void); | |
| 2745 | + PyObject *dll; | |
| 2746 | + PyObject *obj; | |
| 2747 | + CFuncPtrObject *self; | |
| 2748 | + void *handle; | |
| 2749 | + PyObject *paramflags = NULL; | |
| 2750 | + | |
| 2751 | + if (!PyArg_ParseTuple(args, "(O&O)|O", _get_name, &name, &dll, ¶mflags)) | |
| 2752 | + return NULL; | |
| 2753 | + if (paramflags == Py_None) | |
| 2754 | + paramflags = NULL; | |
| 2755 | + | |
| 2756 | + obj = PyObject_GetAttrString(dll, "_handle"); | |
| 2757 | + if (!obj) | |
| 2758 | + return NULL; | |
| 2759 | + if (!PyInt_Check(obj) && !PyLong_Check(obj)) { | |
| 2760 | + PyErr_SetString(PyExc_TypeError, | |
| 2761 | + "the _handle attribute of the second argument must be an integer"); | |
| 2762 | + Py_DECREF(obj); | |
| 2763 | + return NULL; | |
| 2764 | + } | |
| 2765 | + handle = (void *)PyLong_AsVoidPtr(obj); | |
| 2766 | + Py_DECREF(obj); | |
| 2767 | + if (PyErr_Occurred()) { | |
| 2768 | + PyErr_SetString(PyExc_ValueError, | |
| 2769 | + "could not convert the _handle attribute to a pointer"); | |
| 2770 | + return NULL; | |
| 2771 | + } | |
| 2772 | + | |
| 2773 | +#ifdef MS_WIN32 | |
| 2774 | + address = FindAddress(handle, name, (PyObject *)type); | |
| 2775 | + if (!address) { | |
| 2776 | + if (!IS_INTRESOURCE(name)) | |
| 2777 | + PyErr_Format(PyExc_AttributeError, | |
| 2778 | + "function '%s' not found", | |
| 2779 | + name); | |
| 2780 | + else | |
| 2781 | + PyErr_Format(PyExc_AttributeError, | |
| 2782 | + "function ordinal %d not found", | |
| 2783 | + (WORD)(size_t)name); | |
| 2784 | + return NULL; | |
| 2785 | + } | |
| 2786 | +#else | |
| 2787 | + address = (PPROC)ctypes_dlsym(handle, name); | |
| 2788 | + if (!address) { | |
| 2789 | + PyErr_Format(PyExc_AttributeError, | |
| 2790 | +#ifdef __CYGWIN__ | |
| 2791 | +/* dlerror() isn't very helpful on cygwin */ | |
| 2792 | + "function '%s' not found (%s) ", | |
| 2793 | + name, | |
| 2794 | +#endif | |
| 2795 | + ctypes_dlerror()); | |
| 2796 | + return NULL; | |
| 2797 | + } | |
| 2798 | +#endif | |
| 2799 | + if (!_validate_paramflags(type, paramflags)) | |
| 2800 | + return NULL; | |
| 2801 | + | |
| 2802 | + self = (CFuncPtrObject *)GenericCData_new(type, args, kwds); | |
| 2803 | + if (!self) | |
| 2804 | + return NULL; | |
| 2805 | + | |
| 2806 | + Py_XINCREF(paramflags); | |
| 2807 | + self->paramflags = paramflags; | |
| 2808 | + | |
| 2809 | + *(void **)self->b_ptr = address; | |
| 2810 | + | |
| 2811 | + Py_INCREF((PyObject *)dll); /* for KeepRef */ | |
| 2812 | + if (-1 == KeepRef((CDataObject *)self, 0, dll)) { | |
| 2813 | + Py_DECREF((PyObject *)self); | |
| 2814 | + return NULL; | |
| 2815 | + } | |
| 2816 | + | |
| 2817 | + Py_INCREF(self); | |
| 2818 | + self->callable = (PyObject *)self; | |
| 2819 | + return (PyObject *)self; | |
| 2820 | +} | |
| 2821 | + | |
| 2822 | +#ifdef MS_WIN32 | |
| 2823 | +static PyObject * | |
| 2824 | +CFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 2825 | +{ | |
| 2826 | + CFuncPtrObject *self; | |
| 2827 | + int index; | |
| 2828 | + char *name = NULL; | |
| 2829 | + PyObject *paramflags = NULL; | |
| 2830 | + GUID *iid = NULL; | |
| 2831 | + int iid_len = 0; | |
| 2832 | + | |
| 2833 | + if (!PyArg_ParseTuple(args, "is|Oz#", &index, &name, ¶mflags, &iid, &iid_len)) | |
| 2834 | + return NULL; | |
| 2835 | + if (paramflags == Py_None) | |
| 2836 | + paramflags = NULL; | |
| 2837 | + | |
| 2838 | + if (!_validate_paramflags(type, paramflags)) | |
| 2839 | + return NULL; | |
| 2840 | + | |
| 2841 | + self = (CFuncPtrObject *)GenericCData_new(type, args, kwds); | |
| 2842 | + self->index = index + 0x1000; | |
| 2843 | + Py_XINCREF(paramflags); | |
| 2844 | + self->paramflags = paramflags; | |
| 2845 | + if (iid_len == sizeof(GUID)) | |
| 2846 | + self->iid = iid; | |
| 2847 | + return (PyObject *)self; | |
| 2848 | +} | |
| 2849 | +#endif | |
| 2850 | + | |
| 2851 | +/* | |
| 2852 | + CFuncPtr_new accepts different argument lists in addition to the standard | |
| 2853 | + _basespec_ keyword arg: | |
| 2854 | + | |
| 2855 | + one argument form | |
| 2856 | + "i" - function address | |
| 2857 | + "O" - must be a callable, creates a C callable function | |
| 2858 | + | |
| 2859 | + two or more argument forms (the third argument is a paramflags tuple) | |
| 2860 | + "(sO)|..." - (function name, dll object (with an integer handle)), paramflags | |
| 2861 | + "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags | |
| 2862 | + "is|..." - vtable index, method name, creates callable calling COM vtbl | |
| 2863 | +*/ | |
| 2864 | +static PyObject * | |
| 2865 | +CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 2866 | +{ | |
| 2867 | + CFuncPtrObject *self; | |
| 2868 | + PyObject *callable; | |
| 2869 | + StgDictObject *dict; | |
| 2870 | + ffi_info *thunk; | |
| 2871 | + | |
| 2872 | + if (PyTuple_GET_SIZE(args) == 0) | |
| 2873 | + return GenericCData_new(type, args, kwds); | |
| 2874 | + | |
| 2875 | + if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0))) | |
| 2876 | + return CFuncPtr_FromDll(type, args, kwds); | |
| 2877 | + | |
| 2878 | +#ifdef MS_WIN32 | |
| 2879 | + if (2 <= PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0))) | |
| 2880 | + return CFuncPtr_FromVtblIndex(type, args, kwds); | |
| 2881 | +#endif | |
| 2882 | + | |
| 2883 | + if (1 == PyTuple_GET_SIZE(args) | |
| 2884 | + && (PyInt_Check(PyTuple_GET_ITEM(args, 0)) | |
| 2885 | + || PyLong_Check(PyTuple_GET_ITEM(args, 0)))) { | |
| 2886 | + CDataObject *ob; | |
| 2887 | + void *ptr = PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, 0)); | |
| 2888 | + if (ptr == NULL) | |
| 2889 | + return NULL; | |
| 2890 | + ob = (CDataObject *)GenericCData_new(type, args, kwds); | |
| 2891 | + if (ob == NULL) | |
| 2892 | + return NULL; | |
| 2893 | + *(void **)ob->b_ptr = ptr; | |
| 2894 | + return (PyObject *)ob; | |
| 2895 | + } | |
| 2896 | + | |
| 2897 | + if (!PyArg_ParseTuple(args, "O", &callable)) | |
| 2898 | + return NULL; | |
| 2899 | + if (!PyCallable_Check(callable)) { | |
| 2900 | + PyErr_SetString(PyExc_TypeError, | |
| 2901 | + "argument must be callable or integer function address"); | |
| 2902 | + return NULL; | |
| 2903 | + } | |
| 2904 | + | |
| 2905 | + /* XXX XXX This would allow to pass additional options. For COM | |
| 2906 | + method *implementations*, we would probably want different | |
| 2907 | + behaviour than in 'normal' callback functions: return a HRESULT if | |
| 2908 | + an exception occurrs in the callback, and print the traceback not | |
| 2909 | + only on the console, but also to OutputDebugString() or something | |
| 2910 | + like that. | |
| 2911 | + */ | |
| 2912 | +/* | |
| 2913 | + if (kwds && PyDict_GetItemString(kwds, "options")) { | |
| 2914 | + ... | |
| 2915 | + } | |
| 2916 | +*/ | |
| 2917 | + | |
| 2918 | + dict = PyType_stgdict((PyObject *)type); | |
| 2919 | + /* XXXX Fails if we do: 'CFuncPtr(lambda x: x)' */ | |
| 2920 | + if (!dict || !dict->argtypes) { | |
| 2921 | + PyErr_SetString(PyExc_TypeError, | |
| 2922 | + "cannot construct instance of this class:" | |
| 2923 | + " no argtypes"); | |
| 2924 | + return NULL; | |
| 2925 | + } | |
| 2926 | + | |
| 2927 | + /*****************************************************************/ | |
| 2928 | + /* The thunk keeps unowned references to callable and dict->argtypes | |
| 2929 | + so we have to keep them alive somewhere else: callable is kept in self, | |
| 2930 | + dict->argtypes is in the type's stgdict. | |
| 2931 | + */ | |
| 2932 | + thunk = AllocFunctionCallback(callable, | |
| 2933 | + dict->argtypes, | |
| 2934 | + dict->restype, | |
| 2935 | + dict->flags & FUNCFLAG_CDECL); | |
| 2936 | + if (!thunk) | |
| 2937 | + return NULL; | |
| 2938 | + | |
| 2939 | + self = (CFuncPtrObject *)GenericCData_new(type, args, kwds); | |
| 2940 | + if (self == NULL) | |
| 2941 | + return NULL; | |
| 2942 | + | |
| 2943 | + Py_INCREF(callable); | |
| 2944 | + self->callable = callable; | |
| 2945 | + | |
| 2946 | + self->thunk = thunk; | |
| 2947 | + *(void **)self->b_ptr = *(void **)thunk; | |
| 2948 | + | |
| 2949 | + /* We store ourself in self->b_objects[0], because the whole instance | |
| 2950 | + must be kept alive if stored in a structure field, for example. | |
| 2951 | + Cycle GC to the rescue! And we have a unittest proving that this works | |
| 2952 | + correctly... | |
| 2953 | + */ | |
| 2954 | + | |
| 2955 | + Py_INCREF((PyObject *)self); /* for KeepRef */ | |
| 2956 | + if (-1 == KeepRef((CDataObject *)self, 0, (PyObject *)self)) { | |
| 2957 | + Py_DECREF((PyObject *)self); | |
| 2958 | + return NULL; | |
| 2959 | + } | |
| 2960 | + | |
| 2961 | + return (PyObject *)self; | |
| 2962 | +} | |
| 2963 | + | |
| 2964 | + | |
| 2965 | +/* | |
| 2966 | + _byref consumes a refcount to its argument | |
| 2967 | +*/ | |
| 2968 | +static PyObject * | |
| 2969 | +_byref(PyObject *obj) | |
| 2970 | +{ | |
| 2971 | + PyCArgObject *parg; | |
| 2972 | + if (!CDataObject_Check(obj)) { | |
| 2973 | + PyErr_SetString(PyExc_TypeError, | |
| 2974 | + "expected CData instance"); | |
| 2975 | + return NULL; | |
| 2976 | + } | |
| 2977 | + | |
| 2978 | + parg = new_CArgObject(); | |
| 2979 | + if (parg == NULL) { | |
| 2980 | + Py_DECREF(obj); | |
| 2981 | + return NULL; | |
| 2982 | + } | |
| 2983 | + | |
| 2984 | + parg->tag = 'P'; | |
| 2985 | + parg->pffi_type = &ffi_type_pointer; | |
| 2986 | + parg->obj = obj; | |
| 2987 | + parg->value.p = ((CDataObject *)obj)->b_ptr; | |
| 2988 | + return (PyObject *)parg; | |
| 2989 | +} | |
| 2990 | + | |
| 2991 | +static PyObject * | |
| 2992 | +_get_arg(int *pindex, char *name, PyObject *defval, PyObject *inargs, PyObject *kwds) | |
| 2993 | +{ | |
| 2994 | + PyObject *v; | |
| 2995 | + | |
| 2996 | + if (*pindex < PyTuple_GET_SIZE(inargs)) { | |
| 2997 | + v = PyTuple_GET_ITEM(inargs, *pindex); | |
| 2998 | + ++*pindex; | |
| 2999 | + Py_INCREF(v); | |
| 3000 | + return v; | |
| 3001 | + } | |
| 3002 | + if (kwds && (v = PyDict_GetItemString(kwds, name))) { | |
| 3003 | + ++*pindex; | |
| 3004 | + Py_INCREF(v); | |
| 3005 | + return v; | |
| 3006 | + } | |
| 3007 | + if (defval) { | |
| 3008 | + Py_INCREF(defval); | |
| 3009 | + return defval; | |
| 3010 | + } | |
| 3011 | + /* we can't currently emit a better error message */ | |
| 3012 | + if (name) | |
| 3013 | + PyErr_Format(PyExc_TypeError, | |
| 3014 | + "required argument '%s' missing", name); | |
| 3015 | + else | |
| 3016 | + PyErr_Format(PyExc_TypeError, | |
| 3017 | + "not enough arguments"); | |
| 3018 | + return NULL; | |
| 3019 | +} | |
| 3020 | + | |
| 3021 | +/* | |
| 3022 | + This function implements higher level functionality plus the ability to call | |
| 3023 | + functions with keyword arguments by looking at parameter flags. parameter | |
| 3024 | + flags is a tuple of 1, 2 or 3-tuples. The first entry in each is an integer | |
| 3025 | + specifying the direction of the data transfer for this parameter - 'in', | |
| 3026 | + 'out' or 'inout' (zero means the same as 'in'). The second entry is the | |
| 3027 | + parameter name, and the third is the default value if the parameter is | |
| 3028 | + missing in the function call. | |
| 3029 | + | |
| 3030 | + This function builds and returns a new tuple 'callargs' which contains the | |
| 3031 | + parameters to use in the call. Items on this tuple are copied from the | |
| 3032 | + 'inargs' tuple for 'in' and 'in, out' parameters, and constructed from the | |
| 3033 | + 'argtypes' tuple for 'out' parameters. It also calculates numretvals which | |
| 3034 | + is the number of return values for the function, outmask/inoutmask are | |
| 3035 | + bitmasks containing indexes into the callargs tuple specifying which | |
| 3036 | + parameters have to be returned. _build_result builds the return value of the | |
| 3037 | + function. | |
| 3038 | +*/ | |
| 3039 | +static PyObject * | |
| 3040 | +_build_callargs(CFuncPtrObject *self, PyObject *argtypes, | |
| 3041 | + PyObject *inargs, PyObject *kwds, | |
| 3042 | + int *poutmask, int *pinoutmask, unsigned int *pnumretvals) | |
| 3043 | +{ | |
| 3044 | + PyObject *paramflags = self->paramflags; | |
| 3045 | + PyObject *callargs; | |
| 3046 | + StgDictObject *dict; | |
| 3047 | + int i, len; | |
| 3048 | + int inargs_index = 0; | |
| 3049 | + /* It's a little bit difficult to determine how many arguments the | |
| 3050 | + function call requires/accepts. For simplicity, we count the consumed | |
| 3051 | + args and compare this to the number of supplied args. */ | |
| 3052 | + int actual_args; | |
| 3053 | + | |
| 3054 | + *poutmask = 0; | |
| 3055 | + *pinoutmask = 0; | |
| 3056 | + *pnumretvals = 0; | |
| 3057 | + | |
| 3058 | + /* Trivial cases, where we either return inargs itself, or a slice of it. */ | |
| 3059 | + if (argtypes == NULL || paramflags == NULL || PyTuple_GET_SIZE(argtypes) == 0) { | |
| 3060 | +#ifdef MS_WIN32 | |
| 3061 | + if (self->index) | |
| 3062 | + return PyTuple_GetSlice(inargs, 1, PyTuple_GET_SIZE(inargs)); | |
| 3063 | +#endif | |
| 3064 | + Py_INCREF(inargs); | |
| 3065 | + return inargs; | |
| 3066 | + } | |
| 3067 | + | |
| 3068 | + len = PyTuple_GET_SIZE(argtypes); | |
| 3069 | + callargs = PyTuple_New(len); /* the argument tuple we build */ | |
| 3070 | + if (callargs == NULL) | |
| 3071 | + return NULL; | |
| 3072 | + | |
| 3073 | +#ifdef MS_WIN32 | |
| 3074 | + /* For a COM method, skip the first arg */ | |
| 3075 | + if (self->index) { | |
| 3076 | + inargs_index = 1; | |
| 3077 | + } | |
| 3078 | +#endif | |
| 3079 | + for (i = 0; i < len; ++i) { | |
| 3080 | + PyObject *item = PyTuple_GET_ITEM(paramflags, i); | |
| 3081 | + PyObject *ob; | |
| 3082 | + int flag; | |
| 3083 | + char *name = NULL; | |
| 3084 | + PyObject *defval = NULL; | |
| 3085 | + | |
| 3086 | + /* This way seems to be ~2 us faster than the PyArg_ParseTuple | |
| 3087 | + calls below. */ | |
| 3088 | + /* We HAVE already checked that the tuple can be parsed with "i|zO", so... */ | |
| 3089 | + int tsize = PyTuple_GET_SIZE(item); | |
| 3090 | + flag = PyInt_AS_LONG(PyTuple_GET_ITEM(item, 0)); | |
| 3091 | + name = tsize > 1 ? PyString_AS_STRING(PyTuple_GET_ITEM(item, 1)) : NULL; | |
| 3092 | + defval = tsize > 2 ? PyTuple_GET_ITEM(item, 2) : NULL; | |
| 3093 | + | |
| 3094 | + switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) { | |
| 3095 | + case PARAMFLAG_FIN | PARAMFLAG_FLCID: | |
| 3096 | + /* ['in', 'lcid'] parameter. Always taken from defval, | |
| 3097 | + if given, else the integer 0. */ | |
| 3098 | + if (defval == NULL) { | |
| 3099 | + defval = PyInt_FromLong(0); | |
| 3100 | + if (defval == NULL) | |
| 3101 | + goto error; | |
| 3102 | + } else | |
| 3103 | + Py_INCREF(defval); | |
| 3104 | + PyTuple_SET_ITEM(callargs, i, defval); | |
| 3105 | + break; | |
| 3106 | + case (PARAMFLAG_FIN | PARAMFLAG_FOUT): | |
| 3107 | + *pinoutmask |= (1 << i); /* mark as inout arg */ | |
| 3108 | + (*pnumretvals)++; | |
| 3109 | + /* fall through to PARAMFLAG_FIN... */ | |
| 3110 | + case 0: | |
| 3111 | + case PARAMFLAG_FIN: | |
| 3112 | + /* 'in' parameter. Copy it from inargs. */ | |
| 3113 | + ob =_get_arg(&inargs_index, name, defval, inargs, kwds); | |
| 3114 | + if (ob == NULL) | |
| 3115 | + goto error; | |
| 3116 | + PyTuple_SET_ITEM(callargs, i, ob); | |
| 3117 | + break; | |
| 3118 | + case PARAMFLAG_FOUT: | |
| 3119 | + /* XXX Refactor this code into a separate function. */ | |
| 3120 | + /* 'out' parameter. | |
| 3121 | + argtypes[i] must be a POINTER to a c type. | |
| 3122 | + | |
| 3123 | + Cannot by supplied in inargs, but a defval will be used | |
| 3124 | + if available. XXX Should we support getting it from kwds? | |
| 3125 | + */ | |
| 3126 | + if (defval) { | |
| 3127 | + /* XXX Using mutable objects as defval will | |
| 3128 | + make the function non-threadsafe, unless we | |
| 3129 | + copy the object in each invocation */ | |
| 3130 | + Py_INCREF(defval); | |
| 3131 | + PyTuple_SET_ITEM(callargs, i, defval); | |
| 3132 | + *poutmask |= (1 << i); /* mark as out arg */ | |
| 3133 | + (*pnumretvals)++; | |
| 3134 | + break; | |
| 3135 | + } | |
| 3136 | + ob = PyTuple_GET_ITEM(argtypes, i); | |
| 3137 | + dict = PyType_stgdict(ob); | |
| 3138 | + if (dict == NULL) { | |
| 3139 | + /* Cannot happen: _validate_paramflags() | |
| 3140 | + would not accept such an object */ | |
| 3141 | + PyErr_Format(PyExc_RuntimeError, | |
| 3142 | + "NULL stgdict unexpected"); | |
| 3143 | + goto error; | |
| 3144 | + } | |
| 3145 | + if (PyString_Check(dict->proto)) { | |
| 3146 | + PyErr_Format( | |
| 3147 | + PyExc_TypeError, | |
| 3148 | + "%s 'out' parameter must be passed as default value", | |
| 3149 | + ((PyTypeObject *)ob)->tp_name); | |
| 3150 | + goto error; | |
| 3151 | + } | |
| 3152 | + if (ArrayTypeObject_Check(ob)) | |
| 3153 | + ob = PyObject_CallObject(ob, NULL); | |
| 3154 | + else | |
| 3155 | + /* Create an instance of the pointed-to type */ | |
| 3156 | + ob = PyObject_CallObject(dict->proto, NULL); | |
| 3157 | + /* | |
| 3158 | + XXX Is the following correct any longer? | |
| 3159 | + We must not pass a byref() to the array then but | |
| 3160 | + the array instance itself. Then, we cannot retrive | |
| 3161 | + the result from the PyCArgObject. | |
| 3162 | + */ | |
| 3163 | + if (ob == NULL) | |
| 3164 | + goto error; | |
| 3165 | + /* The .from_param call that will ocurr later will pass this | |
| 3166 | + as a byref parameter. */ | |
| 3167 | + PyTuple_SET_ITEM(callargs, i, ob); | |
| 3168 | + *poutmask |= (1 << i); /* mark as out arg */ | |
| 3169 | + (*pnumretvals)++; | |
| 3170 | + break; | |
| 3171 | + default: | |
| 3172 | + PyErr_Format(PyExc_ValueError, | |
| 3173 | + "paramflag %d not yet implemented", flag); | |
| 3174 | + goto error; | |
| 3175 | + break; | |
| 3176 | + } | |
| 3177 | + } | |
| 3178 | + | |
| 3179 | + /* We have counted the arguments we have consumed in 'inargs_index'. This | |
| 3180 | + must be the same as len(inargs) + len(kwds), otherwise we have | |
| 3181 | + either too much or not enough arguments. */ | |
| 3182 | + | |
| 3183 | + actual_args = PyTuple_GET_SIZE(inargs) + (kwds ? PyDict_Size(kwds) : 0); | |
| 3184 | + if (actual_args != inargs_index) { | |
| 3185 | + /* When we have default values or named parameters, this error | |
| 3186 | + message is misleading. See unittests/test_paramflags.py | |
| 3187 | + */ | |
| 3188 | + PyErr_Format(PyExc_TypeError, | |
| 3189 | + "call takes exactly %d arguments (%d given)", | |
| 3190 | + inargs_index, actual_args); | |
| 3191 | + goto error; | |
| 3192 | + } | |
| 3193 | + | |
| 3194 | + /* outmask is a bitmask containing indexes into callargs. Items at | |
| 3195 | + these indexes contain values to return. | |
| 3196 | + */ | |
| 3197 | + return callargs; | |
| 3198 | + error: | |
| 3199 | + Py_DECREF(callargs); | |
| 3200 | + return NULL; | |
| 3201 | +} | |
| 3202 | + | |
| 3203 | +/* See also: | |
| 3204 | + http://msdn.microsoft.com/library/en-us/com/html/769127a1-1a14-4ed4-9d38-7cf3e571b661.asp | |
| 3205 | +*/ | |
| 3206 | +/* | |
| 3207 | + Build return value of a function. | |
| 3208 | + | |
| 3209 | + Consumes the refcount on result and callargs. | |
| 3210 | +*/ | |
| 3211 | +static PyObject * | |
| 3212 | +_build_result(PyObject *result, PyObject *callargs, | |
| 3213 | + int outmask, int inoutmask, unsigned int numretvals) | |
| 3214 | +{ | |
| 3215 | + unsigned int i, index; | |
| 3216 | + int bit; | |
| 3217 | + PyObject *tup = NULL; | |
| 3218 | + | |
| 3219 | + if (callargs == NULL) | |
| 3220 | + return result; | |
| 3221 | + if (result == NULL || numretvals == 0) { | |
| 3222 | + Py_DECREF(callargs); | |
| 3223 | + return result; | |
| 3224 | + } | |
| 3225 | + Py_DECREF(result); | |
| 3226 | + | |
| 3227 | + /* tup will not be allocated if numretvals == 1 */ | |
| 3228 | + /* allocate tuple to hold the result */ | |
| 3229 | + if (numretvals > 1) { | |
| 3230 | + tup = PyTuple_New(numretvals); | |
| 3231 | + if (tup == NULL) { | |
| 3232 | + Py_DECREF(callargs); | |
| 3233 | + return NULL; | |
| 3234 | + } | |
| 3235 | + } | |
| 3236 | + | |
| 3237 | + index = 0; | |
| 3238 | + for (bit = 1, i = 0; i < 32; ++i, bit <<= 1) { | |
| 3239 | + PyObject *v; | |
| 3240 | + if (bit & inoutmask) { | |
| 3241 | + v = PyTuple_GET_ITEM(callargs, i); | |
| 3242 | + Py_INCREF(v); | |
| 3243 | + if (numretvals == 1) { | |
| 3244 | + Py_DECREF(callargs); | |
| 3245 | + return v; | |
| 3246 | + } | |
| 3247 | + PyTuple_SET_ITEM(tup, index, v); | |
| 3248 | + index++; | |
| 3249 | + } else if (bit & outmask) { | |
| 3250 | + v = PyTuple_GET_ITEM(callargs, i); | |
| 3251 | + v = PyObject_CallMethod(v, "__ctypes_from_outparam__", NULL); | |
| 3252 | + if (v == NULL || numretvals == 1) { | |
| 3253 | + Py_DECREF(callargs); | |
| 3254 | + return v; | |
| 3255 | + } | |
| 3256 | + PyTuple_SET_ITEM(tup, index, v); | |
| 3257 | + index++; | |
| 3258 | + } | |
| 3259 | + if (index == numretvals) | |
| 3260 | + break; | |
| 3261 | + } | |
| 3262 | + | |
| 3263 | + Py_DECREF(callargs); | |
| 3264 | + return tup; | |
| 3265 | +} | |
| 3266 | + | |
| 3267 | +static PyObject * | |
| 3268 | +CFuncPtr_call(CFuncPtrObject *self, PyObject *inargs, PyObject *kwds) | |
| 3269 | +{ | |
| 3270 | + PyObject *restype; | |
| 3271 | + PyObject *converters; | |
| 3272 | + PyObject *checker; | |
| 3273 | + PyObject *argtypes; | |
| 3274 | + StgDictObject *dict = PyObject_stgdict((PyObject *)self); | |
| 3275 | + PyObject *result; | |
| 3276 | + PyObject *callargs; | |
| 3277 | + PyObject *errcheck; | |
| 3278 | +#ifdef MS_WIN32 | |
| 3279 | + IUnknown *piunk = NULL; | |
| 3280 | +#endif | |
| 3281 | + void *pProc = NULL; | |
| 3282 | + | |
| 3283 | + int inoutmask; | |
| 3284 | + int outmask; | |
| 3285 | + unsigned int numretvals; | |
| 3286 | + | |
| 3287 | + assert(dict); /* Cannot be NULL for CFuncPtrObject instances */ | |
| 3288 | + restype = self->restype ? self->restype : dict->restype; | |
| 3289 | + converters = self->converters ? self->converters : dict->converters; | |
| 3290 | + checker = self->checker ? self->checker : dict->checker; | |
| 3291 | + argtypes = self->argtypes ? self->argtypes : dict->argtypes; | |
| 3292 | +/* later, we probably want to have an errcheck field in stgdict */ | |
| 3293 | + errcheck = self->errcheck /* ? self->errcheck : dict->errcheck */; | |
| 3294 | + | |
| 3295 | + | |
| 3296 | + pProc = *(void **)self->b_ptr; | |
| 3297 | +#ifdef MS_WIN32 | |
| 3298 | + if (self->index) { | |
| 3299 | + /* It's a COM method */ | |
| 3300 | + CDataObject *this; | |
| 3301 | + this = (CDataObject *)PyTuple_GetItem(inargs, 0); /* borrowed ref! */ | |
| 3302 | + if (!this) { | |
| 3303 | + PyErr_SetString(PyExc_ValueError, | |
| 3304 | + "native com method call without 'this' parameter"); | |
| 3305 | + return NULL; | |
| 3306 | + } | |
| 3307 | + if (!CDataObject_Check(this)) { | |
| 3308 | + PyErr_SetString(PyExc_TypeError, | |
| 3309 | + "Expected a COM this pointer as first argument"); | |
| 3310 | + return NULL; | |
| 3311 | + } | |
| 3312 | + /* there should be more checks? No, in Python */ | |
| 3313 | + /* First arg is an pointer to an interface instance */ | |
| 3314 | + if (!this->b_ptr || *(void **)this->b_ptr == NULL) { | |
| 3315 | + PyErr_SetString(PyExc_ValueError, | |
| 3316 | + "NULL COM pointer access"); | |
| 3317 | + return NULL; | |
| 3318 | + } | |
| 3319 | + piunk = *(IUnknown **)this->b_ptr; | |
| 3320 | + if (NULL == piunk->lpVtbl) { | |
| 3321 | + PyErr_SetString(PyExc_ValueError, | |
| 3322 | + "COM method call without VTable"); | |
| 3323 | + return NULL; | |
| 3324 | + } | |
| 3325 | + pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000]; | |
| 3326 | + } | |
| 3327 | +#endif | |
| 3328 | + callargs = _build_callargs(self, argtypes, | |
| 3329 | + inargs, kwds, | |
| 3330 | + &outmask, &inoutmask, &numretvals); | |
| 3331 | + if (callargs == NULL) | |
| 3332 | + return NULL; | |
| 3333 | + | |
| 3334 | + if (converters) { | |
| 3335 | + int required = PyTuple_GET_SIZE(converters); | |
| 3336 | + int actual = PyTuple_GET_SIZE(callargs); | |
| 3337 | + | |
| 3338 | + if ((dict->flags & FUNCFLAG_CDECL) == FUNCFLAG_CDECL) { | |
| 3339 | + /* For cdecl functions, we allow more actual arguments | |
| 3340 | + than the length of the argtypes tuple. | |
| 3341 | + */ | |
| 3342 | + if (required > actual) { | |
| 3343 | + Py_DECREF(callargs); | |
| 3344 | + PyErr_Format(PyExc_TypeError, | |
| 3345 | + "this function takes at least %d argument%s (%d given)", | |
| 3346 | + required, | |
| 3347 | + required == 1 ? "" : "s", | |
| 3348 | + actual); | |
| 3349 | + return NULL; | |
| 3350 | + } | |
| 3351 | + } else if (required != actual) { | |
| 3352 | + Py_DECREF(callargs); | |
| 3353 | + PyErr_Format(PyExc_TypeError, | |
| 3354 | + "this function takes %d argument%s (%d given)", | |
| 3355 | + required, | |
| 3356 | + required == 1 ? "" : "s", | |
| 3357 | + actual); | |
| 3358 | + return NULL; | |
| 3359 | + } | |
| 3360 | + } | |
| 3361 | + | |
| 3362 | + result = _CallProc(pProc, | |
| 3363 | + callargs, | |
| 3364 | +#ifdef MS_WIN32 | |
| 3365 | + piunk, | |
| 3366 | + self->iid, | |
| 3367 | +#endif | |
| 3368 | + dict->flags, | |
| 3369 | + converters, | |
| 3370 | + restype, | |
| 3371 | + checker); | |
| 3372 | +/* The 'errcheck' protocol */ | |
| 3373 | + if (result != NULL && errcheck) { | |
| 3374 | + PyObject *v = PyObject_CallFunctionObjArgs(errcheck, | |
| 3375 | + result, | |
| 3376 | + self, | |
| 3377 | + callargs, | |
| 3378 | + NULL); | |
| 3379 | + /* If the errcheck funtion failed, return NULL. | |
| 3380 | + If the errcheck function returned callargs unchanged, | |
| 3381 | + continue normal processing. | |
| 3382 | + If the errcheck function returned something else, | |
| 3383 | + use that as result. | |
| 3384 | + */ | |
| 3385 | + if (v == NULL || v != callargs) { | |
| 3386 | + Py_DECREF(result); | |
| 3387 | + Py_DECREF(callargs); | |
| 3388 | + return v; | |
| 3389 | + } | |
| 3390 | + Py_DECREF(v); | |
| 3391 | + } | |
| 3392 | + | |
| 3393 | + return _build_result(result, callargs, | |
| 3394 | + outmask, inoutmask, numretvals); | |
| 3395 | +} | |
| 3396 | + | |
| 3397 | +static int | |
| 3398 | +CFuncPtr_traverse(CFuncPtrObject *self, visitproc visit, void *arg) | |
| 3399 | +{ | |
| 3400 | + Py_VISIT(self->callable); | |
| 3401 | + Py_VISIT(self->restype); | |
| 3402 | + Py_VISIT(self->checker); | |
| 3403 | + Py_VISIT(self->errcheck); | |
| 3404 | + Py_VISIT(self->argtypes); | |
| 3405 | + Py_VISIT(self->converters); | |
| 3406 | + Py_VISIT(self->paramflags); | |
| 3407 | + return CData_traverse((CDataObject *)self, visit, arg); | |
| 3408 | +} | |
| 3409 | + | |
| 3410 | +static int | |
| 3411 | +CFuncPtr_clear(CFuncPtrObject *self) | |
| 3412 | +{ | |
| 3413 | + Py_CLEAR(self->callable); | |
| 3414 | + Py_CLEAR(self->restype); | |
| 3415 | + Py_CLEAR(self->checker); | |
| 3416 | + Py_CLEAR(self->errcheck); | |
| 3417 | + Py_CLEAR(self->argtypes); | |
| 3418 | + Py_CLEAR(self->converters); | |
| 3419 | + Py_CLEAR(self->paramflags); | |
| 3420 | + | |
| 3421 | + if (self->thunk) { | |
| 3422 | + FreeClosure(self->thunk->pcl); | |
| 3423 | + PyMem_Free(self->thunk); | |
| 3424 | + self->thunk = NULL; | |
| 3425 | + } | |
| 3426 | + | |
| 3427 | + return CData_clear((CDataObject *)self); | |
| 3428 | +} | |
| 3429 | + | |
| 3430 | +static void | |
| 3431 | +CFuncPtr_dealloc(CFuncPtrObject *self) | |
| 3432 | +{ | |
| 3433 | + CFuncPtr_clear(self); | |
| 3434 | + self->ob_type->tp_free((PyObject *)self); | |
| 3435 | +} | |
| 3436 | + | |
| 3437 | +static PyObject * | |
| 3438 | +CFuncPtr_repr(CFuncPtrObject *self) | |
| 3439 | +{ | |
| 3440 | +#ifdef MS_WIN32 | |
| 3441 | + if (self->index) | |
| 3442 | + return PyString_FromFormat("<COM method offset %d: %s at %p>", | |
| 3443 | + self->index - 0x1000, | |
| 3444 | + self->ob_type->tp_name, | |
| 3445 | + self); | |
| 3446 | +#endif | |
| 3447 | + return PyString_FromFormat("<%s object at %p>", | |
| 3448 | + self->ob_type->tp_name, | |
| 3449 | + self); | |
| 3450 | +} | |
| 3451 | + | |
| 3452 | +PyTypeObject CFuncPtr_Type = { | |
| 3453 | + PyObject_HEAD_INIT(NULL) | |
| 3454 | + 0, | |
| 3455 | + "_ctypes.CFuncPtr", | |
| 3456 | + sizeof(CFuncPtrObject), /* tp_basicsize */ | |
| 3457 | + 0, /* tp_itemsize */ | |
| 3458 | + (destructor)CFuncPtr_dealloc, /* tp_dealloc */ | |
| 3459 | + 0, /* tp_print */ | |
| 3460 | + 0, /* tp_getattr */ | |
| 3461 | + 0, /* tp_setattr */ | |
| 3462 | + 0, /* tp_compare */ | |
| 3463 | + (reprfunc)CFuncPtr_repr, /* tp_repr */ | |
| 3464 | + 0, /* tp_as_number */ | |
| 3465 | + 0, /* tp_as_sequence */ | |
| 3466 | + 0, /* tp_as_mapping */ | |
| 3467 | + 0, /* tp_hash */ | |
| 3468 | + (ternaryfunc)CFuncPtr_call, /* tp_call */ | |
| 3469 | + 0, /* tp_str */ | |
| 3470 | + 0, /* tp_getattro */ | |
| 3471 | + 0, /* tp_setattro */ | |
| 3472 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 3473 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 3474 | + "Function Pointer", /* tp_doc */ | |
| 3475 | + (traverseproc)CFuncPtr_traverse, /* tp_traverse */ | |
| 3476 | + (inquiry)CFuncPtr_clear, /* tp_clear */ | |
| 3477 | + 0, /* tp_richcompare */ | |
| 3478 | + 0, /* tp_weaklistoffset */ | |
| 3479 | + 0, /* tp_iter */ | |
| 3480 | + 0, /* tp_iternext */ | |
| 3481 | + 0, /* tp_methods */ | |
| 3482 | + 0, /* tp_members */ | |
| 3483 | + CFuncPtr_getsets, /* tp_getset */ | |
| 3484 | + 0, /* tp_base */ | |
| 3485 | + 0, /* tp_dict */ | |
| 3486 | + 0, /* tp_descr_get */ | |
| 3487 | + 0, /* tp_descr_set */ | |
| 3488 | + 0, /* tp_dictoffset */ | |
| 3489 | + 0, /* tp_init */ | |
| 3490 | + 0, /* tp_alloc */ | |
| 3491 | + CFuncPtr_new, /* tp_new */ | |
| 3492 | + 0, /* tp_free */ | |
| 3493 | +}; | |
| 3494 | + | |
| 3495 | +/*****************************************************************/ | |
| 3496 | +/* | |
| 3497 | + Struct_Type | |
| 3498 | +*/ | |
| 3499 | +static int | |
| 3500 | +IBUG(char *msg) | |
| 3501 | +{ | |
| 3502 | + PyErr_Format(PyExc_RuntimeError, | |
| 3503 | + "inconsistent state in CDataObject (%s)", msg); | |
| 3504 | + return -1; | |
| 3505 | +} | |
| 3506 | + | |
| 3507 | +static int | |
| 3508 | +Struct_init(PyObject *self, PyObject *args, PyObject *kwds) | |
| 3509 | +{ | |
| 3510 | + int i; | |
| 3511 | + PyObject *fields; | |
| 3512 | + | |
| 3513 | +/* Optimization possible: Store the attribute names _fields_[x][0] | |
| 3514 | + * in C accessible fields somewhere ? | |
| 3515 | + */ | |
| 3516 | + | |
| 3517 | +/* Check this code again for correctness! */ | |
| 3518 | + | |
| 3519 | + if (!PyTuple_Check(args)) { | |
| 3520 | + PyErr_SetString(PyExc_TypeError, | |
| 3521 | + "args not a tuple?"); | |
| 3522 | + return -1; | |
| 3523 | + } | |
| 3524 | + if (PyTuple_GET_SIZE(args)) { | |
| 3525 | + fields = PyObject_GetAttrString(self, "_fields_"); | |
| 3526 | + if (!fields) { | |
| 3527 | + PyErr_Clear(); | |
| 3528 | + fields = PyTuple_New(0); | |
| 3529 | + if (!fields) | |
| 3530 | + return -1; | |
| 3531 | + } | |
| 3532 | + | |
| 3533 | + if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) { | |
| 3534 | + Py_DECREF(fields); | |
| 3535 | + PyErr_SetString(PyExc_ValueError, | |
| 3536 | + "too many initializers"); | |
| 3537 | + return -1; | |
| 3538 | + } | |
| 3539 | + | |
| 3540 | + for (i = 0; i < PyTuple_GET_SIZE(args); ++i) { | |
| 3541 | + PyObject *pair = PySequence_GetItem(fields, i); | |
| 3542 | + PyObject *name; | |
| 3543 | + PyObject *val; | |
| 3544 | + if (!pair) { | |
| 3545 | + Py_DECREF(fields); | |
| 3546 | + return IBUG("_fields_[i] failed"); | |
| 3547 | + } | |
| 3548 | + | |
| 3549 | + name = PySequence_GetItem(pair, 0); | |
| 3550 | + if (!name) { | |
| 3551 | + Py_DECREF(pair); | |
| 3552 | + Py_DECREF(fields); | |
| 3553 | + return IBUG("_fields_[i][0] failed"); | |
| 3554 | + } | |
| 3555 | + | |
| 3556 | + val = PyTuple_GET_ITEM(args, i); | |
| 3557 | + if (-1 == PyObject_SetAttr(self, name, val)) { | |
| 3558 | + Py_DECREF(pair); | |
| 3559 | + Py_DECREF(name); | |
| 3560 | + Py_DECREF(fields); | |
| 3561 | + return -1; | |
| 3562 | + } | |
| 3563 | + | |
| 3564 | + Py_DECREF(name); | |
| 3565 | + Py_DECREF(pair); | |
| 3566 | + } | |
| 3567 | + Py_DECREF(fields); | |
| 3568 | + } | |
| 3569 | + | |
| 3570 | + if (kwds) { | |
| 3571 | + PyObject *key, *value; | |
| 3572 | + Py_ssize_t pos = 0; | |
| 3573 | + while(PyDict_Next(kwds, &pos, &key, &value)) { | |
| 3574 | + if (-1 == PyObject_SetAttr(self, key, value)) | |
| 3575 | + return -1; | |
| 3576 | + } | |
| 3577 | + } | |
| 3578 | + return 0; | |
| 3579 | +} | |
| 3580 | + | |
| 3581 | +static PyTypeObject Struct_Type = { | |
| 3582 | + PyObject_HEAD_INIT(NULL) | |
| 3583 | + 0, | |
| 3584 | + "_ctypes.Structure", | |
| 3585 | + sizeof(CDataObject), /* tp_basicsize */ | |
| 3586 | + 0, /* tp_itemsize */ | |
| 3587 | + 0, /* tp_dealloc */ | |
| 3588 | + 0, /* tp_print */ | |
| 3589 | + 0, /* tp_getattr */ | |
| 3590 | + 0, /* tp_setattr */ | |
| 3591 | + 0, /* tp_compare */ | |
| 3592 | + 0, /* tp_repr */ | |
| 3593 | + 0, /* tp_as_number */ | |
| 3594 | + 0, /* tp_as_sequence */ | |
| 3595 | + 0, /* tp_as_mapping */ | |
| 3596 | + 0, /* tp_hash */ | |
| 3597 | + 0, /* tp_call */ | |
| 3598 | + 0, /* tp_str */ | |
| 3599 | + 0, /* tp_getattro */ | |
| 3600 | + 0, /* tp_setattro */ | |
| 3601 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 3602 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 3603 | + "Structure base class", /* tp_doc */ | |
| 3604 | + (traverseproc)CData_traverse, /* tp_traverse */ | |
| 3605 | + (inquiry)CData_clear, /* tp_clear */ | |
| 3606 | + 0, /* tp_richcompare */ | |
| 3607 | + 0, /* tp_weaklistoffset */ | |
| 3608 | + 0, /* tp_iter */ | |
| 3609 | + 0, /* tp_iternext */ | |
| 3610 | + 0, /* tp_methods */ | |
| 3611 | + 0, /* tp_members */ | |
| 3612 | + 0, /* tp_getset */ | |
| 3613 | + 0, /* tp_base */ | |
| 3614 | + 0, /* tp_dict */ | |
| 3615 | + 0, /* tp_descr_get */ | |
| 3616 | + 0, /* tp_descr_set */ | |
| 3617 | + 0, /* tp_dictoffset */ | |
| 3618 | + Struct_init, /* tp_init */ | |
| 3619 | + 0, /* tp_alloc */ | |
| 3620 | + GenericCData_new, /* tp_new */ | |
| 3621 | + 0, /* tp_free */ | |
| 3622 | +}; | |
| 3623 | + | |
| 3624 | +static PyTypeObject Union_Type = { | |
| 3625 | + PyObject_HEAD_INIT(NULL) | |
| 3626 | + 0, | |
| 3627 | + "_ctypes.Union", | |
| 3628 | + sizeof(CDataObject), /* tp_basicsize */ | |
| 3629 | + 0, /* tp_itemsize */ | |
| 3630 | + 0, /* tp_dealloc */ | |
| 3631 | + 0, /* tp_print */ | |
| 3632 | + 0, /* tp_getattr */ | |
| 3633 | + 0, /* tp_setattr */ | |
| 3634 | + 0, /* tp_compare */ | |
| 3635 | + 0, /* tp_repr */ | |
| 3636 | + 0, /* tp_as_number */ | |
| 3637 | + 0, /* tp_as_sequence */ | |
| 3638 | + 0, /* tp_as_mapping */ | |
| 3639 | + 0, /* tp_hash */ | |
| 3640 | + 0, /* tp_call */ | |
| 3641 | + 0, /* tp_str */ | |
| 3642 | + 0, /* tp_getattro */ | |
| 3643 | + 0, /* tp_setattro */ | |
| 3644 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 3645 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 3646 | + "Union base class", /* tp_doc */ | |
| 3647 | + (traverseproc)CData_traverse, /* tp_traverse */ | |
| 3648 | + (inquiry)CData_clear, /* tp_clear */ | |
| 3649 | + 0, /* tp_richcompare */ | |
| 3650 | + 0, /* tp_weaklistoffset */ | |
| 3651 | + 0, /* tp_iter */ | |
| 3652 | + 0, /* tp_iternext */ | |
| 3653 | + 0, /* tp_methods */ | |
| 3654 | + 0, /* tp_members */ | |
| 3655 | + 0, /* tp_getset */ | |
| 3656 | + 0, /* tp_base */ | |
| 3657 | + 0, /* tp_dict */ | |
| 3658 | + 0, /* tp_descr_get */ | |
| 3659 | + 0, /* tp_descr_set */ | |
| 3660 | + 0, /* tp_dictoffset */ | |
| 3661 | + Struct_init, /* tp_init */ | |
| 3662 | + 0, /* tp_alloc */ | |
| 3663 | + GenericCData_new, /* tp_new */ | |
| 3664 | + 0, /* tp_free */ | |
| 3665 | +}; | |
| 3666 | + | |
| 3667 | + | |
| 3668 | +/******************************************************************/ | |
| 3669 | +/* | |
| 3670 | + Array_Type | |
| 3671 | +*/ | |
| 3672 | +static int | |
| 3673 | +Array_init(CDataObject *self, PyObject *args, PyObject *kw) | |
| 3674 | +{ | |
| 3675 | + int i; | |
| 3676 | + int n; | |
| 3677 | + | |
| 3678 | + if (!PyTuple_Check(args)) { | |
| 3679 | + PyErr_SetString(PyExc_TypeError, | |
| 3680 | + "args not a tuple?"); | |
| 3681 | + return -1; | |
| 3682 | + } | |
| 3683 | + n = PyTuple_GET_SIZE(args); | |
| 3684 | + for (i = 0; i < n; ++i) { | |
| 3685 | + PyObject *v; | |
| 3686 | + v = PyTuple_GET_ITEM(args, i); | |
| 3687 | + if (-1 == PySequence_SetItem((PyObject *)self, i, v)) | |
| 3688 | + return -1; | |
| 3689 | + } | |
| 3690 | + return 0; | |
| 3691 | +} | |
| 3692 | + | |
| 3693 | +static PyObject * | |
| 3694 | +Array_item(PyObject *_self, Py_ssize_t index) | |
| 3695 | +{ | |
| 3696 | + CDataObject *self = (CDataObject *)_self; | |
| 3697 | + int offset, size; | |
| 3698 | + StgDictObject *stgdict; | |
| 3699 | + | |
| 3700 | + | |
| 3701 | + if (index < 0 || index >= self->b_length) { | |
| 3702 | + PyErr_SetString(PyExc_IndexError, | |
| 3703 | + "invalid index"); | |
| 3704 | + return NULL; | |
| 3705 | + } | |
| 3706 | + | |
| 3707 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 3708 | + assert(stgdict); /* Cannot be NULL for array instances */ | |
| 3709 | + /* Would it be clearer if we got the item size from | |
| 3710 | + stgdict->proto's stgdict? | |
| 3711 | + */ | |
| 3712 | + size = stgdict->size / stgdict->length; | |
| 3713 | + offset = index * size; | |
| 3714 | + | |
| 3715 | + return CData_get(stgdict->proto, stgdict->getfunc, (PyObject *)self, | |
| 3716 | + index, size, self->b_ptr + offset); | |
| 3717 | +} | |
| 3718 | + | |
| 3719 | +static PyObject * | |
| 3720 | +Array_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh) | |
| 3721 | +{ | |
| 3722 | + CDataObject *self = (CDataObject *)_self; | |
| 3723 | + StgDictObject *stgdict, *itemdict; | |
| 3724 | + PyObject *proto; | |
| 3725 | + PyListObject *np; | |
| 3726 | + Py_ssize_t i, len; | |
| 3727 | + | |
| 3728 | + if (ilow < 0) | |
| 3729 | + ilow = 0; | |
| 3730 | + else if (ilow > self->b_length) | |
| 3731 | + ilow = self->b_length; | |
| 3732 | + if (ihigh < ilow) | |
| 3733 | + ihigh = ilow; | |
| 3734 | + else if (ihigh > self->b_length) | |
| 3735 | + ihigh = self->b_length; | |
| 3736 | + len = ihigh - ilow; | |
| 3737 | + | |
| 3738 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 3739 | + assert(stgdict); /* Cannot be NULL for array object instances */ | |
| 3740 | + proto = stgdict->proto; | |
| 3741 | + itemdict = PyType_stgdict(proto); | |
| 3742 | + assert(itemdict); /* proto is the item type of the array, a ctypes | |
| 3743 | + type, so this cannot be NULL */ | |
| 3744 | + if (itemdict->getfunc == getentry("c")->getfunc) { | |
| 3745 | + char *ptr = (char *)self->b_ptr; | |
| 3746 | + return PyString_FromStringAndSize(ptr + ilow, len); | |
| 3747 | +#ifdef CTYPES_UNICODE | |
| 3748 | + } else if (itemdict->getfunc == getentry("u")->getfunc) { | |
| 3749 | + wchar_t *ptr = (wchar_t *)self->b_ptr; | |
| 3750 | + return PyUnicode_FromWideChar(ptr + ilow, len); | |
| 3751 | +#endif | |
| 3752 | + } | |
| 3753 | + | |
| 3754 | + np = (PyListObject *) PyList_New(len); | |
| 3755 | + if (np == NULL) | |
| 3756 | + return NULL; | |
| 3757 | + | |
| 3758 | + for (i = 0; i < len; i++) { | |
| 3759 | + PyObject *v = Array_item(_self, i+ilow); | |
| 3760 | + PyList_SET_ITEM(np, i, v); | |
| 3761 | + } | |
| 3762 | + return (PyObject *)np; | |
| 3763 | +} | |
| 3764 | + | |
| 3765 | +static int | |
| 3766 | +Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value) | |
| 3767 | +{ | |
| 3768 | + CDataObject *self = (CDataObject *)_self; | |
| 3769 | + int size, offset; | |
| 3770 | + StgDictObject *stgdict; | |
| 3771 | + char *ptr; | |
| 3772 | + | |
| 3773 | + if (value == NULL) { | |
| 3774 | + PyErr_SetString(PyExc_TypeError, | |
| 3775 | + "Array does not support item deletion"); | |
| 3776 | + return -1; | |
| 3777 | + } | |
| 3778 | + | |
| 3779 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 3780 | + assert(stgdict); /* Cannot be NULL for array object instances */ | |
| 3781 | + if (index < 0 || index >= stgdict->length) { | |
| 3782 | + PyErr_SetString(PyExc_IndexError, | |
| 3783 | + "invalid index"); | |
| 3784 | + return -1; | |
| 3785 | + } | |
| 3786 | + size = stgdict->size / stgdict->length; | |
| 3787 | + offset = index * size; | |
| 3788 | + ptr = self->b_ptr + offset; | |
| 3789 | + | |
| 3790 | + return CData_set((PyObject *)self, stgdict->proto, stgdict->setfunc, value, | |
| 3791 | + index, size, ptr); | |
| 3792 | +} | |
| 3793 | + | |
| 3794 | +static int | |
| 3795 | +Array_ass_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *value) | |
| 3796 | +{ | |
| 3797 | + CDataObject *self = (CDataObject *)_self; | |
| 3798 | + int i, len; | |
| 3799 | + | |
| 3800 | + if (value == NULL) { | |
| 3801 | + PyErr_SetString(PyExc_TypeError, | |
| 3802 | + "Array does not support item deletion"); | |
| 3803 | + return -1; | |
| 3804 | + } | |
| 3805 | + | |
| 3806 | + if (ilow < 0) | |
| 3807 | + ilow = 0; | |
| 3808 | + else if (ilow > self->b_length) | |
| 3809 | + ilow = self->b_length; | |
| 3810 | + if (ihigh < 0) | |
| 3811 | + ihigh = 0; | |
| 3812 | + if (ihigh < ilow) | |
| 3813 | + ihigh = ilow; | |
| 3814 | + else if (ihigh > self->b_length) | |
| 3815 | + ihigh = self->b_length; | |
| 3816 | + | |
| 3817 | + len = PySequence_Length(value); | |
| 3818 | + if (len != ihigh - ilow) { | |
| 3819 | + PyErr_SetString(PyExc_ValueError, | |
| 3820 | + "Can only assign sequence of same size"); | |
| 3821 | + return -1; | |
| 3822 | + } | |
| 3823 | + for (i = 0; i < len; i++) { | |
| 3824 | + PyObject *item = PySequence_GetItem(value, i); | |
| 3825 | + int result; | |
| 3826 | + if (item == NULL) | |
| 3827 | + return -1; | |
| 3828 | + result = Array_ass_item(_self, i+ilow, item); | |
| 3829 | + Py_DECREF(item); | |
| 3830 | + if (result == -1) | |
| 3831 | + return -1; | |
| 3832 | + } | |
| 3833 | + return 0; | |
| 3834 | +} | |
| 3835 | + | |
| 3836 | +static Py_ssize_t | |
| 3837 | +Array_length(PyObject *_self) | |
| 3838 | +{ | |
| 3839 | + CDataObject *self = (CDataObject *)_self; | |
| 3840 | + return self->b_length; | |
| 3841 | +} | |
| 3842 | + | |
| 3843 | +static PySequenceMethods Array_as_sequence = { | |
| 3844 | + Array_length, /* sq_length; */ | |
| 3845 | + 0, /* sq_concat; */ | |
| 3846 | + 0, /* sq_repeat; */ | |
| 3847 | + Array_item, /* sq_item; */ | |
| 3848 | + Array_slice, /* sq_slice; */ | |
| 3849 | + Array_ass_item, /* sq_ass_item; */ | |
| 3850 | + Array_ass_slice, /* sq_ass_slice; */ | |
| 3851 | + 0, /* sq_contains; */ | |
| 3852 | + | |
| 3853 | + 0, /* sq_inplace_concat; */ | |
| 3854 | + 0, /* sq_inplace_repeat; */ | |
| 3855 | +}; | |
| 3856 | + | |
| 3857 | +PyTypeObject Array_Type = { | |
| 3858 | + PyObject_HEAD_INIT(NULL) | |
| 3859 | + 0, | |
| 3860 | + "_ctypes.Array", | |
| 3861 | + sizeof(CDataObject), /* tp_basicsize */ | |
| 3862 | + 0, /* tp_itemsize */ | |
| 3863 | + 0, /* tp_dealloc */ | |
| 3864 | + 0, /* tp_print */ | |
| 3865 | + 0, /* tp_getattr */ | |
| 3866 | + 0, /* tp_setattr */ | |
| 3867 | + 0, /* tp_compare */ | |
| 3868 | + 0, /* tp_repr */ | |
| 3869 | + 0, /* tp_as_number */ | |
| 3870 | + &Array_as_sequence, /* tp_as_sequence */ | |
| 3871 | + 0, /* tp_as_mapping */ | |
| 3872 | + 0, /* tp_hash */ | |
| 3873 | + 0, /* tp_call */ | |
| 3874 | + 0, /* tp_str */ | |
| 3875 | + 0, /* tp_getattro */ | |
| 3876 | + 0, /* tp_setattro */ | |
| 3877 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 3878 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 3879 | + "XXX to be provided", /* tp_doc */ | |
| 3880 | + (traverseproc)CData_traverse, /* tp_traverse */ | |
| 3881 | + (inquiry)CData_clear, /* tp_clear */ | |
| 3882 | + 0, /* tp_richcompare */ | |
| 3883 | + 0, /* tp_weaklistoffset */ | |
| 3884 | + 0, /* tp_iter */ | |
| 3885 | + 0, /* tp_iternext */ | |
| 3886 | + 0, /* tp_methods */ | |
| 3887 | + 0, /* tp_members */ | |
| 3888 | + 0, /* tp_getset */ | |
| 3889 | + 0, /* tp_base */ | |
| 3890 | + 0, /* tp_dict */ | |
| 3891 | + 0, /* tp_descr_get */ | |
| 3892 | + 0, /* tp_descr_set */ | |
| 3893 | + 0, /* tp_dictoffset */ | |
| 3894 | + (initproc)Array_init, /* tp_init */ | |
| 3895 | + 0, /* tp_alloc */ | |
| 3896 | + GenericCData_new, /* tp_new */ | |
| 3897 | + 0, /* tp_free */ | |
| 3898 | +}; | |
| 3899 | + | |
| 3900 | +PyObject * | |
| 3901 | +CreateArrayType(PyObject *itemtype, Py_ssize_t length) | |
| 3902 | +{ | |
| 3903 | + static PyObject *cache; | |
| 3904 | + PyObject *key; | |
| 3905 | + PyObject *result; | |
| 3906 | + char name[256]; | |
| 3907 | + | |
| 3908 | + if (cache == NULL) { | |
| 3909 | + cache = PyDict_New(); | |
| 3910 | + if (cache == NULL) | |
| 3911 | + return NULL; | |
| 3912 | + } | |
| 3913 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 3914 | + key = Py_BuildValue("(Oi)", itemtype, length); | |
| 3915 | +#else | |
| 3916 | + key = Py_BuildValue("(On)", itemtype, length); | |
| 3917 | +#endif | |
| 3918 | + if (!key) | |
| 3919 | + return NULL; | |
| 3920 | + result = PyDict_GetItem(cache, key); | |
| 3921 | + if (result) { | |
| 3922 | + Py_INCREF(result); | |
| 3923 | + Py_DECREF(key); | |
| 3924 | + return result; | |
| 3925 | + } | |
| 3926 | + | |
| 3927 | + if (!PyType_Check(itemtype)) { | |
| 3928 | + PyErr_SetString(PyExc_TypeError, | |
| 3929 | + "Expected a type object"); | |
| 3930 | + return NULL; | |
| 3931 | + } | |
| 3932 | +#ifdef MS_WIN64 | |
| 3933 | + sprintf(name, "%.200s_Array_%Id", | |
| 3934 | + ((PyTypeObject *)itemtype)->tp_name, length); | |
| 3935 | +#else | |
| 3936 | + sprintf(name, "%.200s_Array_%ld", | |
| 3937 | + ((PyTypeObject *)itemtype)->tp_name, (long)length); | |
| 3938 | +#endif | |
| 3939 | + | |
| 3940 | + result = PyObject_CallFunction((PyObject *)&ArrayType_Type, | |
| 3941 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 3942 | + "s(O){s:i,s:O}", | |
| 3943 | +#else | |
| 3944 | + "s(O){s:n,s:O}", | |
| 3945 | +#endif | |
| 3946 | + name, | |
| 3947 | + &Array_Type, | |
| 3948 | + "_length_", | |
| 3949 | + length, | |
| 3950 | + "_type_", | |
| 3951 | + itemtype | |
| 3952 | + ); | |
| 3953 | + if (!result) | |
| 3954 | + return NULL; | |
| 3955 | + PyDict_SetItem(cache, key, result); | |
| 3956 | + Py_DECREF(key); | |
| 3957 | + return result; | |
| 3958 | +} | |
| 3959 | + | |
| 3960 | + | |
| 3961 | +/******************************************************************/ | |
| 3962 | +/* | |
| 3963 | + Simple_Type | |
| 3964 | +*/ | |
| 3965 | + | |
| 3966 | +static int | |
| 3967 | +Simple_set_value(CDataObject *self, PyObject *value) | |
| 3968 | +{ | |
| 3969 | + PyObject *result; | |
| 3970 | + StgDictObject *dict = PyObject_stgdict((PyObject *)self); | |
| 3971 | + | |
| 3972 | + assert(dict); /* Cannot be NULL for CDataObject instances */ | |
| 3973 | + assert(dict->setfunc); | |
| 3974 | + result = dict->setfunc(self->b_ptr, value, dict->size); | |
| 3975 | + if (!result) | |
| 3976 | + return -1; | |
| 3977 | + | |
| 3978 | + /* consumes the refcount the setfunc returns */ | |
| 3979 | + return KeepRef(self, 0, result); | |
| 3980 | +} | |
| 3981 | + | |
| 3982 | +static int | |
| 3983 | +Simple_init(CDataObject *self, PyObject *args, PyObject *kw) | |
| 3984 | +{ | |
| 3985 | + PyObject *value = NULL; | |
| 3986 | + if (!PyArg_UnpackTuple(args, "__init__", 0, 1, &value)) | |
| 3987 | + return -1; | |
| 3988 | + if (value) | |
| 3989 | + return Simple_set_value(self, value); | |
| 3990 | + return 0; | |
| 3991 | +} | |
| 3992 | + | |
| 3993 | +static PyObject * | |
| 3994 | +Simple_get_value(CDataObject *self) | |
| 3995 | +{ | |
| 3996 | + StgDictObject *dict; | |
| 3997 | + dict = PyObject_stgdict((PyObject *)self); | |
| 3998 | + assert(dict); /* Cannot be NULL for CDataObject instances */ | |
| 3999 | + assert(dict->getfunc); | |
| 4000 | + return dict->getfunc(self->b_ptr, self->b_size); | |
| 4001 | +} | |
| 4002 | + | |
| 4003 | +static PyGetSetDef Simple_getsets[] = { | |
| 4004 | + { "value", (getter)Simple_get_value, (setter)Simple_set_value, | |
| 4005 | + "current value", NULL }, | |
| 4006 | + { NULL, NULL } | |
| 4007 | +}; | |
| 4008 | + | |
| 4009 | +static PyObject * | |
| 4010 | +Simple_from_outparm(PyObject *self, PyObject *args) | |
| 4011 | +{ | |
| 4012 | + if (IsSimpleSubType((PyObject *)self->ob_type)) { | |
| 4013 | + Py_INCREF(self); | |
| 4014 | + return self; | |
| 4015 | + } | |
| 4016 | + /* call stgdict->getfunc */ | |
| 4017 | + return Simple_get_value((CDataObject *)self); | |
| 4018 | +} | |
| 4019 | + | |
| 4020 | +static PyMethodDef Simple_methods[] = { | |
| 4021 | + { "__ctypes_from_outparam__", Simple_from_outparm, METH_NOARGS, }, | |
| 4022 | + { NULL, NULL }, | |
| 4023 | +}; | |
| 4024 | + | |
| 4025 | +static int Simple_nonzero(CDataObject *self) | |
| 4026 | +{ | |
| 4027 | + return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size); | |
| 4028 | +} | |
| 4029 | + | |
| 4030 | +static PyNumberMethods Simple_as_number = { | |
| 4031 | + 0, /* nb_add */ | |
| 4032 | + 0, /* nb_subtract */ | |
| 4033 | + 0, /* nb_multiply */ | |
| 4034 | + 0, /* nb_divide */ | |
| 4035 | + 0, /* nb_remainder */ | |
| 4036 | + 0, /* nb_divmod */ | |
| 4037 | + 0, /* nb_power */ | |
| 4038 | + 0, /* nb_negative */ | |
| 4039 | + 0, /* nb_positive */ | |
| 4040 | + 0, /* nb_absolute */ | |
| 4041 | + (inquiry)Simple_nonzero, /* nb_nonzero */ | |
| 4042 | +}; | |
| 4043 | + | |
| 4044 | +#if (PY_VERSION_HEX < 0x02040000) | |
| 4045 | +/* Only in Python 2.4 and up */ | |
| 4046 | +static PyObject * | |
| 4047 | +PyTuple_Pack(int n, ...) | |
| 4048 | +{ | |
| 4049 | + int i; | |
| 4050 | + PyObject *o; | |
| 4051 | + PyObject *result; | |
| 4052 | + PyObject **items; | |
| 4053 | + va_list vargs; | |
| 4054 | + | |
| 4055 | + va_start(vargs, n); | |
| 4056 | + result = PyTuple_New(n); | |
| 4057 | + if (result == NULL) | |
| 4058 | + return NULL; | |
| 4059 | + items = ((PyTupleObject *)result)->ob_item; | |
| 4060 | + for (i = 0; i < n; i++) { | |
| 4061 | + o = va_arg(vargs, PyObject *); | |
| 4062 | + Py_INCREF(o); | |
| 4063 | + items[i] = o; | |
| 4064 | + } | |
| 4065 | + va_end(vargs); | |
| 4066 | + return result; | |
| 4067 | +} | |
| 4068 | +#endif | |
| 4069 | + | |
| 4070 | +/* "%s(%s)" % (self.__class__.__name__, self.value) */ | |
| 4071 | +static PyObject * | |
| 4072 | +Simple_repr(CDataObject *self) | |
| 4073 | +{ | |
| 4074 | + PyObject *val, *name, *args, *result; | |
| 4075 | + static PyObject *format; | |
| 4076 | + | |
| 4077 | + if (self->ob_type->tp_base != &Simple_Type) { | |
| 4078 | + return PyString_FromFormat("<%s object at %p>", | |
| 4079 | + self->ob_type->tp_name, self); | |
| 4080 | + } | |
| 4081 | + | |
| 4082 | + if (format == NULL) { | |
| 4083 | + format = PyString_FromString("%s(%r)"); | |
| 4084 | + if (format == NULL) | |
| 4085 | + return NULL; | |
| 4086 | + } | |
| 4087 | + | |
| 4088 | + val = Simple_get_value(self); | |
| 4089 | + if (val == NULL) | |
| 4090 | + return NULL; | |
| 4091 | + | |
| 4092 | + name = PyString_FromString(self->ob_type->tp_name); | |
| 4093 | + if (name == NULL) { | |
| 4094 | + Py_DECREF(val); | |
| 4095 | + return NULL; | |
| 4096 | + } | |
| 4097 | + | |
| 4098 | + args = PyTuple_Pack(2, name, val); | |
| 4099 | + Py_DECREF(name); | |
| 4100 | + Py_DECREF(val); | |
| 4101 | + if (args == NULL) | |
| 4102 | + return NULL; | |
| 4103 | + | |
| 4104 | + result = PyString_Format(format, args); | |
| 4105 | + Py_DECREF(args); | |
| 4106 | + return result; | |
| 4107 | +} | |
| 4108 | + | |
| 4109 | +static PyTypeObject Simple_Type = { | |
| 4110 | + PyObject_HEAD_INIT(NULL) | |
| 4111 | + 0, | |
| 4112 | + "_ctypes._SimpleCData", | |
| 4113 | + sizeof(CDataObject), /* tp_basicsize */ | |
| 4114 | + 0, /* tp_itemsize */ | |
| 4115 | + 0, /* tp_dealloc */ | |
| 4116 | + 0, /* tp_print */ | |
| 4117 | + 0, /* tp_getattr */ | |
| 4118 | + 0, /* tp_setattr */ | |
| 4119 | + 0, /* tp_compare */ | |
| 4120 | + (reprfunc)&Simple_repr, /* tp_repr */ | |
| 4121 | + &Simple_as_number, /* tp_as_number */ | |
| 4122 | + 0, /* tp_as_sequence */ | |
| 4123 | + 0, /* tp_as_mapping */ | |
| 4124 | + 0, /* tp_hash */ | |
| 4125 | + 0, /* tp_call */ | |
| 4126 | + 0, /* tp_str */ | |
| 4127 | + 0, /* tp_getattro */ | |
| 4128 | + 0, /* tp_setattro */ | |
| 4129 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 4130 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 4131 | + "XXX to be provided", /* tp_doc */ | |
| 4132 | + (traverseproc)CData_traverse, /* tp_traverse */ | |
| 4133 | + (inquiry)CData_clear, /* tp_clear */ | |
| 4134 | + 0, /* tp_richcompare */ | |
| 4135 | + 0, /* tp_weaklistoffset */ | |
| 4136 | + 0, /* tp_iter */ | |
| 4137 | + 0, /* tp_iternext */ | |
| 4138 | + Simple_methods, /* tp_methods */ | |
| 4139 | + 0, /* tp_members */ | |
| 4140 | + Simple_getsets, /* tp_getset */ | |
| 4141 | + 0, /* tp_base */ | |
| 4142 | + 0, /* tp_dict */ | |
| 4143 | + 0, /* tp_descr_get */ | |
| 4144 | + 0, /* tp_descr_set */ | |
| 4145 | + 0, /* tp_dictoffset */ | |
| 4146 | + (initproc)Simple_init, /* tp_init */ | |
| 4147 | + 0, /* tp_alloc */ | |
| 4148 | + GenericCData_new, /* tp_new */ | |
| 4149 | + 0, /* tp_free */ | |
| 4150 | +}; | |
| 4151 | + | |
| 4152 | +/******************************************************************/ | |
| 4153 | +/* | |
| 4154 | + Pointer_Type | |
| 4155 | +*/ | |
| 4156 | +static PyObject * | |
| 4157 | +Pointer_item(PyObject *_self, Py_ssize_t index) | |
| 4158 | +{ | |
| 4159 | + CDataObject *self = (CDataObject *)_self; | |
| 4160 | + int size; | |
| 4161 | + Py_ssize_t offset; | |
| 4162 | + StgDictObject *stgdict, *itemdict; | |
| 4163 | + PyObject *proto; | |
| 4164 | + | |
| 4165 | + if (*(void **)self->b_ptr == NULL) { | |
| 4166 | + PyErr_SetString(PyExc_ValueError, | |
| 4167 | + "NULL pointer access"); | |
| 4168 | + return NULL; | |
| 4169 | + } | |
| 4170 | + | |
| 4171 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 4172 | + assert(stgdict); /* Cannot be NULL for pointer object instances */ | |
| 4173 | + | |
| 4174 | + proto = stgdict->proto; | |
| 4175 | + assert(proto); | |
| 4176 | + itemdict = PyType_stgdict(proto); | |
| 4177 | + assert(itemdict); /* proto is the item type of the pointer, a ctypes | |
| 4178 | + type, so this cannot be NULL */ | |
| 4179 | + | |
| 4180 | + size = itemdict->size; | |
| 4181 | + offset = index * itemdict->size; | |
| 4182 | + | |
| 4183 | + return CData_get(proto, stgdict->getfunc, (PyObject *)self, | |
| 4184 | + index, size, (*(char **)self->b_ptr) + offset); | |
| 4185 | +} | |
| 4186 | + | |
| 4187 | +static int | |
| 4188 | +Pointer_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value) | |
| 4189 | +{ | |
| 4190 | + CDataObject *self = (CDataObject *)_self; | |
| 4191 | + int size; | |
| 4192 | + Py_ssize_t offset; | |
| 4193 | + StgDictObject *stgdict, *itemdict; | |
| 4194 | + PyObject *proto; | |
| 4195 | + | |
| 4196 | + if (value == NULL) { | |
| 4197 | + PyErr_SetString(PyExc_TypeError, | |
| 4198 | + "Pointer does not support item deletion"); | |
| 4199 | + return -1; | |
| 4200 | + } | |
| 4201 | + | |
| 4202 | + if (*(void **)self->b_ptr == NULL) { | |
| 4203 | + PyErr_SetString(PyExc_ValueError, | |
| 4204 | + "NULL pointer access"); | |
| 4205 | + return -1; | |
| 4206 | + } | |
| 4207 | + | |
| 4208 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 4209 | + assert(stgdict); /* Cannot be NULL fr pointer instances */ | |
| 4210 | + | |
| 4211 | + proto = stgdict->proto; | |
| 4212 | + assert(proto); | |
| 4213 | + | |
| 4214 | + itemdict = PyType_stgdict(proto); | |
| 4215 | + assert(itemdict); /* Cannot be NULL because the itemtype of a pointer | |
| 4216 | + is always a ctypes type */ | |
| 4217 | + | |
| 4218 | + size = itemdict->size; | |
| 4219 | + offset = index * itemdict->size; | |
| 4220 | + | |
| 4221 | + return CData_set((PyObject *)self, proto, stgdict->setfunc, value, | |
| 4222 | + index, size, (*(char **)self->b_ptr) + offset); | |
| 4223 | +} | |
| 4224 | + | |
| 4225 | +static PyObject * | |
| 4226 | +Pointer_get_contents(CDataObject *self, void *closure) | |
| 4227 | +{ | |
| 4228 | + StgDictObject *stgdict; | |
| 4229 | + | |
| 4230 | + if (*(void **)self->b_ptr == NULL) { | |
| 4231 | + PyErr_SetString(PyExc_ValueError, | |
| 4232 | + "NULL pointer access"); | |
| 4233 | + return NULL; | |
| 4234 | + } | |
| 4235 | + | |
| 4236 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 4237 | + assert(stgdict); /* Cannot be NULL fr pointer instances */ | |
| 4238 | + return CData_FromBaseObj(stgdict->proto, | |
| 4239 | + (PyObject *)self, 0, | |
| 4240 | + *(void **)self->b_ptr); | |
| 4241 | +} | |
| 4242 | + | |
| 4243 | +static int | |
| 4244 | +Pointer_set_contents(CDataObject *self, PyObject *value, void *closure) | |
| 4245 | +{ | |
| 4246 | + StgDictObject *stgdict; | |
| 4247 | + CDataObject *dst; | |
| 4248 | + PyObject *keep; | |
| 4249 | + | |
| 4250 | + if (value == NULL) { | |
| 4251 | + PyErr_SetString(PyExc_TypeError, | |
| 4252 | + "Pointer does not support item deletion"); | |
| 4253 | + return -1; | |
| 4254 | + } | |
| 4255 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 4256 | + assert(stgdict); /* Cannot be NULL fr pointer instances */ | |
| 4257 | + assert(stgdict->proto); | |
| 4258 | + if (!CDataObject_Check(value) | |
| 4259 | + || 0 == PyObject_IsInstance(value, stgdict->proto)) { | |
| 4260 | + /* XXX PyObject_IsInstance could return -1! */ | |
| 4261 | + PyErr_Format(PyExc_TypeError, | |
| 4262 | + "expected %s instead of %s", | |
| 4263 | + ((PyTypeObject *)(stgdict->proto))->tp_name, | |
| 4264 | + value->ob_type->tp_name); | |
| 4265 | + return -1; | |
| 4266 | + } | |
| 4267 | + | |
| 4268 | + dst = (CDataObject *)value; | |
| 4269 | + *(void **)self->b_ptr = dst->b_ptr; | |
| 4270 | + | |
| 4271 | + /* | |
| 4272 | + A Pointer instance must keep a the value it points to alive. So, a | |
| 4273 | + pointer instance has b_length set to 2 instead of 1, and we set | |
| 4274 | + 'value' itself as the second item of the b_objects list, additionally. | |
| 4275 | + */ | |
| 4276 | + Py_INCREF(value); | |
| 4277 | + if (-1 == KeepRef(self, 1, value)) | |
| 4278 | + return -1; | |
| 4279 | + | |
| 4280 | + keep = GetKeepedObjects(dst); | |
| 4281 | + Py_INCREF(keep); | |
| 4282 | + return KeepRef(self, 0, keep); | |
| 4283 | +} | |
| 4284 | + | |
| 4285 | +static PyGetSetDef Pointer_getsets[] = { | |
| 4286 | + { "contents", (getter)Pointer_get_contents, | |
| 4287 | + (setter)Pointer_set_contents, | |
| 4288 | + "the object this pointer points to (read-write)", NULL }, | |
| 4289 | + { NULL, NULL } | |
| 4290 | +}; | |
| 4291 | + | |
| 4292 | +static int | |
| 4293 | +Pointer_init(CDataObject *self, PyObject *args, PyObject *kw) | |
| 4294 | +{ | |
| 4295 | + PyObject *value = NULL; | |
| 4296 | + | |
| 4297 | + if (!PyArg_ParseTuple(args, "|O:POINTER", &value)) | |
| 4298 | + return -1; | |
| 4299 | + if (value == NULL) | |
| 4300 | + return 0; | |
| 4301 | + return Pointer_set_contents(self, value, NULL); | |
| 4302 | +} | |
| 4303 | + | |
| 4304 | +static PyObject * | |
| 4305 | +Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw) | |
| 4306 | +{ | |
| 4307 | + StgDictObject *dict = PyType_stgdict((PyObject *)type); | |
| 4308 | + if (!dict || !dict->proto) { | |
| 4309 | + PyErr_SetString(PyExc_TypeError, | |
| 4310 | + "Cannot create instance: has no _type_"); | |
| 4311 | + return NULL; | |
| 4312 | + } | |
| 4313 | + return GenericCData_new(type, args, kw); | |
| 4314 | +} | |
| 4315 | + | |
| 4316 | +static PyObject * | |
| 4317 | +Pointer_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh) | |
| 4318 | +{ | |
| 4319 | + CDataObject *self = (CDataObject *)_self; | |
| 4320 | + PyListObject *np; | |
| 4321 | + StgDictObject *stgdict, *itemdict; | |
| 4322 | + PyObject *proto; | |
| 4323 | + Py_ssize_t i, len; | |
| 4324 | + | |
| 4325 | + if (ilow < 0) | |
| 4326 | + ilow = 0; | |
| 4327 | + if (ihigh < ilow) | |
| 4328 | + ihigh = ilow; | |
| 4329 | + len = ihigh - ilow; | |
| 4330 | + | |
| 4331 | + stgdict = PyObject_stgdict((PyObject *)self); | |
| 4332 | + assert(stgdict); /* Cannot be NULL fr pointer instances */ | |
| 4333 | + proto = stgdict->proto; | |
| 4334 | + assert(proto); | |
| 4335 | + itemdict = PyType_stgdict(proto); | |
| 4336 | + assert(itemdict); | |
| 4337 | + if (itemdict->getfunc == getentry("c")->getfunc) { | |
| 4338 | + char *ptr = *(char **)self->b_ptr; | |
| 4339 | + return PyString_FromStringAndSize(ptr + ilow, len); | |
| 4340 | +#ifdef CTYPES_UNICODE | |
| 4341 | + } else if (itemdict->getfunc == getentry("u")->getfunc) { | |
| 4342 | + wchar_t *ptr = *(wchar_t **)self->b_ptr; | |
| 4343 | + return PyUnicode_FromWideChar(ptr + ilow, len); | |
| 4344 | +#endif | |
| 4345 | + } | |
| 4346 | + | |
| 4347 | + np = (PyListObject *) PyList_New(len); | |
| 4348 | + if (np == NULL) | |
| 4349 | + return NULL; | |
| 4350 | + | |
| 4351 | + for (i = 0; i < len; i++) { | |
| 4352 | + PyObject *v = Pointer_item(_self, i+ilow); | |
| 4353 | + PyList_SET_ITEM(np, i, v); | |
| 4354 | + } | |
| 4355 | + return (PyObject *)np; | |
| 4356 | +} | |
| 4357 | + | |
| 4358 | +static PySequenceMethods Pointer_as_sequence = { | |
| 4359 | + 0, /* inquiry sq_length; */ | |
| 4360 | + 0, /* binaryfunc sq_concat; */ | |
| 4361 | + 0, /* intargfunc sq_repeat; */ | |
| 4362 | + Pointer_item, /* intargfunc sq_item; */ | |
| 4363 | + Pointer_slice, /* intintargfunc sq_slice; */ | |
| 4364 | + Pointer_ass_item, /* intobjargproc sq_ass_item; */ | |
| 4365 | + 0, /* intintobjargproc sq_ass_slice; */ | |
| 4366 | + 0, /* objobjproc sq_contains; */ | |
| 4367 | + /* Added in release 2.0 */ | |
| 4368 | + 0, /* binaryfunc sq_inplace_concat; */ | |
| 4369 | + 0, /* intargfunc sq_inplace_repeat; */ | |
| 4370 | +}; | |
| 4371 | + | |
| 4372 | +static int | |
| 4373 | +Pointer_nonzero(CDataObject *self) | |
| 4374 | +{ | |
| 4375 | + return *(void **)self->b_ptr != NULL; | |
| 4376 | +} | |
| 4377 | + | |
| 4378 | +static PyNumberMethods Pointer_as_number = { | |
| 4379 | + 0, /* nb_add */ | |
| 4380 | + 0, /* nb_subtract */ | |
| 4381 | + 0, /* nb_multiply */ | |
| 4382 | + 0, /* nb_divide */ | |
| 4383 | + 0, /* nb_remainder */ | |
| 4384 | + 0, /* nb_divmod */ | |
| 4385 | + 0, /* nb_power */ | |
| 4386 | + 0, /* nb_negative */ | |
| 4387 | + 0, /* nb_positive */ | |
| 4388 | + 0, /* nb_absolute */ | |
| 4389 | + (inquiry)Pointer_nonzero, /* nb_nonzero */ | |
| 4390 | +}; | |
| 4391 | + | |
| 4392 | +PyTypeObject Pointer_Type = { | |
| 4393 | + PyObject_HEAD_INIT(NULL) | |
| 4394 | + 0, | |
| 4395 | + "_ctypes._Pointer", | |
| 4396 | + sizeof(CDataObject), /* tp_basicsize */ | |
| 4397 | + 0, /* tp_itemsize */ | |
| 4398 | + 0, /* tp_dealloc */ | |
| 4399 | + 0, /* tp_print */ | |
| 4400 | + 0, /* tp_getattr */ | |
| 4401 | + 0, /* tp_setattr */ | |
| 4402 | + 0, /* tp_compare */ | |
| 4403 | + 0, /* tp_repr */ | |
| 4404 | + &Pointer_as_number, /* tp_as_number */ | |
| 4405 | + &Pointer_as_sequence, /* tp_as_sequence */ | |
| 4406 | + 0, /* tp_as_mapping */ | |
| 4407 | + 0, /* tp_hash */ | |
| 4408 | + 0, /* tp_call */ | |
| 4409 | + 0, /* tp_str */ | |
| 4410 | + 0, /* tp_getattro */ | |
| 4411 | + 0, /* tp_setattro */ | |
| 4412 | + &CData_as_buffer, /* tp_as_buffer */ | |
| 4413 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
| 4414 | + "XXX to be provided", /* tp_doc */ | |
| 4415 | + (traverseproc)CData_traverse, /* tp_traverse */ | |
| 4416 | + (inquiry)CData_clear, /* tp_clear */ | |
| 4417 | + 0, /* tp_richcompare */ | |
| 4418 | + 0, /* tp_weaklistoffset */ | |
| 4419 | + 0, /* tp_iter */ | |
| 4420 | + 0, /* tp_iternext */ | |
| 4421 | + 0, /* tp_methods */ | |
| 4422 | + 0, /* tp_members */ | |
| 4423 | + Pointer_getsets, /* tp_getset */ | |
| 4424 | + 0, /* tp_base */ | |
| 4425 | + 0, /* tp_dict */ | |
| 4426 | + 0, /* tp_descr_get */ | |
| 4427 | + 0, /* tp_descr_set */ | |
| 4428 | + 0, /* tp_dictoffset */ | |
| 4429 | + (initproc)Pointer_init, /* tp_init */ | |
| 4430 | + 0, /* tp_alloc */ | |
| 4431 | + Pointer_new, /* tp_new */ | |
| 4432 | + 0, /* tp_free */ | |
| 4433 | +}; | |
| 4434 | + | |
| 4435 | + | |
| 4436 | +/******************************************************************/ | |
| 4437 | +/* | |
| 4438 | + * Module initialization. | |
| 4439 | + */ | |
| 4440 | + | |
| 4441 | +static char *module_docs = | |
| 4442 | +"Create and manipulate C compatible data types in Python."; | |
| 4443 | + | |
| 4444 | +#ifdef MS_WIN32 | |
| 4445 | + | |
| 4446 | +static char comerror_doc[] = "Raised when a COM method call failed."; | |
| 4447 | + | |
| 4448 | +static PyObject * | |
| 4449 | +comerror_str(PyObject *ignored, PyObject *self) | |
| 4450 | +{ | |
| 4451 | + PyObject *args = PyObject_GetAttrString(self, "args"); | |
| 4452 | + PyObject *result; | |
| 4453 | + if (args == NULL) | |
| 4454 | + return NULL; | |
| 4455 | + result = PyObject_Str(args); | |
| 4456 | + Py_DECREF(args); | |
| 4457 | + return result; | |
| 4458 | +} | |
| 4459 | + | |
| 4460 | +static PyObject * | |
| 4461 | +comerror_init(PyObject *self, PyObject *args) | |
| 4462 | +{ | |
| 4463 | + PyObject *hresult, *text, *details; | |
| 4464 | + PyObject *a; | |
| 4465 | + int status; | |
| 4466 | + | |
| 4467 | + if (!PyArg_ParseTuple(args, "OOOO:COMError", &self, &hresult, &text, &details)) | |
| 4468 | + return NULL; | |
| 4469 | + | |
| 4470 | + a = PySequence_GetSlice(args, 1, PySequence_Size(args)); | |
| 4471 | + if (!a) | |
| 4472 | + return NULL; | |
| 4473 | + status = PyObject_SetAttrString(self, "args", a); | |
| 4474 | + Py_DECREF(a); | |
| 4475 | + if (status < 0) | |
| 4476 | + return NULL; | |
| 4477 | + | |
| 4478 | + if (PyObject_SetAttrString(self, "hresult", hresult) < 0) | |
| 4479 | + return NULL; | |
| 4480 | + | |
| 4481 | + if (PyObject_SetAttrString(self, "text", text) < 0) | |
| 4482 | + return NULL; | |
| 4483 | + | |
| 4484 | + if (PyObject_SetAttrString(self, "details", details) < 0) | |
| 4485 | + return NULL; | |
| 4486 | + | |
| 4487 | + Py_INCREF(Py_None); | |
| 4488 | + return Py_None; | |
| 4489 | +} | |
| 4490 | + | |
| 4491 | +static PyMethodDef comerror_methods[] = { | |
| 4492 | + { "__str__", comerror_str, METH_O }, | |
| 4493 | + { "__init__", comerror_init, METH_VARARGS }, | |
| 4494 | + { NULL, NULL }, | |
| 4495 | +}; | |
| 4496 | + | |
| 4497 | +PyObject *COMError; | |
| 4498 | + | |
| 4499 | +static int | |
| 4500 | +create_comerror(void) | |
| 4501 | +{ | |
| 4502 | + PyObject *dict = PyDict_New(); | |
| 4503 | + PyMethodDef *methods = comerror_methods; | |
| 4504 | + PyObject *s; | |
| 4505 | + int status; | |
| 4506 | + | |
| 4507 | + ComError = PyErr_NewException("_ctypes.COMError", | |
| 4508 | + NULL, | |
| 4509 | + dict); | |
| 4510 | + if (ComError == NULL) | |
| 4511 | + return -1; | |
| 4512 | + while (methods->ml_name) { | |
| 4513 | + /* get a wrapper for the built-in function */ | |
| 4514 | + PyObject *func = PyCFunction_New(methods, NULL); | |
| 4515 | + PyObject *meth; | |
| 4516 | + if (func == NULL) | |
| 4517 | + return -1; | |
| 4518 | + meth = PyMethod_New(func, NULL, ComError); | |
| 4519 | + Py_DECREF(func); | |
| 4520 | + if (meth == NULL) | |
| 4521 | + return -1; | |
| 4522 | + PyDict_SetItemString(dict, methods->ml_name, meth); | |
| 4523 | + Py_DECREF(meth); | |
| 4524 | + ++methods; | |
| 4525 | + } | |
| 4526 | + Py_INCREF(ComError); | |
| 4527 | + s = PyString_FromString(comerror_doc); | |
| 4528 | + if (s == NULL) | |
| 4529 | + return -1; | |
| 4530 | + status = PyDict_SetItemString(dict, "__doc__", s); | |
| 4531 | + Py_DECREF(s); | |
| 4532 | + return status; | |
| 4533 | +} | |
| 4534 | + | |
| 4535 | +#endif | |
| 4536 | + | |
| 4537 | +static PyObject * | |
| 4538 | +string_at(const char *ptr, int size) | |
| 4539 | +{ | |
| 4540 | + if (size == -1) | |
| 4541 | + return PyString_FromString(ptr); | |
| 4542 | + return PyString_FromStringAndSize(ptr, size); | |
| 4543 | +} | |
| 4544 | + | |
| 4545 | +static int | |
| 4546 | +cast_check_pointertype(PyObject *arg) | |
| 4547 | +{ | |
| 4548 | + StgDictObject *dict; | |
| 4549 | + | |
| 4550 | + if (PointerTypeObject_Check(arg)) | |
| 4551 | + return 1; | |
| 4552 | + if (CFuncPtrTypeObject_Check(arg)) | |
| 4553 | + return 1; | |
| 4554 | + dict = PyType_stgdict(arg); | |
| 4555 | + if (dict) { | |
| 4556 | + if (PyString_Check(dict->proto) | |
| 4557 | + && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) { | |
| 4558 | + /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ | |
| 4559 | + return 1; | |
| 4560 | + } | |
| 4561 | + } | |
| 4562 | + PyErr_Format(PyExc_TypeError, | |
| 4563 | + "cast() argument 2 must be a pointer type, not %s", | |
| 4564 | + PyType_Check(arg) | |
| 4565 | + ? ((PyTypeObject *)arg)->tp_name | |
| 4566 | + : arg->ob_type->tp_name); | |
| 4567 | + return 0; | |
| 4568 | +} | |
| 4569 | + | |
| 4570 | +static PyObject * | |
| 4571 | +cast(void *ptr, PyObject *src, PyObject *ctype) | |
| 4572 | +{ | |
| 4573 | + CDataObject *result; | |
| 4574 | + if (0 == cast_check_pointertype(ctype)) | |
| 4575 | + return NULL; | |
| 4576 | + result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL); | |
| 4577 | + if (result == NULL) | |
| 4578 | + return NULL; | |
| 4579 | + | |
| 4580 | + /* | |
| 4581 | + The casted objects '_objects' member: | |
| 4582 | + | |
| 4583 | + It must certainly contain the source objects one. | |
| 4584 | + It must contain the source object itself. | |
| 4585 | + */ | |
| 4586 | + if (CDataObject_Check(src)) { | |
| 4587 | + CDataObject *obj = (CDataObject *)src; | |
| 4588 | + /* CData_GetContainer will initialize src.b_objects, we need | |
| 4589 | + this so it can be shared */ | |
| 4590 | + CData_GetContainer(obj); | |
| 4591 | + /* But we need a dictionary! */ | |
| 4592 | + if (obj->b_objects == Py_None) { | |
| 4593 | + Py_DECREF(Py_None); | |
| 4594 | + obj->b_objects = PyDict_New(); | |
| 4595 | + if (obj->b_objects == NULL) | |
| 4596 | + goto failed; | |
| 4597 | + } | |
| 4598 | + Py_XINCREF(obj->b_objects); | |
| 4599 | + result->b_objects = obj->b_objects; | |
| 4600 | + if (result->b_objects && PyDict_Check(result->b_objects)) { | |
| 4601 | + PyObject *index; | |
| 4602 | + int rc; | |
| 4603 | + index = PyLong_FromVoidPtr((void *)src); | |
| 4604 | + if (index == NULL) | |
| 4605 | + goto failed; | |
| 4606 | + rc = PyDict_SetItem(result->b_objects, index, src); | |
| 4607 | + Py_DECREF(index); | |
| 4608 | + if (rc == -1) | |
| 4609 | + goto failed; | |
| 4610 | + } | |
| 4611 | + } | |
| 4612 | + /* Should we assert that result is a pointer type? */ | |
| 4613 | + memcpy(result->b_ptr, &ptr, sizeof(void *)); | |
| 4614 | + return (PyObject *)result; | |
| 4615 | + | |
| 4616 | + failed: | |
| 4617 | + Py_DECREF(result); | |
| 4618 | + return NULL; | |
| 4619 | +} | |
| 4620 | + | |
| 4621 | +#ifdef CTYPES_UNICODE | |
| 4622 | +static PyObject * | |
| 4623 | +wstring_at(const wchar_t *ptr, int size) | |
| 4624 | +{ | |
| 4625 | + if (size == -1) | |
| 4626 | + size = wcslen(ptr); | |
| 4627 | + return PyUnicode_FromWideChar(ptr, size); | |
| 4628 | +} | |
| 4629 | +#endif | |
| 4630 | + | |
| 4631 | +PyMODINIT_FUNC | |
| 4632 | +init_ctypes(void) | |
| 4633 | +{ | |
| 4634 | + PyObject *m; | |
| 4635 | + | |
| 4636 | +/* Note: | |
| 4637 | + ob_type is the metatype (the 'type'), defaults to PyType_Type, | |
| 4638 | + tp_base is the base type, defaults to 'object' aka PyBaseObject_Type. | |
| 4639 | +*/ | |
| 4640 | +#ifdef WITH_THREAD | |
| 4641 | + PyEval_InitThreads(); | |
| 4642 | +#endif | |
| 4643 | + m = Py_InitModule3("_ctypes", module_methods, module_docs); | |
| 4644 | + if (!m) | |
| 4645 | + return; | |
| 4646 | + | |
| 4647 | + if (PyType_Ready(&PyCArg_Type) < 0) | |
| 4648 | + return; | |
| 4649 | + | |
| 4650 | + /* StgDict is derived from PyDict_Type */ | |
| 4651 | + StgDict_Type.tp_base = &PyDict_Type; | |
| 4652 | + if (PyType_Ready(&StgDict_Type) < 0) | |
| 4653 | + return; | |
| 4654 | + | |
| 4655 | + /************************************************* | |
| 4656 | + * | |
| 4657 | + * Metaclasses | |
| 4658 | + */ | |
| 4659 | + | |
| 4660 | + StructType_Type.tp_base = &PyType_Type; | |
| 4661 | + if (PyType_Ready(&StructType_Type) < 0) | |
| 4662 | + return; | |
| 4663 | + | |
| 4664 | + UnionType_Type.tp_base = &PyType_Type; | |
| 4665 | + if (PyType_Ready(&UnionType_Type) < 0) | |
| 4666 | + return; | |
| 4667 | + | |
| 4668 | + PointerType_Type.tp_base = &PyType_Type; | |
| 4669 | + if (PyType_Ready(&PointerType_Type) < 0) | |
| 4670 | + return; | |
| 4671 | + | |
| 4672 | + ArrayType_Type.tp_base = &PyType_Type; | |
| 4673 | + if (PyType_Ready(&ArrayType_Type) < 0) | |
| 4674 | + return; | |
| 4675 | + | |
| 4676 | + SimpleType_Type.tp_base = &PyType_Type; | |
| 4677 | + if (PyType_Ready(&SimpleType_Type) < 0) | |
| 4678 | + return; | |
| 4679 | + | |
| 4680 | + CFuncPtrType_Type.tp_base = &PyType_Type; | |
| 4681 | + if (PyType_Ready(&CFuncPtrType_Type) < 0) | |
| 4682 | + return; | |
| 4683 | + | |
| 4684 | + /************************************************* | |
| 4685 | + * | |
| 4686 | + * Classes using a custom metaclass | |
| 4687 | + */ | |
| 4688 | + | |
| 4689 | + if (PyType_Ready(&CData_Type) < 0) | |
| 4690 | + return; | |
| 4691 | + | |
| 4692 | + Struct_Type.ob_type = &StructType_Type; | |
| 4693 | + Struct_Type.tp_base = &CData_Type; | |
| 4694 | + if (PyType_Ready(&Struct_Type) < 0) | |
| 4695 | + return; | |
| 4696 | + PyModule_AddObject(m, "Structure", (PyObject *)&Struct_Type); | |
| 4697 | + | |
| 4698 | + Union_Type.ob_type = &UnionType_Type; | |
| 4699 | + Union_Type.tp_base = &CData_Type; | |
| 4700 | + if (PyType_Ready(&Union_Type) < 0) | |
| 4701 | + return; | |
| 4702 | + PyModule_AddObject(m, "Union", (PyObject *)&Union_Type); | |
| 4703 | + | |
| 4704 | + Pointer_Type.ob_type = &PointerType_Type; | |
| 4705 | + Pointer_Type.tp_base = &CData_Type; | |
| 4706 | + if (PyType_Ready(&Pointer_Type) < 0) | |
| 4707 | + return; | |
| 4708 | + PyModule_AddObject(m, "_Pointer", (PyObject *)&Pointer_Type); | |
| 4709 | + | |
| 4710 | + Array_Type.ob_type = &ArrayType_Type; | |
| 4711 | + Array_Type.tp_base = &CData_Type; | |
| 4712 | + if (PyType_Ready(&Array_Type) < 0) | |
| 4713 | + return; | |
| 4714 | + PyModule_AddObject(m, "Array", (PyObject *)&Array_Type); | |
| 4715 | + | |
| 4716 | + Simple_Type.ob_type = &SimpleType_Type; | |
| 4717 | + Simple_Type.tp_base = &CData_Type; | |
| 4718 | + if (PyType_Ready(&Simple_Type) < 0) | |
| 4719 | + return; | |
| 4720 | + PyModule_AddObject(m, "_SimpleCData", (PyObject *)&Simple_Type); | |
| 4721 | + | |
| 4722 | + CFuncPtr_Type.ob_type = &CFuncPtrType_Type; | |
| 4723 | + CFuncPtr_Type.tp_base = &CData_Type; | |
| 4724 | + if (PyType_Ready(&CFuncPtr_Type) < 0) | |
| 4725 | + return; | |
| 4726 | + PyModule_AddObject(m, "CFuncPtr", (PyObject *)&CFuncPtr_Type); | |
| 4727 | + | |
| 4728 | + /************************************************* | |
| 4729 | + * | |
| 4730 | + * Simple classes | |
| 4731 | + */ | |
| 4732 | + | |
| 4733 | + /* CField_Type is derived from PyBaseObject_Type */ | |
| 4734 | + if (PyType_Ready(&CField_Type) < 0) | |
| 4735 | + return; | |
| 4736 | + | |
| 4737 | + /************************************************* | |
| 4738 | + * | |
| 4739 | + * Other stuff | |
| 4740 | + */ | |
| 4741 | + | |
| 4742 | +#ifdef MS_WIN32 | |
| 4743 | + if (create_comerror() < 0) | |
| 4744 | + return; | |
| 4745 | + PyModule_AddObject(m, "COMError", ComError); | |
| 4746 | + | |
| 4747 | + PyModule_AddObject(m, "FUNCFLAG_HRESULT", PyInt_FromLong(FUNCFLAG_HRESULT)); | |
| 4748 | + PyModule_AddObject(m, "FUNCFLAG_STDCALL", PyInt_FromLong(FUNCFLAG_STDCALL)); | |
| 4749 | +#endif | |
| 4750 | + PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL)); | |
| 4751 | + PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI)); | |
| 4752 | + PyModule_AddStringConstant(m, "__version__", "1.0.2"); | |
| 4753 | + | |
| 4754 | + PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); | |
| 4755 | + PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset)); | |
| 4756 | + PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at)); | |
| 4757 | + PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast)); | |
| 4758 | +#ifdef CTYPES_UNICODE | |
| 4759 | + PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at)); | |
| 4760 | +#endif | |
| 4761 | + | |
| 4762 | +/* If RTLD_LOCAL is not defined (Windows!), set it to zero. */ | |
| 4763 | +#ifndef RTLD_LOCAL | |
| 4764 | +#define RTLD_LOCAL 0 | |
| 4765 | +#endif | |
| 4766 | + | |
| 4767 | +/* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as | |
| 4768 | + RTLD_LOCAL. | |
| 4769 | +*/ | |
| 4770 | +#ifndef RTLD_GLOBAL | |
| 4771 | +#define RTLD_GLOBAL RTLD_LOCAL | |
| 4772 | +#endif | |
| 4773 | + | |
| 4774 | + PyModule_AddObject(m, "RTLD_LOCAL", PyInt_FromLong(RTLD_LOCAL)); | |
| 4775 | + PyModule_AddObject(m, "RTLD_GLOBAL", PyInt_FromLong(RTLD_GLOBAL)); | |
| 4776 | + | |
| 4777 | + PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); | |
| 4778 | + if (PyExc_ArgError) { | |
| 4779 | + Py_INCREF(PyExc_ArgError); | |
| 4780 | + PyModule_AddObject(m, "ArgumentError", PyExc_ArgError); | |
| 4781 | + } | |
| 4782 | + /************************************************* | |
| 4783 | + * | |
| 4784 | + * Others... | |
| 4785 | + */ | |
| 4786 | + init_callbacks_in_module(m); | |
| 4787 | +} | |
| 4788 | + | |
| 4789 | +/***************************************************************** | |
| 4790 | + * replacements for broken Python api functions (in Python 2.3). | |
| 4791 | + * See #1047269 Buffer overwrite in PyUnicode_AsWideChar | |
| 4792 | + */ | |
| 4793 | + | |
| 4794 | +#ifdef HAVE_WCHAR_H | |
| 4795 | + | |
| 4796 | +PyObject *My_PyUnicode_FromWideChar(register const wchar_t *w, | |
| 4797 | + Py_ssize_t size) | |
| 4798 | +{ | |
| 4799 | + PyUnicodeObject *unicode; | |
| 4800 | + | |
| 4801 | + if (w == NULL) { | |
| 4802 | + PyErr_BadInternalCall(); | |
| 4803 | + return NULL; | |
| 4804 | + } | |
| 4805 | + | |
| 4806 | + unicode = (PyUnicodeObject *)PyUnicode_FromUnicode(NULL, size); | |
| 4807 | + if (!unicode) | |
| 4808 | + return NULL; | |
| 4809 | + | |
| 4810 | + /* Copy the wchar_t data into the new object */ | |
| 4811 | +#ifdef HAVE_USABLE_WCHAR_T | |
| 4812 | + memcpy(unicode->str, w, size * sizeof(wchar_t)); | |
| 4813 | +#else | |
| 4814 | + { | |
| 4815 | + register Py_UNICODE *u; | |
| 4816 | + register int i; | |
| 4817 | + u = PyUnicode_AS_UNICODE(unicode); | |
| 4818 | + /* In Python, the following line has a one-off error */ | |
| 4819 | + for (i = size; i > 0; i--) | |
| 4820 | + *u++ = *w++; | |
| 4821 | + } | |
| 4822 | +#endif | |
| 4823 | + | |
| 4824 | + return (PyObject *)unicode; | |
| 4825 | +} | |
| 4826 | + | |
| 4827 | +int My_PyUnicode_AsWideChar(PyUnicodeObject *unicode, | |
| 4828 | + register wchar_t *w, | |
| 4829 | + Py_ssize_t size) | |
| 4830 | +{ | |
| 4831 | + if (unicode == NULL) { | |
| 4832 | + PyErr_BadInternalCall(); | |
| 4833 | + return -1; | |
| 4834 | + } | |
| 4835 | + if (size > PyUnicode_GET_SIZE(unicode)) | |
| 4836 | + size = PyUnicode_GET_SIZE(unicode); | |
| 4837 | +#ifdef HAVE_USABLE_WCHAR_T | |
| 4838 | + memcpy(w, unicode->str, size * sizeof(wchar_t)); | |
| 4839 | +#else | |
| 4840 | + { | |
| 4841 | + register Py_UNICODE *u; | |
| 4842 | + register int i; | |
| 4843 | + u = PyUnicode_AS_UNICODE(unicode); | |
| 4844 | + /* In Python, the following line has a one-off error */ | |
| 4845 | + for (i = size; i > 0; i--) | |
| 4846 | + *w++ = *u++; | |
| 4847 | + } | |
| 4848 | +#endif | |
| 4849 | + | |
| 4850 | + return size; | |
| 4851 | +} | |
| 4852 | + | |
| 4853 | +#endif | |
| 4854 | + | |
| 4855 | +/* | |
| 4856 | + Local Variables: | |
| 4857 | + compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~" | |
| 4858 | + End: | |
| 4859 | +*/ | |
| @@ -0,0 +1,548 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | + | |
| 6 | +#include <Python.h> | |
| 7 | + | |
| 8 | +/* | |
| 9 | + Backwards compatibility: | |
| 10 | + Python2.2 used LONG_LONG instead of PY_LONG_LONG | |
| 11 | +*/ | |
| 12 | +#if defined(HAVE_LONG_LONG) && !defined(PY_LONG_LONG) | |
| 13 | +#define PY_LONG_LONG LONG_LONG | |
| 14 | +#endif | |
| 15 | + | |
| 16 | +#ifdef MS_WIN32 | |
| 17 | +#include <windows.h> | |
| 18 | +#endif | |
| 19 | + | |
| 20 | +#if defined(MS_WIN32) || defined(__CYGWIN__) | |
| 21 | +#define EXPORT(x) __declspec(dllexport) x | |
| 22 | +#else | |
| 23 | +#define EXPORT(x) x | |
| 24 | +#endif | |
| 25 | + | |
| 26 | +/* some functions handy for testing */ | |
| 27 | + | |
| 28 | +EXPORT(char *)my_strtok(char *token, const char *delim) | |
| 29 | +{ | |
| 30 | + return strtok(token, delim); | |
| 31 | +} | |
| 32 | + | |
| 33 | +EXPORT(char *)my_strchr(const char *s, int c) | |
| 34 | +{ | |
| 35 | + return strchr(s, c); | |
| 36 | +} | |
| 37 | + | |
| 38 | + | |
| 39 | +EXPORT(double) my_sqrt(double a) | |
| 40 | +{ | |
| 41 | + return sqrt(a); | |
| 42 | +} | |
| 43 | + | |
| 44 | +EXPORT(void) my_qsort(void *base, size_t num, size_t width, int(*compare)(const void*, const void*)) | |
| 45 | +{ | |
| 46 | + qsort(base, num, width, compare); | |
| 47 | +} | |
| 48 | + | |
| 49 | +EXPORT(int *) _testfunc_ai8(int a[8]) | |
| 50 | +{ | |
| 51 | + return a; | |
| 52 | +} | |
| 53 | + | |
| 54 | +EXPORT(void) _testfunc_v(int a, int b, int *presult) | |
| 55 | +{ | |
| 56 | + *presult = a + b; | |
| 57 | +} | |
| 58 | + | |
| 59 | +EXPORT(int) _testfunc_i_bhilfd(signed char b, short h, int i, long l, float f, double d) | |
| 60 | +{ | |
| 61 | +/* printf("_testfunc_i_bhilfd got %d %d %d %ld %f %f\n", | |
| 62 | + b, h, i, l, f, d); | |
| 63 | +*/ | |
| 64 | + return (int)(b + h + i + l + f + d); | |
| 65 | +} | |
| 66 | + | |
| 67 | +EXPORT(float) _testfunc_f_bhilfd(signed char b, short h, int i, long l, float f, double d) | |
| 68 | +{ | |
| 69 | +/* printf("_testfunc_f_bhilfd got %d %d %d %ld %f %f\n", | |
| 70 | + b, h, i, l, f, d); | |
| 71 | +*/ | |
| 72 | + return (float)(b + h + i + l + f + d); | |
| 73 | +} | |
| 74 | + | |
| 75 | +EXPORT(double) _testfunc_d_bhilfd(signed char b, short h, int i, long l, float f, double d) | |
| 76 | +{ | |
| 77 | +/* printf("_testfunc_d_bhilfd got %d %d %d %ld %f %f\n", | |
| 78 | + b, h, i, l, f, d); | |
| 79 | +*/ | |
| 80 | + return (double)(b + h + i + l + f + d); | |
| 81 | +} | |
| 82 | + | |
| 83 | +EXPORT(char *) _testfunc_p_p(void *s) | |
| 84 | +{ | |
| 85 | + return (char *)s; | |
| 86 | +} | |
| 87 | + | |
| 88 | +EXPORT(void *) _testfunc_c_p_p(int *argcp, char **argv) | |
| 89 | +{ | |
| 90 | + return argv[(*argcp)-1]; | |
| 91 | +} | |
| 92 | + | |
| 93 | +EXPORT(void *) get_strchr(void) | |
| 94 | +{ | |
| 95 | + return (void *)strchr; | |
| 96 | +} | |
| 97 | + | |
| 98 | +EXPORT(char *) my_strdup(char *src) | |
| 99 | +{ | |
| 100 | + char *dst = (char *)malloc(strlen(src)+1); | |
| 101 | + if (!dst) | |
| 102 | + return NULL; | |
| 103 | + strcpy(dst, src); | |
| 104 | + return dst; | |
| 105 | +} | |
| 106 | + | |
| 107 | +EXPORT(void)my_free(void *ptr) | |
| 108 | +{ | |
| 109 | + free(ptr); | |
| 110 | +} | |
| 111 | + | |
| 112 | +#ifdef HAVE_WCHAR_H | |
| 113 | +EXPORT(wchar_t *) my_wcsdup(wchar_t *src) | |
| 114 | +{ | |
| 115 | + size_t len = wcslen(src); | |
| 116 | + wchar_t *ptr = (wchar_t *)malloc((len + 1) * sizeof(wchar_t)); | |
| 117 | + if (ptr == NULL) | |
| 118 | + return NULL; | |
| 119 | + memcpy(ptr, src, (len+1) * sizeof(wchar_t)); | |
| 120 | + return ptr; | |
| 121 | +} | |
| 122 | + | |
| 123 | +EXPORT(size_t) my_wcslen(wchar_t *src) | |
| 124 | +{ | |
| 125 | + return wcslen(src); | |
| 126 | +} | |
| 127 | +#endif | |
| 128 | + | |
| 129 | +#ifndef MS_WIN32 | |
| 130 | +# ifndef __stdcall | |
| 131 | +# define __stdcall /* */ | |
| 132 | +# endif | |
| 133 | +#endif | |
| 134 | + | |
| 135 | +typedef struct { | |
| 136 | + int (*c)(int, int); | |
| 137 | + int (__stdcall *s)(int, int); | |
| 138 | +} FUNCS; | |
| 139 | + | |
| 140 | +EXPORT(int) _testfunc_callfuncp(FUNCS *fp) | |
| 141 | +{ | |
| 142 | + fp->c(1, 2); | |
| 143 | + fp->s(3, 4); | |
| 144 | + return 0; | |
| 145 | +} | |
| 146 | + | |
| 147 | +EXPORT(int) _testfunc_deref_pointer(int *pi) | |
| 148 | +{ | |
| 149 | + return *pi; | |
| 150 | +} | |
| 151 | + | |
| 152 | +#ifdef MS_WIN32 | |
| 153 | +EXPORT(int) _testfunc_piunk(IUnknown FAR *piunk) | |
| 154 | +{ | |
| 155 | + piunk->lpVtbl->AddRef(piunk); | |
| 156 | + return piunk->lpVtbl->Release(piunk); | |
| 157 | +} | |
| 158 | +#endif | |
| 159 | + | |
| 160 | +EXPORT(int) _testfunc_callback_with_pointer(int (*func)(int *)) | |
| 161 | +{ | |
| 162 | + int table[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | |
| 163 | + | |
| 164 | + return (*func)(table); | |
| 165 | +} | |
| 166 | + | |
| 167 | +#ifdef HAVE_LONG_LONG | |
| 168 | +EXPORT(PY_LONG_LONG) _testfunc_q_bhilfdq(signed char b, short h, int i, long l, float f, | |
| 169 | + double d, PY_LONG_LONG q) | |
| 170 | +{ | |
| 171 | + return (PY_LONG_LONG)(b + h + i + l + f + d + q); | |
| 172 | +} | |
| 173 | + | |
| 174 | +EXPORT(PY_LONG_LONG) _testfunc_q_bhilfd(signed char b, short h, int i, long l, float f, double d) | |
| 175 | +{ | |
| 176 | + return (PY_LONG_LONG)(b + h + i + l + f + d); | |
| 177 | +} | |
| 178 | + | |
| 179 | +EXPORT(int) _testfunc_callback_i_if(int value, int (*func)(int)) | |
| 180 | +{ | |
| 181 | + int sum = 0; | |
| 182 | + while (value != 0) { | |
| 183 | + sum += func(value); | |
| 184 | + value /= 2; | |
| 185 | + } | |
| 186 | + return sum; | |
| 187 | +} | |
| 188 | + | |
| 189 | +EXPORT(PY_LONG_LONG) _testfunc_callback_q_qf(PY_LONG_LONG value, | |
| 190 | + PY_LONG_LONG (*func)(PY_LONG_LONG)) | |
| 191 | +{ | |
| 192 | + PY_LONG_LONG sum = 0; | |
| 193 | + | |
| 194 | + while (value != 0) { | |
| 195 | + sum += func(value); | |
| 196 | + value /= 2; | |
| 197 | + } | |
| 198 | + return sum; | |
| 199 | +} | |
| 200 | + | |
| 201 | +#endif | |
| 202 | + | |
| 203 | +typedef struct { | |
| 204 | + char *name; | |
| 205 | + char *value; | |
| 206 | +} SPAM; | |
| 207 | + | |
| 208 | +typedef struct { | |
| 209 | + char *name; | |
| 210 | + int num_spams; | |
| 211 | + SPAM *spams; | |
| 212 | +} EGG; | |
| 213 | + | |
| 214 | +SPAM my_spams[2] = { | |
| 215 | + { "name1", "value1" }, | |
| 216 | + { "name2", "value2" }, | |
| 217 | +}; | |
| 218 | + | |
| 219 | +EGG my_eggs[1] = { | |
| 220 | + { "first egg", 1, my_spams } | |
| 221 | +}; | |
| 222 | + | |
| 223 | +EXPORT(int) getSPAMANDEGGS(EGG **eggs) | |
| 224 | +{ | |
| 225 | + *eggs = my_eggs; | |
| 226 | + return 1; | |
| 227 | +} | |
| 228 | + | |
| 229 | +typedef struct tagpoint { | |
| 230 | + int x; | |
| 231 | + int y; | |
| 232 | +} point; | |
| 233 | + | |
| 234 | +EXPORT(int) _testfunc_byval(point in, point *pout) | |
| 235 | +{ | |
| 236 | + if (pout) { | |
| 237 | + pout->x = in.x; | |
| 238 | + pout->y = in.y; | |
| 239 | + } | |
| 240 | + return in.x + in.y; | |
| 241 | +} | |
| 242 | + | |
| 243 | +EXPORT (int) an_integer = 42; | |
| 244 | + | |
| 245 | +EXPORT(int) get_an_integer(void) | |
| 246 | +{ | |
| 247 | + return an_integer; | |
| 248 | +} | |
| 249 | + | |
| 250 | +EXPORT(double) | |
| 251 | +integrate(double a, double b, double (*f)(double), long nstep) | |
| 252 | +{ | |
| 253 | + double x, sum=0.0, dx=(b-a)/(double)nstep; | |
| 254 | + for(x=a+0.5*dx; (b-x)*(x-a)>0.0; x+=dx) | |
| 255 | + sum += f(x); | |
| 256 | + return sum/(double)nstep; | |
| 257 | +} | |
| 258 | + | |
| 259 | +typedef struct { | |
| 260 | + void (*initialize)(void *(*)(int), void(*)(void *)); | |
| 261 | +} xxx_library; | |
| 262 | + | |
| 263 | +static void _xxx_init(void *(*Xalloc)(int), void (*Xfree)(void *)) | |
| 264 | +{ | |
| 265 | + void *ptr; | |
| 266 | + | |
| 267 | + printf("_xxx_init got %p %p\n", Xalloc, Xfree); | |
| 268 | + printf("calling\n"); | |
| 269 | + ptr = Xalloc(32); | |
| 270 | + Xfree(ptr); | |
| 271 | + printf("calls done, ptr was %p\n", ptr); | |
| 272 | +} | |
| 273 | + | |
| 274 | +xxx_library _xxx_lib = { | |
| 275 | + _xxx_init | |
| 276 | +}; | |
| 277 | + | |
| 278 | +EXPORT(xxx_library) *library_get(void) | |
| 279 | +{ | |
| 280 | + return &_xxx_lib; | |
| 281 | +} | |
| 282 | + | |
| 283 | +#ifdef MS_WIN32 | |
| 284 | +/* See Don Box (german), pp 79ff. */ | |
| 285 | +EXPORT(void) GetString(BSTR *pbstr) | |
| 286 | +{ | |
| 287 | + *pbstr = SysAllocString(L"Goodbye!"); | |
| 288 | +} | |
| 289 | +#endif | |
| 290 | + | |
| 291 | +/* | |
| 292 | + * Some do-nothing functions, for speed tests | |
| 293 | + */ | |
| 294 | +PyObject *py_func_si(PyObject *self, PyObject *args) | |
| 295 | +{ | |
| 296 | + char *name; | |
| 297 | + int i; | |
| 298 | + if (!PyArg_ParseTuple(args, "si", &name, &i)) | |
| 299 | + return NULL; | |
| 300 | + Py_INCREF(Py_None); | |
| 301 | + return Py_None; | |
| 302 | +} | |
| 303 | + | |
| 304 | +EXPORT(void) _py_func_si(char *s, int i) | |
| 305 | +{ | |
| 306 | +} | |
| 307 | + | |
| 308 | +PyObject *py_func(PyObject *self, PyObject *args) | |
| 309 | +{ | |
| 310 | + Py_INCREF(Py_None); | |
| 311 | + return Py_None; | |
| 312 | +} | |
| 313 | + | |
| 314 | +EXPORT(void) _py_func(void) | |
| 315 | +{ | |
| 316 | +} | |
| 317 | + | |
| 318 | +EXPORT(PY_LONG_LONG) last_tf_arg_s; | |
| 319 | +EXPORT(unsigned PY_LONG_LONG) last_tf_arg_u; | |
| 320 | + | |
| 321 | +struct BITS { | |
| 322 | + int A: 1, B:2, C:3, D:4, E: 5, F: 6, G: 7, H: 8, I: 9; | |
| 323 | + short M: 1, N: 2, O: 3, P: 4, Q: 5, R: 6, S: 7; | |
| 324 | +}; | |
| 325 | + | |
| 326 | +DL_EXPORT(void) set_bitfields(struct BITS *bits, char name, int value) | |
| 327 | +{ | |
| 328 | + switch (name) { | |
| 329 | + case 'A': bits->A = value; break; | |
| 330 | + case 'B': bits->B = value; break; | |
| 331 | + case 'C': bits->C = value; break; | |
| 332 | + case 'D': bits->D = value; break; | |
| 333 | + case 'E': bits->E = value; break; | |
| 334 | + case 'F': bits->F = value; break; | |
| 335 | + case 'G': bits->G = value; break; | |
| 336 | + case 'H': bits->H = value; break; | |
| 337 | + case 'I': bits->I = value; break; | |
| 338 | + | |
| 339 | + case 'M': bits->M = value; break; | |
| 340 | + case 'N': bits->N = value; break; | |
| 341 | + case 'O': bits->O = value; break; | |
| 342 | + case 'P': bits->P = value; break; | |
| 343 | + case 'Q': bits->Q = value; break; | |
| 344 | + case 'R': bits->R = value; break; | |
| 345 | + case 'S': bits->S = value; break; | |
| 346 | + } | |
| 347 | +} | |
| 348 | + | |
| 349 | +DL_EXPORT(int) unpack_bitfields(struct BITS *bits, char name) | |
| 350 | +{ | |
| 351 | + switch (name) { | |
| 352 | + case 'A': return bits->A; | |
| 353 | + case 'B': return bits->B; | |
| 354 | + case 'C': return bits->C; | |
| 355 | + case 'D': return bits->D; | |
| 356 | + case 'E': return bits->E; | |
| 357 | + case 'F': return bits->F; | |
| 358 | + case 'G': return bits->G; | |
| 359 | + case 'H': return bits->H; | |
| 360 | + case 'I': return bits->I; | |
| 361 | + | |
| 362 | + case 'M': return bits->M; | |
| 363 | + case 'N': return bits->N; | |
| 364 | + case 'O': return bits->O; | |
| 365 | + case 'P': return bits->P; | |
| 366 | + case 'Q': return bits->Q; | |
| 367 | + case 'R': return bits->R; | |
| 368 | + case 'S': return bits->S; | |
| 369 | + } | |
| 370 | + return 0; | |
| 371 | +} | |
| 372 | + | |
| 373 | +PyMethodDef module_methods[] = { | |
| 374 | +/* {"get_last_tf_arg_s", get_last_tf_arg_s, METH_NOARGS}, | |
| 375 | + {"get_last_tf_arg_u", get_last_tf_arg_u, METH_NOARGS}, | |
| 376 | +*/ | |
| 377 | + {"func_si", py_func_si, METH_VARARGS}, | |
| 378 | + {"func", py_func, METH_NOARGS}, | |
| 379 | + { NULL, NULL, 0, NULL}, | |
| 380 | +}; | |
| 381 | + | |
| 382 | +#define S last_tf_arg_s = (PY_LONG_LONG)c | |
| 383 | +#define U last_tf_arg_u = (unsigned PY_LONG_LONG)c | |
| 384 | + | |
| 385 | +EXPORT(signed char) tf_b(signed char c) { S; return c/3; } | |
| 386 | +EXPORT(unsigned char) tf_B(unsigned char c) { U; return c/3; } | |
| 387 | +EXPORT(short) tf_h(short c) { S; return c/3; } | |
| 388 | +EXPORT(unsigned short) tf_H(unsigned short c) { U; return c/3; } | |
| 389 | +EXPORT(int) tf_i(int c) { S; return c/3; } | |
| 390 | +EXPORT(unsigned int) tf_I(unsigned int c) { U; return c/3; } | |
| 391 | +EXPORT(long) tf_l(long c) { S; return c/3; } | |
| 392 | +EXPORT(unsigned long) tf_L(unsigned long c) { U; return c/3; } | |
| 393 | +EXPORT(PY_LONG_LONG) tf_q(PY_LONG_LONG c) { S; return c/3; } | |
| 394 | +EXPORT(unsigned PY_LONG_LONG) tf_Q(unsigned PY_LONG_LONG c) { U; return c/3; } | |
| 395 | +EXPORT(float) tf_f(float c) { S; return c/3; } | |
| 396 | +EXPORT(double) tf_d(double c) { S; return c/3; } | |
| 397 | + | |
| 398 | +#ifdef MS_WIN32 | |
| 399 | +EXPORT(signed char) __stdcall s_tf_b(signed char c) { S; return c/3; } | |
| 400 | +EXPORT(unsigned char) __stdcall s_tf_B(unsigned char c) { U; return c/3; } | |
| 401 | +EXPORT(short) __stdcall s_tf_h(short c) { S; return c/3; } | |
| 402 | +EXPORT(unsigned short) __stdcall s_tf_H(unsigned short c) { U; return c/3; } | |
| 403 | +EXPORT(int) __stdcall s_tf_i(int c) { S; return c/3; } | |
| 404 | +EXPORT(unsigned int) __stdcall s_tf_I(unsigned int c) { U; return c/3; } | |
| 405 | +EXPORT(long) __stdcall s_tf_l(long c) { S; return c/3; } | |
| 406 | +EXPORT(unsigned long) __stdcall s_tf_L(unsigned long c) { U; return c/3; } | |
| 407 | +EXPORT(PY_LONG_LONG) __stdcall s_tf_q(PY_LONG_LONG c) { S; return c/3; } | |
| 408 | +EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_Q(unsigned PY_LONG_LONG c) { U; return c/3; } | |
| 409 | +EXPORT(float) __stdcall s_tf_f(float c) { S; return c/3; } | |
| 410 | +EXPORT(double) __stdcall s_tf_d(double c) { S; return c/3; } | |
| 411 | +#endif | |
| 412 | +/*******/ | |
| 413 | + | |
| 414 | +EXPORT(signed char) tf_bb(signed char x, signed char c) { S; return c/3; } | |
| 415 | +EXPORT(unsigned char) tf_bB(signed char x, unsigned char c) { U; return c/3; } | |
| 416 | +EXPORT(short) tf_bh(signed char x, short c) { S; return c/3; } | |
| 417 | +EXPORT(unsigned short) tf_bH(signed char x, unsigned short c) { U; return c/3; } | |
| 418 | +EXPORT(int) tf_bi(signed char x, int c) { S; return c/3; } | |
| 419 | +EXPORT(unsigned int) tf_bI(signed char x, unsigned int c) { U; return c/3; } | |
| 420 | +EXPORT(long) tf_bl(signed char x, long c) { S; return c/3; } | |
| 421 | +EXPORT(unsigned long) tf_bL(signed char x, unsigned long c) { U; return c/3; } | |
| 422 | +EXPORT(PY_LONG_LONG) tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; } | |
| 423 | +EXPORT(unsigned PY_LONG_LONG) tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; } | |
| 424 | +EXPORT(float) tf_bf(signed char x, float c) { S; return c/3; } | |
| 425 | +EXPORT(double) tf_bd(signed char x, double c) { S; return c/3; } | |
| 426 | +EXPORT(void) tv_i(int c) { S; return; } | |
| 427 | + | |
| 428 | +#ifdef MS_WIN32 | |
| 429 | +EXPORT(signed char) __stdcall s_tf_bb(signed char x, signed char c) { S; return c/3; } | |
| 430 | +EXPORT(unsigned char) __stdcall s_tf_bB(signed char x, unsigned char c) { U; return c/3; } | |
| 431 | +EXPORT(short) __stdcall s_tf_bh(signed char x, short c) { S; return c/3; } | |
| 432 | +EXPORT(unsigned short) __stdcall s_tf_bH(signed char x, unsigned short c) { U; return c/3; } | |
| 433 | +EXPORT(int) __stdcall s_tf_bi(signed char x, int c) { S; return c/3; } | |
| 434 | +EXPORT(unsigned int) __stdcall s_tf_bI(signed char x, unsigned int c) { U; return c/3; } | |
| 435 | +EXPORT(long) __stdcall s_tf_bl(signed char x, long c) { S; return c/3; } | |
| 436 | +EXPORT(unsigned long) __stdcall s_tf_bL(signed char x, unsigned long c) { U; return c/3; } | |
| 437 | +EXPORT(PY_LONG_LONG) __stdcall s_tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; } | |
| 438 | +EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; } | |
| 439 | +EXPORT(float) __stdcall s_tf_bf(signed char x, float c) { S; return c/3; } | |
| 440 | +EXPORT(double) __stdcall s_tf_bd(signed char x, double c) { S; return c/3; } | |
| 441 | +EXPORT(void) __stdcall s_tv_i(int c) { S; return; } | |
| 442 | +#endif | |
| 443 | + | |
| 444 | +/********/ | |
| 445 | + | |
| 446 | +#ifndef MS_WIN32 | |
| 447 | + | |
| 448 | +typedef struct { | |
| 449 | + long x; | |
| 450 | + long y; | |
| 451 | +} POINT; | |
| 452 | + | |
| 453 | +typedef struct { | |
| 454 | + long left; | |
| 455 | + long top; | |
| 456 | + long right; | |
| 457 | + long bottom; | |
| 458 | +} RECT; | |
| 459 | + | |
| 460 | +#endif | |
| 461 | + | |
| 462 | +EXPORT(int) PointInRect(RECT *prc, POINT pt) | |
| 463 | +{ | |
| 464 | + if (pt.x < prc->left) | |
| 465 | + return 0; | |
| 466 | + if (pt.x > prc->right) | |
| 467 | + return 0; | |
| 468 | + if (pt.y < prc->top) | |
| 469 | + return 0; | |
| 470 | + if (pt.y > prc->bottom) | |
| 471 | + return 0; | |
| 472 | + return 1; | |
| 473 | +} | |
| 474 | + | |
| 475 | +typedef struct { | |
| 476 | + short x; | |
| 477 | + short y; | |
| 478 | +} S2H; | |
| 479 | + | |
| 480 | +EXPORT(S2H) ret_2h_func(S2H inp) | |
| 481 | +{ | |
| 482 | + inp.x *= 2; | |
| 483 | + inp.y *= 3; | |
| 484 | + return inp; | |
| 485 | +} | |
| 486 | + | |
| 487 | +typedef struct { | |
| 488 | + int a, b, c, d, e, f, g, h; | |
| 489 | +} S8I; | |
| 490 | + | |
| 491 | +EXPORT(S8I) ret_8i_func(S8I inp) | |
| 492 | +{ | |
| 493 | + inp.a *= 2; | |
| 494 | + inp.b *= 3; | |
| 495 | + inp.c *= 4; | |
| 496 | + inp.d *= 5; | |
| 497 | + inp.e *= 6; | |
| 498 | + inp.f *= 7; | |
| 499 | + inp.g *= 8; | |
| 500 | + inp.h *= 9; | |
| 501 | + return inp; | |
| 502 | +} | |
| 503 | + | |
| 504 | +EXPORT(int) GetRectangle(int flag, RECT *prect) | |
| 505 | +{ | |
| 506 | + if (flag == 0) | |
| 507 | + return 0; | |
| 508 | + prect->left = (int)flag; | |
| 509 | + prect->top = (int)flag + 1; | |
| 510 | + prect->right = (int)flag + 2; | |
| 511 | + prect->bottom = (int)flag + 3; | |
| 512 | + return 1; | |
| 513 | +} | |
| 514 | + | |
| 515 | +EXPORT(void) TwoOutArgs(int a, int *pi, int b, int *pj) | |
| 516 | +{ | |
| 517 | + *pi += a; | |
| 518 | + *pj += b; | |
| 519 | +} | |
| 520 | + | |
| 521 | +#ifdef MS_WIN32 | |
| 522 | +EXPORT(S2H) __stdcall s_ret_2h_func(S2H inp) { return ret_2h_func(inp); } | |
| 523 | +EXPORT(S8I) __stdcall s_ret_8i_func(S8I inp) { return ret_8i_func(inp); } | |
| 524 | +#endif | |
| 525 | + | |
| 526 | +#ifdef MS_WIN32 | |
| 527 | +/* Should port this */ | |
| 528 | +#include <stdlib.h> | |
| 529 | +#include <search.h> | |
| 530 | + | |
| 531 | +EXPORT (HRESULT) KeepObject(IUnknown *punk) | |
| 532 | +{ | |
| 533 | + static IUnknown *pobj; | |
| 534 | + if (punk) | |
| 535 | + punk->lpVtbl->AddRef(punk); | |
| 536 | + if (pobj) | |
| 537 | + pobj->lpVtbl->Release(pobj); | |
| 538 | + pobj = punk; | |
| 539 | + return S_OK; | |
| 540 | +} | |
| 541 | + | |
| 542 | +#endif | |
| 543 | + | |
| 544 | +DL_EXPORT(void) | |
| 545 | +init_ctypes_test(void) | |
| 546 | +{ | |
| 547 | + Py_InitModule("_ctypes_test", module_methods); | |
| 548 | +} | |
| @@ -0,0 +1 @@ | ||
| 1 | +extern int _testfunc_i_bhilfd(char b, short h, int i, long l, float f, double d); | |
| @@ -0,0 +1,499 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | +#include "Python.h" | |
| 6 | +#include "compile.h" /* required only for 2.3, as it seems */ | |
| 7 | +#include "frameobject.h" | |
| 8 | + | |
| 9 | +#include <ffi.h> | |
| 10 | +#ifdef MS_WIN32 | |
| 11 | +#include <windows.h> | |
| 12 | +#endif | |
| 13 | +#include "ctypes.h" | |
| 14 | + | |
| 15 | +static void | |
| 16 | +PrintError(char *msg, ...) | |
| 17 | +{ | |
| 18 | + char buf[512]; | |
| 19 | + PyObject *f = PySys_GetObject("stderr"); | |
| 20 | + va_list marker; | |
| 21 | + | |
| 22 | + va_start(marker, msg); | |
| 23 | + vsnprintf(buf, sizeof(buf), msg, marker); | |
| 24 | + va_end(marker); | |
| 25 | + if (f) | |
| 26 | + PyFile_WriteString(buf, f); | |
| 27 | + PyErr_Print(); | |
| 28 | +} | |
| 29 | + | |
| 30 | + | |
| 31 | +/* after code that pyrex generates */ | |
| 32 | +void _AddTraceback(char *funcname, char *filename, int lineno) | |
| 33 | +{ | |
| 34 | + PyObject *py_srcfile = 0; | |
| 35 | + PyObject *py_funcname = 0; | |
| 36 | + PyObject *py_globals = 0; | |
| 37 | + PyObject *empty_tuple = 0; | |
| 38 | + PyObject *empty_string = 0; | |
| 39 | + PyCodeObject *py_code = 0; | |
| 40 | + PyFrameObject *py_frame = 0; | |
| 41 | + | |
| 42 | + py_srcfile = PyString_FromString(filename); | |
| 43 | + if (!py_srcfile) goto bad; | |
| 44 | + py_funcname = PyString_FromString(funcname); | |
| 45 | + if (!py_funcname) goto bad; | |
| 46 | + py_globals = PyDict_New(); | |
| 47 | + if (!py_globals) goto bad; | |
| 48 | + empty_tuple = PyTuple_New(0); | |
| 49 | + if (!empty_tuple) goto bad; | |
| 50 | + empty_string = PyString_FromString(""); | |
| 51 | + if (!empty_string) goto bad; | |
| 52 | + py_code = PyCode_New( | |
| 53 | + 0, /*int argcount,*/ | |
| 54 | + 0, /*int nlocals,*/ | |
| 55 | + 0, /*int stacksize,*/ | |
| 56 | + 0, /*int flags,*/ | |
| 57 | + empty_string, /*PyObject *code,*/ | |
| 58 | + empty_tuple, /*PyObject *consts,*/ | |
| 59 | + empty_tuple, /*PyObject *names,*/ | |
| 60 | + empty_tuple, /*PyObject *varnames,*/ | |
| 61 | + empty_tuple, /*PyObject *freevars,*/ | |
| 62 | + empty_tuple, /*PyObject *cellvars,*/ | |
| 63 | + py_srcfile, /*PyObject *filename,*/ | |
| 64 | + py_funcname, /*PyObject *name,*/ | |
| 65 | + lineno, /*int firstlineno,*/ | |
| 66 | + empty_string /*PyObject *lnotab*/ | |
| 67 | + ); | |
| 68 | + if (!py_code) goto bad; | |
| 69 | + py_frame = PyFrame_New( | |
| 70 | + PyThreadState_Get(), /*PyThreadState *tstate,*/ | |
| 71 | + py_code, /*PyCodeObject *code,*/ | |
| 72 | + py_globals, /*PyObject *globals,*/ | |
| 73 | + 0 /*PyObject *locals*/ | |
| 74 | + ); | |
| 75 | + if (!py_frame) goto bad; | |
| 76 | + py_frame->f_lineno = lineno; | |
| 77 | + PyTraceBack_Here(py_frame); | |
| 78 | + bad: | |
| 79 | + Py_XDECREF(py_globals); | |
| 80 | + Py_XDECREF(py_srcfile); | |
| 81 | + Py_XDECREF(py_funcname); | |
| 82 | + Py_XDECREF(empty_tuple); | |
| 83 | + Py_XDECREF(empty_string); | |
| 84 | + Py_XDECREF(py_code); | |
| 85 | + Py_XDECREF(py_frame); | |
| 86 | +} | |
| 87 | + | |
| 88 | +#ifdef MS_WIN32 | |
| 89 | +/* | |
| 90 | + * We must call AddRef() on non-NULL COM pointers we receive as arguments | |
| 91 | + * to callback functions - these functions are COM method implementations. | |
| 92 | + * The Python instances we create have a __del__ method which calls Release(). | |
| 93 | + * | |
| 94 | + * The presence of a class attribute named '_needs_com_addref_' triggers this | |
| 95 | + * behaviour. It would also be possible to call the AddRef() Python method, | |
| 96 | + * after checking for PyObject_IsTrue(), but this would probably be somewhat | |
| 97 | + * slower. | |
| 98 | + */ | |
| 99 | +static void | |
| 100 | +TryAddRef(StgDictObject *dict, CDataObject *obj) | |
| 101 | +{ | |
| 102 | + IUnknown *punk; | |
| 103 | + | |
| 104 | + if (NULL == PyDict_GetItemString((PyObject *)dict, "_needs_com_addref_")) | |
| 105 | + return; | |
| 106 | + | |
| 107 | + punk = *(IUnknown **)obj->b_ptr; | |
| 108 | + if (punk) | |
| 109 | + punk->lpVtbl->AddRef(punk); | |
| 110 | + return; | |
| 111 | +} | |
| 112 | +#endif | |
| 113 | + | |
| 114 | +/****************************************************************************** | |
| 115 | + * | |
| 116 | + * Call the python object with all arguments | |
| 117 | + * | |
| 118 | + */ | |
| 119 | +static void _CallPythonObject(void *mem, | |
| 120 | + ffi_type *restype, | |
| 121 | + SETFUNC setfunc, | |
| 122 | + PyObject *callable, | |
| 123 | + PyObject *converters, | |
| 124 | + void **pArgs) | |
| 125 | +{ | |
| 126 | + int i; | |
| 127 | + PyObject *result; | |
| 128 | + PyObject *arglist = NULL; | |
| 129 | + int nArgs; | |
| 130 | +#ifdef WITH_THREAD | |
| 131 | + PyGILState_STATE state = PyGILState_Ensure(); | |
| 132 | +#endif | |
| 133 | + | |
| 134 | + nArgs = PySequence_Length(converters); | |
| 135 | + /* Hm. What to return in case of error? | |
| 136 | + For COM, 0xFFFFFFFF seems better than 0. | |
| 137 | + */ | |
| 138 | + if (nArgs < 0) { | |
| 139 | + PrintError("BUG: PySequence_Length"); | |
| 140 | + goto Done; | |
| 141 | + } | |
| 142 | + | |
| 143 | + arglist = PyTuple_New(nArgs); | |
| 144 | + if (!arglist) { | |
| 145 | + PrintError("PyTuple_New()"); | |
| 146 | + goto Done; | |
| 147 | + } | |
| 148 | + for (i = 0; i < nArgs; ++i) { | |
| 149 | + /* Note: new reference! */ | |
| 150 | + PyObject *cnv = PySequence_GetItem(converters, i); | |
| 151 | + StgDictObject *dict; | |
| 152 | + if (cnv) | |
| 153 | + dict = PyType_stgdict(cnv); | |
| 154 | + else { | |
| 155 | + PrintError("Getting argument converter %d\n", i); | |
| 156 | + goto Done; | |
| 157 | + } | |
| 158 | + | |
| 159 | + if (dict && dict->getfunc && !IsSimpleSubType(cnv)) { | |
| 160 | + PyObject *v = dict->getfunc(*pArgs, dict->size); | |
| 161 | + if (!v) { | |
| 162 | + PrintError("create argument %d:\n", i); | |
| 163 | + Py_DECREF(cnv); | |
| 164 | + goto Done; | |
| 165 | + } | |
| 166 | + PyTuple_SET_ITEM(arglist, i, v); | |
| 167 | + /* XXX XXX XX | |
| 168 | + We have the problem that c_byte or c_short have dict->size of | |
| 169 | + 1 resp. 4, but these parameters are pushed as sizeof(int) bytes. | |
| 170 | + BTW, the same problem occurrs when they are pushed as parameters | |
| 171 | + */ | |
| 172 | + } else if (dict) { | |
| 173 | + /* Hm, shouldn't we use CData_AtAddress() or something like that instead? */ | |
| 174 | + CDataObject *obj = (CDataObject *)PyObject_CallFunctionObjArgs(cnv, NULL); | |
| 175 | + if (!obj) { | |
| 176 | + PrintError("create argument %d:\n", i); | |
| 177 | + Py_DECREF(cnv); | |
| 178 | + goto Done; | |
| 179 | + } | |
| 180 | + if (!CDataObject_Check(obj)) { | |
| 181 | + Py_DECREF(obj); | |
| 182 | + Py_DECREF(cnv); | |
| 183 | + PrintError("unexpected result of create argument %d:\n", i); | |
| 184 | + goto Done; | |
| 185 | + } | |
| 186 | + memcpy(obj->b_ptr, *pArgs, dict->size); | |
| 187 | + PyTuple_SET_ITEM(arglist, i, (PyObject *)obj); | |
| 188 | +#ifdef MS_WIN32 | |
| 189 | + TryAddRef(dict, obj); | |
| 190 | +#endif | |
| 191 | + } else { | |
| 192 | + PyErr_SetString(PyExc_TypeError, | |
| 193 | + "cannot build parameter"); | |
| 194 | + PrintError("Parsing argument %d\n", i); | |
| 195 | + Py_DECREF(cnv); | |
| 196 | + goto Done; | |
| 197 | + } | |
| 198 | + Py_DECREF(cnv); | |
| 199 | + /* XXX error handling! */ | |
| 200 | + pArgs++; | |
| 201 | + } | |
| 202 | + | |
| 203 | +#define CHECK(what, x) \ | |
| 204 | +if (x == NULL) _AddTraceback(what, __FILE__, __LINE__ - 1), PyErr_Print() | |
| 205 | + | |
| 206 | + result = PyObject_CallObject(callable, arglist); | |
| 207 | + CHECK("'calling callback function'", result); | |
| 208 | + if ((restype != &ffi_type_void) && result) { | |
| 209 | + PyObject *keep; | |
| 210 | + assert(setfunc); | |
| 211 | +#ifdef WORDS_BIGENDIAN | |
| 212 | + /* See the corresponding code in callproc.c, around line 961 */ | |
| 213 | + if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg)) | |
| 214 | + mem = (char *)mem + sizeof(ffi_arg) - restype->size; | |
| 215 | +#endif | |
| 216 | + keep = setfunc(mem, result, 0); | |
| 217 | + CHECK("'converting callback result'", keep); | |
| 218 | + /* keep is an object we have to keep alive so that the result | |
| 219 | + stays valid. If there is no such object, the setfunc will | |
| 220 | + have returned Py_None. | |
| 221 | + | |
| 222 | + If there is such an object, we have no choice than to keep | |
| 223 | + it alive forever - but a refcount and/or memory leak will | |
| 224 | + be the result. EXCEPT when restype is py_object - Python | |
| 225 | + itself knows how to manage the refcount of these objects. | |
| 226 | + */ | |
| 227 | + if (keep == NULL) /* Could not convert callback result. */ | |
| 228 | + PyErr_WriteUnraisable(callable); | |
| 229 | + else if (keep == Py_None) /* Nothing to keep */ | |
| 230 | + Py_DECREF(keep); | |
| 231 | + else if (setfunc != getentry("O")->setfunc) { | |
| 232 | + if (-1 == PyErr_Warn(PyExc_RuntimeWarning, | |
| 233 | + "memory leak in callback function.")) | |
| 234 | + PyErr_WriteUnraisable(callable); | |
| 235 | + } | |
| 236 | + } | |
| 237 | + Py_XDECREF(result); | |
| 238 | + Done: | |
| 239 | + Py_XDECREF(arglist); | |
| 240 | +#ifdef WITH_THREAD | |
| 241 | + PyGILState_Release(state); | |
| 242 | +#endif | |
| 243 | +} | |
| 244 | + | |
| 245 | +static void closure_fcn(ffi_cif *cif, | |
| 246 | + void *resp, | |
| 247 | + void **args, | |
| 248 | + void *userdata) | |
| 249 | +{ | |
| 250 | + ffi_info *p = userdata; | |
| 251 | + | |
| 252 | + _CallPythonObject(resp, | |
| 253 | + p->restype, | |
| 254 | + p->setfunc, | |
| 255 | + p->callable, | |
| 256 | + p->converters, | |
| 257 | + args); | |
| 258 | +} | |
| 259 | + | |
| 260 | +ffi_info *AllocFunctionCallback(PyObject *callable, | |
| 261 | + PyObject *converters, | |
| 262 | + PyObject *restype, | |
| 263 | + int is_cdecl) | |
| 264 | +{ | |
| 265 | + int result; | |
| 266 | + ffi_info *p; | |
| 267 | + int nArgs, i; | |
| 268 | + ffi_abi cc; | |
| 269 | + | |
| 270 | + nArgs = PySequence_Size(converters); | |
| 271 | + p = (ffi_info *)PyMem_Malloc(sizeof(ffi_info) + sizeof(ffi_type) * (nArgs + 1)); | |
| 272 | + if (p == NULL) { | |
| 273 | + PyErr_NoMemory(); | |
| 274 | + return NULL; | |
| 275 | + } | |
| 276 | + p->pcl = MallocClosure(); | |
| 277 | + if (p->pcl == NULL) { | |
| 278 | + PyErr_NoMemory(); | |
| 279 | + goto error; | |
| 280 | + } | |
| 281 | + | |
| 282 | + for (i = 0; i < nArgs; ++i) { | |
| 283 | + PyObject *cnv = PySequence_GetItem(converters, i); | |
| 284 | + if (cnv == NULL) | |
| 285 | + goto error; | |
| 286 | + p->atypes[i] = GetType(cnv); | |
| 287 | + Py_DECREF(cnv); | |
| 288 | + } | |
| 289 | + p->atypes[i] = NULL; | |
| 290 | + | |
| 291 | + if (restype == Py_None) { | |
| 292 | + p->setfunc = NULL; | |
| 293 | + p->restype = &ffi_type_void; | |
| 294 | + } else { | |
| 295 | + StgDictObject *dict = PyType_stgdict(restype); | |
| 296 | + if (dict == NULL || dict->setfunc == NULL) { | |
| 297 | + PyErr_SetString(PyExc_TypeError, | |
| 298 | + "invalid result type for callback function"); | |
| 299 | + goto error; | |
| 300 | + } | |
| 301 | + p->setfunc = dict->setfunc; | |
| 302 | + p->restype = &dict->ffi_type_pointer; | |
| 303 | + } | |
| 304 | + | |
| 305 | + cc = FFI_DEFAULT_ABI; | |
| 306 | +#if defined(MS_WIN32) && !defined(_WIN32_WCE) | |
| 307 | + if (is_cdecl == 0) | |
| 308 | + cc = FFI_STDCALL; | |
| 309 | +#endif | |
| 310 | + result = ffi_prep_cif(&p->cif, cc, nArgs, | |
| 311 | + GetType(restype), | |
| 312 | + &p->atypes[0]); | |
| 313 | + if (result != FFI_OK) { | |
| 314 | + PyErr_Format(PyExc_RuntimeError, | |
| 315 | + "ffi_prep_cif failed with %d", result); | |
| 316 | + goto error; | |
| 317 | + } | |
| 318 | + result = ffi_prep_closure(p->pcl, &p->cif, closure_fcn, p); | |
| 319 | + if (result != FFI_OK) { | |
| 320 | + PyErr_Format(PyExc_RuntimeError, | |
| 321 | + "ffi_prep_closure failed with %d", result); | |
| 322 | + goto error; | |
| 323 | + } | |
| 324 | + | |
| 325 | + p->converters = converters; | |
| 326 | + p->callable = callable; | |
| 327 | + return p; | |
| 328 | + | |
| 329 | + error: | |
| 330 | + if (p) { | |
| 331 | + if (p->pcl) | |
| 332 | + FreeClosure(p->pcl); | |
| 333 | + PyMem_Free(p); | |
| 334 | + } | |
| 335 | + return NULL; | |
| 336 | +} | |
| 337 | + | |
| 338 | +/**************************************************************************** | |
| 339 | + * | |
| 340 | + * callback objects: initialization | |
| 341 | + */ | |
| 342 | + | |
| 343 | +void init_callbacks_in_module(PyObject *m) | |
| 344 | +{ | |
| 345 | + if (PyType_Ready((PyTypeObject *)&PyType_Type) < 0) | |
| 346 | + return; | |
| 347 | +} | |
| 348 | + | |
| 349 | +#ifdef MS_WIN32 | |
| 350 | + | |
| 351 | +static void LoadPython(void) | |
| 352 | +{ | |
| 353 | + if (!Py_IsInitialized()) { | |
| 354 | +#ifdef WITH_THREAD | |
| 355 | + PyEval_InitThreads(); | |
| 356 | +#endif | |
| 357 | + Py_Initialize(); | |
| 358 | + } | |
| 359 | +} | |
| 360 | + | |
| 361 | +/******************************************************************/ | |
| 362 | + | |
| 363 | +long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) | |
| 364 | +{ | |
| 365 | + PyObject *mod, *func, *result; | |
| 366 | + long retval; | |
| 367 | + static PyObject *context; | |
| 368 | + | |
| 369 | + if (context == NULL) | |
| 370 | + context = PyString_FromString("_ctypes.DllGetClassObject"); | |
| 371 | + | |
| 372 | + mod = PyImport_ImportModule("ctypes"); | |
| 373 | + if (!mod) { | |
| 374 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 375 | + /* There has been a warning before about this already */ | |
| 376 | + return E_FAIL; | |
| 377 | + } | |
| 378 | + | |
| 379 | + func = PyObject_GetAttrString(mod, "DllGetClassObject"); | |
| 380 | + Py_DECREF(mod); | |
| 381 | + if (!func) { | |
| 382 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 383 | + return E_FAIL; | |
| 384 | + } | |
| 385 | + | |
| 386 | + result = PyObject_CallFunction(func, | |
| 387 | + "iii", rclsid, riid, ppv); | |
| 388 | + Py_DECREF(func); | |
| 389 | + if (!result) { | |
| 390 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 391 | + return E_FAIL; | |
| 392 | + } | |
| 393 | + | |
| 394 | + retval = PyInt_AsLong(result); | |
| 395 | + if (PyErr_Occurred()) { | |
| 396 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 397 | + retval = E_FAIL; | |
| 398 | + } | |
| 399 | + Py_DECREF(result); | |
| 400 | + return retval; | |
| 401 | +} | |
| 402 | + | |
| 403 | +STDAPI DllGetClassObject(REFCLSID rclsid, | |
| 404 | + REFIID riid, | |
| 405 | + LPVOID *ppv) | |
| 406 | +{ | |
| 407 | + long result; | |
| 408 | +#ifdef WITH_THREAD | |
| 409 | + PyGILState_STATE state; | |
| 410 | +#endif | |
| 411 | + | |
| 412 | + LoadPython(); | |
| 413 | +#ifdef WITH_THREAD | |
| 414 | + state = PyGILState_Ensure(); | |
| 415 | +#endif | |
| 416 | + result = Call_GetClassObject(rclsid, riid, ppv); | |
| 417 | +#ifdef WITH_THREAD | |
| 418 | + PyGILState_Release(state); | |
| 419 | +#endif | |
| 420 | + return result; | |
| 421 | +} | |
| 422 | + | |
| 423 | +long Call_CanUnloadNow(void) | |
| 424 | +{ | |
| 425 | + PyObject *mod, *func, *result; | |
| 426 | + long retval; | |
| 427 | + static PyObject *context; | |
| 428 | + | |
| 429 | + if (context == NULL) | |
| 430 | + context = PyString_FromString("_ctypes.DllCanUnloadNow"); | |
| 431 | + | |
| 432 | + mod = PyImport_ImportModule("ctypes"); | |
| 433 | + if (!mod) { | |
| 434 | +/* OutputDebugString("Could not import ctypes"); */ | |
| 435 | + /* We assume that this error can only occur when shutting | |
| 436 | + down, so we silently ignore it */ | |
| 437 | + PyErr_Clear(); | |
| 438 | + return E_FAIL; | |
| 439 | + } | |
| 440 | + /* Other errors cannot be raised, but are printed to stderr */ | |
| 441 | + func = PyObject_GetAttrString(mod, "DllCanUnloadNow"); | |
| 442 | + Py_DECREF(mod); | |
| 443 | + if (!func) { | |
| 444 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 445 | + return E_FAIL; | |
| 446 | + } | |
| 447 | + | |
| 448 | + result = PyObject_CallFunction(func, NULL); | |
| 449 | + Py_DECREF(func); | |
| 450 | + if (!result) { | |
| 451 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 452 | + return E_FAIL; | |
| 453 | + } | |
| 454 | + | |
| 455 | + retval = PyInt_AsLong(result); | |
| 456 | + if (PyErr_Occurred()) { | |
| 457 | + PyErr_WriteUnraisable(context ? context : Py_None); | |
| 458 | + retval = E_FAIL; | |
| 459 | + } | |
| 460 | + Py_DECREF(result); | |
| 461 | + return retval; | |
| 462 | +} | |
| 463 | + | |
| 464 | +/* | |
| 465 | + DllRegisterServer and DllUnregisterServer still missing | |
| 466 | +*/ | |
| 467 | + | |
| 468 | +STDAPI DllCanUnloadNow(void) | |
| 469 | +{ | |
| 470 | + long result; | |
| 471 | +#ifdef WITH_THREAD | |
| 472 | + PyGILState_STATE state = PyGILState_Ensure(); | |
| 473 | +#endif | |
| 474 | + result = Call_CanUnloadNow(); | |
| 475 | +#ifdef WITH_THREAD | |
| 476 | + PyGILState_Release(state); | |
| 477 | +#endif | |
| 478 | + return result; | |
| 479 | +} | |
| 480 | + | |
| 481 | +#ifndef Py_NO_ENABLE_SHARED | |
| 482 | +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes) | |
| 483 | +{ | |
| 484 | + switch(fdwReason) { | |
| 485 | + case DLL_PROCESS_ATTACH: | |
| 486 | + DisableThreadLibraryCalls(hinstDLL); | |
| 487 | + break; | |
| 488 | + } | |
| 489 | + return TRUE; | |
| 490 | +} | |
| 491 | +#endif | |
| 492 | + | |
| 493 | +#endif | |
| 494 | + | |
| 495 | +/* | |
| 496 | + Local Variables: | |
| 497 | + compile-command: "cd .. && python setup.py -q build_ext" | |
| 498 | + End: | |
| 499 | +*/ | |
| @@ -0,0 +1,1581 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | + | |
| 6 | +/* | |
| 7 | + * History: First version dated from 3/97, derived from my SCMLIB version | |
| 8 | + * for win16. | |
| 9 | + */ | |
| 10 | +/* | |
| 11 | + * Related Work: | |
| 12 | + * - calldll http://www.nightmare.com/software.html | |
| 13 | + * - libffi http://sourceware.cygnus.com/libffi/ | |
| 14 | + * - ffcall http://clisp.cons.org/~haible/packages-ffcall.html | |
| 15 | + * and, of course, Don Beaudry's MESS package, but this is more ctypes | |
| 16 | + * related. | |
| 17 | + */ | |
| 18 | + | |
| 19 | + | |
| 20 | +/* | |
| 21 | + How are functions called, and how are parameters converted to C ? | |
| 22 | + | |
| 23 | + 1. _ctypes.c::CFuncPtr_call receives an argument tuple 'inargs' and a | |
| 24 | + keyword dictionary 'kwds'. | |
| 25 | + | |
| 26 | + 2. After several checks, _build_callargs() is called which returns another | |
| 27 | + tuple 'callargs'. This may be the same tuple as 'inargs', a slice of | |
| 28 | + 'inargs', or a completely fresh tuple, depending on several things (is is a | |
| 29 | + COM method, are 'paramflags' available). | |
| 30 | + | |
| 31 | + 3. _build_callargs also calculates bitarrays containing indexes into | |
| 32 | + the callargs tuple, specifying how to build the return value(s) of | |
| 33 | + the function. | |
| 34 | + | |
| 35 | + 4. _CallProc is then called with the 'callargs' tuple. _CallProc first | |
| 36 | + allocates two arrays. The first is an array of 'struct argument' items, the | |
| 37 | + second array has 'void *' entried. | |
| 38 | + | |
| 39 | + 5. If 'converters' are present (converters is a sequence of argtypes' | |
| 40 | + from_param methods), for each item in 'callargs' converter is called and the | |
| 41 | + result passed to ConvParam. If 'converters' are not present, each argument | |
| 42 | + is directly passed to ConvParm. | |
| 43 | + | |
| 44 | + 6. For each arg, ConvParam stores the contained C data (or a pointer to it, | |
| 45 | + for structures) into the 'struct argument' array. | |
| 46 | + | |
| 47 | + 7. Finally, a loop fills the 'void *' array so that each item points to the | |
| 48 | + data contained in or pointed to by the 'struct argument' array. | |
| 49 | + | |
| 50 | + 8. The 'void *' argument array is what _call_function_pointer | |
| 51 | + expects. _call_function_pointer then has very little to do - only some | |
| 52 | + libffi specific stuff, then it calls ffi_call. | |
| 53 | + | |
| 54 | + So, there are 4 data structures holding processed arguments: | |
| 55 | + - the inargs tuple (in CFuncPtr_call) | |
| 56 | + - the callargs tuple (in CFuncPtr_call) | |
| 57 | + - the 'struct argguments' array | |
| 58 | + - the 'void *' array | |
| 59 | + | |
| 60 | + */ | |
| 61 | + | |
| 62 | +#include "Python.h" | |
| 63 | +#include "structmember.h" | |
| 64 | + | |
| 65 | +#ifdef MS_WIN32 | |
| 66 | +#include <windows.h> | |
| 67 | +#else | |
| 68 | +#include "ctypes_dlfcn.h" | |
| 69 | +#endif | |
| 70 | + | |
| 71 | +#ifdef MS_WIN32 | |
| 72 | +#include <malloc.h> | |
| 73 | +#endif | |
| 74 | + | |
| 75 | +#include <ffi.h> | |
| 76 | +#include "ctypes.h" | |
| 77 | + | |
| 78 | +#if defined(_DEBUG) || defined(__MINGW32__) | |
| 79 | +/* Don't use structured exception handling on Windows if this is defined. | |
| 80 | + MingW, AFAIK, doesn't support it. | |
| 81 | +*/ | |
| 82 | +#define DONT_USE_SEH | |
| 83 | +#endif | |
| 84 | + | |
| 85 | +#ifdef MS_WIN32 | |
| 86 | +PyObject *ComError; | |
| 87 | + | |
| 88 | +static TCHAR *FormatError(DWORD code) | |
| 89 | +{ | |
| 90 | + TCHAR *lpMsgBuf; | |
| 91 | + DWORD n; | |
| 92 | + n = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, | |
| 93 | + NULL, | |
| 94 | + code, | |
| 95 | + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language | |
| 96 | + (LPTSTR) &lpMsgBuf, | |
| 97 | + 0, | |
| 98 | + NULL); | |
| 99 | + if (n) { | |
| 100 | + while (isspace(lpMsgBuf[n-1])) | |
| 101 | + --n; | |
| 102 | + lpMsgBuf[n] = '\0'; /* rstrip() */ | |
| 103 | + } | |
| 104 | + return lpMsgBuf; | |
| 105 | +} | |
| 106 | + | |
| 107 | +#ifndef DONT_USE_SEH | |
| 108 | +void SetException(DWORD code, EXCEPTION_RECORD *pr) | |
| 109 | +{ | |
| 110 | + TCHAR *lpMsgBuf; | |
| 111 | + lpMsgBuf = FormatError(code); | |
| 112 | + if(lpMsgBuf) { | |
| 113 | + PyErr_SetFromWindowsErr(code); | |
| 114 | + LocalFree(lpMsgBuf); | |
| 115 | + } else { | |
| 116 | + switch (code) { | |
| 117 | + case EXCEPTION_ACCESS_VIOLATION: | |
| 118 | + /* The thread attempted to read from or write | |
| 119 | + to a virtual address for which it does not | |
| 120 | + have the appropriate access. */ | |
| 121 | + if (pr->ExceptionInformation[0] == 0) | |
| 122 | + PyErr_Format(PyExc_WindowsError, | |
| 123 | + "exception: access violation reading %p", | |
| 124 | + pr->ExceptionInformation[1]); | |
| 125 | + else | |
| 126 | + PyErr_Format(PyExc_WindowsError, | |
| 127 | + "exception: access violation writing %p", | |
| 128 | + pr->ExceptionInformation[1]); | |
| 129 | + break; | |
| 130 | + case EXCEPTION_BREAKPOINT: | |
| 131 | + /* A breakpoint was encountered. */ | |
| 132 | + PyErr_SetString(PyExc_WindowsError, | |
| 133 | + "exception: breakpoint encountered"); | |
| 134 | + break; | |
| 135 | + | |
| 136 | + case EXCEPTION_DATATYPE_MISALIGNMENT: | |
| 137 | + /* The thread attempted to read or write data that is | |
| 138 | + misaligned on hardware that does not provide | |
| 139 | + alignment. For example, 16-bit values must be | |
| 140 | + aligned on 2-byte boundaries, 32-bit values on | |
| 141 | + 4-byte boundaries, and so on. */ | |
| 142 | + PyErr_SetString(PyExc_WindowsError, | |
| 143 | + "exception: datatype misalignment"); | |
| 144 | + break; | |
| 145 | + | |
| 146 | + case EXCEPTION_SINGLE_STEP: | |
| 147 | + /* A trace trap or other single-instruction mechanism | |
| 148 | + signaled that one instruction has been executed. */ | |
| 149 | + PyErr_SetString(PyExc_WindowsError, | |
| 150 | + "exception: single step"); | |
| 151 | + break; | |
| 152 | + | |
| 153 | + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: | |
| 154 | + /* The thread attempted to access an array element | |
| 155 | + that is out of bounds, and the underlying hardware | |
| 156 | + supports bounds checking. */ | |
| 157 | + PyErr_SetString(PyExc_WindowsError, | |
| 158 | + "exception: array bounds exceeded"); | |
| 159 | + break; | |
| 160 | + | |
| 161 | + case EXCEPTION_FLT_DENORMAL_OPERAND: | |
| 162 | + /* One of the operands in a floating-point operation | |
| 163 | + is denormal. A denormal value is one that is too | |
| 164 | + small to represent as a standard floating-point | |
| 165 | + value. */ | |
| 166 | + PyErr_SetString(PyExc_WindowsError, | |
| 167 | + "exception: floating-point operand denormal"); | |
| 168 | + break; | |
| 169 | + | |
| 170 | + case EXCEPTION_FLT_DIVIDE_BY_ZERO: | |
| 171 | + /* The thread attempted to divide a floating-point | |
| 172 | + value by a floating-point divisor of zero. */ | |
| 173 | + PyErr_SetString(PyExc_WindowsError, | |
| 174 | + "exception: float divide by zero"); | |
| 175 | + break; | |
| 176 | + | |
| 177 | + case EXCEPTION_FLT_INEXACT_RESULT: | |
| 178 | + /* The result of a floating-point operation cannot be | |
| 179 | + represented exactly as a decimal fraction. */ | |
| 180 | + PyErr_SetString(PyExc_WindowsError, | |
| 181 | + "exception: float inexact"); | |
| 182 | + break; | |
| 183 | + | |
| 184 | + case EXCEPTION_FLT_INVALID_OPERATION: | |
| 185 | + /* This exception represents any floating-point | |
| 186 | + exception not included in this list. */ | |
| 187 | + PyErr_SetString(PyExc_WindowsError, | |
| 188 | + "exception: float invalid operation"); | |
| 189 | + break; | |
| 190 | + | |
| 191 | + case EXCEPTION_FLT_OVERFLOW: | |
| 192 | + /* The exponent of a floating-point operation is | |
| 193 | + greater than the magnitude allowed by the | |
| 194 | + corresponding type. */ | |
| 195 | + PyErr_SetString(PyExc_WindowsError, | |
| 196 | + "exception: float overflow"); | |
| 197 | + break; | |
| 198 | + | |
| 199 | + case EXCEPTION_FLT_STACK_CHECK: | |
| 200 | + /* The stack overflowed or underflowed as the result | |
| 201 | + of a floating-point operation. */ | |
| 202 | + PyErr_SetString(PyExc_WindowsError, | |
| 203 | + "exception: stack over/underflow"); | |
| 204 | + break; | |
| 205 | + | |
| 206 | + case EXCEPTION_STACK_OVERFLOW: | |
| 207 | + /* The stack overflowed or underflowed as the result | |
| 208 | + of a floating-point operation. */ | |
| 209 | + PyErr_SetString(PyExc_WindowsError, | |
| 210 | + "exception: stack overflow"); | |
| 211 | + break; | |
| 212 | + | |
| 213 | + case EXCEPTION_FLT_UNDERFLOW: | |
| 214 | + /* The exponent of a floating-point operation is less | |
| 215 | + than the magnitude allowed by the corresponding | |
| 216 | + type. */ | |
| 217 | + PyErr_SetString(PyExc_WindowsError, | |
| 218 | + "exception: float underflow"); | |
| 219 | + break; | |
| 220 | + | |
| 221 | + case EXCEPTION_INT_DIVIDE_BY_ZERO: | |
| 222 | + /* The thread attempted to divide an integer value by | |
| 223 | + an integer divisor of zero. */ | |
| 224 | + PyErr_SetString(PyExc_WindowsError, | |
| 225 | + "exception: integer divide by zero"); | |
| 226 | + break; | |
| 227 | + | |
| 228 | + case EXCEPTION_INT_OVERFLOW: | |
| 229 | + /* The result of an integer operation caused a carry | |
| 230 | + out of the most significant bit of the result. */ | |
| 231 | + PyErr_SetString(PyExc_WindowsError, | |
| 232 | + "exception: integer overflow"); | |
| 233 | + break; | |
| 234 | + | |
| 235 | + case EXCEPTION_PRIV_INSTRUCTION: | |
| 236 | + /* The thread attempted to execute an instruction | |
| 237 | + whose operation is not allowed in the current | |
| 238 | + machine mode. */ | |
| 239 | + PyErr_SetString(PyExc_WindowsError, | |
| 240 | + "exception: priviledged instruction"); | |
| 241 | + break; | |
| 242 | + | |
| 243 | + case EXCEPTION_NONCONTINUABLE_EXCEPTION: | |
| 244 | + /* The thread attempted to continue execution after a | |
| 245 | + noncontinuable exception occurred. */ | |
| 246 | + PyErr_SetString(PyExc_WindowsError, | |
| 247 | + "exception: nocontinuable"); | |
| 248 | + break; | |
| 249 | + default: | |
| 250 | + printf("error %d\n", code); | |
| 251 | + PyErr_Format(PyExc_WindowsError, | |
| 252 | + "exception code 0x%08x", | |
| 253 | + code); | |
| 254 | + break; | |
| 255 | + } | |
| 256 | + } | |
| 257 | +} | |
| 258 | + | |
| 259 | +static DWORD HandleException(EXCEPTION_POINTERS *ptrs, | |
| 260 | + DWORD *pdw, EXCEPTION_RECORD *record) | |
| 261 | +{ | |
| 262 | + *pdw = ptrs->ExceptionRecord->ExceptionCode; | |
| 263 | + *record = *ptrs->ExceptionRecord; | |
| 264 | + return EXCEPTION_EXECUTE_HANDLER; | |
| 265 | +} | |
| 266 | +#endif | |
| 267 | + | |
| 268 | +static PyObject * | |
| 269 | +check_hresult(PyObject *self, PyObject *args) | |
| 270 | +{ | |
| 271 | + HRESULT hr; | |
| 272 | + if (!PyArg_ParseTuple(args, "i", &hr)) | |
| 273 | + return NULL; | |
| 274 | + if (FAILED(hr)) | |
| 275 | + return PyErr_SetFromWindowsErr(hr); | |
| 276 | + return PyInt_FromLong(hr); | |
| 277 | +} | |
| 278 | + | |
| 279 | +#endif | |
| 280 | + | |
| 281 | +/**************************************************************/ | |
| 282 | + | |
| 283 | +PyCArgObject * | |
| 284 | +new_CArgObject(void) | |
| 285 | +{ | |
| 286 | + PyCArgObject *p; | |
| 287 | + p = PyObject_New(PyCArgObject, &PyCArg_Type); | |
| 288 | + if (p == NULL) | |
| 289 | + return NULL; | |
| 290 | + p->pffi_type = NULL; | |
| 291 | + p->tag = '\0'; | |
| 292 | + p->obj = NULL; | |
| 293 | + memset(&p->value, 0, sizeof(p->value)); | |
| 294 | + return p; | |
| 295 | +} | |
| 296 | + | |
| 297 | +static void | |
| 298 | +PyCArg_dealloc(PyCArgObject *self) | |
| 299 | +{ | |
| 300 | + Py_XDECREF(self->obj); | |
| 301 | + PyObject_Del(self); | |
| 302 | +} | |
| 303 | + | |
| 304 | +static PyObject * | |
| 305 | +PyCArg_repr(PyCArgObject *self) | |
| 306 | +{ | |
| 307 | + char buffer[256]; | |
| 308 | + switch(self->tag) { | |
| 309 | + case 'b': | |
| 310 | + case 'B': | |
| 311 | + sprintf(buffer, "<cparam '%c' (%d)>", | |
| 312 | + self->tag, self->value.b); | |
| 313 | + break; | |
| 314 | + case 'h': | |
| 315 | + case 'H': | |
| 316 | + sprintf(buffer, "<cparam '%c' (%d)>", | |
| 317 | + self->tag, self->value.h); | |
| 318 | + break; | |
| 319 | + case 'i': | |
| 320 | + case 'I': | |
| 321 | + sprintf(buffer, "<cparam '%c' (%d)>", | |
| 322 | + self->tag, self->value.i); | |
| 323 | + break; | |
| 324 | + case 'l': | |
| 325 | + case 'L': | |
| 326 | + sprintf(buffer, "<cparam '%c' (%ld)>", | |
| 327 | + self->tag, self->value.l); | |
| 328 | + break; | |
| 329 | + | |
| 330 | +#ifdef HAVE_LONG_LONG | |
| 331 | + case 'q': | |
| 332 | + case 'Q': | |
| 333 | + sprintf(buffer, | |
| 334 | +#ifdef MS_WIN32 | |
| 335 | + "<cparam '%c' (%I64d)>", | |
| 336 | +#else | |
| 337 | + "<cparam '%c' (%qd)>", | |
| 338 | +#endif | |
| 339 | + self->tag, self->value.q); | |
| 340 | + break; | |
| 341 | +#endif | |
| 342 | + case 'd': | |
| 343 | + sprintf(buffer, "<cparam '%c' (%f)>", | |
| 344 | + self->tag, self->value.d); | |
| 345 | + break; | |
| 346 | + case 'f': | |
| 347 | + sprintf(buffer, "<cparam '%c' (%f)>", | |
| 348 | + self->tag, self->value.f); | |
| 349 | + break; | |
| 350 | + | |
| 351 | + case 'c': | |
| 352 | + sprintf(buffer, "<cparam '%c' (%c)>", | |
| 353 | + self->tag, self->value.c); | |
| 354 | + break; | |
| 355 | + | |
| 356 | +/* Hm, are these 'z' and 'Z' codes useful at all? | |
| 357 | + Shouldn't they be replaced by the functionality of c_string | |
| 358 | + and c_wstring ? | |
| 359 | +*/ | |
| 360 | + case 'z': | |
| 361 | + case 'Z': | |
| 362 | + case 'P': | |
| 363 | + sprintf(buffer, "<cparam '%c' (%08lx)>", | |
| 364 | + self->tag, (long)self->value.p); | |
| 365 | + break; | |
| 366 | + | |
| 367 | + default: | |
| 368 | + sprintf(buffer, "<cparam '%c' at %08lx>", | |
| 369 | + self->tag, (long)self); | |
| 370 | + break; | |
| 371 | + } | |
| 372 | + return PyString_FromString(buffer); | |
| 373 | +} | |
| 374 | + | |
| 375 | +static PyMemberDef PyCArgType_members[] = { | |
| 376 | + { "_obj", T_OBJECT, | |
| 377 | + offsetof(PyCArgObject, obj), READONLY, | |
| 378 | + "the wrapped object" }, | |
| 379 | + { NULL }, | |
| 380 | +}; | |
| 381 | + | |
| 382 | +PyTypeObject PyCArg_Type = { | |
| 383 | + PyObject_HEAD_INIT(NULL) | |
| 384 | + 0, | |
| 385 | + "CArgObject", | |
| 386 | + sizeof(PyCArgObject), | |
| 387 | + 0, | |
| 388 | + (destructor)PyCArg_dealloc, /* tp_dealloc */ | |
| 389 | + 0, /* tp_print */ | |
| 390 | + 0, /* tp_getattr */ | |
| 391 | + 0, /* tp_setattr */ | |
| 392 | + 0, /* tp_compare */ | |
| 393 | + (reprfunc)PyCArg_repr, /* tp_repr */ | |
| 394 | + 0, /* tp_as_number */ | |
| 395 | + 0, /* tp_as_sequence */ | |
| 396 | + 0, /* tp_as_mapping */ | |
| 397 | + 0, /* tp_hash */ | |
| 398 | + 0, /* tp_call */ | |
| 399 | + 0, /* tp_str */ | |
| 400 | + 0, /* tp_getattro */ | |
| 401 | + 0, /* tp_setattro */ | |
| 402 | + 0, /* tp_as_buffer */ | |
| 403 | + Py_TPFLAGS_DEFAULT, /* tp_flags */ | |
| 404 | + 0, /* tp_doc */ | |
| 405 | + 0, /* tp_traverse */ | |
| 406 | + 0, /* tp_clear */ | |
| 407 | + 0, /* tp_richcompare */ | |
| 408 | + 0, /* tp_weaklistoffset */ | |
| 409 | + 0, /* tp_iter */ | |
| 410 | + 0, /* tp_iternext */ | |
| 411 | + 0, /* tp_methods */ | |
| 412 | + PyCArgType_members, /* tp_members */ | |
| 413 | +}; | |
| 414 | + | |
| 415 | +/****************************************************************/ | |
| 416 | +/* | |
| 417 | + * Convert a PyObject * into a parameter suitable to pass to an | |
| 418 | + * C function call. | |
| 419 | + * | |
| 420 | + * 1. Python integers are converted to C int and passed by value. | |
| 421 | + * | |
| 422 | + * 2. 3-tuples are expected to have a format character in the first | |
| 423 | + * item, which must be 'i', 'f', 'd', 'q', or 'P'. | |
| 424 | + * The second item will have to be an integer, float, double, long long | |
| 425 | + * or integer (denoting an address void *), will be converted to the | |
| 426 | + * corresponding C data type and passed by value. | |
| 427 | + * | |
| 428 | + * 3. Other Python objects are tested for an '_as_parameter_' attribute. | |
| 429 | + * The value of this attribute must be an integer which will be passed | |
| 430 | + * by value, or a 2-tuple or 3-tuple which will be used according | |
| 431 | + * to point 2 above. The third item (if any), is ignored. It is normally | |
| 432 | + * used to keep the object alive where this parameter refers to. | |
| 433 | + * XXX This convention is dangerous - you can construct arbitrary tuples | |
| 434 | + * in Python and pass them. Would it be safer to use a custom container | |
| 435 | + * datatype instead of a tuple? | |
| 436 | + * | |
| 437 | + * 4. Other Python objects cannot be passed as parameters - an exception is raised. | |
| 438 | + * | |
| 439 | + * 5. ConvParam will store the converted result in a struct containing format | |
| 440 | + * and value. | |
| 441 | + */ | |
| 442 | + | |
| 443 | +union result { | |
| 444 | + char c; | |
| 445 | + char b; | |
| 446 | + short h; | |
| 447 | + int i; | |
| 448 | + long l; | |
| 449 | +#ifdef HAVE_LONG_LONG | |
| 450 | + PY_LONG_LONG q; | |
| 451 | +#endif | |
| 452 | + double d; | |
| 453 | + float f; | |
| 454 | + void *p; | |
| 455 | +}; | |
| 456 | + | |
| 457 | +struct argument { | |
| 458 | + ffi_type *ffi_type; | |
| 459 | + PyObject *keep; | |
| 460 | + union result value; | |
| 461 | +}; | |
| 462 | + | |
| 463 | +/* | |
| 464 | + * Convert a single Python object into a PyCArgObject and return it. | |
| 465 | + */ | |
| 466 | +static int ConvParam(PyObject *obj, int index, struct argument *pa) | |
| 467 | +{ | |
| 468 | + StgDictObject *dict; | |
| 469 | + pa->keep = NULL; /* so we cannot forget it later */ | |
| 470 | + | |
| 471 | + dict = PyObject_stgdict(obj); | |
| 472 | + if (dict) { | |
| 473 | + PyCArgObject *carg; | |
| 474 | + assert(dict->paramfunc); | |
| 475 | + /* If it has an stgdict, it is a CDataObject */ | |
| 476 | + carg = dict->paramfunc((CDataObject *)obj); | |
| 477 | + pa->ffi_type = carg->pffi_type; | |
| 478 | + memcpy(&pa->value, &carg->value, sizeof(pa->value)); | |
| 479 | + pa->keep = (PyObject *)carg; | |
| 480 | + return 0; | |
| 481 | + } | |
| 482 | + | |
| 483 | + if (PyCArg_CheckExact(obj)) { | |
| 484 | + PyCArgObject *carg = (PyCArgObject *)obj; | |
| 485 | + pa->ffi_type = carg->pffi_type; | |
| 486 | + Py_INCREF(obj); | |
| 487 | + pa->keep = obj; | |
| 488 | + memcpy(&pa->value, &carg->value, sizeof(pa->value)); | |
| 489 | + return 0; | |
| 490 | + } | |
| 491 | + | |
| 492 | + /* check for None, integer, string or unicode and use directly if successful */ | |
| 493 | + if (obj == Py_None) { | |
| 494 | + pa->ffi_type = &ffi_type_pointer; | |
| 495 | + pa->value.p = NULL; | |
| 496 | + return 0; | |
| 497 | + } | |
| 498 | + | |
| 499 | + if (PyInt_Check(obj)) { | |
| 500 | + pa->ffi_type = &ffi_type_sint; | |
| 501 | + pa->value.i = PyInt_AS_LONG(obj); | |
| 502 | + return 0; | |
| 503 | + } | |
| 504 | + | |
| 505 | + if (PyLong_Check(obj)) { | |
| 506 | + pa->ffi_type = &ffi_type_sint; | |
| 507 | + pa->value.i = (long)PyLong_AsUnsignedLong(obj); | |
| 508 | + if (pa->value.i == -1 && PyErr_Occurred()) { | |
| 509 | + PyErr_Clear(); | |
| 510 | + pa->value.i = PyLong_AsLong(obj); | |
| 511 | + if (pa->value.i == -1 && PyErr_Occurred()) { | |
| 512 | + PyErr_SetString(PyExc_OverflowError, | |
| 513 | + "long int too long to convert"); | |
| 514 | + return -1; | |
| 515 | + } | |
| 516 | + } | |
| 517 | + return 0; | |
| 518 | + } | |
| 519 | + | |
| 520 | + if (PyString_Check(obj)) { | |
| 521 | + pa->ffi_type = &ffi_type_pointer; | |
| 522 | + pa->value.p = PyString_AS_STRING(obj); | |
| 523 | + Py_INCREF(obj); | |
| 524 | + pa->keep = obj; | |
| 525 | + return 0; | |
| 526 | + } | |
| 527 | + | |
| 528 | +#ifdef CTYPES_UNICODE | |
| 529 | + if (PyUnicode_Check(obj)) { | |
| 530 | +#ifdef HAVE_USABLE_WCHAR_T | |
| 531 | + pa->ffi_type = &ffi_type_pointer; | |
| 532 | + pa->value.p = PyUnicode_AS_UNICODE(obj); | |
| 533 | + Py_INCREF(obj); | |
| 534 | + pa->keep = obj; | |
| 535 | + return 0; | |
| 536 | +#else | |
| 537 | + int size = PyUnicode_GET_SIZE(obj); | |
| 538 | + size += 1; /* terminating NUL */ | |
| 539 | + size *= sizeof(wchar_t); | |
| 540 | + pa->value.p = PyMem_Malloc(size); | |
| 541 | + if (!pa->value.p) | |
| 542 | + return -1; | |
| 543 | + memset(pa->value.p, 0, size); | |
| 544 | + pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free); | |
| 545 | + if (!pa->keep) { | |
| 546 | + PyMem_Free(pa->value.p); | |
| 547 | + return -1; | |
| 548 | + } | |
| 549 | + if (-1 == PyUnicode_AsWideChar((PyUnicodeObject *)obj, | |
| 550 | + pa->value.p, PyUnicode_GET_SIZE(obj))) | |
| 551 | + return -1; | |
| 552 | + return 0; | |
| 553 | +#endif | |
| 554 | + } | |
| 555 | +#endif | |
| 556 | + | |
| 557 | + { | |
| 558 | + PyObject *arg; | |
| 559 | + arg = PyObject_GetAttrString(obj, "_as_parameter_"); | |
| 560 | + /* Which types should we exactly allow here? | |
| 561 | + integers are required for using Python classes | |
| 562 | + as parameters (they have to expose the '_as_parameter_' | |
| 563 | + attribute) | |
| 564 | + */ | |
| 565 | + if (arg) { | |
| 566 | + int result; | |
| 567 | + result = ConvParam(arg, index, pa); | |
| 568 | + Py_DECREF(arg); | |
| 569 | + return result; | |
| 570 | + } | |
| 571 | + PyErr_Format(PyExc_TypeError, | |
| 572 | + "Don't know how to convert parameter %d", index); | |
| 573 | + return -1; | |
| 574 | + } | |
| 575 | +} | |
| 576 | + | |
| 577 | + | |
| 578 | +ffi_type *GetType(PyObject *obj) | |
| 579 | +{ | |
| 580 | + StgDictObject *dict; | |
| 581 | + if (obj == NULL) | |
| 582 | + return &ffi_type_sint; | |
| 583 | + dict = PyType_stgdict(obj); | |
| 584 | + if (dict == NULL) | |
| 585 | + return &ffi_type_sint; | |
| 586 | +#if defined(MS_WIN32) && !defined(_WIN32_WCE) | |
| 587 | + /* This little trick works correctly with MSVC. | |
| 588 | + It returns small structures in registers | |
| 589 | + */ | |
| 590 | + if (dict->ffi_type_pointer.type == FFI_TYPE_STRUCT) { | |
| 591 | + if (dict->ffi_type_pointer.size <= 4) | |
| 592 | + return &ffi_type_sint32; | |
| 593 | + else if (dict->ffi_type_pointer.size <= 8) | |
| 594 | + return &ffi_type_sint64; | |
| 595 | + } | |
| 596 | +#endif | |
| 597 | + return &dict->ffi_type_pointer; | |
| 598 | +} | |
| 599 | + | |
| 600 | + | |
| 601 | +/* | |
| 602 | + * libffi uses: | |
| 603 | + * | |
| 604 | + * ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, | |
| 605 | + * unsigned int nargs, | |
| 606 | + * ffi_type *rtype, | |
| 607 | + * ffi_type **atypes); | |
| 608 | + * | |
| 609 | + * and then | |
| 610 | + * | |
| 611 | + * void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); | |
| 612 | + */ | |
| 613 | +static int _call_function_pointer(int flags, | |
| 614 | + PPROC pProc, | |
| 615 | + void **avalues, | |
| 616 | + ffi_type **atypes, | |
| 617 | + ffi_type *restype, | |
| 618 | + void *resmem, | |
| 619 | + int argcount) | |
| 620 | +{ | |
| 621 | +#ifdef WITH_THREAD | |
| 622 | + PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */ | |
| 623 | +#endif | |
| 624 | + ffi_cif cif; | |
| 625 | + int cc; | |
| 626 | +#ifdef MS_WIN32 | |
| 627 | + int delta; | |
| 628 | +#ifndef DONT_USE_SEH | |
| 629 | + DWORD dwExceptionCode = 0; | |
| 630 | + EXCEPTION_RECORD record; | |
| 631 | +#endif | |
| 632 | +#endif | |
| 633 | + /* XXX check before here */ | |
| 634 | + if (restype == NULL) { | |
| 635 | + PyErr_SetString(PyExc_RuntimeError, | |
| 636 | + "No ffi_type for result"); | |
| 637 | + return -1; | |
| 638 | + } | |
| 639 | + | |
| 640 | + cc = FFI_DEFAULT_ABI; | |
| 641 | +#if defined(MS_WIN32) && !defined(_WIN32_WCE) | |
| 642 | + if ((flags & FUNCFLAG_CDECL) == 0) | |
| 643 | + cc = FFI_STDCALL; | |
| 644 | +#endif | |
| 645 | + if (FFI_OK != ffi_prep_cif(&cif, | |
| 646 | + cc, | |
| 647 | + argcount, | |
| 648 | + restype, | |
| 649 | + atypes)) { | |
| 650 | + PyErr_SetString(PyExc_RuntimeError, | |
| 651 | + "ffi_prep_cif failed"); | |
| 652 | + return -1; | |
| 653 | + } | |
| 654 | + | |
| 655 | +#ifdef WITH_THREAD | |
| 656 | + if ((flags & FUNCFLAG_PYTHONAPI) == 0) | |
| 657 | + Py_UNBLOCK_THREADS | |
| 658 | +#endif | |
| 659 | +#ifdef MS_WIN32 | |
| 660 | +#ifndef DONT_USE_SEH | |
| 661 | + __try { | |
| 662 | +#endif | |
| 663 | + delta = | |
| 664 | +#endif | |
| 665 | + ffi_call(&cif, (void *)pProc, resmem, avalues); | |
| 666 | +#ifdef MS_WIN32 | |
| 667 | +#ifndef DONT_USE_SEH | |
| 668 | + } | |
| 669 | + __except (HandleException(GetExceptionInformation(), | |
| 670 | + &dwExceptionCode, &record)) { | |
| 671 | + ; | |
| 672 | + } | |
| 673 | +#endif | |
| 674 | +#endif | |
| 675 | +#ifdef WITH_THREAD | |
| 676 | + if ((flags & FUNCFLAG_PYTHONAPI) == 0) | |
| 677 | + Py_BLOCK_THREADS | |
| 678 | +#endif | |
| 679 | +#ifdef MS_WIN32 | |
| 680 | +#ifndef DONT_USE_SEH | |
| 681 | + if (dwExceptionCode) { | |
| 682 | + SetException(dwExceptionCode, &record); | |
| 683 | + return -1; | |
| 684 | + } | |
| 685 | +#endif | |
| 686 | + if (delta < 0) { | |
| 687 | + if (flags & FUNCFLAG_CDECL) | |
| 688 | + PyErr_Format(PyExc_ValueError, | |
| 689 | + "Procedure called with not enough " | |
| 690 | + "arguments (%d bytes missing) " | |
| 691 | + "or wrong calling convention", | |
| 692 | + -delta); | |
| 693 | + else | |
| 694 | + PyErr_Format(PyExc_ValueError, | |
| 695 | + "Procedure probably called with not enough " | |
| 696 | + "arguments (%d bytes missing)", | |
| 697 | + -delta); | |
| 698 | + return -1; | |
| 699 | + } else if (delta > 0) { | |
| 700 | + PyErr_Format(PyExc_ValueError, | |
| 701 | + "Procedure probably called with too many " | |
| 702 | + "arguments (%d bytes in excess)", | |
| 703 | + delta); | |
| 704 | + return -1; | |
| 705 | + } | |
| 706 | +#endif | |
| 707 | + if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred()) | |
| 708 | + return -1; | |
| 709 | + return 0; | |
| 710 | +} | |
| 711 | + | |
| 712 | +/* | |
| 713 | + * Convert the C value in result into a Python object, depending on restype. | |
| 714 | + * | |
| 715 | + * - If restype is NULL, return a Python integer. | |
| 716 | + * - If restype is None, return None. | |
| 717 | + * - If restype is a simple ctypes type (c_int, c_void_p), call the type's getfunc, | |
| 718 | + * pass the result to checker and return the result. | |
| 719 | + * - If restype is another ctypes type, return an instance of that. | |
| 720 | + * - Otherwise, call restype and return the result. | |
| 721 | + */ | |
| 722 | +static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker) | |
| 723 | +{ | |
| 724 | + StgDictObject *dict; | |
| 725 | + PyObject *retval, *v; | |
| 726 | + | |
| 727 | + if (restype == NULL) | |
| 728 | + return PyInt_FromLong(*(int *)result); | |
| 729 | + | |
| 730 | + if (restype == Py_None) { | |
| 731 | + Py_INCREF(Py_None); | |
| 732 | + return Py_None; | |
| 733 | + } | |
| 734 | + | |
| 735 | + dict = PyType_stgdict(restype); | |
| 736 | + if (dict == NULL) | |
| 737 | + return PyObject_CallFunction(restype, "i", *(int *)result); | |
| 738 | + | |
| 739 | + if (dict->getfunc && !IsSimpleSubType(restype)) { | |
| 740 | + retval = dict->getfunc(result, dict->size); | |
| 741 | + /* If restype is py_object (detected by comparing getfunc with | |
| 742 | + O_get), we have to call Py_DECREF because O_get has already | |
| 743 | + called Py_INCREF. | |
| 744 | + */ | |
| 745 | + if (dict->getfunc == getentry("O")->getfunc) { | |
| 746 | + Py_DECREF(retval); | |
| 747 | + } | |
| 748 | + } else | |
| 749 | + retval = CData_FromBaseObj(restype, NULL, 0, result); | |
| 750 | + | |
| 751 | + if (!checker || !retval) | |
| 752 | + return retval; | |
| 753 | + | |
| 754 | + v = PyObject_CallFunctionObjArgs(checker, retval, NULL); | |
| 755 | + if (v == NULL) | |
| 756 | + _AddTraceback("GetResult", __FILE__, __LINE__-2); | |
| 757 | + Py_DECREF(retval); | |
| 758 | + return v; | |
| 759 | +} | |
| 760 | + | |
| 761 | +/* | |
| 762 | + * Raise a new exception 'exc_class', adding additional text to the original | |
| 763 | + * exception string. | |
| 764 | + */ | |
| 765 | +void Extend_Error_Info(PyObject *exc_class, char *fmt, ...) | |
| 766 | +{ | |
| 767 | + va_list vargs; | |
| 768 | + PyObject *tp, *v, *tb, *s, *cls_str, *msg_str; | |
| 769 | + | |
| 770 | + va_start(vargs, fmt); | |
| 771 | + s = PyString_FromFormatV(fmt, vargs); | |
| 772 | + va_end(vargs); | |
| 773 | + if (!s) | |
| 774 | + return; | |
| 775 | + | |
| 776 | + PyErr_Fetch(&tp, &v, &tb); | |
| 777 | + PyErr_NormalizeException(&tp, &v, &tb); | |
| 778 | + cls_str = PyObject_Str(tp); | |
| 779 | + if (cls_str) { | |
| 780 | + PyString_ConcatAndDel(&s, cls_str); | |
| 781 | + PyString_ConcatAndDel(&s, PyString_FromString(": ")); | |
| 782 | + if (s == NULL) | |
| 783 | + goto error; | |
| 784 | + } else | |
| 785 | + PyErr_Clear(); | |
| 786 | + msg_str = PyObject_Str(v); | |
| 787 | + if (msg_str) | |
| 788 | + PyString_ConcatAndDel(&s, msg_str); | |
| 789 | + else { | |
| 790 | + PyErr_Clear(); | |
| 791 | + PyString_ConcatAndDel(&s, PyString_FromString("???")); | |
| 792 | + if (s == NULL) | |
| 793 | + goto error; | |
| 794 | + } | |
| 795 | + PyErr_SetObject(exc_class, s); | |
| 796 | +error: | |
| 797 | + Py_XDECREF(tp); | |
| 798 | + Py_XDECREF(v); | |
| 799 | + Py_XDECREF(tb); | |
| 800 | + Py_XDECREF(s); | |
| 801 | +} | |
| 802 | + | |
| 803 | + | |
| 804 | +#ifdef MS_WIN32 | |
| 805 | + | |
| 806 | +static PyObject * | |
| 807 | +GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk) | |
| 808 | +{ | |
| 809 | + HRESULT hr; | |
| 810 | + ISupportErrorInfo *psei = NULL; | |
| 811 | + IErrorInfo *pei = NULL; | |
| 812 | + BSTR descr=NULL, helpfile=NULL, source=NULL; | |
| 813 | + GUID guid; | |
| 814 | + DWORD helpcontext=0; | |
| 815 | + LPOLESTR progid; | |
| 816 | + PyObject *obj; | |
| 817 | + TCHAR *text; | |
| 818 | + | |
| 819 | + /* We absolutely have to release the GIL during COM method calls, | |
| 820 | + otherwise we may get a deadlock! | |
| 821 | + */ | |
| 822 | +#ifdef WITH_THREAD | |
| 823 | + Py_BEGIN_ALLOW_THREADS | |
| 824 | +#endif | |
| 825 | + | |
| 826 | + hr = pIunk->lpVtbl->QueryInterface(pIunk, &IID_ISupportErrorInfo, (void **)&psei); | |
| 827 | + if (FAILED(hr)) | |
| 828 | + goto failed; | |
| 829 | + | |
| 830 | + hr = psei->lpVtbl->InterfaceSupportsErrorInfo(psei, riid); | |
| 831 | + psei->lpVtbl->Release(psei); | |
| 832 | + if (FAILED(hr)) | |
| 833 | + goto failed; | |
| 834 | + | |
| 835 | + hr = GetErrorInfo(0, &pei); | |
| 836 | + if (hr != S_OK) | |
| 837 | + goto failed; | |
| 838 | + | |
| 839 | + pei->lpVtbl->GetDescription(pei, &descr); | |
| 840 | + pei->lpVtbl->GetGUID(pei, &guid); | |
| 841 | + pei->lpVtbl->GetHelpContext(pei, &helpcontext); | |
| 842 | + pei->lpVtbl->GetHelpFile(pei, &helpfile); | |
| 843 | + pei->lpVtbl->GetSource(pei, &source); | |
| 844 | + | |
| 845 | + pei->lpVtbl->Release(pei); | |
| 846 | + | |
| 847 | + failed: | |
| 848 | +#ifdef WITH_THREAD | |
| 849 | + Py_END_ALLOW_THREADS | |
| 850 | +#endif | |
| 851 | + | |
| 852 | + progid = NULL; | |
| 853 | + ProgIDFromCLSID(&guid, &progid); | |
| 854 | + | |
| 855 | + text = FormatError(errcode); | |
| 856 | + obj = Py_BuildValue( | |
| 857 | +#ifdef _UNICODE | |
| 858 | + "iu(uuuiu)", | |
| 859 | +#else | |
| 860 | + "is(uuuiu)", | |
| 861 | +#endif | |
| 862 | + errcode, | |
| 863 | + text, | |
| 864 | + descr, source, helpfile, helpcontext, | |
| 865 | + progid); | |
| 866 | + if (obj) { | |
| 867 | + PyErr_SetObject(ComError, obj); | |
| 868 | + Py_DECREF(obj); | |
| 869 | + } | |
| 870 | + LocalFree(text); | |
| 871 | + | |
| 872 | + if (descr) | |
| 873 | + SysFreeString(descr); | |
| 874 | + if (helpfile) | |
| 875 | + SysFreeString(helpfile); | |
| 876 | + if (source) | |
| 877 | + SysFreeString(source); | |
| 878 | + | |
| 879 | + return NULL; | |
| 880 | +} | |
| 881 | +#endif | |
| 882 | + | |
| 883 | +/* | |
| 884 | + * Requirements, must be ensured by the caller: | |
| 885 | + * - argtuple is tuple of arguments | |
| 886 | + * - argtypes is either NULL, or a tuple of the same size as argtuple | |
| 887 | + * | |
| 888 | + * - XXX various requirements for restype, not yet collected | |
| 889 | + */ | |
| 890 | +PyObject *_CallProc(PPROC pProc, | |
| 891 | + PyObject *argtuple, | |
| 892 | +#ifdef MS_WIN32 | |
| 893 | + IUnknown *pIunk, | |
| 894 | + GUID *iid, | |
| 895 | +#endif | |
| 896 | + int flags, | |
| 897 | + PyObject *argtypes, /* misleading name: This is a tuple of | |
| 898 | + methods, not types: the .from_param | |
| 899 | + class methods of the types */ | |
| 900 | + PyObject *restype, | |
| 901 | + PyObject *checker) | |
| 902 | +{ | |
| 903 | + int i, n, argcount, argtype_count; | |
| 904 | + void *resbuf; | |
| 905 | + struct argument *args, *pa; | |
| 906 | + ffi_type **atypes; | |
| 907 | + ffi_type *rtype; | |
| 908 | + void **avalues; | |
| 909 | + PyObject *retval = NULL; | |
| 910 | + | |
| 911 | + n = argcount = PyTuple_GET_SIZE(argtuple); | |
| 912 | +#ifdef MS_WIN32 | |
| 913 | + /* an optional COM object this pointer */ | |
| 914 | + if (pIunk) | |
| 915 | + ++argcount; | |
| 916 | +#endif | |
| 917 | + | |
| 918 | + args = (struct argument *)alloca(sizeof(struct argument) * argcount); | |
| 919 | + if (!args) { | |
| 920 | + PyErr_NoMemory(); | |
| 921 | + return NULL; | |
| 922 | + } | |
| 923 | + memset(args, 0, sizeof(struct argument) * argcount); | |
| 924 | + argtype_count = argtypes ? PyTuple_GET_SIZE(argtypes) : 0; | |
| 925 | +#ifdef MS_WIN32 | |
| 926 | + if (pIunk) { | |
| 927 | + args[0].ffi_type = &ffi_type_pointer; | |
| 928 | + args[0].value.p = pIunk; | |
| 929 | + pa = &args[1]; | |
| 930 | + } else | |
| 931 | +#endif | |
| 932 | + pa = &args[0]; | |
| 933 | + | |
| 934 | + /* Convert the arguments */ | |
| 935 | + for (i = 0; i < n; ++i, ++pa) { | |
| 936 | + PyObject *converter; | |
| 937 | + PyObject *arg; | |
| 938 | + int err; | |
| 939 | + | |
| 940 | + arg = PyTuple_GET_ITEM(argtuple, i); /* borrowed ref */ | |
| 941 | + /* For cdecl functions, we allow more actual arguments | |
| 942 | + than the length of the argtypes tuple. | |
| 943 | + This is checked in _ctypes::CFuncPtr_Call | |
| 944 | + */ | |
| 945 | + if (argtypes && argtype_count > i) { | |
| 946 | + PyObject *v; | |
| 947 | + converter = PyTuple_GET_ITEM(argtypes, i); | |
| 948 | + v = PyObject_CallFunctionObjArgs(converter, | |
| 949 | + arg, | |
| 950 | + NULL); | |
| 951 | + if (v == NULL) { | |
| 952 | + Extend_Error_Info(PyExc_ArgError, "argument %d: ", i+1); | |
| 953 | + goto cleanup; | |
| 954 | + } | |
| 955 | + | |
| 956 | + err = ConvParam(v, i+1, pa); | |
| 957 | + Py_DECREF(v); | |
| 958 | + if (-1 == err) { | |
| 959 | + Extend_Error_Info(PyExc_ArgError, "argument %d: ", i+1); | |
| 960 | + goto cleanup; | |
| 961 | + } | |
| 962 | + } else { | |
| 963 | + err = ConvParam(arg, i+1, pa); | |
| 964 | + if (-1 == err) { | |
| 965 | + Extend_Error_Info(PyExc_ArgError, "argument %d: ", i+1); | |
| 966 | + goto cleanup; /* leaking ? */ | |
| 967 | + } | |
| 968 | + } | |
| 969 | + } | |
| 970 | + | |
| 971 | + rtype = GetType(restype); | |
| 972 | + resbuf = alloca(max(rtype->size, sizeof(ffi_arg))); | |
| 973 | + | |
| 974 | + avalues = (void **)alloca(sizeof(void *) * argcount); | |
| 975 | + atypes = (ffi_type **)alloca(sizeof(ffi_type *) * argcount); | |
| 976 | + if (!resbuf || !avalues || !atypes) { | |
| 977 | + PyErr_NoMemory(); | |
| 978 | + goto cleanup; | |
| 979 | + } | |
| 980 | + for (i = 0; i < argcount; ++i) { | |
| 981 | + atypes[i] = args[i].ffi_type; | |
| 982 | + if (atypes[i]->type == FFI_TYPE_STRUCT) | |
| 983 | + avalues[i] = (void *)args[i].value.p; | |
| 984 | + else | |
| 985 | + avalues[i] = (void *)&args[i].value; | |
| 986 | + } | |
| 987 | + | |
| 988 | + if (-1 == _call_function_pointer(flags, pProc, avalues, atypes, | |
| 989 | + rtype, resbuf, argcount)) | |
| 990 | + goto cleanup; | |
| 991 | + | |
| 992 | +#ifdef WORDS_BIGENDIAN | |
| 993 | + /* libffi returns the result in a buffer with sizeof(ffi_arg). This | |
| 994 | + causes problems on big endian machines, since the result buffer | |
| 995 | + address cannot simply be used as result pointer, instead we must | |
| 996 | + adjust the pointer value: | |
| 997 | + */ | |
| 998 | + /* | |
| 999 | + XXX I should find out and clarify why this is needed at all, | |
| 1000 | + especially why adjusting for ffi_type_float must be avoided on | |
| 1001 | + 64-bit platforms. | |
| 1002 | + */ | |
| 1003 | + if (rtype->type != FFI_TYPE_FLOAT | |
| 1004 | + && rtype->type != FFI_TYPE_STRUCT | |
| 1005 | + && rtype->size < sizeof(ffi_arg)) | |
| 1006 | + resbuf = (char *)resbuf + sizeof(ffi_arg) - rtype->size; | |
| 1007 | +#endif | |
| 1008 | + | |
| 1009 | +#ifdef MS_WIN32 | |
| 1010 | + if (iid && pIunk) { | |
| 1011 | + if (*(int *)resbuf & 0x80000000) | |
| 1012 | + retval = GetComError(*(HRESULT *)resbuf, iid, pIunk); | |
| 1013 | + else | |
| 1014 | + retval = PyInt_FromLong(*(int *)resbuf); | |
| 1015 | + } else if (flags & FUNCFLAG_HRESULT) { | |
| 1016 | + if (*(int *)resbuf & 0x80000000) | |
| 1017 | + retval = PyErr_SetFromWindowsErr(*(int *)resbuf); | |
| 1018 | + else | |
| 1019 | + retval = PyInt_FromLong(*(int *)resbuf); | |
| 1020 | + } else | |
| 1021 | +#endif | |
| 1022 | + retval = GetResult(restype, resbuf, checker); | |
| 1023 | + cleanup: | |
| 1024 | + for (i = 0; i < argcount; ++i) | |
| 1025 | + Py_XDECREF(args[i].keep); | |
| 1026 | + return retval; | |
| 1027 | +} | |
| 1028 | + | |
| 1029 | +#ifdef MS_WIN32 | |
| 1030 | + | |
| 1031 | +#ifdef _UNICODE | |
| 1032 | +# define PYBUILD_TSTR "u" | |
| 1033 | +#else | |
| 1034 | +# define PYBUILD_TSTR "s" | |
| 1035 | +# ifndef _T | |
| 1036 | +# define _T(text) text | |
| 1037 | +# endif | |
| 1038 | +#endif | |
| 1039 | + | |
| 1040 | +static char format_error_doc[] = | |
| 1041 | +"FormatError([integer]) -> string\n\ | |
| 1042 | +\n\ | |
| 1043 | +Convert a win32 error code into a string. If the error code is not\n\ | |
| 1044 | +given, the return value of a call to GetLastError() is used.\n"; | |
| 1045 | +static PyObject *format_error(PyObject *self, PyObject *args) | |
| 1046 | +{ | |
| 1047 | + PyObject *result; | |
| 1048 | + TCHAR *lpMsgBuf; | |
| 1049 | + DWORD code = 0; | |
| 1050 | + if (!PyArg_ParseTuple(args, "|i:FormatError", &code)) | |
| 1051 | + return NULL; | |
| 1052 | + if (code == 0) | |
| 1053 | + code = GetLastError(); | |
| 1054 | + lpMsgBuf = FormatError(code); | |
| 1055 | + if (lpMsgBuf) { | |
| 1056 | + result = Py_BuildValue(PYBUILD_TSTR, lpMsgBuf); | |
| 1057 | + LocalFree(lpMsgBuf); | |
| 1058 | + } else { | |
| 1059 | + result = Py_BuildValue("s", "<no description>"); | |
| 1060 | + } | |
| 1061 | + return result; | |
| 1062 | +} | |
| 1063 | + | |
| 1064 | +static char load_library_doc[] = | |
| 1065 | +"LoadLibrary(name) -> handle\n\ | |
| 1066 | +\n\ | |
| 1067 | +Load an executable (usually a DLL), and return a handle to it.\n\ | |
| 1068 | +The handle may be used to locate exported functions in this\n\ | |
| 1069 | +module.\n"; | |
| 1070 | +static PyObject *load_library(PyObject *self, PyObject *args) | |
| 1071 | +{ | |
| 1072 | + TCHAR *name; | |
| 1073 | + PyObject *nameobj; | |
| 1074 | + PyObject *ignored; | |
| 1075 | + HMODULE hMod; | |
| 1076 | + if (!PyArg_ParseTuple(args, "O|O:LoadLibrary", &nameobj, &ignored)) | |
| 1077 | + return NULL; | |
| 1078 | +#ifdef _UNICODE | |
| 1079 | + name = alloca((PyString_Size(nameobj) + 1) * sizeof(WCHAR)); | |
| 1080 | + if (!name) { | |
| 1081 | + PyErr_NoMemory(); | |
| 1082 | + return NULL; | |
| 1083 | + } | |
| 1084 | + | |
| 1085 | + { | |
| 1086 | + int r; | |
| 1087 | + char *aname = PyString_AsString(nameobj); | |
| 1088 | + if(!aname) | |
| 1089 | + return NULL; | |
| 1090 | + r = MultiByteToWideChar(CP_ACP, 0, aname, -1, name, PyString_Size(nameobj) + 1); | |
| 1091 | + name[r] = 0; | |
| 1092 | + } | |
| 1093 | +#else | |
| 1094 | + name = PyString_AsString(nameobj); | |
| 1095 | + if(!name) | |
| 1096 | + return NULL; | |
| 1097 | +#endif | |
| 1098 | + | |
| 1099 | + hMod = LoadLibrary(name); | |
| 1100 | + if (!hMod) | |
| 1101 | + return PyErr_SetFromWindowsErr(GetLastError()); | |
| 1102 | + return Py_BuildValue("i", hMod); | |
| 1103 | +} | |
| 1104 | + | |
| 1105 | +static char free_library_doc[] = | |
| 1106 | +"FreeLibrary(handle) -> void\n\ | |
| 1107 | +\n\ | |
| 1108 | +Free the handle of an executable previously loaded by LoadLibrary.\n"; | |
| 1109 | +static PyObject *free_library(PyObject *self, PyObject *args) | |
| 1110 | +{ | |
| 1111 | + HMODULE hMod; | |
| 1112 | + if (!PyArg_ParseTuple(args, "i:FreeLibrary", &hMod)) | |
| 1113 | + return NULL; | |
| 1114 | + if (!FreeLibrary(hMod)) | |
| 1115 | + return PyErr_SetFromWindowsErr(GetLastError()); | |
| 1116 | + Py_INCREF(Py_None); | |
| 1117 | + return Py_None; | |
| 1118 | +} | |
| 1119 | + | |
| 1120 | +/* obsolete, should be removed */ | |
| 1121 | +/* Only used by sample code (in samples\Windows\COM.py) */ | |
| 1122 | +static PyObject * | |
| 1123 | +call_commethod(PyObject *self, PyObject *args) | |
| 1124 | +{ | |
| 1125 | + IUnknown *pIunk; | |
| 1126 | + int index; | |
| 1127 | + PyObject *arguments; | |
| 1128 | + PPROC *lpVtbl; | |
| 1129 | + PyObject *result; | |
| 1130 | + CDataObject *pcom; | |
| 1131 | + PyObject *argtypes = NULL; | |
| 1132 | + | |
| 1133 | + if (!PyArg_ParseTuple(args, | |
| 1134 | + "OiO!|O!", | |
| 1135 | + &pcom, &index, | |
| 1136 | + &PyTuple_Type, &arguments, | |
| 1137 | + &PyTuple_Type, &argtypes)) | |
| 1138 | + return NULL; | |
| 1139 | + | |
| 1140 | + if (argtypes && (PyTuple_GET_SIZE(arguments) != PyTuple_GET_SIZE(argtypes))) { | |
| 1141 | + PyErr_Format(PyExc_TypeError, | |
| 1142 | + "Method takes %d arguments (%d given)", | |
| 1143 | + PyTuple_GET_SIZE(argtypes), PyTuple_GET_SIZE(arguments)); | |
| 1144 | + return NULL; | |
| 1145 | + } | |
| 1146 | + | |
| 1147 | + if (!CDataObject_Check(pcom) || (pcom->b_size != sizeof(void *))) { | |
| 1148 | + PyErr_Format(PyExc_TypeError, | |
| 1149 | + "COM Pointer expected instead of %s instance", | |
| 1150 | + pcom->ob_type->tp_name); | |
| 1151 | + return NULL; | |
| 1152 | + } | |
| 1153 | + | |
| 1154 | + if ((*(void **)(pcom->b_ptr)) == NULL) { | |
| 1155 | + PyErr_SetString(PyExc_ValueError, | |
| 1156 | + "The COM 'this' pointer is NULL"); | |
| 1157 | + return NULL; | |
| 1158 | + } | |
| 1159 | + | |
| 1160 | + pIunk = (IUnknown *)(*(void **)(pcom->b_ptr)); | |
| 1161 | + lpVtbl = (PPROC *)(pIunk->lpVtbl); | |
| 1162 | + | |
| 1163 | + result = _CallProc(lpVtbl[index], | |
| 1164 | + arguments, | |
| 1165 | +#ifdef MS_WIN32 | |
| 1166 | + pIunk, | |
| 1167 | + NULL, | |
| 1168 | +#endif | |
| 1169 | + FUNCFLAG_HRESULT, /* flags */ | |
| 1170 | + argtypes, /* self->argtypes */ | |
| 1171 | + NULL, /* self->restype */ | |
| 1172 | + NULL); /* checker */ | |
| 1173 | + return result; | |
| 1174 | +} | |
| 1175 | + | |
| 1176 | +static char copy_com_pointer_doc[] = | |
| 1177 | +"CopyComPointer(src, dst) -> HRESULT value\n"; | |
| 1178 | + | |
| 1179 | +static PyObject * | |
| 1180 | +copy_com_pointer(PyObject *self, PyObject *args) | |
| 1181 | +{ | |
| 1182 | + PyObject *p1, *p2, *r = NULL; | |
| 1183 | + struct argument a, b; | |
| 1184 | + IUnknown *src, **pdst; | |
| 1185 | + if (!PyArg_ParseTuple(args, "OO:CopyComPointer", &p1, &p2)) | |
| 1186 | + return NULL; | |
| 1187 | + a.keep = b.keep = NULL; | |
| 1188 | + | |
| 1189 | + if (-1 == ConvParam(p1, 0, &a) || -1 == ConvParam(p2, 1, &b)) | |
| 1190 | + goto done; | |
| 1191 | + src = (IUnknown *)a.value.p; | |
| 1192 | + pdst = (IUnknown **)b.value.p; | |
| 1193 | + | |
| 1194 | + if (pdst == NULL) | |
| 1195 | + r = PyInt_FromLong(E_POINTER); | |
| 1196 | + else { | |
| 1197 | + if (src) | |
| 1198 | + src->lpVtbl->AddRef(src); | |
| 1199 | + *pdst = src; | |
| 1200 | + r = PyInt_FromLong(S_OK); | |
| 1201 | + } | |
| 1202 | + done: | |
| 1203 | + Py_XDECREF(a.keep); | |
| 1204 | + Py_XDECREF(b.keep); | |
| 1205 | + return r; | |
| 1206 | +} | |
| 1207 | +#else | |
| 1208 | + | |
| 1209 | +static PyObject *py_dl_open(PyObject *self, PyObject *args) | |
| 1210 | +{ | |
| 1211 | + char *name; | |
| 1212 | + void * handle; | |
| 1213 | +#ifdef RTLD_LOCAL | |
| 1214 | + int mode = RTLD_NOW | RTLD_LOCAL; | |
| 1215 | +#else | |
| 1216 | + /* cygwin doesn't define RTLD_LOCAL */ | |
| 1217 | + int mode = RTLD_NOW; | |
| 1218 | +#endif | |
| 1219 | + if (!PyArg_ParseTuple(args, "z|i:dlopen", &name, &mode)) | |
| 1220 | + return NULL; | |
| 1221 | + mode |= RTLD_NOW; | |
| 1222 | + handle = ctypes_dlopen(name, mode); | |
| 1223 | + if (!handle) { | |
| 1224 | + PyErr_SetString(PyExc_OSError, | |
| 1225 | + ctypes_dlerror()); | |
| 1226 | + return NULL; | |
| 1227 | + } | |
| 1228 | + return PyLong_FromVoidPtr(handle); | |
| 1229 | +} | |
| 1230 | + | |
| 1231 | +static PyObject *py_dl_close(PyObject *self, PyObject *args) | |
| 1232 | +{ | |
| 1233 | + void * handle; | |
| 1234 | + | |
| 1235 | + if (!PyArg_ParseTuple(args, "i:dlclose", &handle)) | |
| 1236 | + return NULL; | |
| 1237 | + if (dlclose(handle)) { | |
| 1238 | + PyErr_SetString(PyExc_OSError, | |
| 1239 | + ctypes_dlerror()); | |
| 1240 | + return NULL; | |
| 1241 | + } | |
| 1242 | + Py_INCREF(Py_None); | |
| 1243 | + return Py_None; | |
| 1244 | +} | |
| 1245 | + | |
| 1246 | +static PyObject *py_dl_sym(PyObject *self, PyObject *args) | |
| 1247 | +{ | |
| 1248 | + char *name; | |
| 1249 | + void *handle; | |
| 1250 | + void *ptr; | |
| 1251 | + | |
| 1252 | + if (!PyArg_ParseTuple(args, "is:dlsym", &handle, &name)) | |
| 1253 | + return NULL; | |
| 1254 | + ptr = ctypes_dlsym(handle, name); | |
| 1255 | + if (!ptr) { | |
| 1256 | + PyErr_SetString(PyExc_OSError, | |
| 1257 | + ctypes_dlerror()); | |
| 1258 | + return NULL; | |
| 1259 | + } | |
| 1260 | + return Py_BuildValue("i", ptr); | |
| 1261 | +} | |
| 1262 | +#endif | |
| 1263 | + | |
| 1264 | +/* | |
| 1265 | + * Only for debugging so far: So that we can call CFunction instances | |
| 1266 | + * | |
| 1267 | + * XXX Needs to accept more arguments: flags, argtypes, restype | |
| 1268 | + */ | |
| 1269 | +static PyObject * | |
| 1270 | +call_function(PyObject *self, PyObject *args) | |
| 1271 | +{ | |
| 1272 | + PPROC func; | |
| 1273 | + PyObject *arguments; | |
| 1274 | + PyObject *result; | |
| 1275 | + | |
| 1276 | + if (!PyArg_ParseTuple(args, | |
| 1277 | + "iO!", | |
| 1278 | + &func, | |
| 1279 | + &PyTuple_Type, &arguments)) | |
| 1280 | + return NULL; | |
| 1281 | + | |
| 1282 | + result = _CallProc(func, | |
| 1283 | + arguments, | |
| 1284 | +#ifdef MS_WIN32 | |
| 1285 | + NULL, | |
| 1286 | + NULL, | |
| 1287 | +#endif | |
| 1288 | + 0, /* flags */ | |
| 1289 | + NULL, /* self->argtypes */ | |
| 1290 | + NULL, /* self->restype */ | |
| 1291 | + NULL); /* checker */ | |
| 1292 | + return result; | |
| 1293 | +} | |
| 1294 | + | |
| 1295 | +/* | |
| 1296 | + * Only for debugging so far: So that we can call CFunction instances | |
| 1297 | + * | |
| 1298 | + * XXX Needs to accept more arguments: flags, argtypes, restype | |
| 1299 | + */ | |
| 1300 | +static PyObject * | |
| 1301 | +call_cdeclfunction(PyObject *self, PyObject *args) | |
| 1302 | +{ | |
| 1303 | + PPROC func; | |
| 1304 | + PyObject *arguments; | |
| 1305 | + PyObject *result; | |
| 1306 | + | |
| 1307 | + if (!PyArg_ParseTuple(args, | |
| 1308 | + "iO!", | |
| 1309 | + &func, | |
| 1310 | + &PyTuple_Type, &arguments)) | |
| 1311 | + return NULL; | |
| 1312 | + | |
| 1313 | + result = _CallProc(func, | |
| 1314 | + arguments, | |
| 1315 | +#ifdef MS_WIN32 | |
| 1316 | + NULL, | |
| 1317 | + NULL, | |
| 1318 | +#endif | |
| 1319 | + FUNCFLAG_CDECL, /* flags */ | |
| 1320 | + NULL, /* self->argtypes */ | |
| 1321 | + NULL, /* self->restype */ | |
| 1322 | + NULL); /* checker */ | |
| 1323 | + return result; | |
| 1324 | +} | |
| 1325 | + | |
| 1326 | +/***************************************************************** | |
| 1327 | + * functions | |
| 1328 | + */ | |
| 1329 | +static char sizeof_doc[] = | |
| 1330 | +"sizeof(C type) -> integer\n" | |
| 1331 | +"sizeof(C instance) -> integer\n" | |
| 1332 | +"Return the size in bytes of a C instance"; | |
| 1333 | + | |
| 1334 | +static PyObject * | |
| 1335 | +sizeof_func(PyObject *self, PyObject *obj) | |
| 1336 | +{ | |
| 1337 | + StgDictObject *dict; | |
| 1338 | + | |
| 1339 | + dict = PyType_stgdict(obj); | |
| 1340 | + if (dict) | |
| 1341 | + return PyInt_FromLong(dict->size); | |
| 1342 | + | |
| 1343 | + if (CDataObject_Check(obj)) | |
| 1344 | + return PyInt_FromLong(((CDataObject *)obj)->b_size); | |
| 1345 | + PyErr_SetString(PyExc_TypeError, | |
| 1346 | + "this type has no size"); | |
| 1347 | + return NULL; | |
| 1348 | +} | |
| 1349 | + | |
| 1350 | +static char alignment_doc[] = | |
| 1351 | +"alignment(C type) -> integer\n" | |
| 1352 | +"alignment(C instance) -> integer\n" | |
| 1353 | +"Return the alignment requirements of a C instance"; | |
| 1354 | + | |
| 1355 | +static PyObject * | |
| 1356 | +align_func(PyObject *self, PyObject *obj) | |
| 1357 | +{ | |
| 1358 | + StgDictObject *dict; | |
| 1359 | + | |
| 1360 | + dict = PyType_stgdict(obj); | |
| 1361 | + if (dict) | |
| 1362 | + return PyInt_FromLong(dict->align); | |
| 1363 | + | |
| 1364 | + dict = PyObject_stgdict(obj); | |
| 1365 | + if (dict) | |
| 1366 | + return PyInt_FromLong(dict->align); | |
| 1367 | + | |
| 1368 | + PyErr_SetString(PyExc_TypeError, | |
| 1369 | + "no alignment info"); | |
| 1370 | + return NULL; | |
| 1371 | +} | |
| 1372 | + | |
| 1373 | +static char byref_doc[] = | |
| 1374 | +"byref(C instance) -> byref-object\n" | |
| 1375 | +"Return a pointer lookalike to a C instance, only usable\n" | |
| 1376 | +"as function argument"; | |
| 1377 | + | |
| 1378 | +/* | |
| 1379 | + * We must return something which can be converted to a parameter, | |
| 1380 | + * but still has a reference to self. | |
| 1381 | + */ | |
| 1382 | +static PyObject * | |
| 1383 | +byref(PyObject *self, PyObject *obj) | |
| 1384 | +{ | |
| 1385 | + PyCArgObject *parg; | |
| 1386 | + if (!CDataObject_Check(obj)) { | |
| 1387 | + PyErr_Format(PyExc_TypeError, | |
| 1388 | + "byref() argument must be a ctypes instance, not '%s'", | |
| 1389 | + obj->ob_type->tp_name); | |
| 1390 | + return NULL; | |
| 1391 | + } | |
| 1392 | + | |
| 1393 | + parg = new_CArgObject(); | |
| 1394 | + if (parg == NULL) | |
| 1395 | + return NULL; | |
| 1396 | + | |
| 1397 | + parg->tag = 'P'; | |
| 1398 | + parg->pffi_type = &ffi_type_pointer; | |
| 1399 | + Py_INCREF(obj); | |
| 1400 | + parg->obj = obj; | |
| 1401 | + parg->value.p = ((CDataObject *)obj)->b_ptr; | |
| 1402 | + return (PyObject *)parg; | |
| 1403 | +} | |
| 1404 | + | |
| 1405 | +static char addressof_doc[] = | |
| 1406 | +"addressof(C instance) -> integer\n" | |
| 1407 | +"Return the address of the C instance internal buffer"; | |
| 1408 | + | |
| 1409 | +static PyObject * | |
| 1410 | +addressof(PyObject *self, PyObject *obj) | |
| 1411 | +{ | |
| 1412 | + if (CDataObject_Check(obj)) | |
| 1413 | + return PyLong_FromVoidPtr(((CDataObject *)obj)->b_ptr); | |
| 1414 | + PyErr_SetString(PyExc_TypeError, | |
| 1415 | + "invalid type"); | |
| 1416 | + return NULL; | |
| 1417 | +} | |
| 1418 | + | |
| 1419 | +static int | |
| 1420 | +converter(PyObject *obj, void **address) | |
| 1421 | +{ | |
| 1422 | + *address = PyLong_AsVoidPtr(obj); | |
| 1423 | + return *address != NULL; | |
| 1424 | +} | |
| 1425 | + | |
| 1426 | +static PyObject * | |
| 1427 | +My_PyObj_FromPtr(PyObject *self, PyObject *args) | |
| 1428 | +{ | |
| 1429 | + PyObject *ob; | |
| 1430 | + if (!PyArg_ParseTuple(args, "O&:PyObj_FromPtr", converter, &ob)) | |
| 1431 | + return NULL; | |
| 1432 | + Py_INCREF(ob); | |
| 1433 | + return ob; | |
| 1434 | +} | |
| 1435 | + | |
| 1436 | +static PyObject * | |
| 1437 | +My_Py_INCREF(PyObject *self, PyObject *arg) | |
| 1438 | +{ | |
| 1439 | + Py_INCREF(arg); /* that's what this function is for */ | |
| 1440 | + Py_INCREF(arg); /* that for returning it */ | |
| 1441 | + return arg; | |
| 1442 | +} | |
| 1443 | + | |
| 1444 | +static PyObject * | |
| 1445 | +My_Py_DECREF(PyObject *self, PyObject *arg) | |
| 1446 | +{ | |
| 1447 | + Py_DECREF(arg); /* that's what this function is for */ | |
| 1448 | + Py_INCREF(arg); /* that's for returning it */ | |
| 1449 | + return arg; | |
| 1450 | +} | |
| 1451 | + | |
| 1452 | +#ifdef CTYPES_UNICODE | |
| 1453 | + | |
| 1454 | +static char set_conversion_mode_doc[] = | |
| 1455 | +"set_conversion_mode(encoding, errors) -> (previous-encoding, previous-errors)\n\ | |
| 1456 | +\n\ | |
| 1457 | +Set the encoding and error handling ctypes uses when converting\n\ | |
| 1458 | +between unicode and strings. Returns the previous values.\n"; | |
| 1459 | + | |
| 1460 | +static PyObject * | |
| 1461 | +set_conversion_mode(PyObject *self, PyObject *args) | |
| 1462 | +{ | |
| 1463 | + char *coding, *mode; | |
| 1464 | + PyObject *result; | |
| 1465 | + | |
| 1466 | + if (!PyArg_ParseTuple(args, "zs:set_conversion_mode", &coding, &mode)) | |
| 1467 | + return NULL; | |
| 1468 | + result = Py_BuildValue("(zz)", conversion_mode_encoding, conversion_mode_errors); | |
| 1469 | + if (coding) { | |
| 1470 | + PyMem_Free(conversion_mode_encoding); | |
| 1471 | + conversion_mode_encoding = PyMem_Malloc(strlen(coding) + 1); | |
| 1472 | + strcpy(conversion_mode_encoding, coding); | |
| 1473 | + } else { | |
| 1474 | + conversion_mode_encoding = NULL; | |
| 1475 | + } | |
| 1476 | + PyMem_Free(conversion_mode_errors); | |
| 1477 | + conversion_mode_errors = PyMem_Malloc(strlen(mode) + 1); | |
| 1478 | + strcpy(conversion_mode_errors, mode); | |
| 1479 | + return result; | |
| 1480 | +} | |
| 1481 | +#endif | |
| 1482 | + | |
| 1483 | +static PyObject * | |
| 1484 | +resize(PyObject *self, PyObject *args) | |
| 1485 | +{ | |
| 1486 | + CDataObject *obj; | |
| 1487 | + StgDictObject *dict; | |
| 1488 | + Py_ssize_t size; | |
| 1489 | + | |
| 1490 | + if (!PyArg_ParseTuple(args, | |
| 1491 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 1492 | + "Oi:resize", | |
| 1493 | +#else | |
| 1494 | + "On:resize", | |
| 1495 | +#endif | |
| 1496 | + (PyObject *)&obj, &size)) | |
| 1497 | + return NULL; | |
| 1498 | + | |
| 1499 | + dict = PyObject_stgdict((PyObject *)obj); | |
| 1500 | + if (dict == NULL) { | |
| 1501 | + PyErr_SetString(PyExc_TypeError, | |
| 1502 | + "excepted ctypes instance"); | |
| 1503 | + return NULL; | |
| 1504 | + } | |
| 1505 | + if (size < dict->size) { | |
| 1506 | + PyErr_Format(PyExc_ValueError, | |
| 1507 | +#if PY_VERSION_HEX < 0x02050000 | |
| 1508 | + "minimum size is %d", | |
| 1509 | +#else | |
| 1510 | + "minimum size is %zd", | |
| 1511 | +#endif | |
| 1512 | + dict->size); | |
| 1513 | + return NULL; | |
| 1514 | + } | |
| 1515 | + if (obj->b_needsfree == 0) { | |
| 1516 | + PyErr_Format(PyExc_ValueError, | |
| 1517 | + "Memory cannot be resized because this object doesn't own it"); | |
| 1518 | + return NULL; | |
| 1519 | + } | |
| 1520 | + if (size <= sizeof(obj->b_value)) { | |
| 1521 | + /* internal default buffer is large enough */ | |
| 1522 | + obj->b_size = size; | |
| 1523 | + goto done; | |
| 1524 | + } | |
| 1525 | + if (obj->b_size <= sizeof(obj->b_value)) { | |
| 1526 | + /* We are currently using the objects default buffer, but it | |
| 1527 | + isn't large enough any more. */ | |
| 1528 | + void *ptr = PyMem_Malloc(size); | |
| 1529 | + if (ptr == NULL) | |
| 1530 | + return PyErr_NoMemory(); | |
| 1531 | + memset(ptr, 0, size); | |
| 1532 | + memmove(ptr, obj->b_ptr, obj->b_size); | |
| 1533 | + obj->b_ptr = ptr; | |
| 1534 | + obj->b_size = size; | |
| 1535 | + } else { | |
| 1536 | + void * ptr = PyMem_Realloc(obj->b_ptr, size); | |
| 1537 | + if (ptr == NULL) | |
| 1538 | + return PyErr_NoMemory(); | |
| 1539 | + obj->b_ptr = ptr; | |
| 1540 | + obj->b_size = size; | |
| 1541 | + } | |
| 1542 | + done: | |
| 1543 | + Py_INCREF(Py_None); | |
| 1544 | + return Py_None; | |
| 1545 | +} | |
| 1546 | + | |
| 1547 | +PyMethodDef module_methods[] = { | |
| 1548 | + {"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"}, | |
| 1549 | +#ifdef CTYPES_UNICODE | |
| 1550 | + {"set_conversion_mode", set_conversion_mode, METH_VARARGS, set_conversion_mode_doc}, | |
| 1551 | +#endif | |
| 1552 | +#ifdef MS_WIN32 | |
| 1553 | + {"CopyComPointer", copy_com_pointer, METH_VARARGS, copy_com_pointer_doc}, | |
| 1554 | + {"FormatError", format_error, METH_VARARGS, format_error_doc}, | |
| 1555 | + {"LoadLibrary", load_library, METH_VARARGS, load_library_doc}, | |
| 1556 | + {"FreeLibrary", free_library, METH_VARARGS, free_library_doc}, | |
| 1557 | + {"call_commethod", call_commethod, METH_VARARGS }, | |
| 1558 | + {"_check_HRESULT", check_hresult, METH_VARARGS}, | |
| 1559 | +#else | |
| 1560 | + {"dlopen", py_dl_open, METH_VARARGS, | |
| 1561 | + "dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"}, | |
| 1562 | + {"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"}, | |
| 1563 | + {"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"}, | |
| 1564 | +#endif | |
| 1565 | + {"alignment", align_func, METH_O, alignment_doc}, | |
| 1566 | + {"sizeof", sizeof_func, METH_O, sizeof_doc}, | |
| 1567 | + {"byref", byref, METH_O, byref_doc}, | |
| 1568 | + {"addressof", addressof, METH_O, addressof_doc}, | |
| 1569 | + {"call_function", call_function, METH_VARARGS }, | |
| 1570 | + {"call_cdeclfunction", call_cdeclfunction, METH_VARARGS }, | |
| 1571 | + {"PyObj_FromPtr", My_PyObj_FromPtr, METH_VARARGS }, | |
| 1572 | + {"Py_INCREF", My_Py_INCREF, METH_O }, | |
| 1573 | + {"Py_DECREF", My_Py_DECREF, METH_O }, | |
| 1574 | + {NULL, NULL} /* Sentinel */ | |
| 1575 | +}; | |
| 1576 | + | |
| 1577 | +/* | |
| 1578 | + Local Variables: | |
| 1579 | + compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~" | |
| 1580 | + End: | |
| 1581 | +*/ | |
| @@ -0,0 +1,1668 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | +#include "Python.h" | |
| 6 | + | |
| 7 | +#include <ffi.h> | |
| 8 | +#ifdef MS_WIN32 | |
| 9 | +#include <windows.h> | |
| 10 | +#endif | |
| 11 | +#include "ctypes.h" | |
| 12 | + | |
| 13 | +/******************************************************************/ | |
| 14 | +/* | |
| 15 | + CField_Type | |
| 16 | +*/ | |
| 17 | +static PyObject * | |
| 18 | +CField_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 19 | +{ | |
| 20 | + CFieldObject *obj; | |
| 21 | + obj = (CFieldObject *)type->tp_alloc(type, 0); | |
| 22 | + return (PyObject *)obj; | |
| 23 | +} | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * Expects the size, index and offset for the current field in *psize and | |
| 27 | + * *poffset, stores the total size so far in *psize, the offset for the next | |
| 28 | + * field in *poffset, the alignment requirements for the current field in | |
| 29 | + * *palign, and returns a field desriptor for this field. | |
| 30 | + */ | |
| 31 | +/* | |
| 32 | + * bitfields extension: | |
| 33 | + * bitsize != 0: this is a bit field. | |
| 34 | + * pbitofs points to the current bit offset, this will be updated. | |
| 35 | + * prev_desc points to the type of the previous bitfield, if any. | |
| 36 | + */ | |
| 37 | +PyObject * | |
| 38 | +CField_FromDesc(PyObject *desc, int index, | |
| 39 | + int *pfield_size, int bitsize, int *pbitofs, | |
| 40 | + int *psize, int *poffset, int *palign, | |
| 41 | + int pack, int big_endian) | |
| 42 | +{ | |
| 43 | + CFieldObject *self; | |
| 44 | + PyObject *proto; | |
| 45 | + int size, align, length; | |
| 46 | + SETFUNC setfunc = NULL; | |
| 47 | + GETFUNC getfunc = NULL; | |
| 48 | + StgDictObject *dict; | |
| 49 | + int fieldtype; | |
| 50 | +#define NO_BITFIELD 0 | |
| 51 | +#define NEW_BITFIELD 1 | |
| 52 | +#define CONT_BITFIELD 2 | |
| 53 | +#define EXPAND_BITFIELD 3 | |
| 54 | + | |
| 55 | + self = (CFieldObject *)PyObject_CallObject((PyObject *)&CField_Type, | |
| 56 | + NULL); | |
| 57 | + if (self == NULL) | |
| 58 | + return NULL; | |
| 59 | + dict = PyType_stgdict(desc); | |
| 60 | + if (!dict) { | |
| 61 | + PyErr_SetString(PyExc_TypeError, | |
| 62 | + "has no _stginfo_"); | |
| 63 | + Py_DECREF(self); | |
| 64 | + return NULL; | |
| 65 | + } | |
| 66 | + if (bitsize /* this is a bitfield request */ | |
| 67 | + && *pfield_size /* we have a bitfield open */ | |
| 68 | +#if defined(MS_WIN32) && !defined(__MINGW32__) | |
| 69 | + && dict->size * 8 == *pfield_size /* MSVC */ | |
| 70 | +#else | |
| 71 | + && dict->size * 8 <= *pfield_size /* GCC, MINGW */ | |
| 72 | +#endif | |
| 73 | + && (*pbitofs + bitsize) <= *pfield_size) { | |
| 74 | + /* continue bit field */ | |
| 75 | + fieldtype = CONT_BITFIELD; | |
| 76 | +#ifndef MS_WIN32 | |
| 77 | + } else if (bitsize /* this is a bitfield request */ | |
| 78 | + && *pfield_size /* we have a bitfield open */ | |
| 79 | + && dict->size * 8 >= *pfield_size | |
| 80 | + && (*pbitofs + bitsize) <= dict->size * 8) { | |
| 81 | + /* expand bit field */ | |
| 82 | + fieldtype = EXPAND_BITFIELD; | |
| 83 | +#endif | |
| 84 | + } else if (bitsize) { | |
| 85 | + /* start new bitfield */ | |
| 86 | + fieldtype = NEW_BITFIELD; | |
| 87 | + *pbitofs = 0; | |
| 88 | + *pfield_size = dict->size * 8; | |
| 89 | + } else { | |
| 90 | + /* not a bit field */ | |
| 91 | + fieldtype = NO_BITFIELD; | |
| 92 | + *pbitofs = 0; | |
| 93 | + *pfield_size = 0; | |
| 94 | + } | |
| 95 | + | |
| 96 | + size = dict->size; | |
| 97 | + length = dict->length; | |
| 98 | + proto = desc; | |
| 99 | + | |
| 100 | + /* Field descriptors for 'c_char * n' are be scpecial cased to | |
| 101 | + return a Python string instead of an Array object instance... | |
| 102 | + */ | |
| 103 | + if (ArrayTypeObject_Check(proto)) { | |
| 104 | + StgDictObject *adict = PyType_stgdict(proto); | |
| 105 | + StgDictObject *idict; | |
| 106 | + if (adict && adict->proto) { | |
| 107 | + idict = PyType_stgdict(adict->proto); | |
| 108 | + if (!idict) { | |
| 109 | + PyErr_SetString(PyExc_TypeError, | |
| 110 | + "has no _stginfo_"); | |
| 111 | + Py_DECREF(self); | |
| 112 | + return NULL; | |
| 113 | + } | |
| 114 | + if (idict->getfunc == getentry("c")->getfunc) { | |
| 115 | + struct fielddesc *fd = getentry("s"); | |
| 116 | + getfunc = fd->getfunc; | |
| 117 | + setfunc = fd->setfunc; | |
| 118 | + } | |
| 119 | +#ifdef CTYPES_UNICODE | |
| 120 | + if (idict->getfunc == getentry("u")->getfunc) { | |
| 121 | + struct fielddesc *fd = getentry("U"); | |
| 122 | + getfunc = fd->getfunc; | |
| 123 | + setfunc = fd->setfunc; | |
| 124 | + } | |
| 125 | +#endif | |
| 126 | + } | |
| 127 | + } | |
| 128 | + | |
| 129 | + self->setfunc = setfunc; | |
| 130 | + self->getfunc = getfunc; | |
| 131 | + self->index = index; | |
| 132 | + | |
| 133 | + Py_INCREF(proto); | |
| 134 | + self->proto = proto; | |
| 135 | + | |
| 136 | + switch (fieldtype) { | |
| 137 | + case NEW_BITFIELD: | |
| 138 | + if (big_endian) | |
| 139 | + self->size = (bitsize << 16) + *pfield_size - *pbitofs - bitsize; | |
| 140 | + else | |
| 141 | + self->size = (bitsize << 16) + *pbitofs; | |
| 142 | + *pbitofs = bitsize; | |
| 143 | + /* fall through */ | |
| 144 | + case NO_BITFIELD: | |
| 145 | + if (pack) | |
| 146 | + align = min(pack, dict->align); | |
| 147 | + else | |
| 148 | + align = dict->align; | |
| 149 | + if (align && *poffset % align) { | |
| 150 | + int delta = align - (*poffset % align); | |
| 151 | + *psize += delta; | |
| 152 | + *poffset += delta; | |
| 153 | + } | |
| 154 | + | |
| 155 | + if (bitsize == 0) | |
| 156 | + self->size = size; | |
| 157 | + *psize += size; | |
| 158 | + | |
| 159 | + self->offset = *poffset; | |
| 160 | + *poffset += size; | |
| 161 | + | |
| 162 | + *palign = align; | |
| 163 | + break; | |
| 164 | + | |
| 165 | + case EXPAND_BITFIELD: | |
| 166 | + /* XXX needs more */ | |
| 167 | + *psize += dict->size - *pfield_size/8; | |
| 168 | + | |
| 169 | + *pfield_size = dict->size * 8; | |
| 170 | + | |
| 171 | + if (big_endian) | |
| 172 | + self->size = (bitsize << 16) + *pfield_size - *pbitofs - bitsize; | |
| 173 | + else | |
| 174 | + self->size = (bitsize << 16) + *pbitofs; | |
| 175 | + | |
| 176 | + self->offset = *poffset - size; /* poffset is already updated for the NEXT field */ | |
| 177 | + *pbitofs += bitsize; | |
| 178 | + break; | |
| 179 | + | |
| 180 | + case CONT_BITFIELD: | |
| 181 | + if (big_endian) | |
| 182 | + self->size = (bitsize << 16) + *pfield_size - *pbitofs - bitsize; | |
| 183 | + else | |
| 184 | + self->size = (bitsize << 16) + *pbitofs; | |
| 185 | + | |
| 186 | + self->offset = *poffset - size; /* poffset is already updated for the NEXT field */ | |
| 187 | + *pbitofs += bitsize; | |
| 188 | + break; | |
| 189 | + } | |
| 190 | + | |
| 191 | + return (PyObject *)self; | |
| 192 | +} | |
| 193 | + | |
| 194 | +static int | |
| 195 | +CField_set(CFieldObject *self, PyObject *inst, PyObject *value) | |
| 196 | +{ | |
| 197 | + CDataObject *dst; | |
| 198 | + char *ptr; | |
| 199 | + assert(CDataObject_Check(inst)); | |
| 200 | + dst = (CDataObject *)inst; | |
| 201 | + ptr = dst->b_ptr + self->offset; | |
| 202 | + return CData_set(inst, self->proto, self->setfunc, value, | |
| 203 | + self->index, self->size, ptr); | |
| 204 | +} | |
| 205 | + | |
| 206 | +static PyObject * | |
| 207 | +CField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type) | |
| 208 | +{ | |
| 209 | + CDataObject *src; | |
| 210 | + if (inst == NULL) { | |
| 211 | + Py_INCREF(self); | |
| 212 | + return (PyObject *)self; | |
| 213 | + } | |
| 214 | + assert(CDataObject_Check(inst)); | |
| 215 | + src = (CDataObject *)inst; | |
| 216 | + return CData_get(self->proto, self->getfunc, inst, | |
| 217 | + self->index, self->size, src->b_ptr + self->offset); | |
| 218 | +} | |
| 219 | + | |
| 220 | +static PyObject * | |
| 221 | +CField_get_offset(PyObject *self, void *data) | |
| 222 | +{ | |
| 223 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 224 | + return PyInt_FromLong(((CFieldObject *)self)->offset); | |
| 225 | +#else | |
| 226 | + return PyInt_FromSsize_t(((CFieldObject *)self)->offset); | |
| 227 | +#endif | |
| 228 | +} | |
| 229 | + | |
| 230 | +static PyObject * | |
| 231 | +CField_get_size(PyObject *self, void *data) | |
| 232 | +{ | |
| 233 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 234 | + return PyInt_FromLong(((CFieldObject *)self)->size); | |
| 235 | +#else | |
| 236 | + return PyInt_FromSsize_t(((CFieldObject *)self)->size); | |
| 237 | +#endif | |
| 238 | +} | |
| 239 | + | |
| 240 | +static PyGetSetDef CField_getset[] = { | |
| 241 | + { "offset", CField_get_offset, NULL, "offset in bytes of this field" }, | |
| 242 | + { "size", CField_get_size, NULL, "size in bytes of this field" }, | |
| 243 | + { NULL, NULL, NULL, NULL }, | |
| 244 | +}; | |
| 245 | + | |
| 246 | +static int | |
| 247 | +CField_traverse(CFieldObject *self, visitproc visit, void *arg) | |
| 248 | +{ | |
| 249 | + Py_VISIT(self->proto); | |
| 250 | + return 0; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static int | |
| 254 | +CField_clear(CFieldObject *self) | |
| 255 | +{ | |
| 256 | + Py_CLEAR(self->proto); | |
| 257 | + return 0; | |
| 258 | +} | |
| 259 | + | |
| 260 | +static void | |
| 261 | +CField_dealloc(PyObject *self) | |
| 262 | +{ | |
| 263 | + CField_clear((CFieldObject *)self); | |
| 264 | + self->ob_type->tp_free((PyObject *)self); | |
| 265 | +} | |
| 266 | + | |
| 267 | +static PyObject * | |
| 268 | +CField_repr(CFieldObject *self) | |
| 269 | +{ | |
| 270 | + PyObject *result; | |
| 271 | + int bits = self->size >> 16; | |
| 272 | + int size = self->size & 0xFFFF; | |
| 273 | + const char *name; | |
| 274 | + | |
| 275 | + name = ((PyTypeObject *)self->proto)->tp_name; | |
| 276 | + | |
| 277 | + if (bits) | |
| 278 | + result = PyString_FromFormat( | |
| 279 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 280 | + "<Field type=%s, ofs=%d:%d, bits=%d>", | |
| 281 | +#else | |
| 282 | + "<Field type=%s, ofs=%zd:%d, bits=%d>", | |
| 283 | +#endif | |
| 284 | + name, self->offset, size, bits); | |
| 285 | + else | |
| 286 | + result = PyString_FromFormat( | |
| 287 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 288 | + "<Field type=%s, ofs=%d, size=%d>", | |
| 289 | +#else | |
| 290 | + "<Field type=%s, ofs=%zd, size=%d>", | |
| 291 | +#endif | |
| 292 | + name, self->offset, size); | |
| 293 | + return result; | |
| 294 | +} | |
| 295 | + | |
| 296 | +PyTypeObject CField_Type = { | |
| 297 | + PyObject_HEAD_INIT(NULL) | |
| 298 | + 0, /* ob_size */ | |
| 299 | + "_ctypes.CField", /* tp_name */ | |
| 300 | + sizeof(CFieldObject), /* tp_basicsize */ | |
| 301 | + 0, /* tp_itemsize */ | |
| 302 | + CField_dealloc, /* tp_dealloc */ | |
| 303 | + 0, /* tp_print */ | |
| 304 | + 0, /* tp_getattr */ | |
| 305 | + 0, /* tp_setattr */ | |
| 306 | + 0, /* tp_compare */ | |
| 307 | + (reprfunc)CField_repr, /* tp_repr */ | |
| 308 | + 0, /* tp_as_number */ | |
| 309 | + 0, /* tp_as_sequence */ | |
| 310 | + 0, /* tp_as_mapping */ | |
| 311 | + 0, /* tp_hash */ | |
| 312 | + 0, /* tp_call */ | |
| 313 | + 0, /* tp_str */ | |
| 314 | + 0, /* tp_getattro */ | |
| 315 | + 0, /* tp_setattro */ | |
| 316 | + 0, /* tp_as_buffer */ | |
| 317 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ | |
| 318 | + "Structure/Union member", /* tp_doc */ | |
| 319 | + (traverseproc)CField_traverse, /* tp_traverse */ | |
| 320 | + (inquiry)CField_clear, /* tp_clear */ | |
| 321 | + 0, /* tp_richcompare */ | |
| 322 | + 0, /* tp_weaklistoffset */ | |
| 323 | + 0, /* tp_iter */ | |
| 324 | + 0, /* tp_iternext */ | |
| 325 | + 0, /* tp_methods */ | |
| 326 | + 0, /* tp_members */ | |
| 327 | + CField_getset, /* tp_getset */ | |
| 328 | + 0, /* tp_base */ | |
| 329 | + 0, /* tp_dict */ | |
| 330 | + (descrgetfunc)CField_get, /* tp_descr_get */ | |
| 331 | + (descrsetfunc)CField_set, /* tp_descr_set */ | |
| 332 | + 0, /* tp_dictoffset */ | |
| 333 | + 0, /* tp_init */ | |
| 334 | + 0, /* tp_alloc */ | |
| 335 | + CField_new, /* tp_new */ | |
| 336 | + 0, /* tp_free */ | |
| 337 | +}; | |
| 338 | + | |
| 339 | + | |
| 340 | +/******************************************************************/ | |
| 341 | +/* | |
| 342 | + Accessor functions | |
| 343 | +*/ | |
| 344 | + | |
| 345 | +/* Derived from Modules/structmodule.c: | |
| 346 | + Helper routine to get a Python integer and raise the appropriate error | |
| 347 | + if it isn't one */ | |
| 348 | + | |
| 349 | +static int | |
| 350 | +get_long(PyObject *v, long *p) | |
| 351 | +{ | |
| 352 | + long x; | |
| 353 | + if (!PyInt_Check(v) && !PyLong_Check(v)) { | |
| 354 | + PyErr_Format(PyExc_TypeError, | |
| 355 | + "int expected instead of %s instance", | |
| 356 | + v->ob_type->tp_name); | |
| 357 | + return -1; | |
| 358 | + } | |
| 359 | + x = PyInt_AsUnsignedLongMask(v); | |
| 360 | + if (x == -1 && PyErr_Occurred()) | |
| 361 | + return -1; | |
| 362 | + *p = x; | |
| 363 | + return 0; | |
| 364 | +} | |
| 365 | + | |
| 366 | +/* Same, but handling unsigned long */ | |
| 367 | + | |
| 368 | +static int | |
| 369 | +get_ulong(PyObject *v, unsigned long *p) | |
| 370 | +{ | |
| 371 | + unsigned long x; | |
| 372 | + if (!PyInt_Check(v) && !PyLong_Check(v)) { | |
| 373 | + PyErr_Format(PyExc_TypeError, | |
| 374 | + "int expected instead of %s instance", | |
| 375 | + v->ob_type->tp_name); | |
| 376 | + return -1; | |
| 377 | + } | |
| 378 | + x = PyInt_AsUnsignedLongMask(v); | |
| 379 | + if (x == -1 && PyErr_Occurred()) | |
| 380 | + return -1; | |
| 381 | + *p = x; | |
| 382 | + return 0; | |
| 383 | +} | |
| 384 | + | |
| 385 | +#ifdef HAVE_LONG_LONG | |
| 386 | + | |
| 387 | +/* Same, but handling native long long. */ | |
| 388 | + | |
| 389 | +static int | |
| 390 | +get_longlong(PyObject *v, PY_LONG_LONG *p) | |
| 391 | +{ | |
| 392 | + PY_LONG_LONG x; | |
| 393 | + if (!PyInt_Check(v) && !PyLong_Check(v)) { | |
| 394 | + PyErr_Format(PyExc_TypeError, | |
| 395 | + "int expected instead of %s instance", | |
| 396 | + v->ob_type->tp_name); | |
| 397 | + return -1; | |
| 398 | + } | |
| 399 | + x = PyInt_AsUnsignedLongLongMask(v); | |
| 400 | + if (x == -1 && PyErr_Occurred()) | |
| 401 | + return -1; | |
| 402 | + *p = x; | |
| 403 | + return 0; | |
| 404 | +} | |
| 405 | + | |
| 406 | +/* Same, but handling native unsigned long long. */ | |
| 407 | + | |
| 408 | +static int | |
| 409 | +get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p) | |
| 410 | +{ | |
| 411 | + unsigned PY_LONG_LONG x; | |
| 412 | + if (!PyInt_Check(v) && !PyLong_Check(v)) { | |
| 413 | + PyErr_Format(PyExc_TypeError, | |
| 414 | + "int expected instead of %s instance", | |
| 415 | + v->ob_type->tp_name); | |
| 416 | + return -1; | |
| 417 | + } | |
| 418 | + x = PyInt_AsUnsignedLongLongMask(v); | |
| 419 | + if (x == -1 && PyErr_Occurred()) | |
| 420 | + return -1; | |
| 421 | + *p = x; | |
| 422 | + return 0; | |
| 423 | +} | |
| 424 | + | |
| 425 | +#endif | |
| 426 | + | |
| 427 | +/***************************************************************** | |
| 428 | + * Integer fields, with bitfield support | |
| 429 | + */ | |
| 430 | + | |
| 431 | +/* how to decode the size field, for integer get/set functions */ | |
| 432 | +#define LOW_BIT(x) ((x) & 0xFFFF) | |
| 433 | +#define NUM_BITS(x) ((x) >> 16) | |
| 434 | + | |
| 435 | +/* This seems nore a compiler issue than a Windows/non-Windows one */ | |
| 436 | +#ifdef MS_WIN32 | |
| 437 | +# define BIT_MASK(size) ((1 << NUM_BITS(size))-1) | |
| 438 | +#else | |
| 439 | +# define BIT_MASK(size) ((1LL << NUM_BITS(size))-1) | |
| 440 | +#endif | |
| 441 | + | |
| 442 | +/* This macro CHANGES the first parameter IN PLACE. For proper sign handling, | |
| 443 | + we must first shift left, then right. | |
| 444 | +*/ | |
| 445 | +#define GET_BITFIELD(v, size) \ | |
| 446 | + if (NUM_BITS(size)) { \ | |
| 447 | + v <<= (sizeof(v)*8 - LOW_BIT(size) - NUM_BITS(size)); \ | |
| 448 | + v >>= (sizeof(v)*8 - NUM_BITS(size)); \ | |
| 449 | + } | |
| 450 | + | |
| 451 | +/* This macro RETURNS the first parameter with the bit field CHANGED. */ | |
| 452 | +#define SET(x, v, size) \ | |
| 453 | + (NUM_BITS(size) ? \ | |
| 454 | + ( ( x & ~(BIT_MASK(size) << LOW_BIT(size)) ) | ( (v & BIT_MASK(size)) << LOW_BIT(size) ) ) \ | |
| 455 | + : v) | |
| 456 | + | |
| 457 | +/* byte swapping macros */ | |
| 458 | +#define SWAP_2(v) \ | |
| 459 | + ( ( (v >> 8) & 0x00FF) | \ | |
| 460 | + ( (v << 8) & 0xFF00) ) | |
| 461 | + | |
| 462 | +#define SWAP_4(v) \ | |
| 463 | + ( ( (v & 0x000000FF) << 24 ) | \ | |
| 464 | + ( (v & 0x0000FF00) << 8 ) | \ | |
| 465 | + ( (v & 0x00FF0000) >> 8 ) | \ | |
| 466 | + ( ((v >> 24) & 0xFF)) ) | |
| 467 | + | |
| 468 | +#ifdef _MSC_VER | |
| 469 | +#define SWAP_8(v) \ | |
| 470 | + ( ( (v & 0x00000000000000FFL) << 56 ) | \ | |
| 471 | + ( (v & 0x000000000000FF00L) << 40 ) | \ | |
| 472 | + ( (v & 0x0000000000FF0000L) << 24 ) | \ | |
| 473 | + ( (v & 0x00000000FF000000L) << 8 ) | \ | |
| 474 | + ( (v & 0x000000FF00000000L) >> 8 ) | \ | |
| 475 | + ( (v & 0x0000FF0000000000L) >> 24 ) | \ | |
| 476 | + ( (v & 0x00FF000000000000L) >> 40 ) | \ | |
| 477 | + ( ((v >> 56) & 0xFF)) ) | |
| 478 | +#else | |
| 479 | +#define SWAP_8(v) \ | |
| 480 | + ( ( (v & 0x00000000000000FFLL) << 56 ) | \ | |
| 481 | + ( (v & 0x000000000000FF00LL) << 40 ) | \ | |
| 482 | + ( (v & 0x0000000000FF0000LL) << 24 ) | \ | |
| 483 | + ( (v & 0x00000000FF000000LL) << 8 ) | \ | |
| 484 | + ( (v & 0x000000FF00000000LL) >> 8 ) | \ | |
| 485 | + ( (v & 0x0000FF0000000000LL) >> 24 ) | \ | |
| 486 | + ( (v & 0x00FF000000000000LL) >> 40 ) | \ | |
| 487 | + ( ((v >> 56) & 0xFF)) ) | |
| 488 | +#endif | |
| 489 | + | |
| 490 | +#define SWAP_INT SWAP_4 | |
| 491 | + | |
| 492 | +#if SIZEOF_LONG == 4 | |
| 493 | +# define SWAP_LONG SWAP_4 | |
| 494 | +#elif SIZEOF_LONG == 8 | |
| 495 | +# define SWAP_LONG SWAP_8 | |
| 496 | +#endif | |
| 497 | +/***************************************************************** | |
| 498 | + * The setter methods return an object which must be kept alive, to keep the | |
| 499 | + * data valid which has been stored in the memory block. The ctypes object | |
| 500 | + * instance inserts this object into its 'b_objects' list. | |
| 501 | + * | |
| 502 | + * For simple Python types like integers or characters, there is nothing that | |
| 503 | + * has to been kept alive, so Py_None is returned in these cases. But this | |
| 504 | + * makes inspecting the 'b_objects' list, which is accessible from Python for | |
| 505 | + * debugging, less useful. | |
| 506 | + * | |
| 507 | + * So, defining the _CTYPES_DEBUG_KEEP symbol returns the original value | |
| 508 | + * instead of Py_None. | |
| 509 | + */ | |
| 510 | + | |
| 511 | +#ifdef _CTYPES_DEBUG_KEEP | |
| 512 | +#define _RET(x) Py_INCREF(x); return x | |
| 513 | +#else | |
| 514 | +#define _RET(X) Py_INCREF(Py_None); return Py_None | |
| 515 | +#endif | |
| 516 | + | |
| 517 | +/***************************************************************** | |
| 518 | + * integer accessor methods, supporting bit fields | |
| 519 | + */ | |
| 520 | + | |
| 521 | +static PyObject * | |
| 522 | +b_set(void *ptr, PyObject *value, unsigned size) | |
| 523 | +{ | |
| 524 | + long val; | |
| 525 | + if (get_long(value, &val) < 0) | |
| 526 | + return NULL; | |
| 527 | + *(signed char *)ptr = (signed char)SET(*(signed char *)ptr, (signed char)val, size); | |
| 528 | + _RET(value); | |
| 529 | +} | |
| 530 | + | |
| 531 | + | |
| 532 | +static PyObject * | |
| 533 | +b_get(void *ptr, unsigned size) | |
| 534 | +{ | |
| 535 | + signed char val = *(signed char *)ptr; | |
| 536 | + GET_BITFIELD(val, size); | |
| 537 | + return PyInt_FromLong(val); | |
| 538 | +} | |
| 539 | + | |
| 540 | +static PyObject * | |
| 541 | +B_set(void *ptr, PyObject *value, unsigned size) | |
| 542 | +{ | |
| 543 | + unsigned long val; | |
| 544 | + if (get_ulong(value, &val) < 0) | |
| 545 | + return NULL; | |
| 546 | + *(unsigned char *)ptr = (unsigned char)SET(*(unsigned char*)ptr, | |
| 547 | + (unsigned short)val, size); | |
| 548 | + _RET(value); | |
| 549 | +} | |
| 550 | + | |
| 551 | + | |
| 552 | +static PyObject * | |
| 553 | +B_get(void *ptr, unsigned size) | |
| 554 | +{ | |
| 555 | + unsigned char val = *(unsigned char *)ptr; | |
| 556 | + GET_BITFIELD(val, size); | |
| 557 | + return PyInt_FromLong(val); | |
| 558 | +} | |
| 559 | + | |
| 560 | +static PyObject * | |
| 561 | +h_set(void *ptr, PyObject *value, unsigned size) | |
| 562 | +{ | |
| 563 | + long val; | |
| 564 | + short x; | |
| 565 | + if (get_long(value, &val) < 0) | |
| 566 | + return NULL; | |
| 567 | + memcpy(&x, ptr, sizeof(x)); | |
| 568 | + x = SET(x, (short)val, size); | |
| 569 | + memcpy(ptr, &x, sizeof(x)); | |
| 570 | + _RET(value); | |
| 571 | +} | |
| 572 | + | |
| 573 | + | |
| 574 | +static PyObject * | |
| 575 | +h_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 576 | +{ | |
| 577 | + long val; | |
| 578 | + short field; | |
| 579 | + if (get_long(value, &val) < 0) | |
| 580 | + return NULL; | |
| 581 | + memcpy(&field, ptr, sizeof(field)); | |
| 582 | + field = SWAP_2(field); | |
| 583 | + field = SET(field, (short)val, size); | |
| 584 | + field = SWAP_2(field); | |
| 585 | + memcpy(ptr, &field, sizeof(field)); | |
| 586 | + _RET(value); | |
| 587 | +} | |
| 588 | + | |
| 589 | +static PyObject * | |
| 590 | +h_get(void *ptr, unsigned size) | |
| 591 | +{ | |
| 592 | + short val; | |
| 593 | + memcpy(&val, ptr, sizeof(val)); | |
| 594 | + GET_BITFIELD(val, size); | |
| 595 | + return PyInt_FromLong((long)val); | |
| 596 | +} | |
| 597 | + | |
| 598 | +static PyObject * | |
| 599 | +h_get_sw(void *ptr, unsigned size) | |
| 600 | +{ | |
| 601 | + short val; | |
| 602 | + memcpy(&val, ptr, sizeof(val)); | |
| 603 | + val = SWAP_2(val); | |
| 604 | + GET_BITFIELD(val, size); | |
| 605 | + return PyInt_FromLong(val); | |
| 606 | +} | |
| 607 | + | |
| 608 | +static PyObject * | |
| 609 | +H_set(void *ptr, PyObject *value, unsigned size) | |
| 610 | +{ | |
| 611 | + unsigned long val; | |
| 612 | + unsigned short x; | |
| 613 | + if (get_ulong(value, &val) < 0) | |
| 614 | + return NULL; | |
| 615 | + memcpy(&x, ptr, sizeof(x)); | |
| 616 | + x = SET(x, (unsigned short)val, size); | |
| 617 | + memcpy(ptr, &x, sizeof(x)); | |
| 618 | + _RET(value); | |
| 619 | +} | |
| 620 | + | |
| 621 | +static PyObject * | |
| 622 | +H_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 623 | +{ | |
| 624 | + unsigned long val; | |
| 625 | + unsigned short field; | |
| 626 | + if (get_ulong(value, &val) < 0) | |
| 627 | + return NULL; | |
| 628 | + memcpy(&field, ptr, sizeof(field)); | |
| 629 | + field = SWAP_2(field); | |
| 630 | + field = SET(field, (unsigned short)val, size); | |
| 631 | + field = SWAP_2(field); | |
| 632 | + memcpy(ptr, &field, sizeof(field)); | |
| 633 | + _RET(value); | |
| 634 | +} | |
| 635 | + | |
| 636 | + | |
| 637 | +static PyObject * | |
| 638 | +H_get(void *ptr, unsigned size) | |
| 639 | +{ | |
| 640 | + unsigned short val; | |
| 641 | + memcpy(&val, ptr, sizeof(val)); | |
| 642 | + GET_BITFIELD(val, size); | |
| 643 | + return PyInt_FromLong(val); | |
| 644 | +} | |
| 645 | + | |
| 646 | +static PyObject * | |
| 647 | +H_get_sw(void *ptr, unsigned size) | |
| 648 | +{ | |
| 649 | + unsigned short val; | |
| 650 | + memcpy(&val, ptr, sizeof(val)); | |
| 651 | + val = SWAP_2(val); | |
| 652 | + GET_BITFIELD(val, size); | |
| 653 | + return PyInt_FromLong(val); | |
| 654 | +} | |
| 655 | + | |
| 656 | +static PyObject * | |
| 657 | +i_set(void *ptr, PyObject *value, unsigned size) | |
| 658 | +{ | |
| 659 | + long val; | |
| 660 | + int x; | |
| 661 | + if (get_long(value, &val) < 0) | |
| 662 | + return NULL; | |
| 663 | + memcpy(&x, ptr, sizeof(x)); | |
| 664 | + x = SET(x, (int)val, size); | |
| 665 | + memcpy(ptr, &x, sizeof(x)); | |
| 666 | + _RET(value); | |
| 667 | +} | |
| 668 | + | |
| 669 | +static PyObject * | |
| 670 | +i_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 671 | +{ | |
| 672 | + long val; | |
| 673 | + int field; | |
| 674 | + if (get_long(value, &val) < 0) | |
| 675 | + return NULL; | |
| 676 | + memcpy(&field, ptr, sizeof(field)); | |
| 677 | + field = SWAP_INT(field); | |
| 678 | + field = SET(field, (int)val, size); | |
| 679 | + field = SWAP_INT(field); | |
| 680 | + memcpy(ptr, &field, sizeof(field)); | |
| 681 | + _RET(value); | |
| 682 | +} | |
| 683 | + | |
| 684 | + | |
| 685 | +static PyObject * | |
| 686 | +i_get(void *ptr, unsigned size) | |
| 687 | +{ | |
| 688 | + int val; | |
| 689 | + memcpy(&val, ptr, sizeof(val)); | |
| 690 | + GET_BITFIELD(val, size); | |
| 691 | + return PyInt_FromLong(val); | |
| 692 | +} | |
| 693 | + | |
| 694 | +static PyObject * | |
| 695 | +i_get_sw(void *ptr, unsigned size) | |
| 696 | +{ | |
| 697 | + int val; | |
| 698 | + memcpy(&val, ptr, sizeof(val)); | |
| 699 | + val = SWAP_INT(val); | |
| 700 | + GET_BITFIELD(val, size); | |
| 701 | + return PyInt_FromLong(val); | |
| 702 | +} | |
| 703 | + | |
| 704 | +#ifdef MS_WIN32 | |
| 705 | +/* short BOOL - VARIANT_BOOL */ | |
| 706 | +static PyObject * | |
| 707 | +vBOOL_set(void *ptr, PyObject *value, unsigned size) | |
| 708 | +{ | |
| 709 | + switch (PyObject_IsTrue(value)) { | |
| 710 | + case -1: | |
| 711 | + return NULL; | |
| 712 | + case 0: | |
| 713 | + *(short int *)ptr = VARIANT_FALSE; | |
| 714 | + _RET(value); | |
| 715 | + default: | |
| 716 | + *(short int *)ptr = VARIANT_TRUE; | |
| 717 | + _RET(value); | |
| 718 | + } | |
| 719 | +} | |
| 720 | + | |
| 721 | +static PyObject * | |
| 722 | +vBOOL_get(void *ptr, unsigned size) | |
| 723 | +{ | |
| 724 | + return PyBool_FromLong((long)*(short int *)ptr); | |
| 725 | +} | |
| 726 | +#endif | |
| 727 | + | |
| 728 | +static PyObject * | |
| 729 | +I_set(void *ptr, PyObject *value, unsigned size) | |
| 730 | +{ | |
| 731 | + unsigned long val; | |
| 732 | + unsigned int x; | |
| 733 | + if (get_ulong(value, &val) < 0) | |
| 734 | + return NULL; | |
| 735 | + memcpy(&x, ptr, sizeof(x)); | |
| 736 | + x = SET(x, (unsigned int)val, size); | |
| 737 | + memcpy(ptr, &x, sizeof(x)); | |
| 738 | + _RET(value); | |
| 739 | +} | |
| 740 | + | |
| 741 | +static PyObject * | |
| 742 | +I_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 743 | +{ | |
| 744 | + unsigned long val; | |
| 745 | + unsigned int field; | |
| 746 | + if (get_ulong(value, &val) < 0) | |
| 747 | + return NULL; | |
| 748 | + memcpy(&field, ptr, sizeof(field)); | |
| 749 | + field = (unsigned int)SET(field, (unsigned int)val, size); | |
| 750 | + field = SWAP_INT(field); | |
| 751 | + memcpy(ptr, &field, sizeof(field)); | |
| 752 | + _RET(value); | |
| 753 | +} | |
| 754 | + | |
| 755 | + | |
| 756 | +static PyObject * | |
| 757 | +I_get(void *ptr, unsigned size) | |
| 758 | +{ | |
| 759 | + unsigned int val; | |
| 760 | + memcpy(&val, ptr, sizeof(val)); | |
| 761 | + GET_BITFIELD(val, size); | |
| 762 | + return PyLong_FromUnsignedLong(val); | |
| 763 | +} | |
| 764 | + | |
| 765 | +static PyObject * | |
| 766 | +I_get_sw(void *ptr, unsigned size) | |
| 767 | +{ | |
| 768 | + unsigned int val; | |
| 769 | + memcpy(&val, ptr, sizeof(val)); | |
| 770 | + val = SWAP_INT(val); | |
| 771 | + GET_BITFIELD(val, size); | |
| 772 | + return PyLong_FromUnsignedLong(val); | |
| 773 | +} | |
| 774 | + | |
| 775 | +static PyObject * | |
| 776 | +l_set(void *ptr, PyObject *value, unsigned size) | |
| 777 | +{ | |
| 778 | + long val; | |
| 779 | + long x; | |
| 780 | + if (get_long(value, &val) < 0) | |
| 781 | + return NULL; | |
| 782 | + memcpy(&x, ptr, sizeof(x)); | |
| 783 | + x = SET(x, val, size); | |
| 784 | + memcpy(ptr, &x, sizeof(x)); | |
| 785 | + _RET(value); | |
| 786 | +} | |
| 787 | + | |
| 788 | +static PyObject * | |
| 789 | +l_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 790 | +{ | |
| 791 | + long val; | |
| 792 | + long field; | |
| 793 | + if (get_long(value, &val) < 0) | |
| 794 | + return NULL; | |
| 795 | + memcpy(&field, ptr, sizeof(field)); | |
| 796 | + field = SWAP_LONG(field); | |
| 797 | + field = (long)SET(field, val, size); | |
| 798 | + field = SWAP_LONG(field); | |
| 799 | + memcpy(ptr, &field, sizeof(field)); | |
| 800 | + _RET(value); | |
| 801 | +} | |
| 802 | + | |
| 803 | + | |
| 804 | +static PyObject * | |
| 805 | +l_get(void *ptr, unsigned size) | |
| 806 | +{ | |
| 807 | + long val; | |
| 808 | + memcpy(&val, ptr, sizeof(val)); | |
| 809 | + GET_BITFIELD(val, size); | |
| 810 | + return PyInt_FromLong(val); | |
| 811 | +} | |
| 812 | + | |
| 813 | +static PyObject * | |
| 814 | +l_get_sw(void *ptr, unsigned size) | |
| 815 | +{ | |
| 816 | + long val; | |
| 817 | + memcpy(&val, ptr, sizeof(val)); | |
| 818 | + val = SWAP_LONG(val); | |
| 819 | + GET_BITFIELD(val, size); | |
| 820 | + return PyInt_FromLong(val); | |
| 821 | +} | |
| 822 | + | |
| 823 | +static PyObject * | |
| 824 | +L_set(void *ptr, PyObject *value, unsigned size) | |
| 825 | +{ | |
| 826 | + unsigned long val; | |
| 827 | + unsigned long x; | |
| 828 | + if (get_ulong(value, &val) < 0) | |
| 829 | + return NULL; | |
| 830 | + memcpy(&x, ptr, sizeof(x)); | |
| 831 | + x = SET(x, val, size); | |
| 832 | + memcpy(ptr, &x, sizeof(x)); | |
| 833 | + _RET(value); | |
| 834 | +} | |
| 835 | + | |
| 836 | +static PyObject * | |
| 837 | +L_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 838 | +{ | |
| 839 | + unsigned long val; | |
| 840 | + unsigned long field; | |
| 841 | + if (get_ulong(value, &val) < 0) | |
| 842 | + return NULL; | |
| 843 | + memcpy(&field, ptr, sizeof(field)); | |
| 844 | + field = SWAP_LONG(field); | |
| 845 | + field = (unsigned long)SET(field, val, size); | |
| 846 | + field = SWAP_LONG(field); | |
| 847 | + memcpy(ptr, &field, sizeof(field)); | |
| 848 | + _RET(value); | |
| 849 | +} | |
| 850 | + | |
| 851 | + | |
| 852 | +static PyObject * | |
| 853 | +L_get(void *ptr, unsigned size) | |
| 854 | +{ | |
| 855 | + unsigned long val; | |
| 856 | + memcpy(&val, ptr, sizeof(val)); | |
| 857 | + GET_BITFIELD(val, size); | |
| 858 | + return PyLong_FromUnsignedLong(val); | |
| 859 | +} | |
| 860 | + | |
| 861 | +static PyObject * | |
| 862 | +L_get_sw(void *ptr, unsigned size) | |
| 863 | +{ | |
| 864 | + unsigned long val; | |
| 865 | + memcpy(&val, ptr, sizeof(val)); | |
| 866 | + val = SWAP_LONG(val); | |
| 867 | + GET_BITFIELD(val, size); | |
| 868 | + return PyLong_FromUnsignedLong(val); | |
| 869 | +} | |
| 870 | + | |
| 871 | +#ifdef HAVE_LONG_LONG | |
| 872 | +static PyObject * | |
| 873 | +q_set(void *ptr, PyObject *value, unsigned size) | |
| 874 | +{ | |
| 875 | + PY_LONG_LONG val; | |
| 876 | + PY_LONG_LONG x; | |
| 877 | + if (get_longlong(value, &val) < 0) | |
| 878 | + return NULL; | |
| 879 | + memcpy(&x, ptr, sizeof(x)); | |
| 880 | + x = SET(x, val, size); | |
| 881 | + memcpy(ptr, &x, sizeof(x)); | |
| 882 | + _RET(value); | |
| 883 | +} | |
| 884 | + | |
| 885 | +static PyObject * | |
| 886 | +q_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 887 | +{ | |
| 888 | + PY_LONG_LONG val; | |
| 889 | + PY_LONG_LONG field; | |
| 890 | + if (get_longlong(value, &val) < 0) | |
| 891 | + return NULL; | |
| 892 | + memcpy(&field, ptr, sizeof(field)); | |
| 893 | + field = SWAP_8(field); | |
| 894 | + field = (PY_LONG_LONG)SET(field, val, size); | |
| 895 | + field = SWAP_8(field); | |
| 896 | + memcpy(ptr, &field, sizeof(field)); | |
| 897 | + _RET(value); | |
| 898 | +} | |
| 899 | + | |
| 900 | +static PyObject * | |
| 901 | +q_get(void *ptr, unsigned size) | |
| 902 | +{ | |
| 903 | + PY_LONG_LONG val; | |
| 904 | + memcpy(&val, ptr, sizeof(val)); | |
| 905 | + GET_BITFIELD(val, size); | |
| 906 | + return PyLong_FromLongLong(val); | |
| 907 | +} | |
| 908 | + | |
| 909 | +static PyObject * | |
| 910 | +q_get_sw(void *ptr, unsigned size) | |
| 911 | +{ | |
| 912 | + PY_LONG_LONG val; | |
| 913 | + memcpy(&val, ptr, sizeof(val)); | |
| 914 | + val = SWAP_8(val); | |
| 915 | + GET_BITFIELD(val, size); | |
| 916 | + return PyLong_FromLongLong(val); | |
| 917 | +} | |
| 918 | + | |
| 919 | +static PyObject * | |
| 920 | +Q_set(void *ptr, PyObject *value, unsigned size) | |
| 921 | +{ | |
| 922 | + unsigned PY_LONG_LONG val; | |
| 923 | + unsigned PY_LONG_LONG x; | |
| 924 | + if (get_ulonglong(value, &val) < 0) | |
| 925 | + return NULL; | |
| 926 | + memcpy(&x, ptr, sizeof(x)); | |
| 927 | + x = SET(x, val, size); | |
| 928 | + memcpy(ptr, &x, sizeof(x)); | |
| 929 | + _RET(value); | |
| 930 | +} | |
| 931 | + | |
| 932 | +static PyObject * | |
| 933 | +Q_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 934 | +{ | |
| 935 | + unsigned PY_LONG_LONG val; | |
| 936 | + unsigned PY_LONG_LONG field; | |
| 937 | + if (get_ulonglong(value, &val) < 0) | |
| 938 | + return NULL; | |
| 939 | + memcpy(&field, ptr, sizeof(field)); | |
| 940 | + field = SWAP_8(field); | |
| 941 | + field = (unsigned PY_LONG_LONG)SET(field, val, size); | |
| 942 | + field = SWAP_8(field); | |
| 943 | + memcpy(ptr, &field, sizeof(field)); | |
| 944 | + _RET(value); | |
| 945 | +} | |
| 946 | + | |
| 947 | +static PyObject * | |
| 948 | +Q_get(void *ptr, unsigned size) | |
| 949 | +{ | |
| 950 | + unsigned PY_LONG_LONG val; | |
| 951 | + memcpy(&val, ptr, sizeof(val)); | |
| 952 | + GET_BITFIELD(val, size); | |
| 953 | + return PyLong_FromUnsignedLongLong(val); | |
| 954 | +} | |
| 955 | + | |
| 956 | +static PyObject * | |
| 957 | +Q_get_sw(void *ptr, unsigned size) | |
| 958 | +{ | |
| 959 | + unsigned PY_LONG_LONG val; | |
| 960 | + memcpy(&val, ptr, sizeof(val)); | |
| 961 | + val = SWAP_8(val); | |
| 962 | + GET_BITFIELD(val, size); | |
| 963 | + return PyLong_FromUnsignedLongLong(val); | |
| 964 | +} | |
| 965 | +#endif | |
| 966 | + | |
| 967 | +/***************************************************************** | |
| 968 | + * non-integer accessor methods, not supporting bit fields | |
| 969 | + */ | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | +static PyObject * | |
| 974 | +d_set(void *ptr, PyObject *value, unsigned size) | |
| 975 | +{ | |
| 976 | + double x; | |
| 977 | + | |
| 978 | + x = PyFloat_AsDouble(value); | |
| 979 | + if (x == -1 && PyErr_Occurred()) { | |
| 980 | + PyErr_Format(PyExc_TypeError, | |
| 981 | + " float expected instead of %s instance", | |
| 982 | + value->ob_type->tp_name); | |
| 983 | + return NULL; | |
| 984 | + } | |
| 985 | + memcpy(ptr, &x, sizeof(double)); | |
| 986 | + _RET(value); | |
| 987 | +} | |
| 988 | + | |
| 989 | +static PyObject * | |
| 990 | +d_get(void *ptr, unsigned size) | |
| 991 | +{ | |
| 992 | + double val; | |
| 993 | + memcpy(&val, ptr, sizeof(val)); | |
| 994 | + return PyFloat_FromDouble(val); | |
| 995 | +} | |
| 996 | + | |
| 997 | +static PyObject * | |
| 998 | +d_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 999 | +{ | |
| 1000 | + double x; | |
| 1001 | + | |
| 1002 | + x = PyFloat_AsDouble(value); | |
| 1003 | + if (x == -1 && PyErr_Occurred()) { | |
| 1004 | + PyErr_Format(PyExc_TypeError, | |
| 1005 | + " float expected instead of %s instance", | |
| 1006 | + value->ob_type->tp_name); | |
| 1007 | + return NULL; | |
| 1008 | + } | |
| 1009 | +#ifdef WORDS_BIGENDIAN | |
| 1010 | + if (_PyFloat_Pack8(x, (unsigned char *)ptr, 1)) | |
| 1011 | + return NULL; | |
| 1012 | +#else | |
| 1013 | + if (_PyFloat_Pack8(x, (unsigned char *)ptr, 0)) | |
| 1014 | + return NULL; | |
| 1015 | +#endif | |
| 1016 | + _RET(value); | |
| 1017 | +} | |
| 1018 | + | |
| 1019 | +static PyObject * | |
| 1020 | +d_get_sw(void *ptr, unsigned size) | |
| 1021 | +{ | |
| 1022 | +#ifdef WORDS_BIGENDIAN | |
| 1023 | + return PyFloat_FromDouble(_PyFloat_Unpack8(ptr, 1)); | |
| 1024 | +#else | |
| 1025 | + return PyFloat_FromDouble(_PyFloat_Unpack8(ptr, 0)); | |
| 1026 | +#endif | |
| 1027 | +} | |
| 1028 | + | |
| 1029 | +static PyObject * | |
| 1030 | +f_set(void *ptr, PyObject *value, unsigned size) | |
| 1031 | +{ | |
| 1032 | + float x; | |
| 1033 | + | |
| 1034 | + x = (float)PyFloat_AsDouble(value); | |
| 1035 | + if (x == -1 && PyErr_Occurred()) { | |
| 1036 | + PyErr_Format(PyExc_TypeError, | |
| 1037 | + " float expected instead of %s instance", | |
| 1038 | + value->ob_type->tp_name); | |
| 1039 | + return NULL; | |
| 1040 | + } | |
| 1041 | + memcpy(ptr, &x, sizeof(x)); | |
| 1042 | + _RET(value); | |
| 1043 | +} | |
| 1044 | + | |
| 1045 | +static PyObject * | |
| 1046 | +f_get(void *ptr, unsigned size) | |
| 1047 | +{ | |
| 1048 | + float val; | |
| 1049 | + memcpy(&val, ptr, sizeof(val)); | |
| 1050 | + return PyFloat_FromDouble(val); | |
| 1051 | +} | |
| 1052 | + | |
| 1053 | +static PyObject * | |
| 1054 | +f_set_sw(void *ptr, PyObject *value, unsigned size) | |
| 1055 | +{ | |
| 1056 | + float x; | |
| 1057 | + | |
| 1058 | + x = (float)PyFloat_AsDouble(value); | |
| 1059 | + if (x == -1 && PyErr_Occurred()) { | |
| 1060 | + PyErr_Format(PyExc_TypeError, | |
| 1061 | + " float expected instead of %s instance", | |
| 1062 | + value->ob_type->tp_name); | |
| 1063 | + return NULL; | |
| 1064 | + } | |
| 1065 | +#ifdef WORDS_BIGENDIAN | |
| 1066 | + if (_PyFloat_Pack4(x, (unsigned char *)ptr, 1)) | |
| 1067 | + return NULL; | |
| 1068 | +#else | |
| 1069 | + if (_PyFloat_Pack4(x, (unsigned char *)ptr, 0)) | |
| 1070 | + return NULL; | |
| 1071 | +#endif | |
| 1072 | + _RET(value); | |
| 1073 | +} | |
| 1074 | + | |
| 1075 | +static PyObject * | |
| 1076 | +f_get_sw(void *ptr, unsigned size) | |
| 1077 | +{ | |
| 1078 | +#ifdef WORDS_BIGENDIAN | |
| 1079 | + return PyFloat_FromDouble(_PyFloat_Unpack4(ptr, 1)); | |
| 1080 | +#else | |
| 1081 | + return PyFloat_FromDouble(_PyFloat_Unpack4(ptr, 0)); | |
| 1082 | +#endif | |
| 1083 | +} | |
| 1084 | + | |
| 1085 | +/* | |
| 1086 | + py_object refcounts: | |
| 1087 | + | |
| 1088 | + 1. If we have a py_object instance, O_get must Py_INCREF the returned | |
| 1089 | + object, of course. If O_get is called from a function result, no py_object | |
| 1090 | + instance is created - so callproc.c::GetResult has to call Py_DECREF. | |
| 1091 | + | |
| 1092 | + 2. The memory block in py_object owns a refcount. So, py_object must call | |
| 1093 | + Py_DECREF on destruction. Maybe only when b_needsfree is non-zero. | |
| 1094 | +*/ | |
| 1095 | +static PyObject * | |
| 1096 | +O_get(void *ptr, unsigned size) | |
| 1097 | +{ | |
| 1098 | + PyObject *ob = *(PyObject **)ptr; | |
| 1099 | + if (ob == NULL) { | |
| 1100 | + if (!PyErr_Occurred()) | |
| 1101 | + /* Set an error if not yet set */ | |
| 1102 | + PyErr_SetString(PyExc_ValueError, | |
| 1103 | + "PyObject is NULL"); | |
| 1104 | + return NULL; | |
| 1105 | + } | |
| 1106 | + Py_INCREF(ob); | |
| 1107 | + return ob; | |
| 1108 | +} | |
| 1109 | + | |
| 1110 | +static PyObject * | |
| 1111 | +O_set(void *ptr, PyObject *value, unsigned size) | |
| 1112 | +{ | |
| 1113 | + /* Hm, does the memory block need it's own refcount or not? */ | |
| 1114 | + *(PyObject **)ptr = value; | |
| 1115 | + Py_INCREF(value); | |
| 1116 | + return value; | |
| 1117 | +} | |
| 1118 | + | |
| 1119 | + | |
| 1120 | +static PyObject * | |
| 1121 | +c_set(void *ptr, PyObject *value, unsigned size) | |
| 1122 | +{ | |
| 1123 | + if (!PyString_Check(value) || (1 != PyString_Size(value))) { | |
| 1124 | + PyErr_Format(PyExc_TypeError, | |
| 1125 | + "one character string expected"); | |
| 1126 | + return NULL; | |
| 1127 | + } | |
| 1128 | + *(char *)ptr = PyString_AS_STRING(value)[0]; | |
| 1129 | + _RET(value); | |
| 1130 | +} | |
| 1131 | + | |
| 1132 | + | |
| 1133 | +static PyObject * | |
| 1134 | +c_get(void *ptr, unsigned size) | |
| 1135 | +{ | |
| 1136 | + return PyString_FromStringAndSize((char *)ptr, 1); | |
| 1137 | +} | |
| 1138 | + | |
| 1139 | +#ifdef CTYPES_UNICODE | |
| 1140 | +/* u - a single wchar_t character */ | |
| 1141 | +static PyObject * | |
| 1142 | +u_set(void *ptr, PyObject *value, unsigned size) | |
| 1143 | +{ | |
| 1144 | + int len; | |
| 1145 | + | |
| 1146 | + if (PyString_Check(value)) { | |
| 1147 | + value = PyUnicode_FromEncodedObject(value, | |
| 1148 | + conversion_mode_encoding, | |
| 1149 | + conversion_mode_errors); | |
| 1150 | + if (!value) | |
| 1151 | + return NULL; | |
| 1152 | + } else if (!PyUnicode_Check(value)) { | |
| 1153 | + PyErr_Format(PyExc_TypeError, | |
| 1154 | + "unicode string expected instead of %s instance", | |
| 1155 | + value->ob_type->tp_name); | |
| 1156 | + return NULL; | |
| 1157 | + } else | |
| 1158 | + Py_INCREF(value); | |
| 1159 | + | |
| 1160 | + len = PyUnicode_GET_SIZE(value); | |
| 1161 | + if (len != 1) { | |
| 1162 | + Py_DECREF(value); | |
| 1163 | + PyErr_SetString(PyExc_TypeError, | |
| 1164 | + "one character unicode string expected"); | |
| 1165 | + return NULL; | |
| 1166 | + } | |
| 1167 | + | |
| 1168 | + *(wchar_t *)ptr = PyUnicode_AS_UNICODE(value)[0]; | |
| 1169 | + Py_DECREF(value); | |
| 1170 | + | |
| 1171 | + _RET(value); | |
| 1172 | +} | |
| 1173 | + | |
| 1174 | + | |
| 1175 | +static PyObject * | |
| 1176 | +u_get(void *ptr, unsigned size) | |
| 1177 | +{ | |
| 1178 | + return PyUnicode_FromWideChar((wchar_t *)ptr, 1); | |
| 1179 | +} | |
| 1180 | + | |
| 1181 | +/* U - a unicode string */ | |
| 1182 | +static PyObject * | |
| 1183 | +U_get(void *ptr, unsigned size) | |
| 1184 | +{ | |
| 1185 | + PyObject *result; | |
| 1186 | + unsigned int len; | |
| 1187 | + Py_UNICODE *p; | |
| 1188 | + | |
| 1189 | + size /= sizeof(wchar_t); /* we count character units here, not bytes */ | |
| 1190 | + | |
| 1191 | + result = PyUnicode_FromWideChar((wchar_t *)ptr, size); | |
| 1192 | + if (!result) | |
| 1193 | + return NULL; | |
| 1194 | + /* We need 'result' to be able to count the characters with wcslen, | |
| 1195 | + since ptr may not be NUL terminated. If the length is smaller (if | |
| 1196 | + it was actually NUL terminated, we construct a new one and throw | |
| 1197 | + away the result. | |
| 1198 | + */ | |
| 1199 | + /* chop off at the first NUL character, if any. */ | |
| 1200 | + p = PyUnicode_AS_UNICODE(result); | |
| 1201 | + for (len = 0; len < size; ++len) | |
| 1202 | + if (!p[len]) | |
| 1203 | + break; | |
| 1204 | + | |
| 1205 | + if (len < size) { | |
| 1206 | + PyObject *ob = PyUnicode_FromWideChar((wchar_t *)ptr, len); | |
| 1207 | + Py_DECREF(result); | |
| 1208 | + return ob; | |
| 1209 | + } | |
| 1210 | + return result; | |
| 1211 | +} | |
| 1212 | + | |
| 1213 | +static PyObject * | |
| 1214 | +U_set(void *ptr, PyObject *value, unsigned length) | |
| 1215 | +{ | |
| 1216 | + unsigned int size; | |
| 1217 | + | |
| 1218 | + /* It's easier to calculate in characters than in bytes */ | |
| 1219 | + length /= sizeof(wchar_t); | |
| 1220 | + | |
| 1221 | + if (PyString_Check(value)) { | |
| 1222 | + value = PyUnicode_FromEncodedObject(value, | |
| 1223 | + conversion_mode_encoding, | |
| 1224 | + conversion_mode_errors); | |
| 1225 | + if (!value) | |
| 1226 | + return NULL; | |
| 1227 | + } else if (!PyUnicode_Check(value)) { | |
| 1228 | + PyErr_Format(PyExc_TypeError, | |
| 1229 | + "unicode string expected instead of %s instance", | |
| 1230 | + value->ob_type->tp_name); | |
| 1231 | + return NULL; | |
| 1232 | + } else | |
| 1233 | + Py_INCREF(value); | |
| 1234 | + size = PyUnicode_GET_SIZE(value); | |
| 1235 | + if (size > length) { | |
| 1236 | + PyErr_Format(PyExc_ValueError, | |
| 1237 | + "string too long (%d, maximum length %d)", | |
| 1238 | + size, length); | |
| 1239 | + Py_DECREF(value); | |
| 1240 | + return NULL; | |
| 1241 | + } else if (size < length-1) | |
| 1242 | + /* copy terminating NUL character if there is space */ | |
| 1243 | + size += 1; | |
| 1244 | + PyUnicode_AsWideChar((PyUnicodeObject *)value, (wchar_t *)ptr, size); | |
| 1245 | + return value; | |
| 1246 | +} | |
| 1247 | + | |
| 1248 | +#endif | |
| 1249 | + | |
| 1250 | +static PyObject * | |
| 1251 | +s_get(void *ptr, unsigned size) | |
| 1252 | +{ | |
| 1253 | + PyObject *result; | |
| 1254 | + | |
| 1255 | + result = PyString_FromString((char *)ptr); | |
| 1256 | + if (!result) | |
| 1257 | + return NULL; | |
| 1258 | + /* chop off at the first NUL character, if any. | |
| 1259 | + * On error, result will be deallocated and set to NULL. | |
| 1260 | + */ | |
| 1261 | + size = min(size, strlen(PyString_AS_STRING(result))); | |
| 1262 | + if (result->ob_refcnt == 1) { | |
| 1263 | + /* shorten the result */ | |
| 1264 | + _PyString_Resize(&result, size); | |
| 1265 | + return result; | |
| 1266 | + } else | |
| 1267 | + /* cannot shorten the result */ | |
| 1268 | + return PyString_FromStringAndSize(ptr, size); | |
| 1269 | +} | |
| 1270 | + | |
| 1271 | +static PyObject * | |
| 1272 | +s_set(void *ptr, PyObject *value, unsigned length) | |
| 1273 | +{ | |
| 1274 | + char *data; | |
| 1275 | + unsigned size; | |
| 1276 | + | |
| 1277 | + data = PyString_AsString(value); | |
| 1278 | + if (!data) | |
| 1279 | + return NULL; | |
| 1280 | + size = strlen(data); | |
| 1281 | + if (size < length) { | |
| 1282 | + /* This will copy the leading NUL character | |
| 1283 | + * if there is space for it. | |
| 1284 | + */ | |
| 1285 | + ++size; | |
| 1286 | + } else if (size > length) { | |
| 1287 | + PyErr_Format(PyExc_ValueError, | |
| 1288 | + "string too long (%d, maximum length %d)", | |
| 1289 | + size, length); | |
| 1290 | + return NULL; | |
| 1291 | + } | |
| 1292 | + /* Also copy the terminating NUL character if there is space */ | |
| 1293 | + memcpy((char *)ptr, data, size); | |
| 1294 | + _RET(value); | |
| 1295 | +} | |
| 1296 | + | |
| 1297 | +static PyObject * | |
| 1298 | +z_set(void *ptr, PyObject *value, unsigned size) | |
| 1299 | +{ | |
| 1300 | + if (value == Py_None) { | |
| 1301 | + *(char **)ptr = NULL; | |
| 1302 | + Py_INCREF(value); | |
| 1303 | + return value; | |
| 1304 | + } | |
| 1305 | + if (PyString_Check(value)) { | |
| 1306 | + *(char **)ptr = PyString_AS_STRING(value); | |
| 1307 | + Py_INCREF(value); | |
| 1308 | + return value; | |
| 1309 | + } else if (PyUnicode_Check(value)) { | |
| 1310 | + PyObject *str = PyUnicode_AsEncodedString(value, | |
| 1311 | + conversion_mode_encoding, | |
| 1312 | + conversion_mode_errors); | |
| 1313 | + if (str == NULL) | |
| 1314 | + return NULL; | |
| 1315 | + *(char **)ptr = PyString_AS_STRING(str); | |
| 1316 | + return str; | |
| 1317 | + } else if (PyInt_Check(value) || PyLong_Check(value)) { | |
| 1318 | + *(char **)ptr = (char *)PyInt_AsUnsignedLongMask(value); | |
| 1319 | + _RET(value); | |
| 1320 | + } | |
| 1321 | + PyErr_Format(PyExc_TypeError, | |
| 1322 | + "string or integer address expected instead of %s instance", | |
| 1323 | + value->ob_type->tp_name); | |
| 1324 | + return NULL; | |
| 1325 | +} | |
| 1326 | + | |
| 1327 | +static PyObject * | |
| 1328 | +z_get(void *ptr, unsigned size) | |
| 1329 | +{ | |
| 1330 | + /* XXX What about invalid pointers ??? */ | |
| 1331 | + if (*(void **)ptr) { | |
| 1332 | +#if defined(MS_WIN32) && !defined(_WIN32_WCE) | |
| 1333 | + if (IsBadStringPtrA(*(char **)ptr, -1)) { | |
| 1334 | + PyErr_Format(PyExc_ValueError, | |
| 1335 | + "invalid string pointer %p", | |
| 1336 | + ptr); | |
| 1337 | + return NULL; | |
| 1338 | + } | |
| 1339 | +#endif | |
| 1340 | + return PyString_FromString(*(char **)ptr); | |
| 1341 | + } else { | |
| 1342 | + Py_INCREF(Py_None); | |
| 1343 | + return Py_None; | |
| 1344 | + } | |
| 1345 | +} | |
| 1346 | + | |
| 1347 | +#ifdef CTYPES_UNICODE | |
| 1348 | +static PyObject * | |
| 1349 | +Z_set(void *ptr, PyObject *value, unsigned size) | |
| 1350 | +{ | |
| 1351 | + if (value == Py_None) { | |
| 1352 | + *(wchar_t **)ptr = NULL; | |
| 1353 | + Py_INCREF(value); | |
| 1354 | + return value; | |
| 1355 | + } | |
| 1356 | + if (PyString_Check(value)) { | |
| 1357 | + value = PyUnicode_FromEncodedObject(value, | |
| 1358 | + conversion_mode_encoding, | |
| 1359 | + conversion_mode_errors); | |
| 1360 | + if (!value) | |
| 1361 | + return NULL; | |
| 1362 | + } else if (PyInt_Check(value) || PyLong_Check(value)) { | |
| 1363 | + *(wchar_t **)ptr = (wchar_t *)PyInt_AsUnsignedLongMask(value); | |
| 1364 | + Py_INCREF(Py_None); | |
| 1365 | + return Py_None; | |
| 1366 | + } else if (!PyUnicode_Check(value)) { | |
| 1367 | + PyErr_Format(PyExc_TypeError, | |
| 1368 | + "unicode string or integer address expected instead of %s instance", | |
| 1369 | + value->ob_type->tp_name); | |
| 1370 | + return NULL; | |
| 1371 | + } else | |
| 1372 | + Py_INCREF(value); | |
| 1373 | +#ifdef HAVE_USABLE_WCHAR_T | |
| 1374 | + /* HAVE_USABLE_WCHAR_T means that Py_UNICODE and wchar_t is the same | |
| 1375 | + type. So we can copy directly. Hm, are unicode objects always NUL | |
| 1376 | + terminated in Python, internally? | |
| 1377 | + */ | |
| 1378 | + *(wchar_t **)ptr = PyUnicode_AS_UNICODE(value); | |
| 1379 | + return value; | |
| 1380 | +#else | |
| 1381 | + { | |
| 1382 | + /* We must create a wchar_t* buffer from the unicode object, | |
| 1383 | + and keep it alive */ | |
| 1384 | + PyObject *keep; | |
| 1385 | + wchar_t *buffer; | |
| 1386 | + | |
| 1387 | + int size = PyUnicode_GET_SIZE(value); | |
| 1388 | + size += 1; /* terminating NUL */ | |
| 1389 | + size *= sizeof(wchar_t); | |
| 1390 | + buffer = (wchar_t *)PyMem_Malloc(size); | |
| 1391 | + if (!buffer) | |
| 1392 | + return NULL; | |
| 1393 | + memset(buffer, 0, size); | |
| 1394 | + keep = PyCObject_FromVoidPtr(buffer, PyMem_Free); | |
| 1395 | + if (!keep) { | |
| 1396 | + PyMem_Free(buffer); | |
| 1397 | + return NULL; | |
| 1398 | + } | |
| 1399 | + *(wchar_t **)ptr = (wchar_t *)buffer; | |
| 1400 | + if (-1 == PyUnicode_AsWideChar((PyUnicodeObject *)value, | |
| 1401 | + buffer, PyUnicode_GET_SIZE(value))) { | |
| 1402 | + Py_DECREF(value); | |
| 1403 | + Py_DECREF(keep); | |
| 1404 | + return NULL; | |
| 1405 | + } | |
| 1406 | + Py_DECREF(value); | |
| 1407 | + return keep; | |
| 1408 | + } | |
| 1409 | +#endif | |
| 1410 | +} | |
| 1411 | + | |
| 1412 | +static PyObject * | |
| 1413 | +Z_get(void *ptr, unsigned size) | |
| 1414 | +{ | |
| 1415 | + wchar_t *p; | |
| 1416 | + p = *(wchar_t **)ptr; | |
| 1417 | + if (p) | |
| 1418 | + return PyUnicode_FromWideChar(p, wcslen(p)); | |
| 1419 | + else { | |
| 1420 | + Py_INCREF(Py_None); | |
| 1421 | + return Py_None; | |
| 1422 | + } | |
| 1423 | +} | |
| 1424 | +#endif | |
| 1425 | + | |
| 1426 | +#ifdef MS_WIN32 | |
| 1427 | +static PyObject * | |
| 1428 | +BSTR_set(void *ptr, PyObject *value, unsigned size) | |
| 1429 | +{ | |
| 1430 | + BSTR bstr; | |
| 1431 | + | |
| 1432 | + /* convert value into a PyUnicodeObject or NULL */ | |
| 1433 | + if (Py_None == value) { | |
| 1434 | + value = NULL; | |
| 1435 | + } else if (PyString_Check(value)) { | |
| 1436 | + value = PyUnicode_FromEncodedObject(value, | |
| 1437 | + conversion_mode_encoding, | |
| 1438 | + conversion_mode_errors); | |
| 1439 | + if (!value) | |
| 1440 | + return NULL; | |
| 1441 | + } else if (PyUnicode_Check(value)) { | |
| 1442 | + Py_INCREF(value); /* for the descref below */ | |
| 1443 | + } else { | |
| 1444 | + PyErr_Format(PyExc_TypeError, | |
| 1445 | + "unicode string expected instead of %s instance", | |
| 1446 | + value->ob_type->tp_name); | |
| 1447 | + return NULL; | |
| 1448 | + } | |
| 1449 | + | |
| 1450 | + /* create a BSTR from value */ | |
| 1451 | + if (value) { | |
| 1452 | + bstr = SysAllocStringLen(PyUnicode_AS_UNICODE(value), | |
| 1453 | + PyUnicode_GET_SIZE(value)); | |
| 1454 | + Py_DECREF(value); | |
| 1455 | + } else | |
| 1456 | + bstr = NULL; | |
| 1457 | + | |
| 1458 | + /* free the previous contents, if any */ | |
| 1459 | + if (*(BSTR *)ptr) | |
| 1460 | + SysFreeString(*(BSTR *)ptr); | |
| 1461 | + | |
| 1462 | + /* and store it */ | |
| 1463 | + *(BSTR *)ptr = bstr; | |
| 1464 | + | |
| 1465 | + /* We don't need to keep any other object */ | |
| 1466 | + _RET(value); | |
| 1467 | +} | |
| 1468 | + | |
| 1469 | + | |
| 1470 | +static PyObject * | |
| 1471 | +BSTR_get(void *ptr, unsigned size) | |
| 1472 | +{ | |
| 1473 | + BSTR p; | |
| 1474 | + p = *(BSTR *)ptr; | |
| 1475 | + if (p) | |
| 1476 | + return PyUnicode_FromWideChar(p, SysStringLen(p)); | |
| 1477 | + else { | |
| 1478 | + /* Hm, it seems NULL pointer and zero length string are the | |
| 1479 | + same in BSTR, see Don Box, p 81 | |
| 1480 | + */ | |
| 1481 | + Py_INCREF(Py_None); | |
| 1482 | + return Py_None; | |
| 1483 | + } | |
| 1484 | +} | |
| 1485 | +#endif | |
| 1486 | + | |
| 1487 | +static PyObject * | |
| 1488 | +P_set(void *ptr, PyObject *value, unsigned size) | |
| 1489 | +{ | |
| 1490 | + void *v; | |
| 1491 | + if (value == Py_None) { | |
| 1492 | + *(void **)ptr = NULL; | |
| 1493 | + _RET(value); | |
| 1494 | + } | |
| 1495 | + | |
| 1496 | + if (!PyInt_Check(value) && !PyLong_Check(value)) { | |
| 1497 | + PyErr_SetString(PyExc_TypeError, | |
| 1498 | + "cannot be converted to pointer"); | |
| 1499 | + return NULL; | |
| 1500 | + } | |
| 1501 | + | |
| 1502 | +#if SIZEOF_VOID_P <= SIZEOF_LONG | |
| 1503 | + v = (void *)PyInt_AsUnsignedLongMask(value); | |
| 1504 | +#else | |
| 1505 | +#ifndef HAVE_LONG_LONG | |
| 1506 | +# error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long" | |
| 1507 | +#elif SIZEOF_LONG_LONG < SIZEOF_VOID_P | |
| 1508 | +# error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)" | |
| 1509 | +#endif | |
| 1510 | + v = (void *)PyInt_AsUnsignedLongLongMask(value); | |
| 1511 | +#endif | |
| 1512 | + | |
| 1513 | + if (PyErr_Occurred()) | |
| 1514 | + return NULL; | |
| 1515 | + | |
| 1516 | + *(void **)ptr = v; | |
| 1517 | + _RET(value); | |
| 1518 | +} | |
| 1519 | + | |
| 1520 | +static PyObject * | |
| 1521 | +P_get(void *ptr, unsigned size) | |
| 1522 | +{ | |
| 1523 | + if (*(void **)ptr == NULL) { | |
| 1524 | + Py_INCREF(Py_None); | |
| 1525 | + return Py_None; | |
| 1526 | + } | |
| 1527 | + return PyLong_FromVoidPtr(*(void **)ptr); | |
| 1528 | +} | |
| 1529 | + | |
| 1530 | +static struct fielddesc formattable[] = { | |
| 1531 | + { 's', s_set, s_get, &ffi_type_pointer}, | |
| 1532 | + { 'b', b_set, b_get, &ffi_type_schar}, | |
| 1533 | + { 'B', B_set, B_get, &ffi_type_uchar}, | |
| 1534 | + { 'c', c_set, c_get, &ffi_type_schar}, | |
| 1535 | + { 'd', d_set, d_get, &ffi_type_double, d_set_sw, d_get_sw}, | |
| 1536 | + { 'f', f_set, f_get, &ffi_type_float, f_set_sw, f_get_sw}, | |
| 1537 | + { 'h', h_set, h_get, &ffi_type_sshort, h_set_sw, h_get_sw}, | |
| 1538 | + { 'H', H_set, H_get, &ffi_type_ushort, H_set_sw, H_get_sw}, | |
| 1539 | + { 'i', i_set, i_get, &ffi_type_sint, i_set_sw, i_get_sw}, | |
| 1540 | + { 'I', I_set, I_get, &ffi_type_uint, I_set_sw, I_get_sw}, | |
| 1541 | +/* XXX Hm, sizeof(int) == sizeof(long) doesn't hold on every platform */ | |
| 1542 | +/* As soon as we can get rid of the type codes, this is no longer a problem */ | |
| 1543 | +#if SIZEOF_LONG == 4 | |
| 1544 | + { 'l', l_set, l_get, &ffi_type_sint, l_set_sw, l_get_sw}, | |
| 1545 | + { 'L', L_set, L_get, &ffi_type_uint, L_set_sw, L_get_sw}, | |
| 1546 | +#elif SIZEOF_LONG == 8 | |
| 1547 | + { 'l', l_set, l_get, &ffi_type_slong, l_set_sw, l_get_sw}, | |
| 1548 | + { 'L', L_set, L_get, &ffi_type_ulong, L_set_sw, L_get_sw}, | |
| 1549 | +#else | |
| 1550 | +# error | |
| 1551 | +#endif | |
| 1552 | +#ifdef HAVE_LONG_LONG | |
| 1553 | + { 'q', q_set, q_get, &ffi_type_slong, q_set_sw, q_get_sw}, | |
| 1554 | + { 'Q', Q_set, Q_get, &ffi_type_ulong, Q_set_sw, Q_get_sw}, | |
| 1555 | +#endif | |
| 1556 | + { 'P', P_set, P_get, &ffi_type_pointer}, | |
| 1557 | + { 'z', z_set, z_get, &ffi_type_pointer}, | |
| 1558 | +#ifdef CTYPES_UNICODE | |
| 1559 | + { 'u', u_set, u_get, NULL}, /* ffi_type set later */ | |
| 1560 | + { 'U', U_set, U_get, &ffi_type_pointer}, | |
| 1561 | + { 'Z', Z_set, Z_get, &ffi_type_pointer}, | |
| 1562 | +#endif | |
| 1563 | +#ifdef MS_WIN32 | |
| 1564 | + { 'X', BSTR_set, BSTR_get, &ffi_type_pointer}, | |
| 1565 | + { 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort}, | |
| 1566 | +#endif | |
| 1567 | + { 'O', O_set, O_get, &ffi_type_pointer}, | |
| 1568 | + { 0, NULL, NULL, NULL}, | |
| 1569 | +}; | |
| 1570 | + | |
| 1571 | +/* | |
| 1572 | + Ideas: Implement VARIANT in this table, using 'V' code. | |
| 1573 | + Use '?' as code for BOOL. | |
| 1574 | +*/ | |
| 1575 | + | |
| 1576 | +struct fielddesc * | |
| 1577 | +getentry(char *fmt) | |
| 1578 | +{ | |
| 1579 | + static int initialized = 0; | |
| 1580 | + struct fielddesc *table = formattable; | |
| 1581 | + | |
| 1582 | + if (!initialized) { | |
| 1583 | + initialized = 1; | |
| 1584 | +#ifdef CTYPES_UNICODE | |
| 1585 | + if (sizeof(wchar_t) == sizeof(short)) | |
| 1586 | + getentry("u")->pffi_type = &ffi_type_sshort; | |
| 1587 | + else if (sizeof(wchar_t) == sizeof(int)) | |
| 1588 | + getentry("u")->pffi_type = &ffi_type_sint; | |
| 1589 | + else if (sizeof(wchar_t) == sizeof(long)) | |
| 1590 | + getentry("u")->pffi_type = &ffi_type_slong; | |
| 1591 | +#endif | |
| 1592 | + } | |
| 1593 | + | |
| 1594 | + for (; table->code; ++table) { | |
| 1595 | + if (table->code == fmt[0]) | |
| 1596 | + return table; | |
| 1597 | + } | |
| 1598 | + return NULL; | |
| 1599 | +} | |
| 1600 | + | |
| 1601 | +typedef struct { char c; char x; } s_char; | |
| 1602 | +typedef struct { char c; short x; } s_short; | |
| 1603 | +typedef struct { char c; int x; } s_int; | |
| 1604 | +typedef struct { char c; long x; } s_long; | |
| 1605 | +typedef struct { char c; float x; } s_float; | |
| 1606 | +typedef struct { char c; double x; } s_double; | |
| 1607 | +typedef struct { char c; char *x; } s_char_p; | |
| 1608 | +typedef struct { char c; void *x; } s_void_p; | |
| 1609 | + | |
| 1610 | +/* | |
| 1611 | +#define CHAR_ALIGN (sizeof(s_char) - sizeof(char)) | |
| 1612 | +#define SHORT_ALIGN (sizeof(s_short) - sizeof(short)) | |
| 1613 | +#define INT_ALIGN (sizeof(s_int) - sizeof(int)) | |
| 1614 | +#define LONG_ALIGN (sizeof(s_long) - sizeof(long)) | |
| 1615 | +*/ | |
| 1616 | +#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float)) | |
| 1617 | +#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double)) | |
| 1618 | +/* #define CHAR_P_ALIGN (sizeof(s_char_p) - sizeof(char*)) */ | |
| 1619 | +#define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void*)) | |
| 1620 | + | |
| 1621 | +/* | |
| 1622 | +#ifdef HAVE_USABLE_WCHAR_T | |
| 1623 | +typedef struct { char c; wchar_t x; } s_wchar; | |
| 1624 | +typedef struct { char c; wchar_t *x; } s_wchar_p; | |
| 1625 | + | |
| 1626 | +#define WCHAR_ALIGN (sizeof(s_wchar) - sizeof(wchar_t)) | |
| 1627 | +#define WCHAR_P_ALIGN (sizeof(s_wchar_p) - sizeof(wchar_t*)) | |
| 1628 | +#endif | |
| 1629 | +*/ | |
| 1630 | + | |
| 1631 | +#ifdef HAVE_LONG_LONG | |
| 1632 | +typedef struct { char c; PY_LONG_LONG x; } s_long_long; | |
| 1633 | +#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG)) | |
| 1634 | +#endif | |
| 1635 | + | |
| 1636 | +/* from ffi.h: | |
| 1637 | +typedef struct _ffi_type | |
| 1638 | +{ | |
| 1639 | + size_t size; | |
| 1640 | + unsigned short alignment; | |
| 1641 | + unsigned short type; | |
| 1642 | + struct _ffi_type **elements; | |
| 1643 | +} ffi_type; | |
| 1644 | +*/ | |
| 1645 | + | |
| 1646 | +/* align and size are bogus for void, but they must not be zero */ | |
| 1647 | +ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID }; | |
| 1648 | + | |
| 1649 | +ffi_type ffi_type_uint8 = { 1, 1, FFI_TYPE_UINT8 }; | |
| 1650 | +ffi_type ffi_type_sint8 = { 1, 1, FFI_TYPE_SINT8 }; | |
| 1651 | + | |
| 1652 | +ffi_type ffi_type_uint16 = { 2, 2, FFI_TYPE_UINT16 }; | |
| 1653 | +ffi_type ffi_type_sint16 = { 2, 2, FFI_TYPE_SINT16 }; | |
| 1654 | + | |
| 1655 | +ffi_type ffi_type_uint32 = { 4, 4, FFI_TYPE_UINT32 }; | |
| 1656 | +ffi_type ffi_type_sint32 = { 4, 4, FFI_TYPE_SINT32 }; | |
| 1657 | + | |
| 1658 | +ffi_type ffi_type_uint64 = { 8, LONG_LONG_ALIGN, FFI_TYPE_UINT64 }; | |
| 1659 | +ffi_type ffi_type_sint64 = { 8, LONG_LONG_ALIGN, FFI_TYPE_SINT64 }; | |
| 1660 | + | |
| 1661 | +ffi_type ffi_type_float = { sizeof(float), FLOAT_ALIGN, FFI_TYPE_FLOAT }; | |
| 1662 | +ffi_type ffi_type_double = { sizeof(double), DOUBLE_ALIGN, FFI_TYPE_DOUBLE }; | |
| 1663 | + | |
| 1664 | +/* ffi_type ffi_type_longdouble */ | |
| 1665 | + | |
| 1666 | +ffi_type ffi_type_pointer = { sizeof(void *), VOID_P_ALIGN, FFI_TYPE_POINTER }; | |
| 1667 | + | |
| 1668 | +/*---------------- EOF ----------------*/ | |
| @@ -0,0 +1,407 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | +#if (PY_VERSION_HEX < 0x02050000) | |
| 6 | +typedef int Py_ssize_t; | |
| 7 | +#endif | |
| 8 | + | |
| 9 | +#ifndef MS_WIN32 | |
| 10 | +#define max(a, b) ((a) > (b) ? (a) : (b)) | |
| 11 | +#define min(a, b) ((a) < (b) ? (a) : (b)) | |
| 12 | + | |
| 13 | +#define PARAMFLAG_FIN 0x1 | |
| 14 | +#define PARAMFLAG_FOUT 0x2 | |
| 15 | +#define PARAMFLAG_FLCID 0x4 | |
| 16 | +#endif | |
| 17 | + | |
| 18 | +/* | |
| 19 | + Backwards compatibility: | |
| 20 | + Python2.2 used LONG_LONG instead of PY_LONG_LONG | |
| 21 | +*/ | |
| 22 | +#if defined(HAVE_LONG_LONG) && !defined(PY_LONG_LONG) | |
| 23 | +#define PY_LONG_LONG LONG_LONG | |
| 24 | +#endif | |
| 25 | + | |
| 26 | +typedef struct tagPyCArgObject PyCArgObject; | |
| 27 | +typedef struct tagCDataObject CDataObject; | |
| 28 | +typedef PyObject *(* GETFUNC)(void *, unsigned size); | |
| 29 | +typedef PyObject *(* SETFUNC)(void *, PyObject *value, unsigned size); | |
| 30 | +typedef PyCArgObject *(* PARAMFUNC)(CDataObject *obj); | |
| 31 | + | |
| 32 | +/* A default buffer in CDataObject, which can be used for small C types. If | |
| 33 | +this buffer is too small, PyMem_Malloc will be called to create a larger one, | |
| 34 | +and this one is not used. | |
| 35 | + | |
| 36 | +Making CDataObject a variable size object would be a better solution, but more | |
| 37 | +difficult in the presence of CFuncPtrObject. Maybe later. | |
| 38 | +*/ | |
| 39 | +union value { | |
| 40 | + char c[16]; | |
| 41 | + short s; | |
| 42 | + int i; | |
| 43 | + long l; | |
| 44 | + float f; | |
| 45 | + double d; | |
| 46 | +#ifdef HAVE_LONG_LONG | |
| 47 | + PY_LONG_LONG ll; | |
| 48 | +#endif | |
| 49 | +}; | |
| 50 | + | |
| 51 | +/* | |
| 52 | + Hm. Are there CDataObject's which do not need the b_objects member? In | |
| 53 | + this case we probably should introduce b_flags to mark it as present... If | |
| 54 | + b_objects is not present/unused b_length is unneeded as well. | |
| 55 | +*/ | |
| 56 | + | |
| 57 | +struct tagCDataObject { | |
| 58 | + PyObject_HEAD | |
| 59 | + char *b_ptr; /* pointer to memory block */ | |
| 60 | + int b_needsfree; /* need _we_ free the memory? */ | |
| 61 | + CDataObject *b_base; /* pointer to base object or NULL */ | |
| 62 | + Py_ssize_t b_size; /* size of memory block in bytes */ | |
| 63 | + Py_ssize_t b_length; /* number of references we need */ | |
| 64 | + Py_ssize_t b_index; /* index of this object into base's | |
| 65 | + b_object list */ | |
| 66 | + PyObject *b_objects; /* dictionary of references we need to keep, or Py_None */ | |
| 67 | + union value b_value; | |
| 68 | +}; | |
| 69 | + | |
| 70 | +typedef struct { | |
| 71 | + ffi_closure *pcl; /* the C callable */ | |
| 72 | + ffi_cif cif; | |
| 73 | + PyObject *converters; | |
| 74 | + PyObject *callable; | |
| 75 | + SETFUNC setfunc; | |
| 76 | + ffi_type *restype; | |
| 77 | + ffi_type *atypes[0]; | |
| 78 | +} ffi_info; | |
| 79 | + | |
| 80 | +typedef struct { | |
| 81 | + /* First part identical to tagCDataObject */ | |
| 82 | + PyObject_HEAD | |
| 83 | + char *b_ptr; /* pointer to memory block */ | |
| 84 | + int b_needsfree; /* need _we_ free the memory? */ | |
| 85 | + CDataObject *b_base; /* pointer to base object or NULL */ | |
| 86 | + Py_ssize_t b_size; /* size of memory block in bytes */ | |
| 87 | + Py_ssize_t b_length; /* number of references we need */ | |
| 88 | + Py_ssize_t b_index; /* index of this object into base's | |
| 89 | + b_object list */ | |
| 90 | + PyObject *b_objects; /* list of references we need to keep */ | |
| 91 | + union value b_value; | |
| 92 | + /* end of tagCDataObject, additional fields follow */ | |
| 93 | + | |
| 94 | + ffi_info *thunk; | |
| 95 | + PyObject *callable; | |
| 96 | + | |
| 97 | + /* These two fields will override the ones in the type's stgdict if | |
| 98 | + they are set */ | |
| 99 | + PyObject *converters; | |
| 100 | + PyObject *argtypes; | |
| 101 | + PyObject *restype; | |
| 102 | + PyObject *checker; | |
| 103 | + PyObject *errcheck; | |
| 104 | +#ifdef MS_WIN32 | |
| 105 | + int index; | |
| 106 | + GUID *iid; | |
| 107 | +#endif | |
| 108 | + PyObject *paramflags; | |
| 109 | +} CFuncPtrObject; | |
| 110 | + | |
| 111 | +extern PyTypeObject StgDict_Type; | |
| 112 | +#define StgDict_CheckExact(v) ((v)->ob_type == &StgDict_Type) | |
| 113 | +#define StgDict_Check(v) PyObject_TypeCheck(v, &StgDict_Type) | |
| 114 | + | |
| 115 | +extern int StructUnionType_update_stgdict(PyObject *fields, PyObject *type, int isStruct); | |
| 116 | +extern int PyType_stginfo(PyTypeObject *self, Py_ssize_t *psize, Py_ssize_t *palign, Py_ssize_t *plength); | |
| 117 | +extern int PyObject_stginfo(PyObject *self, Py_ssize_t *psize, Py_ssize_t *palign, Py_ssize_t *plength); | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | +extern PyTypeObject CData_Type; | |
| 122 | +#define CDataObject_CheckExact(v) ((v)->ob_type == &CData_Type) | |
| 123 | +#define CDataObject_Check(v) PyObject_TypeCheck(v, &CData_Type) | |
| 124 | + | |
| 125 | +extern PyTypeObject SimpleType_Type; | |
| 126 | +#define SimpleTypeObject_CheckExact(v) ((v)->ob_type == &SimpleType_Type) | |
| 127 | +#define SimpleTypeObject_Check(v) PyObject_TypeCheck(v, &SimpleType_Type) | |
| 128 | + | |
| 129 | +extern PyTypeObject CField_Type; | |
| 130 | +extern struct fielddesc *getentry(char *fmt); | |
| 131 | + | |
| 132 | + | |
| 133 | +extern PyObject * | |
| 134 | +CField_FromDesc(PyObject *desc, int index, | |
| 135 | + int *pfield_size, int bitsize, int *pbitofs, | |
| 136 | + int *psize, int *poffset, int *palign, | |
| 137 | + int pack, int is_big_endian); | |
| 138 | + | |
| 139 | +extern PyObject *CData_AtAddress(PyObject *type, void *buf); | |
| 140 | +extern PyObject *CData_FromBytes(PyObject *type, char *data, Py_ssize_t length); | |
| 141 | + | |
| 142 | +extern PyTypeObject ArrayType_Type; | |
| 143 | +extern PyTypeObject Array_Type; | |
| 144 | +extern PyTypeObject PointerType_Type; | |
| 145 | +extern PyTypeObject Pointer_Type; | |
| 146 | +extern PyTypeObject CFuncPtr_Type; | |
| 147 | +extern PyTypeObject CFuncPtrType_Type; | |
| 148 | +extern PyTypeObject StructType_Type; | |
| 149 | + | |
| 150 | +#define ArrayTypeObject_Check(v) PyObject_TypeCheck(v, &ArrayType_Type) | |
| 151 | +#define ArrayObject_Check(v) PyObject_TypeCheck(v, &Array_Type) | |
| 152 | +#define PointerObject_Check(v) PyObject_TypeCheck(v, &Pointer_Type) | |
| 153 | +#define PointerTypeObject_Check(v) PyObject_TypeCheck(v, &PointerType_Type) | |
| 154 | +#define CFuncPtrObject_Check(v) PyObject_TypeCheck(v, &CFuncPtr_Type) | |
| 155 | +#define CFuncPtrTypeObject_Check(v) PyObject_TypeCheck(v, &CFuncPtrType_Type) | |
| 156 | +#define StructTypeObject_Check(v) PyObject_TypeCheck(v, &StructType_Type) | |
| 157 | + | |
| 158 | +extern PyObject * | |
| 159 | +CreateArrayType(PyObject *itemtype, Py_ssize_t length); | |
| 160 | + | |
| 161 | +extern void init_callbacks_in_module(PyObject *m); | |
| 162 | + | |
| 163 | +extern PyMethodDef module_methods[]; | |
| 164 | + | |
| 165 | +extern ffi_info *AllocFunctionCallback(PyObject *callable, | |
| 166 | + PyObject *converters, | |
| 167 | + PyObject *restype, | |
| 168 | + int stdcall); | |
| 169 | +/* a table entry describing a predefined ctypes type */ | |
| 170 | +struct fielddesc { | |
| 171 | + char code; | |
| 172 | + SETFUNC setfunc; | |
| 173 | + GETFUNC getfunc; | |
| 174 | + ffi_type *pffi_type; /* always statically allocated */ | |
| 175 | + SETFUNC setfunc_swapped; | |
| 176 | + GETFUNC getfunc_swapped; | |
| 177 | +}; | |
| 178 | + | |
| 179 | +typedef struct { | |
| 180 | + PyObject_HEAD | |
| 181 | + Py_ssize_t offset; | |
| 182 | + Py_ssize_t size; | |
| 183 | + Py_ssize_t index; /* Index into CDataObject's | |
| 184 | + object array */ | |
| 185 | + PyObject *proto; /* a type or NULL */ | |
| 186 | + GETFUNC getfunc; /* getter function if proto is NULL */ | |
| 187 | + SETFUNC setfunc; /* setter function if proto is NULL */ | |
| 188 | + int anonymous; | |
| 189 | +} CFieldObject; | |
| 190 | + | |
| 191 | +/* A subclass of PyDictObject, used as the instance dictionary of ctypes | |
| 192 | + metatypes */ | |
| 193 | +typedef struct { | |
| 194 | + PyDictObject dict; /* first part identical to PyDictObject */ | |
| 195 | +/* The size and align fields are unneeded, they are in ffi_type as well. As | |
| 196 | + an experiment shows, it's trivial to get rid of them, the only thing to | |
| 197 | + remember is that in ArrayType_new the ffi_type fields must be filled in - | |
| 198 | + so far it was unneeded because libffi doesn't support arrays at all | |
| 199 | + (because they are passed as pointers to function calls anyway). But it's | |
| 200 | + too much risk to change that now, and there are other fields which doen't | |
| 201 | + belong into this structure anyway. Maybe in ctypes 2.0... (ctypes 2000?) | |
| 202 | +*/ | |
| 203 | + Py_ssize_t size; /* number of bytes */ | |
| 204 | + Py_ssize_t align; /* alignment requirements */ | |
| 205 | + Py_ssize_t length; /* number of fields */ | |
| 206 | + ffi_type ffi_type_pointer; | |
| 207 | + PyObject *proto; /* Only for Pointer/ArrayObject */ | |
| 208 | + SETFUNC setfunc; /* Only for simple objects */ | |
| 209 | + GETFUNC getfunc; /* Only for simple objects */ | |
| 210 | + PARAMFUNC paramfunc; | |
| 211 | + | |
| 212 | + /* Following fields only used by CFuncPtrType_Type instances */ | |
| 213 | + PyObject *argtypes; /* tuple of CDataObjects */ | |
| 214 | + PyObject *converters; /* tuple([t.from_param for t in argtypes]) */ | |
| 215 | + PyObject *restype; /* CDataObject or NULL */ | |
| 216 | + PyObject *checker; | |
| 217 | + int flags; /* calling convention and such */ | |
| 218 | +} StgDictObject; | |
| 219 | + | |
| 220 | +/**************************************************************** | |
| 221 | + StgDictObject fields | |
| 222 | + | |
| 223 | + setfunc and getfunc is only set for simple data types, it is copied from the | |
| 224 | + corresponding fielddesc entry. These are functions to set and get the value | |
| 225 | + in a memory block. | |
| 226 | + They should probably by used by other types as well. | |
| 227 | + | |
| 228 | + proto is only used for Pointer and Array types - it points to the item type | |
| 229 | + object. | |
| 230 | + | |
| 231 | + Probably all the magic ctypes methods (like from_param) should have C | |
| 232 | + callable wrappers in the StgDictObject. For simple data type, for example, | |
| 233 | + the fielddesc table could have entries for C codec from_param functions or | |
| 234 | + other methods as well, if a subtype overrides this method in Python at | |
| 235 | + construction time, or assigns to it later, tp_setattro should update the | |
| 236 | + StgDictObject function to a generic one. | |
| 237 | + | |
| 238 | + Currently, CFuncPtr types have 'converters' and 'checker' entries in their | |
| 239 | + type dict. They are only used to cache attributes from other entries, whihc | |
| 240 | + is wrong. | |
| 241 | + | |
| 242 | + One use case is the .value attribute that all simple types have. But some | |
| 243 | + complex structures, like VARIANT, represent a single value also, and should | |
| 244 | + have this attribute. | |
| 245 | + | |
| 246 | + Another use case is a _check_retval_ function, which is called when a ctypes | |
| 247 | + type is used as return type of a function to validate and compute the return | |
| 248 | + value. | |
| 249 | + | |
| 250 | + Common ctypes protocol: | |
| 251 | + | |
| 252 | + - setfunc: store a python value in a memory block | |
| 253 | + - getfunc: convert data from a memory block into a python value | |
| 254 | + | |
| 255 | + - checkfunc: validate and convert a return value from a function call | |
| 256 | + - toparamfunc: convert a python value into a function argument | |
| 257 | + | |
| 258 | +*****************************************************************/ | |
| 259 | + | |
| 260 | +/* May return NULL, but does not set an exception! */ | |
| 261 | +extern StgDictObject *PyType_stgdict(PyObject *obj); | |
| 262 | + | |
| 263 | +/* May return NULL, but does not set an exception! */ | |
| 264 | +extern StgDictObject *PyObject_stgdict(PyObject *self); | |
| 265 | + | |
| 266 | +extern int StgDict_clone(StgDictObject *src, StgDictObject *dst); | |
| 267 | + | |
| 268 | +typedef int(* PPROC)(void); | |
| 269 | + | |
| 270 | +PyObject *_CallProc(PPROC pProc, | |
| 271 | + PyObject *arguments, | |
| 272 | +#ifdef MS_WIN32 | |
| 273 | + IUnknown *pIUnk, | |
| 274 | + GUID *iid, | |
| 275 | +#endif | |
| 276 | + int flags, | |
| 277 | + PyObject *argtypes, | |
| 278 | + PyObject *restype, | |
| 279 | + PyObject *checker); | |
| 280 | + | |
| 281 | + | |
| 282 | +#define FUNCFLAG_STDCALL 0x0 | |
| 283 | +#define FUNCFLAG_CDECL 0x1 | |
| 284 | +#define FUNCFLAG_HRESULT 0x2 | |
| 285 | +#define FUNCFLAG_PYTHONAPI 0x4 | |
| 286 | + | |
| 287 | +#define DICTFLAG_FINAL 0x1000 | |
| 288 | + | |
| 289 | +struct tagPyCArgObject { | |
| 290 | + PyObject_HEAD | |
| 291 | + ffi_type *pffi_type; | |
| 292 | + char tag; | |
| 293 | + union { | |
| 294 | + char c; | |
| 295 | + char b; | |
| 296 | + short h; | |
| 297 | + int i; | |
| 298 | + long l; | |
| 299 | +#ifdef HAVE_LONG_LONG | |
| 300 | + PY_LONG_LONG q; | |
| 301 | +#endif | |
| 302 | + double d; | |
| 303 | + float f; | |
| 304 | + void *p; | |
| 305 | + } value; | |
| 306 | + PyObject *obj; | |
| 307 | + int size; /* for the 'V' tag */ | |
| 308 | +}; | |
| 309 | + | |
| 310 | +extern PyTypeObject PyCArg_Type; | |
| 311 | +extern PyCArgObject *new_CArgObject(void); | |
| 312 | +#define PyCArg_CheckExact(v) ((v)->ob_type == &PyCArg_Type) | |
| 313 | +extern PyCArgObject *new_CArgObject(void); | |
| 314 | + | |
| 315 | +extern PyObject * | |
| 316 | +CData_get(PyObject *type, GETFUNC getfunc, PyObject *src, | |
| 317 | + Py_ssize_t index, Py_ssize_t size, char *ptr); | |
| 318 | + | |
| 319 | +extern int | |
| 320 | +CData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, | |
| 321 | + Py_ssize_t index, Py_ssize_t size, char *ptr); | |
| 322 | + | |
| 323 | +extern void Extend_Error_Info(PyObject *exc_class, char *fmt, ...); | |
| 324 | + | |
| 325 | +struct basespec { | |
| 326 | + CDataObject *base; | |
| 327 | + Py_ssize_t index; | |
| 328 | + char *adr; | |
| 329 | +}; | |
| 330 | + | |
| 331 | +extern char basespec_string[]; | |
| 332 | + | |
| 333 | +extern ffi_type *GetType(PyObject *obj); | |
| 334 | + | |
| 335 | +/* exception classes */ | |
| 336 | +extern PyObject *PyExc_ArgError; | |
| 337 | + | |
| 338 | +extern char *conversion_mode_encoding; | |
| 339 | +extern char *conversion_mode_errors; | |
| 340 | + | |
| 341 | +/* Python 2.4 macros, which are not available in Python 2.3 */ | |
| 342 | + | |
| 343 | +#ifndef Py_CLEAR | |
| 344 | +#define Py_CLEAR(op) \ | |
| 345 | + do { \ | |
| 346 | + if (op) { \ | |
| 347 | + PyObject *tmp = (PyObject *)(op); \ | |
| 348 | + (op) = NULL; \ | |
| 349 | + Py_DECREF(tmp); \ | |
| 350 | + } \ | |
| 351 | + } while (0) | |
| 352 | +#endif | |
| 353 | + | |
| 354 | +#ifndef Py_VISIT | |
| 355 | +/* Utility macro to help write tp_traverse functions. | |
| 356 | + * To use this macro, the tp_traverse function must name its arguments | |
| 357 | + * "visit" and "arg". This is intended to keep tp_traverse functions | |
| 358 | + * looking as much alike as possible. | |
| 359 | + */ | |
| 360 | +#define Py_VISIT(op) \ | |
| 361 | + do { \ | |
| 362 | + if (op) { \ | |
| 363 | + int vret = visit((op), arg); \ | |
| 364 | + if (vret) \ | |
| 365 | + return vret; \ | |
| 366 | + } \ | |
| 367 | + } while (0) | |
| 368 | +#endif | |
| 369 | + | |
| 370 | +/* Python's PyUnicode_*WideChar functions are broken ... */ | |
| 371 | +#if defined(Py_USING_UNICODE) && defined(HAVE_WCHAR_H) | |
| 372 | +# define CTYPES_UNICODE | |
| 373 | +#endif | |
| 374 | + | |
| 375 | + | |
| 376 | +#ifdef CTYPES_UNICODE | |
| 377 | +# undef PyUnicode_FromWideChar | |
| 378 | +# define PyUnicode_FromWideChar My_PyUnicode_FromWideChar | |
| 379 | + | |
| 380 | +# undef PyUnicode_AsWideChar | |
| 381 | +# define PyUnicode_AsWideChar My_PyUnicode_AsWideChar | |
| 382 | + | |
| 383 | +extern PyObject *My_PyUnicode_FromWideChar(const wchar_t *, Py_ssize_t); | |
| 384 | +extern int My_PyUnicode_AsWideChar(PyUnicodeObject *, wchar_t *, Py_ssize_t); | |
| 385 | + | |
| 386 | +#endif | |
| 387 | + | |
| 388 | +extern void FreeClosure(void *); | |
| 389 | +extern void *MallocClosure(void); | |
| 390 | + | |
| 391 | +extern void _AddTraceback(char *, char *, int); | |
| 392 | + | |
| 393 | +extern PyObject *CData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr); | |
| 394 | + | |
| 395 | +/* XXX better name needed! */ | |
| 396 | +extern int IsSimpleSubType(PyObject *obj); | |
| 397 | + | |
| 398 | + | |
| 399 | +#ifdef MS_WIN32 | |
| 400 | +extern PyObject *ComError; | |
| 401 | +#endif | |
| 402 | + | |
| 403 | +/* | |
| 404 | + Local Variables: | |
| 405 | + compile-command: "python setup.py -q build install --home ~" | |
| 406 | + End: | |
| 407 | +*/ | |
| @@ -0,0 +1,31 @@ | ||
| 1 | +/***************************************************************** | |
| 2 | + This file should be kept compatible with Python 2.3, see PEP 291. | |
| 3 | + *****************************************************************/ | |
| 4 | + | |
| 5 | +#ifndef _CTYPES_DLFCN_H_ | |
| 6 | +#define _CTYPES_DLFCN_H_ | |
| 7 | + | |
| 8 | +#ifdef __cplusplus | |
| 9 | +extern "C" { | |
| 10 | +#endif /* __cplusplus */ | |
| 11 | + | |
| 12 | +#ifndef MS_WIN32 | |
| 13 | + | |
| 14 | +#include <dlfcn.h> | |
| 15 | + | |
| 16 | +#ifndef CTYPES_DARWIN_DLFCN | |
| 17 | + | |
| 18 | +#define ctypes_dlsym dlsym | |
| 19 | +#define ctypes_dlerror dlerror | |
| 20 | +#define ctypes_dlopen dlopen | |
| 21 | +#define ctypes_dlclose dlclose | |
| 22 | +#define ctypes_dladdr dladdr | |
| 23 | + | |
| 24 | +#endif /* !CTYPES_DARWIN_DLFCN */ | |
| 25 | + | |
| 26 | +#endif /* !MS_WIN32 */ | |
| 27 | + | |
| 28 | +#ifdef __cplusplus | |
| 29 | +} | |
| 30 | +#endif /* __cplusplus */ | |
| 31 | +#endif /* _CTYPES_DLFCN_H_ */ | |
| @@ -0,0 +1,31 @@ | ||
| 1 | +Copyright (c) 2002 Jorge Acereda <jacereda@users.sourceforge.net> & | |
| 2 | + Peter O'Gorman <ogorman@users.sourceforge.net> | |
| 3 | + | |
| 4 | +Portions may be copyright others, see the AUTHORS file included with this | |
| 5 | +distribution. | |
| 6 | + | |
| 7 | +Maintained by Peter O'Gorman <ogorman@users.sourceforge.net> | |
| 8 | + | |
| 9 | +Bug Reports and other queries should go to <ogorman@users.sourceforge.net> | |
| 10 | + | |
| 11 | + | |
| 12 | +Permission is hereby granted, free of charge, to any person obtaining | |
| 13 | +a copy of this software and associated documentation files (the | |
| 14 | +"Software"), to deal in the Software without restriction, including | |
| 15 | +without limitation the rights to use, copy, modify, merge, publish, | |
| 16 | +distribute, sublicense, and/or sell copies of the Software, and to | |
| 17 | +permit persons to whom the Software is furnished to do so, subject to | |
| 18 | +the following conditions: | |
| 19 | + | |
| 20 | +The above copyright notice and this permission notice shall be | |
| 21 | +included in all copies or substantial portions of the Software. | |
| 22 | + | |
| 23 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 24 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 25 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 26 | +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| 27 | +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| 28 | +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| 29 | +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 30 | + | |
| 31 | + | |
| @@ -0,0 +1,95 @@ | ||
| 1 | +dlcompat for Darwin | |
| 2 | +========================= | |
| 3 | + | |
| 4 | +This is dlcompat, a small library that emulates the dlopen() | |
| 5 | +interface on top of Darwin's dyld API. | |
| 6 | + | |
| 7 | +dlcompat allows loading a ".dylib" library (as long as the RTLD_LOCAL | |
| 8 | +flag isn't passed to dlopen()). It can be configured to yield a warning | |
| 9 | +when trying to close it (dynamic libraries cannot currently be unloaded). | |
| 10 | + | |
| 11 | +It automatically searches for modules in several directories when no | |
| 12 | +absolute path is specified and the module is not found in the current | |
| 13 | +directory. | |
| 14 | + | |
| 15 | +The paths searched are those specified in the environment variables | |
| 16 | +LD_LIBRARY_PATH and DYLD_LIBRARY_PATH plus /lib, /usr/local/lib and | |
| 17 | +/usr/lib or the path specified in the environment variable | |
| 18 | +DYLD_FALLBACK_LIBRARY_PATH. | |
| 19 | + | |
| 20 | +In the default install the behavior of dlsym is to automatically prepend | |
| 21 | +an underscore to passed in symbol names, this allows easier porting of | |
| 22 | +applications which were written specifically for ELF based lifeforms. | |
| 23 | + | |
| 24 | +Installation | |
| 25 | +-------------- | |
| 26 | +Type: | |
| 27 | + ./configure | |
| 28 | + make | |
| 29 | + sudo make install | |
| 30 | + | |
| 31 | +This will compile the source file, generate both a static and shared | |
| 32 | +library called libdl and install it into /usr/local/lib. The header | |
| 33 | +file dlfcn.h will be installed in /usr/local/include. | |
| 34 | + | |
| 35 | +If you want to place the files somewhere else, run | |
| 36 | + | |
| 37 | + make clean | |
| 38 | + ./configure --prefix=<prefix> | |
| 39 | + make | |
| 40 | + sudo make install | |
| 41 | + | |
| 42 | +where <prefix> is the hierarchy you want to install into, e.g. /usr | |
| 43 | +for /usr/lib and /usr/include (_NOT_ recommended!). | |
| 44 | + | |
| 45 | +To enable debugging output (useful for me), run | |
| 46 | + | |
| 47 | + make clean | |
| 48 | + ./configure --enable-debug | |
| 49 | + make | |
| 50 | + sudo make install | |
| 51 | + | |
| 52 | +If you want old dlcompat style behavior of not prepending the underscore | |
| 53 | +on calls to dlsym then type: | |
| 54 | + | |
| 55 | + make clean | |
| 56 | + ./configure --enable-fink | |
| 57 | + make | |
| 58 | + sudo make install | |
| 59 | + | |
| 60 | +Usage | |
| 61 | +------- | |
| 62 | +Software that uses GNU autoconf will likely check for a library called | |
| 63 | +libdl, that's why I named it that way. For software that doesn't find | |
| 64 | +the library on its own, you must add a '-ldl' to the appropriate | |
| 65 | +Makefile (or environment) variable, usually LIBS. | |
| 66 | + | |
| 67 | +If you installed dlcompat into a directory other than /usr/local/lib, | |
| 68 | +you must tell the compiler where to find it. Add '-L<prefix>/lib' to | |
| 69 | +LDFLAGS (or CFLAGS) and '-I<prefix>/include' to CPPFLAGS (or CFLAGS). | |
| 70 | + | |
| 71 | +Notes | |
| 72 | +----- | |
| 73 | +If you are writing new software and plan to have Mac OX X compatibility you | |
| 74 | +should look at the dyld api's in /usr/include/mach-o/dyld.h, rather than | |
| 75 | +using dlcompat, using the native api's is the supported method of loading | |
| 76 | +dynamically on Mac OS X, if you want an small example, look at dlfcn_simple.c, | |
| 77 | +which should help get you started. | |
| 78 | + | |
| 79 | +Also note that the functions in dlcompat are not thread safe, and while it is not | |
| 80 | +POSIX spec compliant, it is about as close to compliance as it is going to get though. | |
| 81 | + | |
| 82 | +You can always get the latest version from opendarwin cvs: | |
| 83 | + | |
| 84 | + cvs -d :pserver:anonymous@anoncvs.opendarwin.org:/cvs/od login | |
| 85 | + cvs -z3 -d :pserver:anonymous@anoncvs.opendarwin.org:/cvs/od \ | |
| 86 | + co -d dlcompat proj/dlcompat | |
| 87 | + | |
| 88 | + | |
| 89 | +It is hoped that this library will be useful, and as bug free as possible, if you find | |
| 90 | +any bugs please let us know about them so they can be fixed. | |
| 91 | + | |
| 92 | +Please send bug reports to Peter O'Gorman <ogorman@users.sourceforge.net> | |
| 93 | + | |
| 94 | +Thanks. | |
| 95 | + | |
| @@ -0,0 +1,11 @@ | ||
| 1 | +The files in this directory are taken from | |
| 2 | +http://www.opendarwin.org/cgi-bin/cvsweb.cgi/~checkout~/proj/dlcompat/ | |
| 3 | + | |
| 4 | +The LICENSE in this directory applies to these files. | |
| 5 | + | |
| 6 | +Thomas Heller, Jan 2003 | |
| 7 | + | |
| 8 | +These files have been modified so they fall back to the system | |
| 9 | +dlfcn calls if available in libSystem. | |
| 10 | + | |
| 11 | +Bob Ippolito, Feb 2006 | |
| @@ -0,0 +1,84 @@ | ||
| 1 | +/* | |
| 2 | +Copyright (c) 2002 Jorge Acereda <jacereda@users.sourceforge.net> & | |
| 3 | + Peter O'Gorman <ogorman@users.sourceforge.net> | |
| 4 | + | |
| 5 | +Portions may be copyright others, see the AUTHORS file included with this | |
| 6 | +distribution. | |
| 7 | + | |
| 8 | +Maintained by Peter O'Gorman <ogorman@users.sourceforge.net> | |
| 9 | + | |
| 10 | +Bug Reports and other queries should go to <ogorman@users.sourceforge.net> | |
| 11 | + | |
| 12 | +Permission is hereby granted, free of charge, to any person obtaining | |
| 13 | +a copy of this software and associated documentation files (the | |
| 14 | +"Software"), to deal in the Software without restriction, including | |
| 15 | +without limitation the rights to use, copy, modify, merge, publish, | |
| 16 | +distribute, sublicense, and/or sell copies of the Software, and to | |
| 17 | +permit persons to whom the Software is furnished to do so, subject to | |
| 18 | +the following conditions: | |
| 19 | + | |
| 20 | +The above copyright notice and this permission notice shall be | |
| 21 | +included in all copies or substantial portions of the Software. | |
| 22 | + | |
| 23 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 24 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 25 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 26 | +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| 27 | +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| 28 | +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| 29 | +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 30 | +*/ | |
| 31 | +#ifndef _DLFCN_H_ | |
| 32 | +#define _DLFCN_H_ | |
| 33 | + | |
| 34 | +#include <AvailabilityMacros.h> | |
| 35 | + | |
| 36 | +#ifdef __cplusplus | |
| 37 | +extern "C" { | |
| 38 | +#endif | |
| 39 | + | |
| 40 | + | |
| 41 | +/* | |
| 42 | + * Structure filled in by dladdr(). | |
| 43 | + */ | |
| 44 | + | |
| 45 | +typedef struct dl_info { | |
| 46 | + const char *dli_fname; /* Pathname of shared object */ | |
| 47 | + void *dli_fbase; /* Base address of shared object */ | |
| 48 | + const char *dli_sname; /* Name of nearest symbol */ | |
| 49 | + void *dli_saddr; /* Address of nearest symbol */ | |
| 50 | +} Dl_info; | |
| 51 | + | |
| 52 | + | |
| 53 | +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_2 | |
| 54 | +#warning CTYPES_DARWIN_DLFCN | |
| 55 | +#define CTYPES_DARWIN_DLFCN | |
| 56 | +extern void * (*ctypes_dlopen)(const char *path, int mode); | |
| 57 | +extern void * (*ctypes_dlsym)(void * handle, const char *symbol); | |
| 58 | +extern const char * (*ctypes_dlerror)(void); | |
| 59 | +extern int (*ctypes_dlclose)(void * handle); | |
| 60 | +extern int (*ctypes_dladdr)(const void *, Dl_info *); | |
| 61 | +#else | |
| 62 | +extern void * dlopen(const char *path, int mode); | |
| 63 | +extern void * dlsym(void * handle, const char *symbol); | |
| 64 | +extern const char * dlerror(void); | |
| 65 | +extern int dlclose(void * handle); | |
| 66 | +extern int dladdr(const void *, Dl_info *); | |
| 67 | +#endif | |
| 68 | + | |
| 69 | +#define RTLD_LAZY 0x1 | |
| 70 | +#define RTLD_NOW 0x2 | |
| 71 | +#define RTLD_LOCAL 0x4 | |
| 72 | +#define RTLD_GLOBAL 0x8 | |
| 73 | +#define RTLD_NOLOAD 0x10 | |
| 74 | +#define RTLD_NODELETE 0x80 | |
| 75 | + | |
| 76 | +/* These are from the Mac OS X 10.4 headers */ | |
| 77 | +#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ | |
| 78 | +#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ | |
| 79 | + | |
| 80 | +#ifdef __cplusplus | |
| 81 | +} | |
| 82 | +#endif | |
| 83 | + | |
| 84 | +#endif /* _DLFCN_H_ */ | |
| @@ -0,0 +1,272 @@ | ||
| 1 | +/* | |
| 2 | +Copyright (c) 2002 Peter O'Gorman <ogorman@users.sourceforge.net> | |
| 3 | + | |
| 4 | +Permission is hereby granted, free of charge, to any person obtaining | |
| 5 | +a copy of this software and associated documentation files (the | |
| 6 | +"Software"), to deal in the Software without restriction, including | |
| 7 | +without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | +distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | +permit persons to whom the Software is furnished to do so, subject to | |
| 10 | +the following conditions: | |
| 11 | + | |
| 12 | +The above copyright notice and this permission notice shall be | |
| 13 | +included in all copies or substantial portions of the Software. | |
| 14 | + | |
| 15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 16 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 18 | +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| 19 | +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| 20 | +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| 21 | +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | +*/ | |
| 23 | + | |
| 24 | + | |
| 25 | +/* Just to prove that it isn't that hard to add Mac calls to your code :) | |
| 26 | + This works with pretty much everything, including kde3 xemacs and the gimp, | |
| 27 | + I'd guess that it'd work in at least 95% of cases, use this as your starting | |
| 28 | + point, rather than the mess that is dlfcn.c, assuming that your code does not | |
| 29 | + require ref counting or symbol lookups in dependent libraries | |
| 30 | +*/ | |
| 31 | + | |
| 32 | +#include <stdio.h> | |
| 33 | +#include <stdlib.h> | |
| 34 | +#include <string.h> | |
| 35 | +#include <sys/types.h> | |
| 36 | +#include <sys/stat.h> | |
| 37 | +#include <stdarg.h> | |
| 38 | +#include <limits.h> | |
| 39 | +#include <mach-o/dyld.h> | |
| 40 | +#include <AvailabilityMacros.h> | |
| 41 | +#include "dlfcn.h" | |
| 42 | + | |
| 43 | +#ifdef CTYPES_DARWIN_DLFCN | |
| 44 | + | |
| 45 | +#define ERR_STR_LEN 256 | |
| 46 | + | |
| 47 | +#ifndef MAC_OS_X_VERSION_10_3 | |
| 48 | +#define MAC_OS_X_VERSION_10_3 1030 | |
| 49 | +#endif | |
| 50 | + | |
| 51 | +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 | |
| 52 | +#define DARWIN_HAS_DLOPEN | |
| 53 | +extern void * dlopen(const char *path, int mode) __attribute__((weak_import)); | |
| 54 | +extern void * dlsym(void * handle, const char *symbol) __attribute__((weak_import)); | |
| 55 | +extern const char * dlerror(void) __attribute__((weak_import)); | |
| 56 | +extern int dlclose(void * handle) __attribute__((weak_import)); | |
| 57 | +extern int dladdr(const void *, Dl_info *) __attribute__((weak_import)); | |
| 58 | +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 */ | |
| 59 | + | |
| 60 | +#ifndef DARWIN_HAS_DLOPEN | |
| 61 | +#define dlopen darwin_dlopen | |
| 62 | +#define dlsym darwin_dlsym | |
| 63 | +#define dlerror darwin_dlerror | |
| 64 | +#define dlclose darwin_dlclose | |
| 65 | +#define dladdr darwin_dladdr | |
| 66 | +#endif | |
| 67 | + | |
| 68 | +void * (*ctypes_dlopen)(const char *path, int mode); | |
| 69 | +void * (*ctypes_dlsym)(void * handle, const char *symbol); | |
| 70 | +const char * (*ctypes_dlerror)(void); | |
| 71 | +int (*ctypes_dlclose)(void * handle); | |
| 72 | +int (*ctypes_dladdr)(const void *, Dl_info *); | |
| 73 | + | |
| 74 | +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 | |
| 75 | +/* Mac OS X 10.3+ has dlopen, so strip all this dead code to avoid warnings */ | |
| 76 | + | |
| 77 | +static void *dlsymIntern(void *handle, const char *symbol); | |
| 78 | + | |
| 79 | +static const char *error(int setget, const char *str, ...); | |
| 80 | + | |
| 81 | +/* Set and get the error string for use by dlerror */ | |
| 82 | +static const char *error(int setget, const char *str, ...) | |
| 83 | +{ | |
| 84 | + static char errstr[ERR_STR_LEN]; | |
| 85 | + static int err_filled = 0; | |
| 86 | + const char *retval; | |
| 87 | + va_list arg; | |
| 88 | + if (setget == 0) | |
| 89 | + { | |
| 90 | + va_start(arg, str); | |
| 91 | + strncpy(errstr, "dlcompat: ", ERR_STR_LEN); | |
| 92 | + vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg); | |
| 93 | + va_end(arg); | |
| 94 | + err_filled = 1; | |
| 95 | + retval = NULL; | |
| 96 | + } | |
| 97 | + else | |
| 98 | + { | |
| 99 | + if (!err_filled) | |
| 100 | + retval = NULL; | |
| 101 | + else | |
| 102 | + retval = errstr; | |
| 103 | + err_filled = 0; | |
| 104 | + } | |
| 105 | + return retval; | |
| 106 | +} | |
| 107 | + | |
| 108 | +/* darwin_dlopen */ | |
| 109 | +static void *darwin_dlopen(const char *path, int mode) | |
| 110 | +{ | |
| 111 | + void *module = 0; | |
| 112 | + NSObjectFileImage ofi = 0; | |
| 113 | + NSObjectFileImageReturnCode ofirc; | |
| 114 | + | |
| 115 | + /* If we got no path, the app wants the global namespace, use -1 as the marker | |
| 116 | + in this case */ | |
| 117 | + if (!path) | |
| 118 | + return (void *)-1; | |
| 119 | + | |
| 120 | + /* Create the object file image, works for things linked with the -bundle arg to ld */ | |
| 121 | + ofirc = NSCreateObjectFileImageFromFile(path, &ofi); | |
| 122 | + switch (ofirc) | |
| 123 | + { | |
| 124 | + case NSObjectFileImageSuccess: | |
| 125 | + /* It was okay, so use NSLinkModule to link in the image */ | |
| 126 | + module = NSLinkModule(ofi, path, | |
| 127 | + NSLINKMODULE_OPTION_RETURN_ON_ERROR | |
| 128 | + | (mode & RTLD_GLOBAL) ? 0 : NSLINKMODULE_OPTION_PRIVATE | |
| 129 | + | (mode & RTLD_LAZY) ? 0 : NSLINKMODULE_OPTION_BINDNOW); | |
| 130 | + NSDestroyObjectFileImage(ofi); | |
| 131 | + break; | |
| 132 | + case NSObjectFileImageInappropriateFile: | |
| 133 | + /* It may have been a dynamic library rather than a bundle, try to load it */ | |
| 134 | + module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); | |
| 135 | + break; | |
| 136 | + default: | |
| 137 | + /* God knows what we got */ | |
| 138 | + error(0, "Can not open \"%s\"", path); | |
| 139 | + return 0; | |
| 140 | + } | |
| 141 | + if (!module) | |
| 142 | + error(0, "Can not open \"%s\"", path); | |
| 143 | + return module; | |
| 144 | + | |
| 145 | +} | |
| 146 | + | |
| 147 | +/* dlsymIntern is used by dlsym to find the symbol */ | |
| 148 | +static void *dlsymIntern(void *handle, const char *symbol) | |
| 149 | +{ | |
| 150 | + NSSymbol nssym = 0; | |
| 151 | + /* If the handle is -1, if is the app global context */ | |
| 152 | + if (handle == (void *)-1) | |
| 153 | + { | |
| 154 | + /* Global context, use NSLookupAndBindSymbol */ | |
| 155 | + if (NSIsSymbolNameDefined(symbol)) | |
| 156 | + { | |
| 157 | + nssym = NSLookupAndBindSymbol(symbol); | |
| 158 | + } | |
| 159 | + | |
| 160 | + } | |
| 161 | + /* Now see if the handle is a struch mach_header* or not, use NSLookupSymbol in image | |
| 162 | + for libraries, and NSLookupSymbolInModule for bundles */ | |
| 163 | + else | |
| 164 | + { | |
| 165 | + /* Check for both possible magic numbers depending on x86/ppc byte order */ | |
| 166 | + if ((((struct mach_header *)handle)->magic == MH_MAGIC) || | |
| 167 | + (((struct mach_header *)handle)->magic == MH_CIGAM)) | |
| 168 | + { | |
| 169 | + if (NSIsSymbolNameDefinedInImage((struct mach_header *)handle, symbol)) | |
| 170 | + { | |
| 171 | + nssym = NSLookupSymbolInImage((struct mach_header *)handle, | |
| 172 | + symbol, | |
| 173 | + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | |
| 174 | + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | |
| 175 | + } | |
| 176 | + | |
| 177 | + } | |
| 178 | + else | |
| 179 | + { | |
| 180 | + nssym = NSLookupSymbolInModule(handle, symbol); | |
| 181 | + } | |
| 182 | + } | |
| 183 | + if (!nssym) | |
| 184 | + { | |
| 185 | + error(0, "Symbol \"%s\" Not found", symbol); | |
| 186 | + return NULL; | |
| 187 | + } | |
| 188 | + return NSAddressOfSymbol(nssym); | |
| 189 | +} | |
| 190 | + | |
| 191 | +static const char *darwin_dlerror(void) | |
| 192 | +{ | |
| 193 | + return error(1, (char *)NULL); | |
| 194 | +} | |
| 195 | + | |
| 196 | +static int darwin_dlclose(void *handle) | |
| 197 | +{ | |
| 198 | + if ((((struct mach_header *)handle)->magic == MH_MAGIC) || | |
| 199 | + (((struct mach_header *)handle)->magic == MH_CIGAM)) | |
| 200 | + { | |
| 201 | + error(0, "Can't remove dynamic libraries on darwin"); | |
| 202 | + return 0; | |
| 203 | + } | |
| 204 | + if (!NSUnLinkModule(handle, 0)) | |
| 205 | + { | |
| 206 | + error(0, "unable to unlink module %s", NSNameOfModule(handle)); | |
| 207 | + return 1; | |
| 208 | + } | |
| 209 | + return 0; | |
| 210 | +} | |
| 211 | + | |
| 212 | + | |
| 213 | +/* dlsym, prepend the underscore and call dlsymIntern */ | |
| 214 | +static void *darwin_dlsym(void *handle, const char *symbol) | |
| 215 | +{ | |
| 216 | + static char undersym[257]; /* Saves calls to malloc(3) */ | |
| 217 | + int sym_len = strlen(symbol); | |
| 218 | + void *value = NULL; | |
| 219 | + char *malloc_sym = NULL; | |
| 220 | + | |
| 221 | + if (sym_len < 256) | |
| 222 | + { | |
| 223 | + snprintf(undersym, 256, "_%s", symbol); | |
| 224 | + value = dlsymIntern(handle, undersym); | |
| 225 | + } | |
| 226 | + else | |
| 227 | + { | |
| 228 | + malloc_sym = malloc(sym_len + 2); | |
| 229 | + if (malloc_sym) | |
| 230 | + { | |
| 231 | + sprintf(malloc_sym, "_%s", symbol); | |
| 232 | + value = dlsymIntern(handle, malloc_sym); | |
| 233 | + free(malloc_sym); | |
| 234 | + } | |
| 235 | + else | |
| 236 | + { | |
| 237 | + error(0, "Unable to allocate memory"); | |
| 238 | + } | |
| 239 | + } | |
| 240 | + return value; | |
| 241 | +} | |
| 242 | + | |
| 243 | +static int darwin_dladdr(const void *handle, Dl_info *info) { | |
| 244 | + return 0; | |
| 245 | +} | |
| 246 | +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 */ | |
| 247 | + | |
| 248 | +#if __GNUC__ < 4 | |
| 249 | +#pragma CALL_ON_LOAD ctypes_dlfcn_init | |
| 250 | +#else | |
| 251 | +static void __attribute__ ((constructor)) ctypes_dlfcn_init(void); | |
| 252 | +static | |
| 253 | +#endif | |
| 254 | +void ctypes_dlfcn_init(void) { | |
| 255 | + if (dlopen != NULL) { | |
| 256 | + ctypes_dlsym = dlsym; | |
| 257 | + ctypes_dlopen = dlopen; | |
| 258 | + ctypes_dlerror = dlerror; | |
| 259 | + ctypes_dlclose = dlclose; | |
| 260 | + ctypes_dladdr = dladdr; | |
| 261 | + } else { | |
| 262 | +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 | |
| 263 | + ctypes_dlsym = darwin_dlsym; | |
| 264 | + ctypes_dlopen = darwin_dlopen; | |
| 265 | + ctypes_dlerror = darwin_dlerror; | |
| 266 | + ctypes_dlclose = darwin_dlclose; | |
| 267 | + ctypes_dladdr = darwin_dladdr; | |
| 268 | +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 */ | |
| 269 | + } | |
| 270 | +} | |
| 271 | + | |
| 272 | +#endif /* CTYPES_DARWIN_DLFCN */ | |
| @@ -0,0 +1,20 @@ | ||
| 1 | +libffi - Copyright (c) 1996-2003 Red Hat, Inc. | |
| 2 | + | |
| 3 | +Permission is hereby granted, free of charge, to any person obtaining | |
| 4 | +a copy of this software and associated documentation files (the | |
| 5 | +``Software''), to deal in the Software without restriction, including | |
| 6 | +without limitation the rights to use, copy, modify, merge, publish, | |
| 7 | +distribute, sublicense, and/or sell copies of the Software, and to | |
| 8 | +permit persons to whom the Software is furnished to do so, subject to | |
| 9 | +the following conditions: | |
| 10 | + | |
| 11 | +The above copyright notice and this permission notice shall be included | |
| 12 | +in all copies or substantial portions of the Software. | |
| 13 | + | |
| 14 | +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 15 | +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 16 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 17 | +IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | +OTHER DEALINGS IN THE SOFTWARE. | |
| @@ -0,0 +1,500 @@ | ||
| 1 | +This directory contains the libffi package, which is not part of GCC but | |
| 2 | +shipped with GCC as convenience. | |
| 3 | + | |
| 4 | +Status | |
| 5 | +====== | |
| 6 | + | |
| 7 | +libffi-2.00 has not been released yet! This is a development snapshot! | |
| 8 | + | |
| 9 | +libffi-1.20 was released on October 5, 1998. Check the libffi web | |
| 10 | +page for updates: <URL:http://sources.redhat.com/libffi/>. | |
| 11 | + | |
| 12 | + | |
| 13 | +What is libffi? | |
| 14 | +=============== | |
| 15 | + | |
| 16 | +Compilers for high level languages generate code that follow certain | |
| 17 | +conventions. These conventions are necessary, in part, for separate | |
| 18 | +compilation to work. One such convention is the "calling | |
| 19 | +convention". The "calling convention" is essentially a set of | |
| 20 | +assumptions made by the compiler about where function arguments will | |
| 21 | +be found on entry to a function. A "calling convention" also specifies | |
| 22 | +where the return value for a function is found. | |
| 23 | + | |
| 24 | +Some programs may not know at the time of compilation what arguments | |
| 25 | +are to be passed to a function. For instance, an interpreter may be | |
| 26 | +told at run-time about the number and types of arguments used to call | |
| 27 | +a given function. Libffi can be used in such programs to provide a | |
| 28 | +bridge from the interpreter program to compiled code. | |
| 29 | + | |
| 30 | +The libffi library provides a portable, high level programming | |
| 31 | +interface to various calling conventions. This allows a programmer to | |
| 32 | +call any function specified by a call interface description at run | |
| 33 | +time. | |
| 34 | + | |
| 35 | +Ffi stands for Foreign Function Interface. A foreign function | |
| 36 | +interface is the popular name for the interface that allows code | |
| 37 | +written in one language to call code written in another language. The | |
| 38 | +libffi library really only provides the lowest, machine dependent | |
| 39 | +layer of a fully featured foreign function interface. A layer must | |
| 40 | +exist above libffi that handles type conversions for values passed | |
| 41 | +between the two languages. | |
| 42 | + | |
| 43 | + | |
| 44 | +Supported Platforms and Prerequisites | |
| 45 | +===================================== | |
| 46 | + | |
| 47 | +Libffi has been ported to: | |
| 48 | + | |
| 49 | + SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) | |
| 50 | + | |
| 51 | + Irix 5.3 & 6.2 (System V/o32 & n32) | |
| 52 | + | |
| 53 | + Intel x86 - Linux (System V ABI) | |
| 54 | + | |
| 55 | + Alpha - Linux and OSF/1 | |
| 56 | + | |
| 57 | + m68k - Linux (System V ABI) | |
| 58 | + | |
| 59 | + PowerPC - Linux (System V ABI, Darwin, AIX) | |
| 60 | + | |
| 61 | + ARM - Linux (System V ABI) | |
| 62 | + | |
| 63 | +Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are | |
| 64 | +that other versions will work. Libffi has also been built and tested | |
| 65 | +with the SGI compiler tools. | |
| 66 | + | |
| 67 | +On PowerPC, the tests failed (see the note below). | |
| 68 | + | |
| 69 | +You must use GNU make to build libffi. SGI's make will not work. | |
| 70 | +Sun's probably won't either. | |
| 71 | + | |
| 72 | +If you port libffi to another platform, please let me know! I assume | |
| 73 | +that some will be easy (x86 NetBSD), and others will be more difficult | |
| 74 | +(HP). | |
| 75 | + | |
| 76 | + | |
| 77 | +Installing libffi | |
| 78 | +================= | |
| 79 | + | |
| 80 | +[Note: before actually performing any of these installation steps, | |
| 81 | + you may wish to read the "Platform Specific Notes" below.] | |
| 82 | + | |
| 83 | +First you must configure the distribution for your particular | |
| 84 | +system. Go to the directory you wish to build libffi in and run the | |
| 85 | +"configure" program found in the root directory of the libffi source | |
| 86 | +distribution. | |
| 87 | + | |
| 88 | +You may want to tell configure where to install the libffi library and | |
| 89 | +header files. To do that, use the --prefix configure switch. Libffi | |
| 90 | +will install under /usr/local by default. | |
| 91 | + | |
| 92 | +If you want to enable extra run-time debugging checks use the the | |
| 93 | +--enable-debug configure switch. This is useful when your program dies | |
| 94 | +mysteriously while using libffi. | |
| 95 | + | |
| 96 | +Another useful configure switch is --enable-purify-safety. Using this | |
| 97 | +will add some extra code which will suppress certain warnings when you | |
| 98 | +are using Purify with libffi. Only use this switch when using | |
| 99 | +Purify, as it will slow down the library. | |
| 100 | + | |
| 101 | +Configure has many other options. Use "configure --help" to see them all. | |
| 102 | + | |
| 103 | +Once configure has finished, type "make". Note that you must be using | |
| 104 | +GNU make. SGI's make will not work. Sun's probably won't either. | |
| 105 | +You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. | |
| 106 | + | |
| 107 | +To ensure that libffi is working as advertised, type "make test". | |
| 108 | + | |
| 109 | +To install the library and header files, type "make install". | |
| 110 | + | |
| 111 | + | |
| 112 | +Using libffi | |
| 113 | +============ | |
| 114 | + | |
| 115 | + The Basics | |
| 116 | + ---------- | |
| 117 | + | |
| 118 | +Libffi assumes that you have a pointer to the function you wish to | |
| 119 | +call and that you know the number and types of arguments to pass it, | |
| 120 | +as well as the return type of the function. | |
| 121 | + | |
| 122 | +The first thing you must do is create an ffi_cif object that matches | |
| 123 | +the signature of the function you wish to call. The cif in ffi_cif | |
| 124 | +stands for Call InterFace. To prepare a call interface object, use the | |
| 125 | +following function: | |
| 126 | + | |
| 127 | +ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, | |
| 128 | + unsigned int nargs, | |
| 129 | + ffi_type *rtype, ffi_type **atypes); | |
| 130 | + | |
| 131 | + CIF is a pointer to the call interface object you wish | |
| 132 | + to initialize. | |
| 133 | + | |
| 134 | + ABI is an enum that specifies the calling convention | |
| 135 | + to use for the call. FFI_DEFAULT_ABI defaults | |
| 136 | + to the system's native calling convention. Other | |
| 137 | + ABI's may be used with care. They are system | |
| 138 | + specific. | |
| 139 | + | |
| 140 | + NARGS is the number of arguments this function accepts. | |
| 141 | + libffi does not yet support vararg functions. | |
| 142 | + | |
| 143 | + RTYPE is a pointer to an ffi_type structure that represents | |
| 144 | + the return type of the function. Ffi_type objects | |
| 145 | + describe the types of values. libffi provides | |
| 146 | + ffi_type objects for many of the native C types: | |
| 147 | + signed int, unsigned int, signed char, unsigned char, | |
| 148 | + etc. There is also a pointer ffi_type object and | |
| 149 | + a void ffi_type. Use &ffi_type_void for functions that | |
| 150 | + don't return values. | |
| 151 | + | |
| 152 | + ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. | |
| 153 | + If NARGS is 0, this is ignored. | |
| 154 | + | |
| 155 | + | |
| 156 | +ffi_prep_cif will return a status code that you are responsible | |
| 157 | +for checking. It will be one of the following: | |
| 158 | + | |
| 159 | + FFI_OK - All is good. | |
| 160 | + | |
| 161 | + FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif | |
| 162 | + came across is bad. | |
| 163 | + | |
| 164 | + | |
| 165 | +Before making the call, the VALUES vector should be initialized | |
| 166 | +with pointers to the appropriate argument values. | |
| 167 | + | |
| 168 | +To call the the function using the initialized ffi_cif, use the | |
| 169 | +ffi_call function: | |
| 170 | + | |
| 171 | +void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); | |
| 172 | + | |
| 173 | + CIF is a pointer to the ffi_cif initialized specifically | |
| 174 | + for this function. | |
| 175 | + | |
| 176 | + FN is a pointer to the function you want to call. | |
| 177 | + | |
| 178 | + RVALUE is a pointer to a chunk of memory that is to hold the | |
| 179 | + result of the function call. Currently, it must be | |
| 180 | + at least one word in size (except for the n32 version | |
| 181 | + under Irix 6.x, which must be a pointer to an 8 byte | |
| 182 | + aligned value (a long long). It must also be at least | |
| 183 | + word aligned (depending on the return type, and the | |
| 184 | + system's alignment requirements). If RTYPE is | |
| 185 | + &ffi_type_void, this is ignored. If RVALUE is NULL, | |
| 186 | + the return value is discarded. | |
| 187 | + | |
| 188 | + AVALUES is a vector of void* that point to the memory locations | |
| 189 | + holding the argument values for a call. | |
| 190 | + If NARGS is 0, this is ignored. | |
| 191 | + | |
| 192 | + | |
| 193 | +If you are expecting a return value from FN it will have been stored | |
| 194 | +at RVALUE. | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + An Example | |
| 199 | + ---------- | |
| 200 | + | |
| 201 | +Here is a trivial example that calls puts() a few times. | |
| 202 | + | |
| 203 | + #include <stdio.h> | |
| 204 | + #include <ffi.h> | |
| 205 | + | |
| 206 | + int main() | |
| 207 | + { | |
| 208 | + ffi_cif cif; | |
| 209 | + ffi_type *args[1]; | |
| 210 | + void *values[1]; | |
| 211 | + char *s; | |
| 212 | + int rc; | |
| 213 | + | |
| 214 | + /* Initialize the argument info vectors */ | |
| 215 | + args[0] = &ffi_type_uint; | |
| 216 | + values[0] = &s; | |
| 217 | + | |
| 218 | + /* Initialize the cif */ | |
| 219 | + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, | |
| 220 | + &ffi_type_uint, args) == FFI_OK) | |
| 221 | + { | |
| 222 | + s = "Hello World!"; | |
| 223 | + ffi_call(&cif, puts, &rc, values); | |
| 224 | + /* rc now holds the result of the call to puts */ | |
| 225 | + | |
| 226 | + /* values holds a pointer to the function's arg, so to | |
| 227 | + call puts() again all we need to do is change the | |
| 228 | + value of s */ | |
| 229 | + s = "This is cool!"; | |
| 230 | + ffi_call(&cif, puts, &rc, values); | |
| 231 | + } | |
| 232 | + | |
| 233 | + return 0; | |
| 234 | + } | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + Aggregate Types | |
| 239 | + --------------- | |
| 240 | + | |
| 241 | +Although libffi has no special support for unions or bit-fields, it is | |
| 242 | +perfectly happy passing structures back and forth. You must first | |
| 243 | +describe the structure to libffi by creating a new ffi_type object | |
| 244 | +for it. Here is the definition of ffi_type: | |
| 245 | + | |
| 246 | + typedef struct _ffi_type | |
| 247 | + { | |
| 248 | + unsigned size; | |
| 249 | + short alignment; | |
| 250 | + short type; | |
| 251 | + struct _ffi_type **elements; | |
| 252 | + } ffi_type; | |
| 253 | + | |
| 254 | +All structures must have type set to FFI_TYPE_STRUCT. You may set | |
| 255 | +size and alignment to 0. These will be calculated and reset to the | |
| 256 | +appropriate values by ffi_prep_cif(). | |
| 257 | + | |
| 258 | +elements is a NULL terminated array of pointers to ffi_type objects | |
| 259 | +that describe the type of the structure elements. These may, in turn, | |
| 260 | +be structure elements. | |
| 261 | + | |
| 262 | +The following example initializes a ffi_type object representing the | |
| 263 | +tm struct from Linux's time.h: | |
| 264 | + | |
| 265 | + struct tm { | |
| 266 | + int tm_sec; | |
| 267 | + int tm_min; | |
| 268 | + int tm_hour; | |
| 269 | + int tm_mday; | |
| 270 | + int tm_mon; | |
| 271 | + int tm_year; | |
| 272 | + int tm_wday; | |
| 273 | + int tm_yday; | |
| 274 | + int tm_isdst; | |
| 275 | + /* Those are for future use. */ | |
| 276 | + long int __tm_gmtoff__; | |
| 277 | + __const char *__tm_zone__; | |
| 278 | + }; | |
| 279 | + | |
| 280 | + { | |
| 281 | + ffi_type tm_type; | |
| 282 | + ffi_type *tm_type_elements[12]; | |
| 283 | + int i; | |
| 284 | + | |
| 285 | + tm_type.size = tm_type.alignment = 0; | |
| 286 | + tm_type.elements = &tm_type_elements; | |
| 287 | + | |
| 288 | + for (i = 0; i < 9; i++) | |
| 289 | + tm_type_elements[i] = &ffi_type_sint; | |
| 290 | + | |
| 291 | + tm_type_elements[9] = &ffi_type_slong; | |
| 292 | + tm_type_elements[10] = &ffi_type_pointer; | |
| 293 | + tm_type_elements[11] = NULL; | |
| 294 | + | |
| 295 | + /* tm_type can now be used to represent tm argument types and | |
| 296 | + return types for ffi_prep_cif() */ | |
| 297 | + } | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | +Platform Specific Notes | |
| 302 | +======================= | |
| 303 | + | |
| 304 | + Intel x86 | |
| 305 | + --------- | |
| 306 | + | |
| 307 | +There are no known problems with the x86 port. | |
| 308 | + | |
| 309 | + Sun SPARC - SunOS 4.1.3 & Solaris 2.x | |
| 310 | + ------------------------------------- | |
| 311 | + | |
| 312 | +You must use GNU Make to build libffi on Sun platforms. | |
| 313 | + | |
| 314 | + MIPS - Irix 5.3 & 6.x | |
| 315 | + --------------------- | |
| 316 | + | |
| 317 | +Irix 6.2 and better supports three different calling conventions: o32, | |
| 318 | +n32 and n64. Currently, libffi only supports both o32 and n32 under | |
| 319 | +Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be | |
| 320 | +configured for whichever calling convention it was built for. | |
| 321 | + | |
| 322 | +By default, the configure script will try to build libffi with the GNU | |
| 323 | +development tools. To build libffi with the SGI development tools, set | |
| 324 | +the environment variable CC to either "cc -32" or "cc -n32" before | |
| 325 | +running configure under Irix 6.x (depending on whether you want an o32 | |
| 326 | +or n32 library), or just "cc" for Irix 5.3. | |
| 327 | + | |
| 328 | +With the n32 calling convention, when returning structures smaller | |
| 329 | +than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. | |
| 330 | +Here's one way of forcing this: | |
| 331 | + | |
| 332 | + double struct_storage[2]; | |
| 333 | + my_small_struct *s = (my_small_struct *) struct_storage; | |
| 334 | + /* Use s for RVALUE */ | |
| 335 | + | |
| 336 | +If you don't do this you are liable to get spurious bus errors. | |
| 337 | + | |
| 338 | +"long long" values are not supported yet. | |
| 339 | + | |
| 340 | +You must use GNU Make to build libffi on SGI platforms. | |
| 341 | + | |
| 342 | + ARM - System V ABI | |
| 343 | + ------------------ | |
| 344 | + | |
| 345 | +The ARM port was performed on a NetWinder running ARM Linux ELF | |
| 346 | +(2.0.31) and gcc 2.8.1. | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + PowerPC System V ABI | |
| 351 | + -------------------- | |
| 352 | + | |
| 353 | +There are two `System V ABI's which libffi implements for PowerPC. | |
| 354 | +They differ only in how small structures are returned from functions. | |
| 355 | + | |
| 356 | +In the FFI_SYSV version, structures that are 8 bytes or smaller are | |
| 357 | +returned in registers. This is what GCC does when it is configured | |
| 358 | +for solaris, and is what the System V ABI I have (dated September | |
| 359 | +1995) says. | |
| 360 | + | |
| 361 | +In the FFI_GCC_SYSV version, all structures are returned the same way: | |
| 362 | +by passing a pointer as the first argument to the function. This is | |
| 363 | +what GCC does when it is configured for linux or a generic sysv | |
| 364 | +target. | |
| 365 | + | |
| 366 | +EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a | |
| 367 | +inconsistency with the SysV ABI: When a procedure is called with many | |
| 368 | +floating-point arguments, some of them get put on the stack. They are | |
| 369 | +all supposed to be stored in double-precision format, even if they are | |
| 370 | +only single-precision, but EGCS stores single-precision arguments as | |
| 371 | +single-precision anyway. This causes one test to fail (the `many | |
| 372 | +arguments' test). | |
| 373 | + | |
| 374 | + | |
| 375 | +What's With The Crazy Comments? | |
| 376 | +=============================== | |
| 377 | + | |
| 378 | +You might notice a number of cryptic comments in the code, delimited | |
| 379 | +by /*@ and @*/. These are annotations read by the program LCLint, a | |
| 380 | +tool for statically checking C programs. You can read all about it at | |
| 381 | +<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>. | |
| 382 | + | |
| 383 | + | |
| 384 | +History | |
| 385 | +======= | |
| 386 | + | |
| 387 | +1.20 Oct-5-98 | |
| 388 | + Raffaele Sena produces ARM port. | |
| 389 | + | |
| 390 | +1.19 Oct-5-98 | |
| 391 | + Fixed x86 long double and long long return support. | |
| 392 | + m68k bug fixes from Andreas Schwab. | |
| 393 | + Patch for DU assembler compatibility for the Alpha from Richard | |
| 394 | + Henderson. | |
| 395 | + | |
| 396 | +1.18 Apr-17-98 | |
| 397 | + Bug fixes and MIPS configuration changes. | |
| 398 | + | |
| 399 | +1.17 Feb-24-98 | |
| 400 | + Bug fixes and m68k port from Andreas Schwab. PowerPC port from | |
| 401 | + Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. | |
| 402 | + | |
| 403 | +1.16 Feb-11-98 | |
| 404 | + Richard Henderson produces Alpha port. | |
| 405 | + | |
| 406 | +1.15 Dec-4-97 | |
| 407 | + Fixed an n32 ABI bug. New libtool, auto* support. | |
| 408 | + | |
| 409 | +1.14 May-13-97 | |
| 410 | + libtool is now used to generate shared and static libraries. | |
| 411 | + Fixed a minor portability problem reported by Russ McManus | |
| 412 | + <mcmanr@eq.gs.com>. | |
| 413 | + | |
| 414 | +1.13 Dec-2-96 | |
| 415 | + Added --enable-purify-safety to keep Purify from complaining | |
| 416 | + about certain low level code. | |
| 417 | + Sparc fix for calling functions with < 6 args. | |
| 418 | + Linux x86 a.out fix. | |
| 419 | + | |
| 420 | +1.12 Nov-22-96 | |
| 421 | + Added missing ffi_type_void, needed for supporting void return | |
| 422 | + types. Fixed test case for non MIPS machines. Cygnus Support | |
| 423 | + is now Cygnus Solutions. | |
| 424 | + | |
| 425 | +1.11 Oct-30-96 | |
| 426 | + Added notes about GNU make. | |
| 427 | + | |
| 428 | +1.10 Oct-29-96 | |
| 429 | + Added configuration fix for non GNU compilers. | |
| 430 | + | |
| 431 | +1.09 Oct-29-96 | |
| 432 | + Added --enable-debug configure switch. Clean-ups based on LCLint | |
| 433 | + feedback. ffi_mips.h is always installed. Many configuration | |
| 434 | + fixes. Fixed ffitest.c for sparc builds. | |
| 435 | + | |
| 436 | +1.08 Oct-15-96 | |
| 437 | + Fixed n32 problem. Many clean-ups. | |
| 438 | + | |
| 439 | +1.07 Oct-14-96 | |
| 440 | + Gordon Irlam rewrites v8.S again. Bug fixes. | |
| 441 | + | |
| 442 | +1.06 Oct-14-96 | |
| 443 | + Gordon Irlam improved the sparc port. | |
| 444 | + | |
| 445 | +1.05 Oct-14-96 | |
| 446 | + Interface changes based on feedback. | |
| 447 | + | |
| 448 | +1.04 Oct-11-96 | |
| 449 | + Sparc port complete (modulo struct passing bug). | |
| 450 | + | |
| 451 | +1.03 Oct-10-96 | |
| 452 | + Passing struct args, and returning struct values works for | |
| 453 | + all architectures/calling conventions. Expanded tests. | |
| 454 | + | |
| 455 | +1.02 Oct-9-96 | |
| 456 | + Added SGI n32 support. Fixed bugs in both o32 and Linux support. | |
| 457 | + Added "make test". | |
| 458 | + | |
| 459 | +1.01 Oct-8-96 | |
| 460 | + Fixed float passing bug in mips version. Restructured some | |
| 461 | + of the code. Builds cleanly with SGI tools. | |
| 462 | + | |
| 463 | +1.00 Oct-7-96 | |
| 464 | + First release. No public announcement. | |
| 465 | + | |
| 466 | + | |
| 467 | +Authors & Credits | |
| 468 | +================= | |
| 469 | + | |
| 470 | +libffi was written by Anthony Green <green@cygnus.com>. | |
| 471 | + | |
| 472 | +Portions of libffi were derived from Gianni Mariani's free gencall | |
| 473 | +library for Silicon Graphics machines. | |
| 474 | + | |
| 475 | +The closure mechanism was designed and implemented by Kresten Krab | |
| 476 | +Thorup. | |
| 477 | + | |
| 478 | +The Sparc port was derived from code contributed by the fine folks at | |
| 479 | +Visible Decisions Inc <http://www.vdi.com>. Further enhancements were | |
| 480 | +made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>. | |
| 481 | + | |
| 482 | +The Alpha port was written by Richard Henderson at Cygnus Solutions. | |
| 483 | + | |
| 484 | +Andreas Schwab ported libffi to m68k Linux and provided a number of | |
| 485 | +bug fixes. | |
| 486 | + | |
| 487 | +Geoffrey Keating ported libffi to the PowerPC. | |
| 488 | + | |
| 489 | +Raffaele Sena ported libffi to the ARM. | |
| 490 | + | |
| 491 | +Jesper Skov and Andrew Haley both did more than their fair share of | |
| 492 | +stepping through the code and tracking down bugs. | |
| 493 | + | |
| 494 | +Thanks also to Tom Tromey for bug fixes and configuration help. | |
| 495 | + | |
| 496 | +Thanks to Jim Blandy, who provided some useful feedback on the libffi | |
| 497 | +interface. | |
| 498 | + | |
| 499 | +If you have a problem, or have found a bug, please send a note to | |
| 500 | +green@cygnus.com. | |
| @@ -0,0 +1,92 @@ | ||
| 1 | +# mmap(2) blacklisting. Some platforms provide the mmap library routine | |
| 2 | +# but don't support all of the features we need from it. | |
| 3 | +AC_DEFUN([AC_FUNC_MMAP_BLACKLIST], | |
| 4 | +[ | |
| 5 | +AC_CHECK_HEADER([sys/mman.h], | |
| 6 | + [libffi_header_sys_mman_h=yes], [libffi_header_sys_mman_h=no]) | |
| 7 | +AC_CHECK_FUNC([mmap], [libffi_func_mmap=yes], [libffi_func_mmap=no]) | |
| 8 | +if test "$libffi_header_sys_mman_h" != yes \ | |
| 9 | + || test "$libffi_func_mmap" != yes; then | |
| 10 | + ac_cv_func_mmap_file=no | |
| 11 | + ac_cv_func_mmap_dev_zero=no | |
| 12 | + ac_cv_func_mmap_anon=no | |
| 13 | +else | |
| 14 | + AC_CACHE_CHECK([whether read-only mmap of a plain file works], | |
| 15 | + ac_cv_func_mmap_file, | |
| 16 | + [# Add a system to this blacklist if | |
| 17 | + # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a | |
| 18 | + # memory area containing the same data that you'd get if you applied | |
| 19 | + # read() to the same fd. The only system known to have a problem here | |
| 20 | + # is VMS, where text files have record structure. | |
| 21 | + case "$host_os" in | |
| 22 | + vms* | ultrix*) | |
| 23 | + ac_cv_func_mmap_file=no ;; | |
| 24 | + *) | |
| 25 | + ac_cv_func_mmap_file=yes;; | |
| 26 | + esac]) | |
| 27 | + AC_CACHE_CHECK([whether mmap from /dev/zero works], | |
| 28 | + ac_cv_func_mmap_dev_zero, | |
| 29 | + [# Add a system to this blacklist if it has mmap() but /dev/zero | |
| 30 | + # does not exist, or if mmapping /dev/zero does not give anonymous | |
| 31 | + # zeroed pages with both the following properties: | |
| 32 | + # 1. If you map N consecutive pages in with one call, and then | |
| 33 | + # unmap any subset of those pages, the pages that were not | |
| 34 | + # explicitly unmapped remain accessible. | |
| 35 | + # 2. If you map two adjacent blocks of memory and then unmap them | |
| 36 | + # both at once, they must both go away. | |
| 37 | + # Systems known to be in this category are Windows (all variants), | |
| 38 | + # VMS, and Darwin. | |
| 39 | + case "$host_os" in | |
| 40 | + vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00) | |
| 41 | + ac_cv_func_mmap_dev_zero=no ;; | |
| 42 | + *) | |
| 43 | + ac_cv_func_mmap_dev_zero=yes;; | |
| 44 | + esac]) | |
| 45 | + | |
| 46 | + # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for. | |
| 47 | + AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon, | |
| 48 | + [AC_TRY_COMPILE( | |
| 49 | +[#include <sys/types.h> | |
| 50 | +#include <sys/mman.h> | |
| 51 | +#include <unistd.h> | |
| 52 | + | |
| 53 | +#ifndef MAP_ANONYMOUS | |
| 54 | +#define MAP_ANONYMOUS MAP_ANON | |
| 55 | +#endif | |
| 56 | +], | |
| 57 | +[int n = MAP_ANONYMOUS;], | |
| 58 | + ac_cv_decl_map_anon=yes, | |
| 59 | + ac_cv_decl_map_anon=no)]) | |
| 60 | + | |
| 61 | + if test $ac_cv_decl_map_anon = no; then | |
| 62 | + ac_cv_func_mmap_anon=no | |
| 63 | + else | |
| 64 | + AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works], | |
| 65 | + ac_cv_func_mmap_anon, | |
| 66 | + [# Add a system to this blacklist if it has mmap() and MAP_ANON or | |
| 67 | + # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) | |
| 68 | + # doesn't give anonymous zeroed pages with the same properties listed | |
| 69 | + # above for use of /dev/zero. | |
| 70 | + # Systems known to be in this category are Windows, VMS, and SCO Unix. | |
| 71 | + case "$host_os" in | |
| 72 | + vms* | cygwin* | pe | mingw* | sco* | udk* ) | |
| 73 | + ac_cv_func_mmap_anon=no ;; | |
| 74 | + *) | |
| 75 | + ac_cv_func_mmap_anon=yes;; | |
| 76 | + esac]) | |
| 77 | + fi | |
| 78 | +fi | |
| 79 | + | |
| 80 | +if test $ac_cv_func_mmap_file = yes; then | |
| 81 | + AC_DEFINE(HAVE_MMAP_FILE, 1, | |
| 82 | + [Define if read-only mmap of a plain file works.]) | |
| 83 | +fi | |
| 84 | +if test $ac_cv_func_mmap_dev_zero = yes; then | |
| 85 | + AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1, | |
| 86 | + [Define if mmap of /dev/zero works.]) | |
| 87 | +fi | |
| 88 | +if test $ac_cv_func_mmap_anon = yes; then | |
| 89 | + AC_DEFINE(HAVE_MMAP_ANON, 1, | |
| 90 | + [Define if mmap with MAP_ANON(YMOUS) works.]) | |
| 91 | +fi | |
| 92 | +]) | |
| @@ -0,0 +1,1453 @@ | ||
| 1 | +#! /bin/sh | |
| 2 | +# Attempt to guess a canonical system name. | |
| 3 | +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | |
| 4 | +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. | |
| 5 | + | |
| 6 | +timestamp='2004-11-12' | |
| 7 | + | |
| 8 | +# This file is free software; you can redistribute it and/or modify it | |
| 9 | +# under the terms of the GNU General Public License as published by | |
| 10 | +# the Free Software Foundation; either version 2 of the License, or | |
| 11 | +# (at your option) any later version. | |
| 12 | +# | |
| 13 | +# This program is distributed in the hope that it will be useful, but | |
| 14 | +# WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 16 | +# General Public License for more details. | |
| 17 | +# | |
| 18 | +# You should have received a copy of the GNU General Public License | |
| 19 | +# along with this program; if not, write to the Free Software | |
| 20 | +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 21 | +# | |
| 22 | +# As a special exception to the GNU General Public License, if you | |
| 23 | +# distribute this file as part of a program that contains a | |
| 24 | +# configuration script generated by Autoconf, you may include it under | |
| 25 | +# the same distribution terms that you use for the rest of that program. | |
| 26 | + | |
| 27 | +# Originally written by Per Bothner <per@bothner.com>. | |
| 28 | +# Please send patches to <config-patches@gnu.org>. Submit a context | |
| 29 | +# diff and a properly formatted ChangeLog entry. | |
| 30 | +# | |
| 31 | +# This script attempts to guess a canonical system name similar to | |
| 32 | +# config.sub. If it succeeds, it prints the system name on stdout, and | |
| 33 | +# exits with 0. Otherwise, it exits with 1. | |
| 34 | +# | |
| 35 | +# The plan is that this can be called by configure scripts if you | |
| 36 | +# don't specify an explicit build system type. | |
| 37 | + | |
| 38 | +me=`echo "$0" | sed -e 's,.*/,,'` | |
| 39 | + | |
| 40 | +usage="\ | |
| 41 | +Usage: $0 [OPTION] | |
| 42 | + | |
| 43 | +Output the configuration name of the system \`$me' is run on. | |
| 44 | + | |
| 45 | +Operation modes: | |
| 46 | + -h, --help print this help, then exit | |
| 47 | + -t, --time-stamp print date of last modification, then exit | |
| 48 | + -v, --version print version number, then exit | |
| 49 | + | |
| 50 | +Report bugs and patches to <config-patches@gnu.org>." | |
| 51 | + | |
| 52 | +version="\ | |
| 53 | +GNU config.guess ($timestamp) | |
| 54 | + | |
| 55 | +Originally written by Per Bothner. | |
| 56 | +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 | |
| 57 | +Free Software Foundation, Inc. | |
| 58 | + | |
| 59 | +This is free software; see the source for copying conditions. There is NO | |
| 60 | +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." | |
| 61 | + | |
| 62 | +help=" | |
| 63 | +Try \`$me --help' for more information." | |
| 64 | + | |
| 65 | +# Parse command line | |
| 66 | +while test $# -gt 0 ; do | |
| 67 | + case $1 in | |
| 68 | + --time-stamp | --time* | -t ) | |
| 69 | + echo "$timestamp" ; exit 0 ;; | |
| 70 | + --version | -v ) | |
| 71 | + echo "$version" ; exit 0 ;; | |
| 72 | + --help | --h* | -h ) | |
| 73 | + echo "$usage"; exit 0 ;; | |
| 74 | + -- ) # Stop option processing | |
| 75 | + shift; break ;; | |
| 76 | + - ) # Use stdin as input. | |
| 77 | + break ;; | |
| 78 | + -* ) | |
| 79 | + echo "$me: invalid option $1$help" >&2 | |
| 80 | + exit 1 ;; | |
| 81 | + * ) | |
| 82 | + break ;; | |
| 83 | + esac | |
| 84 | +done | |
| 85 | + | |
| 86 | +if test $# != 0; then | |
| 87 | + echo "$me: too many arguments$help" >&2 | |
| 88 | + exit 1 | |
| 89 | +fi | |
| 90 | + | |
| 91 | +trap 'exit 1' 1 2 15 | |
| 92 | + | |
| 93 | +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a | |
| 94 | +# compiler to aid in system detection is discouraged as it requires | |
| 95 | +# temporary files to be created and, as you can see below, it is a | |
| 96 | +# headache to deal with in a portable fashion. | |
| 97 | + | |
| 98 | +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still | |
| 99 | +# use `HOST_CC' if defined, but it is deprecated. | |
| 100 | + | |
| 101 | +# Portable tmp directory creation inspired by the Autoconf team. | |
| 102 | + | |
| 103 | +set_cc_for_build=' | |
| 104 | +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; | |
| 105 | +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; | |
| 106 | +: ${TMPDIR=/tmp} ; | |
| 107 | + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || | |
| 108 | + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || | |
| 109 | + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || | |
| 110 | + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; | |
| 111 | +dummy=$tmp/dummy ; | |
| 112 | +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; | |
| 113 | +case $CC_FOR_BUILD,$HOST_CC,$CC in | |
| 114 | + ,,) echo "int x;" > $dummy.c ; | |
| 115 | + for c in cc gcc c89 c99 ; do | |
| 116 | + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then | |
| 117 | + CC_FOR_BUILD="$c"; break ; | |
| 118 | + fi ; | |
| 119 | + done ; | |
| 120 | + if test x"$CC_FOR_BUILD" = x ; then | |
| 121 | + CC_FOR_BUILD=no_compiler_found ; | |
| 122 | + fi | |
| 123 | + ;; | |
| 124 | + ,,*) CC_FOR_BUILD=$CC ;; | |
| 125 | + ,*,*) CC_FOR_BUILD=$HOST_CC ;; | |
| 126 | +esac ;' | |
| 127 | + | |
| 128 | +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. | |
| 129 | +# (ghazi@noc.rutgers.edu 1994-08-24) | |
| 130 | +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then | |
| 131 | + PATH=$PATH:/.attbin ; export PATH | |
| 132 | +fi | |
| 133 | + | |
| 134 | +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown | |
| 135 | +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown | |
| 136 | +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown | |
| 137 | +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown | |
| 138 | + | |
| 139 | +# Note: order is significant - the case branches are not exclusive. | |
| 140 | + | |
| 141 | +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in | |
| 142 | + *:NetBSD:*:*) | |
| 143 | + # NetBSD (nbsd) targets should (where applicable) match one or | |
| 144 | + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, | |
| 145 | + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently | |
| 146 | + # switched to ELF, *-*-netbsd* would select the old | |
| 147 | + # object file format. This provides both forward | |
| 148 | + # compatibility and a consistent mechanism for selecting the | |
| 149 | + # object file format. | |
| 150 | + # | |
| 151 | + # Note: NetBSD doesn't particularly care about the vendor | |
| 152 | + # portion of the name. We always set it to "unknown". | |
| 153 | + sysctl="sysctl -n hw.machine_arch" | |
| 154 | + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ | |
| 155 | + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` | |
| 156 | + case "${UNAME_MACHINE_ARCH}" in | |
| 157 | + armeb) machine=armeb-unknown ;; | |
| 158 | + arm*) machine=arm-unknown ;; | |
| 159 | + sh3el) machine=shl-unknown ;; | |
| 160 | + sh3eb) machine=sh-unknown ;; | |
| 161 | + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; | |
| 162 | + esac | |
| 163 | + # The Operating System including object format, if it has switched | |
| 164 | + # to ELF recently, or will in the future. | |
| 165 | + case "${UNAME_MACHINE_ARCH}" in | |
| 166 | + arm*|i386|m68k|ns32k|sh3*|sparc|vax) | |
| 167 | + eval $set_cc_for_build | |
| 168 | + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | |
| 169 | + | grep __ELF__ >/dev/null | |
| 170 | + then | |
| 171 | + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). | |
| 172 | + # Return netbsd for either. FIX? | |
| 173 | + os=netbsd | |
| 174 | + else | |
| 175 | + os=netbsdelf | |
| 176 | + fi | |
| 177 | + ;; | |
| 178 | + *) | |
| 179 | + os=netbsd | |
| 180 | + ;; | |
| 181 | + esac | |
| 182 | + # The OS release | |
| 183 | + # Debian GNU/NetBSD machines have a different userland, and | |
| 184 | + # thus, need a distinct triplet. However, they do not need | |
| 185 | + # kernel version information, so it can be replaced with a | |
| 186 | + # suitable tag, in the style of linux-gnu. | |
| 187 | + case "${UNAME_VERSION}" in | |
| 188 | + Debian*) | |
| 189 | + release='-gnu' | |
| 190 | + ;; | |
| 191 | + *) | |
| 192 | + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` | |
| 193 | + ;; | |
| 194 | + esac | |
| 195 | + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: | |
| 196 | + # contains redundant information, the shorter form: | |
| 197 | + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. | |
| 198 | + echo "${machine}-${os}${release}" | |
| 199 | + exit 0 ;; | |
| 200 | + amd64:OpenBSD:*:*) | |
| 201 | + echo x86_64-unknown-openbsd${UNAME_RELEASE} | |
| 202 | + exit 0 ;; | |
| 203 | + amiga:OpenBSD:*:*) | |
| 204 | + echo m68k-unknown-openbsd${UNAME_RELEASE} | |
| 205 | + exit 0 ;; | |
| 206 | + cats:OpenBSD:*:*) | |
| 207 | + echo arm-unknown-openbsd${UNAME_RELEASE} | |
| 208 | + exit 0 ;; | |
| 209 | + hp300:OpenBSD:*:*) | |
| 210 | + echo m68k-unknown-openbsd${UNAME_RELEASE} | |
| 211 | + exit 0 ;; | |
| 212 | + luna88k:OpenBSD:*:*) | |
| 213 | + echo m88k-unknown-openbsd${UNAME_RELEASE} | |
| 214 | + exit 0 ;; | |
| 215 | + mac68k:OpenBSD:*:*) | |
| 216 | + echo m68k-unknown-openbsd${UNAME_RELEASE} | |
| 217 | + exit 0 ;; | |
| 218 | + macppc:OpenBSD:*:*) | |
| 219 | + echo powerpc-unknown-openbsd${UNAME_RELEASE} | |
| 220 | + exit 0 ;; | |
| 221 | + mvme68k:OpenBSD:*:*) | |
| 222 | + echo m68k-unknown-openbsd${UNAME_RELEASE} | |
| 223 | + exit 0 ;; | |
| 224 | + mvme88k:OpenBSD:*:*) | |
| 225 | + echo m88k-unknown-openbsd${UNAME_RELEASE} | |
| 226 | + exit 0 ;; | |
| 227 | + mvmeppc:OpenBSD:*:*) | |
| 228 | + echo powerpc-unknown-openbsd${UNAME_RELEASE} | |
| 229 | + exit 0 ;; | |
| 230 | + sgi:OpenBSD:*:*) | |
| 231 | + echo mips64-unknown-openbsd${UNAME_RELEASE} | |
| 232 | + exit 0 ;; | |
| 233 | + sun3:OpenBSD:*:*) | |
| 234 | + echo m68k-unknown-openbsd${UNAME_RELEASE} | |
| 235 | + exit 0 ;; | |
| 236 | + *:OpenBSD:*:*) | |
| 237 | + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} | |
| 238 | + exit 0 ;; | |
| 239 | + *:ekkoBSD:*:*) | |
| 240 | + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} | |
| 241 | + exit 0 ;; | |
| 242 | + macppc:MirBSD:*:*) | |
| 243 | + echo powerppc-unknown-mirbsd${UNAME_RELEASE} | |
| 244 | + exit 0 ;; | |
| 245 | + *:MirBSD:*:*) | |
| 246 | + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} | |
| 247 | + exit 0 ;; | |
| 248 | + alpha:OSF1:*:*) | |
| 249 | + case $UNAME_RELEASE in | |
| 250 | + *4.0) | |
| 251 | + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` | |
| 252 | + ;; | |
| 253 | + *5.*) | |
| 254 | + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` | |
| 255 | + ;; | |
| 256 | + esac | |
| 257 | + # According to Compaq, /usr/sbin/psrinfo has been available on | |
| 258 | + # OSF/1 and Tru64 systems produced since 1995. I hope that | |
| 259 | + # covers most systems running today. This code pipes the CPU | |
| 260 | + # types through head -n 1, so we only detect the type of CPU 0. | |
| 261 | + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` | |
| 262 | + case "$ALPHA_CPU_TYPE" in | |
| 263 | + "EV4 (21064)") | |
| 264 | + UNAME_MACHINE="alpha" ;; | |
| 265 | + "EV4.5 (21064)") | |
| 266 | + UNAME_MACHINE="alpha" ;; | |
| 267 | + "LCA4 (21066/21068)") | |
| 268 | + UNAME_MACHINE="alpha" ;; | |
| 269 | + "EV5 (21164)") | |
| 270 | + UNAME_MACHINE="alphaev5" ;; | |
| 271 | + "EV5.6 (21164A)") | |
| 272 | + UNAME_MACHINE="alphaev56" ;; | |
| 273 | + "EV5.6 (21164PC)") | |
| 274 | + UNAME_MACHINE="alphapca56" ;; | |
| 275 | + "EV5.7 (21164PC)") | |
| 276 | + UNAME_MACHINE="alphapca57" ;; | |
| 277 | + "EV6 (21264)") | |
| 278 | + UNAME_MACHINE="alphaev6" ;; | |
| 279 | + "EV6.7 (21264A)") | |
| 280 | + UNAME_MACHINE="alphaev67" ;; | |
| 281 | + "EV6.8CB (21264C)") | |
| 282 | + UNAME_MACHINE="alphaev68" ;; | |
| 283 | + "EV6.8AL (21264B)") | |
| 284 | + UNAME_MACHINE="alphaev68" ;; | |
| 285 | + "EV6.8CX (21264D)") | |
| 286 | + UNAME_MACHINE="alphaev68" ;; | |
| 287 | + "EV6.9A (21264/EV69A)") | |
| 288 | + UNAME_MACHINE="alphaev69" ;; | |
| 289 | + "EV7 (21364)") | |
| 290 | + UNAME_MACHINE="alphaev7" ;; | |
| 291 | + "EV7.9 (21364A)") | |
| 292 | + UNAME_MACHINE="alphaev79" ;; | |
| 293 | + esac | |
| 294 | + # A Pn.n version is a patched version. | |
| 295 | + # A Vn.n version is a released version. | |
| 296 | + # A Tn.n version is a released field test version. | |
| 297 | + # A Xn.n version is an unreleased experimental baselevel. | |
| 298 | + # 1.2 uses "1.2" for uname -r. | |
| 299 | + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` | |
| 300 | + exit 0 ;; | |
| 301 | + Alpha\ *:Windows_NT*:*) | |
| 302 | + # How do we know it's Interix rather than the generic POSIX subsystem? | |
| 303 | + # Should we change UNAME_MACHINE based on the output of uname instead | |
| 304 | + # of the specific Alpha model? | |
| 305 | + echo alpha-pc-interix | |
| 306 | + exit 0 ;; | |
| 307 | + 21064:Windows_NT:50:3) | |
| 308 | + echo alpha-dec-winnt3.5 | |
| 309 | + exit 0 ;; | |
| 310 | + Amiga*:UNIX_System_V:4.0:*) | |
| 311 | + echo m68k-unknown-sysv4 | |
| 312 | + exit 0;; | |
| 313 | + *:[Aa]miga[Oo][Ss]:*:*) | |
| 314 | + echo ${UNAME_MACHINE}-unknown-amigaos | |
| 315 | + exit 0 ;; | |
| 316 | + *:[Mm]orph[Oo][Ss]:*:*) | |
| 317 | + echo ${UNAME_MACHINE}-unknown-morphos | |
| 318 | + exit 0 ;; | |
| 319 | + *:OS/390:*:*) | |
| 320 | + echo i370-ibm-openedition | |
| 321 | + exit 0 ;; | |
| 322 | + *:z/VM:*:*) | |
| 323 | + echo s390-ibm-zvmoe | |
| 324 | + exit 0 ;; | |
| 325 | + *:OS400:*:*) | |
| 326 | + echo powerpc-ibm-os400 | |
| 327 | + exit 0 ;; | |
| 328 | + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) | |
| 329 | + echo arm-acorn-riscix${UNAME_RELEASE} | |
| 330 | + exit 0;; | |
| 331 | + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) | |
| 332 | + echo hppa1.1-hitachi-hiuxmpp | |
| 333 | + exit 0;; | |
| 334 | + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) | |
| 335 | + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. | |
| 336 | + if test "`(/bin/universe) 2>/dev/null`" = att ; then | |
| 337 | + echo pyramid-pyramid-sysv3 | |
| 338 | + else | |
| 339 | + echo pyramid-pyramid-bsd | |
| 340 | + fi | |
| 341 | + exit 0 ;; | |
| 342 | + NILE*:*:*:dcosx) | |
| 343 | + echo pyramid-pyramid-svr4 | |
| 344 | + exit 0 ;; | |
| 345 | + DRS?6000:unix:4.0:6*) | |
| 346 | + echo sparc-icl-nx6 | |
| 347 | + exit 0 ;; | |
| 348 | + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) | |
| 349 | + case `/usr/bin/uname -p` in | |
| 350 | + sparc) echo sparc-icl-nx7 && exit 0 ;; | |
| 351 | + esac ;; | |
| 352 | + sun4H:SunOS:5.*:*) | |
| 353 | + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` | |
| 354 | + exit 0 ;; | |
| 355 | + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) | |
| 356 | + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` | |
| 357 | + exit 0 ;; | |
| 358 | + i86pc:SunOS:5.*:*) | |
| 359 | + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` | |
| 360 | + exit 0 ;; | |
| 361 | + sun4*:SunOS:6*:*) | |
| 362 | + # According to config.sub, this is the proper way to canonicalize | |
| 363 | + # SunOS6. Hard to guess exactly what SunOS6 will be like, but | |
| 364 | + # it's likely to be more like Solaris than SunOS4. | |
| 365 | + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` | |
| 366 | + exit 0 ;; | |
| 367 | + sun4*:SunOS:*:*) | |
| 368 | + case "`/usr/bin/arch -k`" in | |
| 369 | + Series*|S4*) | |
| 370 | + UNAME_RELEASE=`uname -v` | |
| 371 | + ;; | |
| 372 | + esac | |
| 373 | + # Japanese Language versions have a version number like `4.1.3-JL'. | |
| 374 | + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` | |
| 375 | + exit 0 ;; | |
| 376 | + sun3*:SunOS:*:*) | |
| 377 | + echo m68k-sun-sunos${UNAME_RELEASE} | |
| 378 | + exit 0 ;; | |
| 379 | + sun*:*:4.2BSD:*) | |
| 380 | + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` | |
| 381 | + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 | |
| 382 | + case "`/bin/arch`" in | |
| 383 | + sun3) | |
| 384 | + echo m68k-sun-sunos${UNAME_RELEASE} | |
| 385 | + ;; | |
| 386 | + sun4) | |
| 387 | + echo sparc-sun-sunos${UNAME_RELEASE} | |
| 388 | + ;; | |
| 389 | + esac | |
| 390 | + exit 0 ;; | |
| 391 | + aushp:SunOS:*:*) | |
| 392 | + echo sparc-auspex-sunos${UNAME_RELEASE} | |
| 393 | + exit 0 ;; | |
| 394 | + # The situation for MiNT is a little confusing. The machine name | |
| 395 | + # can be virtually everything (everything which is not | |
| 396 | + # "atarist" or "atariste" at least should have a processor | |
| 397 | + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" | |
| 398 | + # to the lowercase version "mint" (or "freemint"). Finally | |
| 399 | + # the system name "TOS" denotes a system which is actually not | |
| 400 | + # MiNT. But MiNT is downward compatible to TOS, so this should | |
| 401 | + # be no problem. | |
| 402 | + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) | |
| 403 | + echo m68k-atari-mint${UNAME_RELEASE} | |
| 404 | + exit 0 ;; | |
| 405 | + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) | |
| 406 | + echo m68k-atari-mint${UNAME_RELEASE} | |
| 407 | + exit 0 ;; | |
| 408 | + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) | |
| 409 | + echo m68k-atari-mint${UNAME_RELEASE} | |
| 410 | + exit 0 ;; | |
| 411 | + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) | |
| 412 | + echo m68k-milan-mint${UNAME_RELEASE} | |
| 413 | + exit 0 ;; | |
| 414 | + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) | |
| 415 | + echo m68k-hades-mint${UNAME_RELEASE} | |
| 416 | + exit 0 ;; | |
| 417 | + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) | |
| 418 | + echo m68k-unknown-mint${UNAME_RELEASE} | |
| 419 | + exit 0 ;; | |
| 420 | + m68k:machten:*:*) | |
| 421 | + echo m68k-apple-machten${UNAME_RELEASE} | |
| 422 | + exit 0 ;; | |
| 423 | + powerpc:machten:*:*) | |
| 424 | + echo powerpc-apple-machten${UNAME_RELEASE} | |
| 425 | + exit 0 ;; | |
| 426 | + RISC*:Mach:*:*) | |
| 427 | + echo mips-dec-mach_bsd4.3 | |
| 428 | + exit 0 ;; | |
| 429 | + RISC*:ULTRIX:*:*) | |
| 430 | + echo mips-dec-ultrix${UNAME_RELEASE} | |
| 431 | + exit 0 ;; | |
| 432 | + VAX*:ULTRIX*:*:*) | |
| 433 | + echo vax-dec-ultrix${UNAME_RELEASE} | |
| 434 | + exit 0 ;; | |
| 435 | + 2020:CLIX:*:* | 2430:CLIX:*:*) | |
| 436 | + echo clipper-intergraph-clix${UNAME_RELEASE} | |
| 437 | + exit 0 ;; | |
| 438 | + mips:*:*:UMIPS | mips:*:*:RISCos) | |
| 439 | + eval $set_cc_for_build | |
| 440 | + sed 's/^ //' << EOF >$dummy.c | |
| 441 | +#ifdef __cplusplus | |
| 442 | +#include <stdio.h> /* for printf() prototype */ | |
| 443 | + int main (int argc, char *argv[]) { | |
| 444 | +#else | |
| 445 | + int main (argc, argv) int argc; char *argv[]; { | |
| 446 | +#endif | |
| 447 | + #if defined (host_mips) && defined (MIPSEB) | |
| 448 | + #if defined (SYSTYPE_SYSV) | |
| 449 | + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); | |
| 450 | + #endif | |
| 451 | + #if defined (SYSTYPE_SVR4) | |
| 452 | + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); | |
| 453 | + #endif | |
| 454 | + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) | |
| 455 | + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); | |
| 456 | + #endif | |
| 457 | + #endif | |
| 458 | + exit (-1); | |
| 459 | + } | |
| 460 | +EOF | |
| 461 | + $CC_FOR_BUILD -o $dummy $dummy.c \ | |
| 462 | + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ | |
| 463 | + && exit 0 | |
| 464 | + echo mips-mips-riscos${UNAME_RELEASE} | |
| 465 | + exit 0 ;; | |
| 466 | + Motorola:PowerMAX_OS:*:*) | |
| 467 | + echo powerpc-motorola-powermax | |
| 468 | + exit 0 ;; | |
| 469 | + Motorola:*:4.3:PL8-*) | |
| 470 | + echo powerpc-harris-powermax | |
| 471 | + exit 0 ;; | |
| 472 | + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) | |
| 473 | + echo powerpc-harris-powermax | |
| 474 | + exit 0 ;; | |
| 475 | + Night_Hawk:Power_UNIX:*:*) | |
| 476 | + echo powerpc-harris-powerunix | |
| 477 | + exit 0 ;; | |
| 478 | + m88k:CX/UX:7*:*) | |
| 479 | + echo m88k-harris-cxux7 | |
| 480 | + exit 0 ;; | |
| 481 | + m88k:*:4*:R4*) | |
| 482 | + echo m88k-motorola-sysv4 | |
| 483 | + exit 0 ;; | |
| 484 | + m88k:*:3*:R3*) | |
| 485 | + echo m88k-motorola-sysv3 | |
| 486 | + exit 0 ;; | |
| 487 | + AViiON:dgux:*:*) | |
| 488 | + # DG/UX returns AViiON for all architectures | |
| 489 | + UNAME_PROCESSOR=`/usr/bin/uname -p` | |
| 490 | + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] | |
| 491 | + then | |
| 492 | + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ | |
| 493 | + [ ${TARGET_BINARY_INTERFACE}x = x ] | |
| 494 | + then | |
| 495 | + echo m88k-dg-dgux${UNAME_RELEASE} | |
| 496 | + else | |
| 497 | + echo m88k-dg-dguxbcs${UNAME_RELEASE} | |
| 498 | + fi | |
| 499 | + else | |
| 500 | + echo i586-dg-dgux${UNAME_RELEASE} | |
| 501 | + fi | |
952 more lines aren’t shown here.
This diff is large: its 1570 lines aren’t shown here.
This diff is large: its 6865 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 314 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 295 lines aren’t shown here.
This diff is large: its 253 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 360 lines aren’t shown here.
This diff is large: its 186 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 382 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 216 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 131 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 563 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 556 lines aren’t shown here.
This diff is large: its 248 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 177 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 649 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 321 lines aren’t shown here.
This diff is large: its 378 lines aren’t shown here.
This diff is large: its 626 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 308 lines aren’t shown here.
This diff is large: its 226 lines aren’t shown here.
This diff is large: its 248 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 248 lines aren’t shown here.
This diff is large: its 320 lines aren’t shown here.
This diff is large: its 1250 lines aren’t shown here.
This diff is large: its 772 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 207 lines aren’t shown here.
This diff is large: its 324 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 752 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 430 lines aren’t shown here.
This diff is large: its 729 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 846 lines aren’t shown here.
This diff is large: its 452 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 526 lines aren’t shown here.
This diff is large: its 609 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 268 lines aren’t shown here.
This diff is large: its 303 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 470 lines aren’t shown here.
This diff is large: its 570 lines aren’t shown here.
This diff is large: its 595 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 383 lines aren’t shown here.
This diff is large: its 413 lines aren’t shown here.
This diff is large: its 374 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 311 lines aren’t shown here.
This diff is large: its 318 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 229 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 501 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 395 lines aren’t shown here.
This diff is large: its 318 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 268 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 495 lines aren’t shown here.
This diff is large: its 481 lines aren’t shown here.
This diff is large: its 2761 lines aren’t shown here.
This diff is large: its 2816 lines aren’t shown here.
This diff is large: its 278 lines aren’t shown here.
This diff is large: its 488 lines aren’t shown here.
This diff is large: its 620 lines aren’t shown here.
This diff is large: its 1648 lines aren’t shown here.
This diff is large: its 789 lines aren’t shown here.
This diff is large: its 876 lines aren’t shown here.
This diff is large: its 581 lines aren’t shown here.
This diff is large: its 376 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 1256 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 1058 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 410 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 203 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 433 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 3430 lines aren’t shown here.
This diff is large: its 727 lines aren’t shown here.
This diff is large: its 1897 lines aren’t shown here.
This diff is large: its 899 lines aren’t shown here.
This diff is large: its 3166 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 177 lines aren’t shown here.
This diff is large: its 3227 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 2142 lines aren’t shown here.
This diff is large: its 1613 lines aren’t shown here.
This diff is large: its 1351 lines aren’t shown here.
This diff is large: its 859 lines aren’t shown here.
This diff is large: its 2231 lines aren’t shown here.
This diff is large: its 5758 lines aren’t shown here.
This diff is large: its 746 lines aren’t shown here.
This diff is large: its 797 lines aren’t shown here.
This diff is large: its 521 lines aren’t shown here.
This diff is large: its 311 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 444 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 1132 lines aren’t shown here.
This diff is large: its 732 lines aren’t shown here.
This diff is large: its 356 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 399 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 4104 lines aren’t shown here.
This diff is large: its 2341 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 4766 lines aren’t shown here.
This diff is large: its 3252 lines aren’t shown here.
This diff is large: its 2634 lines aren’t shown here.
This diff is large: its 1794 lines aren’t shown here.
This diff is large: its 139 lines aren’t shown here.
This diff is large: its 2560 lines aren’t shown here.
This diff is large: its 427 lines aren’t shown here.
This diff is large: its 1371 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 1365 lines aren’t shown here.
This diff is large: its 4989 lines aren’t shown here.
This diff is large: its 371 lines aren’t shown here.
This diff is large: its 279 lines aren’t shown here.
This diff is large: its 789 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 1014 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 6269 lines aren’t shown here.
This diff is large: its 1331 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 1640 lines aren’t shown here.
This diff is large: its 317 lines aren’t shown here.
This diff is large: its 1780 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 608 lines aren’t shown here.
This diff is large: its 2140 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 304 lines aren’t shown here.
This diff is large: its 187 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
This diff is large: its 1391 lines aren’t shown here.
This diff is large: its 516 lines aren’t shown here.
This diff is large: its 639 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 215 lines aren’t shown here.
This diff is large: its 695 lines aren’t shown here.
This diff is large: its 7629 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 786 lines aren’t shown here.
This diff is large: its 505 lines aren’t shown here.
This diff is large: its 2551 lines aren’t shown here.
This diff is large: its 188 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 503 lines aren’t shown here.
This diff is large: its 585 lines aren’t shown here.
This diff is large: its 298 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 377 lines aren’t shown here.
This diff is large: its 382 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 313 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 1187 lines aren’t shown here.
This diff is large: its 445 lines aren’t shown here.
This diff is large: its 603 lines aren’t shown here.
This diff is large: its 1139 lines aren’t shown here.
This diff is large: its 3280 lines aren’t shown here.
This diff is large: its 8753 lines aren’t shown here.
This diff is large: its 989 lines aren’t shown here.
This diff is large: its 199 lines aren’t shown here.
This diff is large: its 2150 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 942 lines aren’t shown here.
This diff is large: its 326 lines aren’t shown here.
This diff is large: its 781 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 735 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 702 lines aren’t shown here.
This diff is large: its 770 lines aren’t shown here.
This diff is large: its 594 lines aren’t shown here.
This diff is large: its 677 lines aren’t shown here.
This diff is large: its 5101 lines aren’t shown here.
This diff is large: its 253 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 1249 lines aren’t shown here.
This diff is large: its 466 lines aren’t shown here.
This diff is large: its 967 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 224 lines aren’t shown here.
This diff is large: its 927 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 721 lines aren’t shown here.
This diff is large: its 1031 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 1224 lines aren’t shown here.
This diff is large: its 5136 lines aren’t shown here.
This diff is large: its 12544 lines aren’t shown here.
This diff is large: its 377 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 1192 lines aren’t shown here.
This diff is large: its 856 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 460 lines aren’t shown here.
This diff is large: its 424 lines aren’t shown here.
This diff is large: its 442 lines aren’t shown here.
This diff is large: its 1737 lines aren’t shown here.
This diff is large: its 332 lines aren’t shown here.
This diff is large: its 566 lines aren’t shown here.
This diff is large: its 1027 lines aren’t shown here.
This diff is large: its 624 lines aren’t shown here.
This diff is large: its 319 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.