1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Write Python objects to files and read them back.
33 This is intended for writing and reading compiled Python code only;
34 a true persistent storage facility would be much harder, since
35 it would have to take circular links and sharing into account. */
38 #include "longintrepr.h"
44 #define TYPE_ELLIPSIS '.'
46 #define TYPE_INT64 'I'
47 #define TYPE_FLOAT 'f'
48 #define TYPE_COMPLEX 'x'
50 #define TYPE_STRING 's'
51 #define TYPE_TUPLE '('
55 #define TYPE_UNKNOWN '?'
60 /* If fp == NULL, the following are valid: */
66 #define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \
67 else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \
77 return; /* An error already occurred */
78 size
= PyString_Size(p
->str
);
79 newsize
= size
+ 1024;
80 if (_PyString_Resize(&p
->str
, newsize
) != 0) {
81 p
->ptr
= p
->end
= NULL
;
84 p
->ptr
= PyString_AS_STRING((PyStringObject
*)p
->str
) + size
;
86 PyString_AS_STRING((PyStringObject
*)p
->str
) + newsize
;
98 fwrite(s
, 1, n
, p
->fp
);
113 w_byte( x
& 0xff, p
);
114 w_byte((x
>> 8) & 0xff, p
);
122 w_byte((int)( x
& 0xff), p
);
123 w_byte((int)((x
>> 8) & 0xff), p
);
124 w_byte((int)((x
>>16) & 0xff), p
);
125 w_byte((int)((x
>>24) & 0xff), p
);
148 w_byte(TYPE_NULL
, p
);
150 else if (v
== Py_None
) {
151 w_byte(TYPE_NONE
, p
);
153 else if (v
== Py_Ellipsis
) {
154 w_byte(TYPE_ELLIPSIS
, p
);
156 else if (PyInt_Check(v
)) {
157 long x
= PyInt_AS_LONG((PyIntObject
*)v
);
161 w_byte(TYPE_INT64
, p
);
171 else if (PyLong_Check(v
)) {
172 PyLongObject
*ob
= (PyLongObject
*)v
;
173 w_byte(TYPE_LONG
, p
);
178 for (i
= 0; i
< n
; i
++)
179 w_short(ob
->ob_digit
[i
], p
);
181 else if (PyFloat_Check(v
)) {
182 extern void PyFloat_AsString
183 Py_PROTO((char *, PyFloatObject
*));
184 char buf
[256]; /* Plenty to format any double */
185 PyFloat_AsString(buf
, (PyFloatObject
*)v
);
187 w_byte(TYPE_FLOAT
, p
);
191 #ifndef WITHOUT_COMPLEX
192 else if (PyComplex_Check(v
)) {
193 extern void PyFloat_AsString
194 Py_PROTO((char *, PyFloatObject
*));
195 char buf
[256]; /* Plenty to format any double */
197 w_byte(TYPE_COMPLEX
, p
);
198 temp
= (PyFloatObject
*)PyFloat_FromDouble(
199 PyComplex_RealAsDouble(v
));
200 PyFloat_AsString(buf
, temp
);
205 temp
= (PyFloatObject
*)PyFloat_FromDouble(
206 PyComplex_ImagAsDouble(v
));
207 PyFloat_AsString(buf
, temp
);
214 else if (PyString_Check(v
)) {
215 w_byte(TYPE_STRING
, p
);
216 n
= PyString_Size(v
);
218 w_string(PyString_AsString(v
), n
, p
);
220 else if (PyTuple_Check(v
)) {
221 w_byte(TYPE_TUPLE
, p
);
224 for (i
= 0; i
< n
; i
++) {
225 w_object(PyTuple_GET_ITEM(v
, i
), p
);
228 else if (PyList_Check(v
)) {
229 w_byte(TYPE_LIST
, p
);
232 for (i
= 0; i
< n
; i
++) {
233 w_object(PyList_GetItem(v
, i
), p
);
236 else if (PyDict_Check(v
)) {
238 PyObject
*key
, *value
;
239 w_byte(TYPE_DICT
, p
);
240 /* This one is NULL object terminated! */
242 while (PyDict_Next(v
, &pos
, &key
, &value
)) {
246 w_object((PyObject
*)NULL
, p
);
248 else if (PyCode_Check(v
)) {
249 PyCodeObject
*co
= (PyCodeObject
*)v
;
250 w_byte(TYPE_CODE
, p
);
251 w_short(co
->co_argcount
, p
);
252 w_short(co
->co_nlocals
, p
);
253 w_short(co
->co_stacksize
, p
);
254 w_short(co
->co_flags
, p
);
255 w_object(co
->co_code
, p
);
256 w_object(co
->co_consts
, p
);
257 w_object(co
->co_names
, p
);
258 w_object(co
->co_varnames
, p
);
259 w_object(co
->co_filename
, p
);
260 w_object(co
->co_name
, p
);
261 w_short(co
->co_firstlineno
, p
);
262 w_object(co
->co_lnotab
, p
);
264 else if ((pb
= v
->ob_type
->tp_as_buffer
) != NULL
&&
265 pb
->bf_getsegcount
!= NULL
&&
266 pb
->bf_getreadbuffer
!= NULL
&&
267 (*pb
->bf_getsegcount
)(v
, NULL
) == 1)
269 /* Write unknown buffer-style objects as a string */
271 w_byte(TYPE_STRING
, p
);
272 n
= (*pb
->bf_getreadbuffer
)(v
, 0, (void **)&s
);
277 w_byte(TYPE_UNKNOWN
, p
);
283 PyMarshal_WriteLongToFile(x
, fp
)
294 PyMarshal_WriteObjectToFile(x
, fp
)
304 typedef WFILE RFILE
; /* Same struct with different invariants */
306 #define rs_byte(p) (((p)->ptr != (p)->end) ? (unsigned char)*(p)->ptr++ : EOF)
308 #define r_byte(p) ((p)->fp ? getc((p)->fp) : rs_byte(p))
317 return fread(s
, 1, n
, p
->fp
);
318 if (p
->end
- p
->ptr
< n
)
320 memcpy(s
, p
->ptr
, n
);
332 /* XXX If your short is > 16 bits, add sign-extension here!!! */
341 register FILE *fp
= p
->fp
;
344 x
|= (long)getc(fp
) << 8;
345 x
|= (long)getc(fp
) << 16;
346 x
|= (long)getc(fp
) << 24;
350 x
|= (long)rs_byte(p
) << 8;
351 x
|= (long)rs_byte(p
) << 16;
352 x
|= (long)rs_byte(p
) << 24;
355 /* Sign extension for 64-bit machines */
356 x
<<= (8*sizeof(long) - 32);
357 x
>>= (8*sizeof(long) - 32);
369 x
= (x
& 0xFFFFFFFF) | (r_long(p
) << 32);
371 if (r_long(p
) != 0) {
372 PyObject
*f
= PySys_GetObject("stderr");
374 (void) PyFile_WriteString(
375 "Warning: un-marshal 64-bit int in 32-bit mode\n",
388 int type
= r_byte(p
);
393 PyErr_SetString(PyExc_EOFError
,
394 "EOF read where object expected");
405 Py_INCREF(Py_Ellipsis
);
409 return PyInt_FromLong(r_long(p
));
412 return PyInt_FromLong(r_long64(p
));
420 ob
= _PyLong_New(size
);
424 for (i
= 0; i
< size
; i
++)
425 ob
->ob_digit
[i
] = r_short(p
);
426 return (PyObject
*)ob
;
431 extern double atof
Py_PROTO((const char *));
435 if (r_string(buf
, (int)n
, p
) != n
) {
436 PyErr_SetString(PyExc_EOFError
,
437 "EOF read where object expected");
441 PyFPE_START_PROTECT("atof", return 0)
443 PyFPE_END_PROTECT(dx
)
444 return PyFloat_FromDouble(dx
);
447 #ifndef WITHOUT_COMPLEX
450 extern double atof
Py_PROTO((const char *));
454 if (r_string(buf
, (int)n
, p
) != n
) {
455 PyErr_SetString(PyExc_EOFError
,
456 "EOF read where object expected");
460 PyFPE_START_PROTECT("atof", return 0)
464 if (r_string(buf
, (int)n
, p
) != n
) {
465 PyErr_SetString(PyExc_EOFError
,
466 "EOF read where object expected");
470 PyFPE_START_PROTECT("atof", return 0)
473 return PyComplex_FromCComplex(c
);
480 PyErr_SetString(PyExc_ValueError
, "bad marshal data");
483 v
= PyString_FromStringAndSize((char *)NULL
, n
);
485 if (r_string(PyString_AsString(v
), (int)n
, p
) != n
) {
488 PyErr_SetString(PyExc_EOFError
,
489 "EOF read where object expected");
497 PyErr_SetString(PyExc_ValueError
, "bad marshal data");
500 v
= PyTuple_New((int)n
);
503 for (i
= 0; i
< n
; i
++) {
510 PyTuple_SET_ITEM(v
, (int)i
, v2
);
517 PyErr_SetString(PyExc_ValueError
, "bad marshal data");
520 v
= PyList_New((int)n
);
523 for (i
= 0; i
< n
; i
++) {
530 PyList_SetItem(v
, (int)i
, v2
);
542 break; /* XXX Assume TYPE_NULL, not an error */
545 PyDict_SetItem(v
, key
, val
);
553 int argcount
= r_short(p
);
554 int nlocals
= r_short(p
);
555 int stacksize
= r_short(p
);
556 int flags
= r_short(p
);
557 PyObject
*code
= NULL
;
558 PyObject
*consts
= NULL
;
559 PyObject
*names
= NULL
;
560 PyObject
*varnames
= NULL
;
561 PyObject
*filename
= NULL
;
562 PyObject
*name
= NULL
;
564 PyObject
*lnotab
= NULL
;
567 if (code
) consts
= r_object(p
);
568 if (consts
) names
= r_object(p
);
569 if (names
) varnames
= r_object(p
);
570 if (varnames
) filename
= r_object(p
);
571 if (filename
) name
= r_object(p
);
573 firstlineno
= r_short(p
);
574 lnotab
= r_object(p
);
577 if (!PyErr_Occurred()) {
578 v
= (PyObject
*) PyCode_New(
579 argcount
, nlocals
, stacksize
, flags
,
580 code
, consts
, names
, varnames
,
581 filename
, name
, firstlineno
, lnotab
);
588 Py_XDECREF(varnames
);
589 Py_XDECREF(filename
);
597 /* Bogus data got written, which isn't ideal.
598 This will let you keep working and recover. */
599 PyErr_SetString(PyExc_ValueError
, "bad marshal data");
606 PyMarshal_ReadLongFromFile(fp
)
615 PyMarshal_ReadObjectFromFile(fp
)
619 if (PyErr_Occurred()) {
620 fprintf(stderr
, "XXX rd_object called with exception set\n");
624 return r_object(&rf
);
628 PyMarshal_ReadObjectFromString(str
, len
)
633 if (PyErr_Occurred()) {
634 fprintf(stderr
, "XXX rds_object called with exception set\n");
641 return r_object(&rf
);
645 PyMarshal_WriteObjectToString(x
) /* wrs_object() */
650 wf
.str
= PyString_FromStringAndSize((char *)NULL
, 50);
653 wf
.ptr
= PyString_AS_STRING((PyStringObject
*)wf
.str
);
654 wf
.end
= wf
.ptr
+ PyString_Size(wf
.str
);
658 _PyString_Resize(&wf
.str
,
660 PyString_AS_STRING((PyStringObject
*)wf
.str
)));
663 PyErr_SetString(PyExc_ValueError
, "unmarshallable object");
669 /* And an interface for Python programs... */
672 marshal_dump(self
, args
)
679 if (!PyArg_Parse(args
, "(OO)", &x
, &f
))
681 if (!PyFile_Check(f
)) {
682 PyErr_SetString(PyExc_TypeError
,
683 "marshal.dump() 2nd arg must be file");
686 wf
.fp
= PyFile_AsFile(f
);
688 wf
.ptr
= wf
.end
= NULL
;
692 PyErr_SetString(PyExc_ValueError
, "unmarshallable object");
700 marshal_load(self
, args
)
707 if (!PyArg_Parse(args
, "O", &f
))
709 if (!PyFile_Check(f
)) {
710 PyErr_SetString(PyExc_TypeError
,
711 "marshal.load() arg must be file");
714 rf
.fp
= PyFile_AsFile(f
);
716 rf
.ptr
= rf
.end
= NULL
;
719 if (PyErr_Occurred()) {
727 marshal_dumps(self
, args
)
732 if (!PyArg_Parse(args
, "O", &x
))
734 return PyMarshal_WriteObjectToString(x
);
738 marshal_loads(self
, args
)
746 if (!PyArg_Parse(args
, "s#", &s
, &n
))
754 if (PyErr_Occurred()) {
761 static PyMethodDef marshal_methods
[] = {
762 {"dump", marshal_dump
},
763 {"load", marshal_load
},
764 {"dumps", marshal_dumps
},
765 {"loads", marshal_loads
},
766 {NULL
, NULL
} /* sentinel */
772 (void) Py_InitModule("marshal", marshal_methods
);