(py-electric-colon): use a save-excursion instead of a progn in
[python/dscho.git] / Python / marshal.c
blob8c01020ddcadef0b9b6bef791ae45d98ad56b820
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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 not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
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. */
30 #include "allobjects.h"
31 #include "modsupport.h"
32 #include "longintrepr.h"
33 #include "compile.h"
34 #include "marshal.h"
36 #include <errno.h>
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 '?'
50 typedef struct {
51 FILE *fp;
52 /* If fp == NULL, the following are valid: */
53 object *str;
54 char *ptr;
55 char *end;
56 } WFILE;
58 #define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \
59 else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \
60 else w_more(c, p)
62 static void
63 w_more(c, p)
64 char c;
65 WFILE *p;
67 int size, newsize;
68 if (p->str == NULL)
69 return; /* An error already occurred */
70 size = getstringsize(p->str);
71 newsize = size + 1024;
72 if (resizestring(&p->str, newsize) != 0) {
73 p->ptr = p->end = NULL;
75 else {
76 p->ptr = GETSTRINGVALUE((stringobject *)p->str) + size;
77 p->end = GETSTRINGVALUE((stringobject *)p->str) + newsize;
78 *p->ptr++ = c;
82 static void
83 w_string(s, n, p)
84 char *s;
85 int n;
86 WFILE *p;
88 if (p->fp != NULL) {
89 fwrite(s, 1, n, p->fp);
91 else {
92 while (--n >= 0) {
93 w_byte(*s, p);
94 s++;
99 static void
100 w_short(x, p)
101 int x;
102 WFILE *p;
104 w_byte( x & 0xff, p);
105 w_byte((x>> 8) & 0xff, p);
108 static void
109 w_long(x, p)
110 long x;
111 WFILE *p;
113 w_byte((int)( x & 0xff), p);
114 w_byte((int)((x>> 8) & 0xff), p);
115 w_byte((int)((x>>16) & 0xff), p);
116 w_byte((int)((x>>24) & 0xff), p);
119 static void
120 w_object(v, p)
121 object *v;
122 WFILE *p;
124 int i, n;
126 if (v == NULL)
127 w_byte(TYPE_NULL, p);
128 else if (v == None)
129 w_byte(TYPE_NONE, p);
130 else if (is_intobject(v)) {
131 w_byte(TYPE_INT, p);
132 w_long(getintvalue(v), p);
134 else if (is_longobject(v)) {
135 longobject *ob = (longobject *)v;
136 w_byte(TYPE_LONG, p);
137 n = ob->ob_size;
138 w_long((long)n, p);
139 if (n < 0)
140 n = -n;
141 for (i = 0; i < n; i++)
142 w_short(ob->ob_digit[i], p);
144 else if (is_floatobject(v)) {
145 extern void float_buf_repr PROTO((char *, floatobject *));
146 char buf[256]; /* Plenty to format any double */
147 float_buf_repr(buf, (floatobject *)v);
148 n = strlen(buf);
149 w_byte(TYPE_FLOAT, p);
150 w_byte(n, p);
151 w_string(buf, n, p);
153 else if (is_stringobject(v)) {
154 w_byte(TYPE_STRING, p);
155 n = getstringsize(v);
156 w_long((long)n, p);
157 w_string(getstringvalue(v), n, p);
159 else if (is_tupleobject(v)) {
160 w_byte(TYPE_TUPLE, p);
161 n = gettuplesize(v);
162 w_long((long)n, p);
163 for (i = 0; i < n; i++) {
164 w_object(GETTUPLEITEM(v, i), p);
167 else if (is_listobject(v)) {
168 w_byte(TYPE_LIST, p);
169 n = getlistsize(v);
170 w_long((long)n, p);
171 for (i = 0; i < n; i++) {
172 w_object(getlistitem(v, i), p);
175 else if (is_dictobject(v)) {
176 int pos;
177 object *key, *value;
178 w_byte(TYPE_DICT, p);
179 /* This one is NULL object terminated! */
180 pos = 0;
181 while (mappinggetnext(v, &pos, &key, &value)) {
182 w_object(key, p);
183 w_object(value, p);
185 w_object((object *)NULL, p);
187 else if (is_codeobject(v)) {
188 codeobject *co = (codeobject *)v;
189 w_byte(TYPE_CODE, p);
190 w_object((object *)co->co_code, p);
191 w_object(co->co_consts, p);
192 w_object(co->co_names, p);
193 w_object(co->co_filename, p);
194 w_object(co->co_name, p);
196 else {
197 w_byte(TYPE_UNKNOWN, p);
201 void
202 wr_long(x, fp)
203 long x;
204 FILE *fp;
206 WFILE wf;
207 wf.fp = fp;
208 w_long(x, &wf);
211 void
212 wr_object(x, fp)
213 object *x;
214 FILE *fp;
216 WFILE wf;
217 wf.fp = fp;
218 w_object(x, &wf);
221 typedef WFILE RFILE; /* Same struct with different invariants */
223 #define rs_byte(p) (((p)->ptr != (p)->end) ? (unsigned char)*(p)->ptr++ : EOF)
225 #define r_byte(p) ((p)->fp ? getc((p)->fp) : rs_byte(p))
227 static int
228 r_string(s, n, p)
229 char *s;
230 int n;
231 RFILE *p;
233 if (p->fp != NULL)
234 return fread(s, 1, n, p->fp);
235 if (p->end - p->ptr < n)
236 n = p->end - p->ptr;
237 memcpy(s, p->ptr, n);
238 p->ptr += n;
239 return n;
242 static int
243 r_short(p)
244 RFILE *p;
246 register short x;
247 x = r_byte(p);
248 x |= r_byte(p) << 8;
249 /* XXX If your short is > 16 bits, add sign-extension here!!! */
250 return x;
253 static long
254 r_long(p)
255 RFILE *p;
257 register long x;
258 register FILE *fp = p->fp;
259 if (fp) {
260 x = getc(fp);
261 x |= (long)getc(fp) << 8;
262 x |= (long)getc(fp) << 16;
263 x |= (long)getc(fp) << 24;
265 else {
266 x = rs_byte(p);
267 x |= (long)rs_byte(p) << 8;
268 x |= (long)rs_byte(p) << 16;
269 x |= (long)rs_byte(p) << 24;
271 /* XXX If your long is > 32 bits, add sign-extension here!!! */
272 return x;
275 static object *
276 r_object(p)
277 RFILE *p;
279 object *v;
280 long i, n;
281 int type = r_byte(p);
283 switch (type) {
285 case EOF:
286 err_setstr(EOFError, "EOF read where object expected");
287 return NULL;
289 case TYPE_NULL:
290 return NULL;
292 case TYPE_NONE:
293 INCREF(None);
294 return None;
296 case TYPE_INT:
297 return newintobject(r_long(p));
299 case TYPE_LONG:
301 int size;
302 longobject *ob;
303 n = r_long(p);
304 size = n<0 ? -n : n;
305 ob = alloclongobject(size);
306 if (ob == NULL)
307 return NULL;
308 ob->ob_size = n;
309 for (i = 0; i < size; i++)
310 ob->ob_digit[i] = r_short(p);
311 return (object *)ob;
314 case TYPE_FLOAT:
316 extern double atof PROTO((const char *));
317 char buf[256];
318 n = r_byte(p);
319 if (r_string(buf, (int)n, p) != n) {
320 err_setstr(EOFError,
321 "EOF read where object expected");
322 return NULL;
324 buf[n] = '\0';
325 return newfloatobject(atof(buf));
328 case TYPE_STRING:
329 n = r_long(p);
330 v = newsizedstringobject((char *)NULL, n);
331 if (v != NULL) {
332 if (r_string(getstringvalue(v), (int)n, p) != n) {
333 DECREF(v);
334 v = NULL;
335 err_setstr(EOFError,
336 "EOF read where object expected");
339 return v;
341 case TYPE_TUPLE:
342 n = r_long(p);
343 v = newtupleobject((int)n);
344 if (v == NULL)
345 return v;
346 for (i = 0; i < n; i++)
347 SETTUPLEITEM(v, (int)i, r_object(p));
348 return v;
350 case TYPE_LIST:
351 n = r_long(p);
352 v = newlistobject((int)n);
353 if (v == NULL)
354 return v;
355 for (i = 0; i < n; i++)
356 setlistitem(v, (int)i, r_object(p));
357 return v;
359 case TYPE_DICT:
360 v = newdictobject();
361 if (v == NULL)
362 return NULL;
363 for (;;) {
364 object *key, *val;
365 key = r_object(p);
366 if (key == NULL)
367 break;
368 val = r_object(p);
369 dict2insert(v, key, val);
370 DECREF(key);
371 XDECREF(val);
373 return v;
375 case TYPE_CODE:
377 object *code = r_object(p);
378 object *consts = r_object(p);
379 object *names = r_object(p);
380 object *filename = r_object(p);
381 object *name = r_object(p);
382 if (!err_occurred()) {
383 v = (object *) newcodeobject(code,
384 consts, names, filename, name);
386 else
387 v = NULL;
388 XDECREF(code);
389 XDECREF(consts);
390 XDECREF(names);
391 XDECREF(filename);
392 XDECREF(name);
395 return v;
397 default:
398 err_setstr(TypeError, "read unknown object");
399 return NULL;
404 long
405 rd_long(fp)
406 FILE *fp;
408 RFILE rf;
409 rf.fp = fp;
410 return r_long(&rf);
413 object *
414 rd_object(fp)
415 FILE *fp;
417 RFILE rf;
418 if (err_occurred()) {
419 fprintf(stderr, "XXX rd_object called with exception set\n");
420 return NULL;
422 rf.fp = fp;
423 return r_object(&rf);
426 object *
427 rds_object(str, len)
428 char *str;
429 int len;
431 RFILE rf;
432 if (err_occurred()) {
433 fprintf(stderr, "XXX rds_object called with exception set\n");
434 return NULL;
436 rf.fp = NULL;
437 rf.str = NULL;
438 rf.ptr = str;
439 rf.end = str + len;
440 return r_object(&rf);
443 /* And an interface for Python programs... */
445 static object *
446 marshal_dump(self, args)
447 object *self;
448 object *args;
450 WFILE wf;
451 object *x;
452 object *f;
453 if (!getargs(args, "(OO)", &x, &f))
454 return NULL;
455 if (!is_fileobject(f)) {
456 err_setstr(TypeError, "marshal.dump() 2nd arg must be file");
457 return NULL;
459 wf.fp = getfilefile(f);
460 wf.str = NULL;
461 wf.ptr = wf.end = NULL;
462 w_object(x, &wf);
463 INCREF(None);
464 return None;
467 static object *
468 marshal_load(self, args)
469 object *self;
470 object *args;
472 RFILE rf;
473 object *f;
474 object *v;
475 if (!getargs(args, "O", &f))
476 return NULL;
477 if (!is_fileobject(f)) {
478 err_setstr(TypeError, "marshal.load() arg must be file");
479 return NULL;
481 rf.fp = getfilefile(f);
482 rf.str = NULL;
483 rf.ptr = rf.end = NULL;
484 err_clear();
485 v = r_object(&rf);
486 if (err_occurred()) {
487 XDECREF(v);
488 v = NULL;
490 return v;
493 static object *
494 marshal_dumps(self, args)
495 object *self;
496 object *args;
498 WFILE wf;
499 object *x;
500 if (!getargs(args, "O", &x))
501 return NULL;
502 wf.fp = NULL;
503 wf.str = newsizedstringobject((char *)NULL, 50);
504 if (wf.str == NULL)
505 return NULL;
506 wf.ptr = GETSTRINGVALUE((stringobject *)wf.str);
507 wf.end = wf.ptr + getstringsize(wf.str);
508 w_object(x, &wf);
509 if (wf.str != NULL)
510 resizestring(&wf.str,
511 (int) (wf.ptr - GETSTRINGVALUE((stringobject *)wf.str)));
512 return wf.str;
515 static object *
516 marshal_loads(self, args)
517 object *self;
518 object *args;
520 RFILE rf;
521 object *v;
522 char *s;
523 int n;
524 if (!getargs(args, "s#", &s, &n))
525 return NULL;
526 rf.fp = NULL;
527 rf.str = args;
528 rf.ptr = s;
529 rf.end = s + n;
530 err_clear();
531 v = r_object(&rf);
532 if (err_occurred()) {
533 XDECREF(v);
534 v = NULL;
536 return v;
539 static struct methodlist marshal_methods[] = {
540 {"dump", marshal_dump},
541 {"load", marshal_load},
542 {"dumps", marshal_dumps},
543 {"loads", marshal_loads},
544 {NULL, NULL} /* sentinel */
547 void
548 initmarshal()
550 (void) initmodule("marshal", marshal_methods);