blob: 2049c9b254776e5e446cff67ea65ae7404d76021 [file] [log] [blame]
Guido van Rossumdce2e3d1991-06-04 19:42:30 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Write Python objects to files and read them back.
26 This is intended for writing and reading compiled Python code only;
27 a true persistent storage facility would be much harder, since
28 it would have to take circular links and sharing into account. */
29
30#include "allobjects.h"
31#include "longintrepr.h"
32#include "compile.h"
33#include "marshal.h"
34
35#include <errno.h>
Guido van Rossum065d71e1991-06-04 20:23:28 +000036extern int errno;
Guido van Rossumdce2e3d1991-06-04 19:42:30 +000037
38#define TYPE_NULL '0'
39#define TYPE_NONE 'N'
40#define TYPE_INT 'i'
41#define TYPE_FLOAT 'f'
42#define TYPE_LONG 'l'
43#define TYPE_STRING 's'
44#define TYPE_TUPLE '('
45#define TYPE_LIST '['
46#define TYPE_DICT '{'
47#define TYPE_CODE 'C'
48#define TYPE_UNKNOWN '?'
49
50#define wr_byte(c, fp) putc((c), (fp))
51
52void
53wr_short(x, fp)
54 int x;
55 FILE *fp;
56{
57 wr_byte( x & 0xff, fp);
58 wr_byte((x>> 8) & 0xff, fp);
59}
60
61void
62wr_long(x, fp)
63 long x;
64 FILE *fp;
65{
66 wr_byte((int)( x & 0xff), fp);
67 wr_byte((int)((x>> 8) & 0xff), fp);
68 wr_byte((int)((x>>16) & 0xff), fp);
69 wr_byte((int)((x>>24) & 0xff), fp);
70}
71
72void
73wr_object(v, fp)
74 object *v;
75 FILE *fp;
76{
77 long i, n;
78
79 if (v == NULL)
80 wr_byte(TYPE_NULL, fp);
81 else if (v == None)
82 wr_byte(TYPE_NONE, fp);
83 else if (is_intobject(v)) {
84 wr_byte(TYPE_INT, fp);
85 wr_long(getintvalue(v), fp);
86 }
87 else if (is_longobject(v)) {
88 longobject *ob = (longobject *)v;
89 wr_byte(TYPE_LONG, fp);
90 n = ob->ob_size;
91 wr_long((long)n, fp);
92 if (n < 0)
93 n = -n;
94 for (i = 0; i < n; i++)
95 wr_short(ob->ob_digit[i], fp);
96 }
97 else if (is_floatobject(v)) {
98 extern void float_buf_repr PROTO((char *, floatobject *));
99 char buf[256]; /* Plenty to format any double */
100 float_buf_repr(buf, (floatobject *)v);
101 n = strlen(buf);
102 wr_byte(TYPE_FLOAT, fp);
103 wr_byte((int)n, fp);
104 fwrite(buf, 1, (int)n, fp);
105 }
106 else if (is_stringobject(v)) {
107 wr_byte(TYPE_STRING, fp);
108 n = getstringsize(v);
109 wr_long(n, fp);
110 fwrite(getstringvalue(v), 1, (int)n, fp);
111 }
112 else if (is_tupleobject(v)) {
113 wr_byte(TYPE_TUPLE, fp);
114 n = gettuplesize(v);
115 wr_long(n, fp);
116 for (i = 0; i < n; i++) {
117 wr_object(gettupleitem(v, (int)i), fp);
118 }
119 }
120 else if (is_listobject(v)) {
121 wr_byte(TYPE_LIST, fp);
122 n = getlistsize(v);
123 wr_long(n, fp);
124 for (i = 0; i < n; i++) {
125 wr_object(getlistitem(v, (int)i), fp);
126 }
127 }
Guido van Rossum64b45521991-06-07 13:58:22 +0000128 else if (is_dictobject(v)) {
129 wr_byte(TYPE_DICT, fp);
130 /* This one is NULL object terminated! */
131 n = getdictsize(v);
132 for (i = 0; i < n; i++) {
133 object *key, *val;
134 extern object *getdict2key();
135 key = getdict2key(v, (int)i);
136 if (key != NULL) {
137 val = dictlookup(v, getstringvalue(key));
138 wr_object(key, fp);
139 wr_object(val, fp);
140 }
141 }
142 wr_object((object *)NULL, fp);
143 }
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000144 else if (is_codeobject(v)) {
145 codeobject *co = (codeobject *)v;
146 wr_byte(TYPE_CODE, fp);
147 wr_object((object *)co->co_code, fp);
148 wr_object(co->co_consts, fp);
149 wr_object(co->co_names, fp);
150 wr_object(co->co_filename, fp);
151 }
152 else {
153 wr_byte(TYPE_UNKNOWN, fp);
154 }
155}
156
157#define rd_byte(fp) getc(fp)
158
159int
160rd_short(fp)
161 FILE *fp;
162{
163 register short x;
164 x = rd_byte(fp);
165 x |= rd_byte(fp) << 8;
166 /* XXX If your short is > 16 bits, add sign-extension here!!! */
167 return x;
168}
169
170long
171rd_long(fp)
172 FILE *fp;
173{
174 register long x;
175 x = rd_byte(fp);
176 x |= (long)rd_byte(fp) << 8;
177 x |= (long)rd_byte(fp) << 16;
178 x |= (long)rd_byte(fp) << 24;
179 /* XXX If your long is > 32 bits, add sign-extension here!!! */
180 return x;
181}
182
183object *
184rd_object(fp)
185 FILE *fp;
186{
187 object *v;
188 long i, n;
189 int type = rd_byte(fp);
190
191 switch (type) {
192
193 case EOF:
194 err_setstr(RuntimeError, "EOF read where object expected");
195 return NULL;
196
197 case TYPE_NULL:
198 return NULL;
199
200 case TYPE_NONE:
201 INCREF(None);
202 return None;
203
204 case TYPE_INT:
205 return newintobject(rd_long(fp));
206
207 case TYPE_LONG:
208 {
209 int size;
210 longobject *ob;
211 n = rd_long(fp);
212 size = n<0 ? -n : n;
213 ob = alloclongobject(size);
214 if (ob == NULL)
215 return NULL;
216 ob->ob_size = n;
217 for (i = 0; i < size; i++)
218 ob->ob_digit[i] = rd_short(fp);
219 return (object *)ob;
220 }
221
222 case TYPE_FLOAT:
223 {
224 extern double strtod();
225 char buf[256];
226 double res;
227 char *end;
228 n = rd_byte(fp);
229 if (fread(buf, 1, (int)n, fp) != n) {
230 err_setstr(RuntimeError,
231 "EOF read where object expected");
232 return NULL;
233 }
234 buf[n] = '\0';
235 errno = 0;
236 res = strtod(buf, &end);
237 if (*end != '\0') {
238 err_setstr(RuntimeError, "bad float syntax");
239 return NULL;
240 }
241 if (errno != 0) {
242 err_setstr(RuntimeError,
243 "float constant too large");
244 return NULL;
245 }
246 return newfloatobject(res);
247 }
248
249 case TYPE_STRING:
250 n = rd_long(fp);
251 v = newsizedstringobject((char *)NULL, n);
252 if (v != NULL) {
253 if (fread(getstringvalue(v), 1, (int)n, fp) != n) {
254 DECREF(v);
255 v = NULL;
256 err_setstr(RuntimeError,
257 "EOF read where object expected");
258 }
259 }
260 return v;
261
262 case TYPE_TUPLE:
263 n = rd_long(fp);
264 v = newtupleobject((int)n);
265 if (v == NULL)
266 return v;
267 for (i = 0; i < n; i++)
268 settupleitem(v, (int)i, rd_object(fp));
269 return v;
270
271 case TYPE_LIST:
272 n = rd_long(fp);
273 v = newlistobject((int)n);
274 if (v == NULL)
275 return v;
276 for (i = 0; i < n; i++)
277 setlistitem(v, (int)i, rd_object(fp));
278 return v;
279
Guido van Rossum64b45521991-06-07 13:58:22 +0000280 case TYPE_DICT:
281 v = newdictobject();
282 if (v == NULL)
283 return NULL;
284 for (;;) {
285 object *key, *val;
286 key = rd_object(fp);
287 if (key == NULL)
288 break;
289 val = rd_object(fp);
290 dict2insert(v, key, val);
291 DECREF(key);
292 XDECREF(val);
293 }
294 return v;
295
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000296 case TYPE_CODE:
297 {
298 object *code = rd_object(fp);
299 object *consts = rd_object(fp);
300 object *names = rd_object(fp);
301 object *filename = rd_object(fp);
302 if (!err_occurred()) {
303 v = (object *) newcodeobject(code,
304 consts, names, filename);
305 }
306 else
307 v = NULL;
308 XDECREF(code);
309 XDECREF(consts);
310 XDECREF(names);
311 XDECREF(filename);
312
313 }
314 return v;
315
316 default:
317 err_setstr(RuntimeError, "read unknown object");
318 return NULL;
319
320 }
321}
322
Guido van Rossum64b45521991-06-07 13:58:22 +0000323/* And an interface for Python programs... */
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000324
325static object *
326dump(self, args)
327 object *self;
328 object *args;
329{
330 object *f;
331 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
332 err_badarg();
333 return NULL;
334 }
335 f = gettupleitem(args, 1);
336 if (f == NULL || !is_fileobject(f)) {
337 err_badarg();
338 return NULL;
339 }
340 wr_object(gettupleitem(args, 0), getfilefile(f));
341 INCREF(None);
342 return None;
343}
344
345static object *
346load(self, f)
347 object *self;
348 object *f;
349{
350 object *v;
351 if (f == NULL || !is_fileobject(f)) {
352 err_badarg();
353 return NULL;
354 }
355 v = rd_object(getfilefile(f));
356 if (err_occurred()) {
357 XDECREF(v);
358 v = NULL;
359 }
360 return v;
361}
362
363static struct methodlist marshal_methods[] = {
364 {"dump", dump},
365 {"load", load},
366 {NULL, NULL} /* sentinel */
367};
368
369void
370initmarshal()
371{
372 (void) initmodule("marshal", marshal_methods);
373}