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.