~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to psi/iscanbin.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: iscanbin.c 9902 2009-07-28 18:20:58Z alexcher $ */
 
14
/* $Id$ */
15
15
/* Ghostscript binary token scanner and writer */
16
16
#include "math_.h"
17
17
#include "memory_.h"
159
159
    pbs->token_type = btype = *p;
160
160
    wanted = bin_token_bytes[btype - MIN_BIN_TOKEN_TYPE] - 1;
161
161
    if (rlimit - p < wanted) {
162
 
        s_end_inline(s, p - 1, rlimit);
163
 
        pstate->s_scan_type = scanning_none;
164
 
        code = scan_Refill;
 
162
        s_end_inline(s, p - 1, rlimit);
 
163
        pstate->s_scan_type = scanning_none;
 
164
        code = scan_Refill;
165
165
    } else {
166
 
        pbs->num_format = bin_token_num_formats[btype - MIN_BIN_TOKEN_TYPE];
167
 
        if (BT_IS_SEQ(btype))
168
 
            code = scan_bos(i_ctx_p, pref, pstate);
169
 
        else
170
 
            code = scan_bin_scalar(i_ctx_p, pref, pstate);
 
166
        pbs->num_format = bin_token_num_formats[btype - MIN_BIN_TOKEN_TYPE];
 
167
        if (BT_IS_SEQ(btype))
 
168
            code = scan_bos(i_ctx_p, pref, pstate);
 
169
        else
 
170
            code = scan_bin_scalar(i_ctx_p, pref, pstate);
171
171
    }
172
172
    if (code == scan_Refill && s->end_status == EOFC)
173
 
        code = gs_note_error(e_syntaxerror);
 
173
        code = gs_note_error(e_syntaxerror);
174
174
    if (code < 0 && pstate->s_error.string[0] == 0)
175
 
        snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
176
 
                 "binary token, type=%d", btype);
 
175
        snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
 
176
                 "binary token, type=%d", btype);
177
177
    return code;
178
178
}
179
179
 
189
189
 
190
190
    s_begin_inline(s, p, rlimit);
191
191
    {
192
 
        uint rcnt = rlimit - p;
193
 
        uint top_size = p[1];
194
 
        uint hsize, size;
195
 
 
196
 
        if (top_size == 0) {
197
 
            /* Extended header (2-byte array size, 4-byte length) */
198
 
            uint lsize;
199
 
 
200
 
            if (rcnt < 7) {
201
 
                s_end_inline(s, p - 1, rlimit);
202
 
                pstate->s_scan_type = scanning_none;
203
 
                return scan_Refill;
204
 
            }
205
 
            pbs->top_size = top_size = sdecodeushort(p + 2, num_format);
206
 
            pbs->lsize = lsize = sdecodeint32(p + 4, num_format);
207
 
            if ((size = lsize) != lsize) {
208
 
                scan_bos_error(pstate, "bin obj seq length too large");
209
 
                return_error(e_limitcheck);
210
 
            }
211
 
            hsize = 8;
212
 
        } else {
213
 
            /* Normal header (1-byte array size, 2-byte length). */
214
 
            /* We already checked rcnt >= 3. */
215
 
            pbs->top_size = top_size;
216
 
            pbs->lsize = size = sdecodeushort(p + 2, num_format);
217
 
            hsize = 4;
218
 
        }
219
 
        if (size < hsize || (size - hsize) >> 3 < top_size) {
220
 
            scan_bos_error(pstate, "sequence too short");
221
 
            return_error(e_syntaxerror); /* size too small */
222
 
        }
 
192
        uint rcnt = rlimit - p;
 
193
        uint top_size = p[1];
 
194
        uint hsize, size;
 
195
 
 
196
        if (top_size == 0) {
 
197
            /* Extended header (2-byte array size, 4-byte length) */
 
198
            uint lsize;
 
199
 
 
200
            if (rcnt < 7) {
 
201
                s_end_inline(s, p - 1, rlimit);
 
202
                pstate->s_scan_type = scanning_none;
 
203
                return scan_Refill;
 
204
            }
 
205
            pbs->top_size = top_size = sdecodeushort(p + 2, num_format);
 
206
            pbs->lsize = lsize = sdecodeint32(p + 4, num_format);
 
207
            if ((size = lsize) != lsize) {
 
208
                scan_bos_error(pstate, "bin obj seq length too large");
 
209
                return_error(e_limitcheck);
 
210
            }
 
211
            hsize = 8;
 
212
        } else {
 
213
            /* Normal header (1-byte array size, 2-byte length). */
 
214
            /* We already checked rcnt >= 3. */
 
215
            pbs->top_size = top_size;
 
216
            pbs->lsize = size = sdecodeushort(p + 2, num_format);
 
217
            hsize = 4;
 
218
        }
 
219
        if (size < hsize || (size - hsize) >> 3 < top_size) {
 
220
            scan_bos_error(pstate, "sequence too short");
 
221
            return_error(e_syntaxerror); /* size too small */
 
222
        }
223
223
        { /* Preliminary syntax check to avoid potentialy large
224
224
           * memory allocation on junk data. Bug 688833
225
225
           */
226
226
          const unsigned char *q, *rend = p + hsize + top_size*8;
227
227
 
228
228
          if (rend > rlimit)
229
 
              rend = rlimit; 
 
229
              rend = rlimit;
230
230
          for (q = p + hsize + 1; q < rend; q += 8) {
231
231
             int c = q[-1] & 0x7f;
232
232
             if (c > 10 && c != BS_TYPE_DICTIONARY) {
233
 
                scan_bos_error(pstate, "invalid object type");
234
 
                return_error(e_syntaxerror);
 
233
                scan_bos_error(pstate, "invalid object type");
 
234
                return_error(e_syntaxerror);
235
235
             }
236
236
             if (*q != 0) {
237
 
                scan_bos_error(pstate, "non-zero unused field");
238
 
                return_error(e_syntaxerror);
 
237
                scan_bos_error(pstate, "non-zero unused field");
 
238
                return_error(e_syntaxerror);
239
239
             }
240
240
          }
241
241
        }
242
 
        /*
243
 
         * Preallocate an array large enough for the worst case,
244
 
         * namely, all objects and no strings.  Note that we must
245
 
         * divide size by 8, not sizeof(ref), since array elements
246
 
         * in binary tokens always occupy 8 bytes regardless of the
247
 
         * size of a ref.
248
 
         */
249
 
        code = ialloc_ref_array(&pbs->bin_array,
250
 
                                a_all + a_executable, size / 8,
251
 
                                "binary object sequence(objects)");
252
 
        if (code < 0)
253
 
            return code;
254
 
        p += hsize - 1;
255
 
        size -= hsize;
256
 
        s_end_inline(s, p, rlimit);
257
 
        pbs->max_array_index = pbs->top_size = top_size;
258
 
        pbs->min_string_index = pbs->size = size;
259
 
        pbs->index = 0;
260
 
        pstate->s_da.is_dynamic = false;
261
 
        pstate->s_da.base = pstate->s_da.next =
262
 
            pstate->s_da.limit = pstate->s_da.buf;
263
 
        code = scan_bos_continue(i_ctx_p, pref, pstate);
264
 
        if (code == scan_Refill || code < 0) {
265
 
            /* Clean up array for GC. */
266
 
            uint index = pbs->index;
 
242
        /*
 
243
         * Preallocate an array large enough for the worst case,
 
244
         * namely, all objects and no strings.  Note that we must
 
245
         * divide size by 8, not sizeof(ref), since array elements
 
246
         * in binary tokens always occupy 8 bytes regardless of the
 
247
         * size of a ref.
 
248
         */
 
249
        code = ialloc_ref_array(&pbs->bin_array,
 
250
                                a_all + a_executable, size / 8,
 
251
                                "binary object sequence(objects)");
 
252
        if (code < 0)
 
253
            return code;
 
254
        p += hsize - 1;
 
255
        size -= hsize;
 
256
        s_end_inline(s, p, rlimit);
 
257
        pbs->max_array_index = pbs->top_size = top_size;
 
258
        pbs->min_string_index = pbs->size = size;
 
259
        pbs->index = 0;
 
260
        pstate->s_da.is_dynamic = false;
 
261
        pstate->s_da.base = pstate->s_da.next =
 
262
            pstate->s_da.limit = pstate->s_da.buf;
 
263
        code = scan_bos_continue(i_ctx_p, pref, pstate);
 
264
        if (code == scan_Refill || code < 0) {
 
265
            /* Clean up array for GC. */
 
266
            uint index = pbs->index;
267
267
 
268
 
            refset_null(pbs->bin_array.value.refs + index,
269
 
                        r_size(&pbs->bin_array) - index);
270
 
        }
271
 
        return code;
 
268
            refset_null(pbs->bin_array.value.refs + index,
 
269
                        r_size(&pbs->bin_array) - index);
 
270
        }
 
271
        return code;
272
272
    }
273
273
}
274
274
 
277
277
scan_bos_error(scanner_state *pstate, const char *msg)
278
278
{
279
279
    snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
280
 
             "bin obj seq, type=%d, elements=%u, size=%lu, %s",
281
 
             pstate->s_ss.binary.token_type,
282
 
             pstate->s_ss.binary.top_size,
283
 
             pstate->s_ss.binary.lsize, msg);
 
280
             "bin obj seq, type=%d, elements=%u, size=%lu, %s",
 
281
             pstate->s_ss.binary.token_type,
 
282
             pstate->s_ss.binary.top_size,
 
283
             pstate->s_ss.binary.lsize, msg);
284
284
}
285
285
 
286
286
/* Scan a non-sequence binary token. */
296
296
    s_begin_inline(s, p, rlimit);
297
297
    wanted = bin_token_bytes[*p - MIN_BIN_TOKEN_TYPE] - 1;
298
298
    switch (*p) {
299
 
        case BT_INT8:
300
 
            make_int(pref, (p[1] ^ 128) - 128);
301
 
            s_end_inline(s, p + 1, rlimit);
302
 
            return 0;
303
 
        case BT_FIXED:
304
 
            num_format = p[1];
305
 
            if (!num_is_valid(num_format))
306
 
                return_error(e_syntaxerror);
307
 
            wanted = 1 + encoded_number_bytes(num_format);
308
 
            if (rlimit - p < wanted) {
309
 
                s_end_inline(s, p - 1, rlimit);
310
 
                pstate->s_scan_type = scanning_none;
311
 
                return scan_Refill;
312
 
            }
313
 
            code = sdecode_number(p + 2, num_format, pref);
314
 
            goto rnum;
315
 
        case BT_INT32_MSB:
316
 
        case BT_INT32_LSB:
317
 
        case BT_INT16_MSB:
318
 
        case BT_INT16_LSB:
319
 
        case BT_FLOAT_IEEE_MSB:
320
 
        case BT_FLOAT_IEEE_LSB:
321
 
        case BT_FLOAT_NATIVE:
322
 
            code = sdecode_number(p + 1, num_format, pref);
323
 
          rnum:
324
 
            switch (code) {
325
 
                case t_integer:
326
 
                case t_real:
327
 
                    r_set_type(pref, code);
328
 
                    break;
329
 
                case t_null:
330
 
                    return_error(e_syntaxerror);
331
 
                default:
332
 
                    return code;
333
 
            }
334
 
            s_end_inline(s, p + wanted, rlimit);
335
 
            return 0;
336
 
        case BT_BOOLEAN:
337
 
            arg = p[1];
338
 
            if (arg & ~1)
339
 
                return_error(e_syntaxerror);
340
 
            make_bool(pref, arg);
341
 
            s_end_inline(s, p + 1, rlimit);
342
 
            return 0;
343
 
        case BT_STRING_256:
344
 
            arg = *++p;
345
 
            goto str;
346
 
        case BT_STRING_64K_MSB:
347
 
        case BT_STRING_64K_LSB:
348
 
            arg = sdecodeushort(p + 1, num_format);
349
 
            p += 2;
350
 
          str:
351
 
            if (s->foreign && rlimit - p >= arg) {
352
 
                /*
353
 
                 * Reference the string directly in the buffer.  It is
354
 
                 * marked writable for consistency with the non-direct
355
 
                 * case, but since the "buffer" may be data compiled into
356
 
                 * the executable, it is probably actually read-only.
357
 
                 */
358
 
                s_end_inline(s, p, rlimit);
359
 
                make_const_string(pref, a_all | avm_foreign, arg, sbufptr(s));
360
 
                sbufskip(s, arg);
361
 
                return 0;
362
 
            } else {
363
 
                byte *str = ialloc_string(arg, "string token");
 
299
        case BT_INT8:
 
300
            make_int(pref, (p[1] ^ 128) - 128);
 
301
            s_end_inline(s, p + 1, rlimit);
 
302
            return 0;
 
303
        case BT_FIXED:
 
304
            num_format = p[1];
 
305
            if (!num_is_valid(num_format))
 
306
                return_error(e_syntaxerror);
 
307
            wanted = 1 + encoded_number_bytes(num_format);
 
308
            if (rlimit - p < wanted) {
 
309
                s_end_inline(s, p - 1, rlimit);
 
310
                pstate->s_scan_type = scanning_none;
 
311
                return scan_Refill;
 
312
            }
 
313
            code = sdecode_number(p + 2, num_format, pref);
 
314
            goto rnum;
 
315
        case BT_INT32_MSB:
 
316
        case BT_INT32_LSB:
 
317
        case BT_INT16_MSB:
 
318
        case BT_INT16_LSB:
 
319
        case BT_FLOAT_IEEE_MSB:
 
320
        case BT_FLOAT_IEEE_LSB:
 
321
        case BT_FLOAT_NATIVE:
 
322
            code = sdecode_number(p + 1, num_format, pref);
 
323
          rnum:
 
324
            switch (code) {
 
325
                case t_integer:
 
326
                case t_real:
 
327
                    r_set_type(pref, code);
 
328
                    break;
 
329
                case t_null:
 
330
                    return_error(e_syntaxerror);
 
331
                default:
 
332
                    return code;
 
333
            }
 
334
            s_end_inline(s, p + wanted, rlimit);
 
335
            return 0;
 
336
        case BT_BOOLEAN:
 
337
            arg = p[1];
 
338
            if (arg & ~1)
 
339
                return_error(e_syntaxerror);
 
340
            make_bool(pref, arg);
 
341
            s_end_inline(s, p + 1, rlimit);
 
342
            return 0;
 
343
        case BT_STRING_256:
 
344
            arg = *++p;
 
345
            goto str;
 
346
        case BT_STRING_64K_MSB:
 
347
        case BT_STRING_64K_LSB:
 
348
            arg = sdecodeushort(p + 1, num_format);
 
349
            p += 2;
 
350
          str:
 
351
            if (s->foreign && rlimit - p >= arg) {
 
352
                /*
 
353
                 * Reference the string directly in the buffer.  It is
 
354
                 * marked writable for consistency with the non-direct
 
355
                 * case, but since the "buffer" may be data compiled into
 
356
                 * the executable, it is probably actually read-only.
 
357
                 */
 
358
                s_end_inline(s, p, rlimit);
 
359
                make_const_string(pref, a_all | avm_foreign, arg, sbufptr(s));
 
360
                sbufskip(s, arg);
 
361
                return 0;
 
362
            } else {
 
363
                byte *str = ialloc_string(arg, "string token");
364
364
 
365
 
                if (str == 0)
366
 
                    return_error(e_VMerror);
367
 
                s_end_inline(s, p, rlimit);
368
 
                pstate->s_da.base = pstate->s_da.next = str;
369
 
                pstate->s_da.limit = str + arg;
370
 
                code = scan_bin_string_continue(i_ctx_p, pref, pstate);
371
 
                if (code == scan_Refill || code < 0) {
372
 
                    pstate->s_da.is_dynamic = true;
373
 
                    make_null(&pbs->bin_array);         /* clean up for GC */
374
 
                    pbs->cont = scan_bin_string_continue;
375
 
                }
376
 
                return code;
377
 
            }
378
 
        case BT_LITNAME_SYSTEM:
379
 
            code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
380
 
                                     pref, "system");
381
 
            goto lname;
382
 
        case BT_EXECNAME_SYSTEM:
383
 
            code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
384
 
                                     pref, "system");
385
 
            goto xname;
386
 
        case BT_LITNAME_USER:
387
 
            code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
388
 
                                     pref, "user");
389
 
          lname:
390
 
            if (code < 0)
391
 
                return code;
392
 
            s_end_inline(s, p + 1, rlimit);
393
 
            return 0;
394
 
        case BT_EXECNAME_USER:
395
 
            code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
396
 
                                     pref, "user");
397
 
          xname:
398
 
            if (code < 0)
399
 
                return code;
400
 
            r_set_attrs(pref, a_executable);
401
 
            s_end_inline(s, p + 1, rlimit);
402
 
            return 0;
403
 
        case BT_NUM_ARRAY:
404
 
            num_format = p[1];
405
 
            if (!num_is_valid(num_format))
406
 
                return_error(e_syntaxerror);
407
 
            arg = sdecodeushort(p + 2, num_format);
408
 
            code = ialloc_ref_array(&pbs->bin_array, a_all, arg,
409
 
                                    "number array token");
410
 
            if (code < 0)
411
 
                return code;
412
 
            pbs->num_format = num_format;
413
 
            pbs->index = 0;
414
 
            p += 3;
415
 
            s_end_inline(s, p, rlimit);
416
 
            code = scan_bin_num_array_continue(i_ctx_p, pref, pstate);
417
 
            if (code == scan_Refill || code < 0) {
418
 
                /* Make sure the array is clean for the GC. */
419
 
                refset_null(pbs->bin_array.value.refs + pbs->index,
420
 
                            arg - pbs->index);
421
 
                pbs->cont = scan_bin_num_array_continue;
422
 
            }
423
 
            return code;
 
365
                if (str == 0)
 
366
                    return_error(e_VMerror);
 
367
                s_end_inline(s, p, rlimit);
 
368
                pstate->s_da.base = pstate->s_da.next = str;
 
369
                pstate->s_da.limit = str + arg;
 
370
                code = scan_bin_string_continue(i_ctx_p, pref, pstate);
 
371
                if (code == scan_Refill || code < 0) {
 
372
                    pstate->s_da.is_dynamic = true;
 
373
                    make_null(&pbs->bin_array);         /* clean up for GC */
 
374
                    pbs->cont = scan_bin_string_continue;
 
375
                }
 
376
                return code;
 
377
            }
 
378
        case BT_LITNAME_SYSTEM:
 
379
            code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
 
380
                                     pref, "system");
 
381
            goto lname;
 
382
        case BT_EXECNAME_SYSTEM:
 
383
            code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
 
384
                                     pref, "system");
 
385
            goto xname;
 
386
        case BT_LITNAME_USER:
 
387
            code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
 
388
                                     pref, "user");
 
389
          lname:
 
390
            if (code < 0)
 
391
                return code;
 
392
            s_end_inline(s, p + 1, rlimit);
 
393
            return 0;
 
394
        case BT_EXECNAME_USER:
 
395
            code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
 
396
                                     pref, "user");
 
397
          xname:
 
398
            if (code < 0)
 
399
                return code;
 
400
            r_set_attrs(pref, a_executable);
 
401
            s_end_inline(s, p + 1, rlimit);
 
402
            return 0;
 
403
        case BT_NUM_ARRAY:
 
404
            num_format = p[1];
 
405
            if (!num_is_valid(num_format))
 
406
                return_error(e_syntaxerror);
 
407
            arg = sdecodeushort(p + 2, num_format);
 
408
            code = ialloc_ref_array(&pbs->bin_array, a_all, arg,
 
409
                                    "number array token");
 
410
            if (code < 0)
 
411
                return code;
 
412
            pbs->num_format = num_format;
 
413
            pbs->index = 0;
 
414
            p += 3;
 
415
            s_end_inline(s, p, rlimit);
 
416
            code = scan_bin_num_array_continue(i_ctx_p, pref, pstate);
 
417
            if (code == scan_Refill || code < 0) {
 
418
                /* Make sure the array is clean for the GC. */
 
419
                refset_null(pbs->bin_array.value.refs + pbs->index,
 
420
                            arg - pbs->index);
 
421
                pbs->cont = scan_bin_num_array_continue;
 
422
            }
 
423
            return code;
424
424
    }
425
425
    return_error(e_syntaxerror);
426
426
}
428
428
/* Get a system or user name. */
429
429
static int
430
430
scan_bin_get_name(scanner_state *pstate, const gs_memory_t *mem,
431
 
                  const ref *pnames /*t_array*/, int index, ref *pref,
432
 
                  const char *usstring)
 
431
                  const ref *pnames /*t_array*/, int index, ref *pref,
 
432
                  const char *usstring)
433
433
{
434
434
    /* Convert all errors to e_undefined to match Adobe. */
435
435
    if (pnames == 0 || array_get(mem, pnames, (long)index, pref) < 0 ||
436
 
        !r_has_type(pref, t_name)) {
437
 
        snprintf(pstate->s_error.string,
438
 
                 sizeof(pstate->s_error.string),
439
 
                 "%s%d", usstring, index);
440
 
        pstate->s_error.is_name = true;
441
 
        return_error(e_undefined);
 
436
        !r_has_type(pref, t_name)) {
 
437
        snprintf(pstate->s_error.string,
 
438
                 sizeof(pstate->s_error.string),
 
439
                 "%s%d", usstring, index);
 
440
        pstate->s_error.is_name = true;
 
441
        return_error(e_undefined);
442
442
    }
443
443
    return 0;
444
444
}
458
458
    */
459
459
    sgets(s, q, wanted, &rcnt);
460
460
    if (rcnt == wanted) {
461
 
        /* Finished collecting the string. */
462
 
        make_string(pref, a_all | icurrent_space,
463
 
                    pstate->s_da.limit - pstate->s_da.base,
464
 
                    pstate->s_da.base);
465
 
        return 0;
 
461
        /* Finished collecting the string. */
 
462
        make_string(pref, a_all | icurrent_space,
 
463
                    pstate->s_da.limit - pstate->s_da.base,
 
464
                    pstate->s_da.base);
 
465
        return 0;
466
466
    }
467
467
    pstate->s_da.next = q + rcnt;
468
468
    pstate->s_scan_type = scanning_binary;
472
472
/* Continue scanning a binary number array. */
473
473
static int
474
474
scan_bin_num_array_continue(i_ctx_t *i_ctx_p, ref * pref,
475
 
                            scanner_state * pstate)
 
475
                            scanner_state * pstate)
476
476
{
477
477
    stream *const s = pstate->s_file.value.pfile;
478
478
    scan_binary_state *const pbs = &pstate->s_ss.binary;
481
481
    uint wanted = encoded_number_bytes(pbs->num_format);
482
482
 
483
483
    for (; index < r_size(&pbs->bin_array); index++, np++) {
484
 
        int code;
 
484
        int code;
485
485
 
486
 
        if (sbufavailable(s) < wanted) {
487
 
            pbs->index = index;
488
 
            pstate->s_scan_type = scanning_binary;
489
 
            return scan_Refill;
490
 
        }
491
 
        code = sdecode_number(sbufptr(s), pbs->num_format, np);
492
 
        switch (code) {
493
 
            case t_integer:
494
 
            case t_real:
495
 
                r_set_type(np, code);
496
 
                sbufskip(s, wanted);
497
 
                break;
498
 
            case t_null:
499
 
                scan_bos_error(pstate, "bad number format");
500
 
                return_error(e_syntaxerror);
501
 
            default:
502
 
                return code;
503
 
        }
 
486
        if (sbufavailable(s) < wanted) {
 
487
            pbs->index = index;
 
488
            pstate->s_scan_type = scanning_binary;
 
489
            return scan_Refill;
 
490
        }
 
491
        code = sdecode_number(sbufptr(s), pbs->num_format, np);
 
492
        switch (code) {
 
493
            case t_integer:
 
494
            case t_real:
 
495
                r_set_type(np, code);
 
496
                sbufskip(s, wanted);
 
497
                break;
 
498
            case t_null:
 
499
                scan_bos_error(pstate, "bad number format");
 
500
                return_error(e_syntaxerror);
 
501
            default:
 
502
                return code;
 
503
        }
504
504
    }
505
505
    *pref = pbs->bin_array;
506
506
    return 0;
532
532
    pbs->cont = scan_bos_continue;  /* in case of premature return */
533
533
    s_begin_inline(s, p, rlimit);
534
534
    for (; index < max_array_index; p += SIZEOF_BIN_SEQ_OBJ, index++) {
535
 
        ref *op = abase + index;
536
 
        uint osize;
537
 
        int value, atype, attrs;
538
 
 
539
 
        s_end_inline(s, p, rlimit);     /* in case of error */
540
 
        if (rlimit - p < SIZEOF_BIN_SEQ_OBJ) {
541
 
            pbs->index = index;
542
 
            pbs->max_array_index = max_array_index;
543
 
            pbs->min_string_index = min_string_index;
544
 
            pstate->s_scan_type = scanning_binary;
545
 
            return scan_Refill;
546
 
        }
547
 
        if (p[2] != 0) { /* reserved, must be 0 */
548
 
            scan_bos_error(pstate, "non-zero unused field");
549
 
            return_error(e_syntaxerror);
550
 
        }
551
 
        attrs = (p[1] & 128 ? a_executable : 0);
552
 
        /*
553
 
         * We always decode all 8 bytes of the object, so we can signal
554
 
         * syntaxerror if any unused field is non-zero (per PLRM).
555
 
         */
556
 
        osize = sdecodeushort(p + 3, num_format);
557
 
        value = sdecodeint32(p + 5, num_format);
558
 
        switch (p[1] & 0x7f) {
559
 
            case BS_TYPE_NULL:
560
 
                if (osize | value) { /* unused */
561
 
                    scan_bos_error(pstate, "non-zero unused field");
562
 
                    return_error(e_syntaxerror);
563
 
                }
564
 
                make_null(op);
565
 
                break;
566
 
            case BS_TYPE_INTEGER:
567
 
                if (osize) {    /* unused */
568
 
                    scan_bos_error(pstate, "non-zero unused field");
569
 
                    return_error(e_syntaxerror);
570
 
                }
571
 
                make_int(op, value);
572
 
                break;
573
 
            case BS_TYPE_REAL:{
574
 
                    float vreal;
575
 
 
576
 
                    if (osize != 0) {   /* fixed-point number */
577
 
                        if (osize > 31) {
578
 
                            scan_bos_error(pstate, "invalid number format");
579
 
                            return_error(e_syntaxerror);
580
 
                        }
581
 
                        /* ldexp requires a signed 2nd argument.... */
582
 
                        vreal = (float)ldexp((double)value, -(int)osize);
583
 
                    } else {
584
 
                        code = sdecode_float(p + 5, num_format, &vreal);
585
 
                        if (code < 0) {
586
 
                            scan_bos_error(pstate, "invalid real number");
587
 
                            return code;
588
 
                        }
589
 
                    }
590
 
                    make_real(op, vreal);
591
 
                    break;
592
 
                }
593
 
            case BS_TYPE_BOOLEAN:
594
 
                if (osize) {    /* unused */
595
 
                    scan_bos_error(pstate, "non-zero unused field");
596
 
                    return_error(e_syntaxerror);
597
 
                }
598
 
                make_bool(op, value != 0);
599
 
                break;
600
 
            case BS_TYPE_STRING:
601
 
                attrs |= a_all;
602
 
              str:
603
 
                if (osize == 0) {
604
 
                    /* For zero-length strings, the offset */
605
 
                    /* doesn't matter, and may be zero. */
606
 
                    make_empty_string(op, attrs);
607
 
                    break;
608
 
                }
609
 
                if (value < max_array_index * SIZEOF_BIN_SEQ_OBJ ||
610
 
                    value + osize > size
611
 
                    ) {
612
 
                    scan_bos_error(pstate, "invalid string offset");
613
 
                    return_error(e_syntaxerror);
614
 
                }
615
 
                if (value < min_string_index) {
616
 
                    /* We have to (re)allocate the strings. */
617
 
                    uint str_size = size - value;
618
 
                    byte *sbase;
619
 
 
620
 
                    if (pstate->s_da.is_dynamic)
621
 
                        sbase = scan_bos_resize(i_ctx_p, pstate, str_size,
622
 
                                                index);
623
 
                    else
624
 
                        sbase = ialloc_string(str_size,
625
 
                                              "bos strings");
626
 
                    if (sbase == 0)
627
 
                        return_error(e_VMerror);
628
 
                    pstate->s_da.is_dynamic = true;
629
 
                    pstate->s_da.base = pstate->s_da.next = sbase;
630
 
                    pstate->s_da.limit = sbase + str_size;
631
 
                    min_string_index = value;
632
 
                }
633
 
                make_string(op, attrs | icurrent_space, osize,
634
 
                            pstate->s_da.base +
635
 
                            (value - min_string_index));
636
 
                break;
637
 
            case BS_TYPE_EVAL_NAME:
638
 
                attrs |= a_readonly;    /* mark as executable for later */
639
 
                /* falls through */
640
 
            case BS_TYPE_NAME:
641
 
                switch (osize) {
642
 
                    case 0:
643
 
                        code = scan_bin_get_name(pstate, imemory,
644
 
                                                 user_names_p, value, op,
645
 
                                                 "user");
646
 
                        goto usn;
647
 
                    case 0xffff:
648
 
                        code = scan_bin_get_name(pstate, imemory,
649
 
                                                 system_names_p, value, op,
650
 
                                                 "system");
651
 
                      usn:
652
 
                        if (code < 0)
653
 
                            return code;
654
 
                        r_set_attrs(op, attrs);
655
 
                        break;
656
 
                    default:
657
 
                        goto str;
658
 
                }
659
 
                break;
660
 
            case BS_TYPE_ARRAY:
661
 
                atype = t_array;
662
 
              arr:
663
 
                if (value + osize > min_string_index ||
664
 
                    value & (SIZEOF_BIN_SEQ_OBJ - 1)
665
 
                    ) {
666
 
                    scan_bos_error(pstate, "bad array offset");
667
 
                    return_error(e_syntaxerror);
668
 
                }
669
 
                {
670
 
                    uint aindex = value / SIZEOF_BIN_SEQ_OBJ;
671
 
 
672
 
                    max_array_index =
673
 
                        max(max_array_index, aindex + osize);
674
 
                    make_tasv_new(op, atype,
675
 
                                  attrs | a_all | icurrent_space,
676
 
                                  osize, refs, abase + aindex);
677
 
                }
678
 
                break;
679
 
            case BS_TYPE_DICTIONARY:    /* EXTENSION */
680
 
                if ((osize & 1) != 0 && osize != 1)
681
 
                    return_error(e_syntaxerror);
682
 
                atype = t_mixedarray;   /* mark as dictionary */
683
 
                goto arr;
684
 
            case BS_TYPE_MARK:
685
 
                if (osize | value) { /* unused */
686
 
                    scan_bos_error(pstate, "non-zero unused field");
687
 
                    return_error(e_syntaxerror);
688
 
                }
689
 
                make_mark(op);
690
 
                break;
691
 
            default:
692
 
                scan_bos_error(pstate, "invalid object type");
693
 
                return_error(e_syntaxerror);
694
 
        }
 
535
        ref *op = abase + index;
 
536
        uint osize;
 
537
        int value, atype, attrs;
 
538
 
 
539
        s_end_inline(s, p, rlimit);     /* in case of error */
 
540
        if (rlimit - p < SIZEOF_BIN_SEQ_OBJ) {
 
541
            pbs->index = index;
 
542
            pbs->max_array_index = max_array_index;
 
543
            pbs->min_string_index = min_string_index;
 
544
            pstate->s_scan_type = scanning_binary;
 
545
            return scan_Refill;
 
546
        }
 
547
        if (p[2] != 0) { /* reserved, must be 0 */
 
548
            scan_bos_error(pstate, "non-zero unused field");
 
549
            return_error(e_syntaxerror);
 
550
        }
 
551
        attrs = (p[1] & 128 ? a_executable : 0);
 
552
        /*
 
553
         * We always decode all 8 bytes of the object, so we can signal
 
554
         * syntaxerror if any unused field is non-zero (per PLRM).
 
555
         */
 
556
        osize = sdecodeushort(p + 3, num_format);
 
557
        value = sdecodeint32(p + 5, num_format);
 
558
        switch (p[1] & 0x7f) {
 
559
            case BS_TYPE_NULL:
 
560
                if (osize | value) { /* unused */
 
561
                    scan_bos_error(pstate, "non-zero unused field");
 
562
                    return_error(e_syntaxerror);
 
563
                }
 
564
                make_null(op);
 
565
                break;
 
566
            case BS_TYPE_INTEGER:
 
567
                if (osize) {    /* unused */
 
568
                    scan_bos_error(pstate, "non-zero unused field");
 
569
                    return_error(e_syntaxerror);
 
570
                }
 
571
                make_int(op, value);
 
572
                break;
 
573
            case BS_TYPE_REAL:{
 
574
                    float vreal;
 
575
 
 
576
                    if (osize != 0) {   /* fixed-point number */
 
577
                        if (osize > 31) {
 
578
                            scan_bos_error(pstate, "invalid number format");
 
579
                            return_error(e_syntaxerror);
 
580
                        }
 
581
                        /* ldexp requires a signed 2nd argument.... */
 
582
                        vreal = (float)ldexp((double)value, -(int)osize);
 
583
                    } else {
 
584
                        code = sdecode_float(p + 5, num_format, &vreal);
 
585
                        if (code < 0) {
 
586
                            scan_bos_error(pstate, "invalid real number");
 
587
                            return code;
 
588
                        }
 
589
                    }
 
590
                    make_real(op, vreal);
 
591
                    break;
 
592
                }
 
593
            case BS_TYPE_BOOLEAN:
 
594
                if (osize) {    /* unused */
 
595
                    scan_bos_error(pstate, "non-zero unused field");
 
596
                    return_error(e_syntaxerror);
 
597
                }
 
598
                make_bool(op, value != 0);
 
599
                break;
 
600
            case BS_TYPE_STRING:
 
601
                attrs |= a_all;
 
602
              str:
 
603
                if (osize == 0) {
 
604
                    /* For zero-length strings, the offset */
 
605
                    /* doesn't matter, and may be zero. */
 
606
                    make_empty_string(op, attrs);
 
607
                    break;
 
608
                }
 
609
                if (value < max_array_index * SIZEOF_BIN_SEQ_OBJ ||
 
610
                    value + osize > size
 
611
                    ) {
 
612
                    scan_bos_error(pstate, "invalid string offset");
 
613
                    return_error(e_syntaxerror);
 
614
                }
 
615
                if (value < min_string_index) {
 
616
                    /* We have to (re)allocate the strings. */
 
617
                    uint str_size = size - value;
 
618
                    byte *sbase;
 
619
 
 
620
                    if (pstate->s_da.is_dynamic)
 
621
                        sbase = scan_bos_resize(i_ctx_p, pstate, str_size,
 
622
                                                index);
 
623
                    else
 
624
                        sbase = ialloc_string(str_size,
 
625
                                              "bos strings");
 
626
                    if (sbase == 0)
 
627
                        return_error(e_VMerror);
 
628
                    pstate->s_da.is_dynamic = true;
 
629
                    pstate->s_da.base = pstate->s_da.next = sbase;
 
630
                    pstate->s_da.limit = sbase + str_size;
 
631
                    min_string_index = value;
 
632
                }
 
633
                make_string(op, attrs | icurrent_space, osize,
 
634
                            pstate->s_da.base +
 
635
                            (value - min_string_index));
 
636
                break;
 
637
            case BS_TYPE_EVAL_NAME:
 
638
                attrs |= a_readonly;    /* mark as executable for later */
 
639
                /* falls through */
 
640
            case BS_TYPE_NAME:
 
641
                switch (osize) {
 
642
                    case 0:
 
643
                        code = scan_bin_get_name(pstate, imemory,
 
644
                                                 user_names_p, value, op,
 
645
                                                 "user");
 
646
                        goto usn;
 
647
                    case 0xffff:
 
648
                        code = scan_bin_get_name(pstate, imemory,
 
649
                                                 system_names_p, value, op,
 
650
                                                 "system");
 
651
                      usn:
 
652
                        if (code < 0)
 
653
                            return code;
 
654
                        r_set_attrs(op, attrs);
 
655
                        break;
 
656
                    default:
 
657
                        goto str;
 
658
                }
 
659
                break;
 
660
            case BS_TYPE_ARRAY:
 
661
                atype = t_array;
 
662
              arr:
 
663
                if (value + osize > min_string_index ||
 
664
                    value & (SIZEOF_BIN_SEQ_OBJ - 1)
 
665
                    ) {
 
666
                    scan_bos_error(pstate, "bad array offset");
 
667
                    return_error(e_syntaxerror);
 
668
                }
 
669
                {
 
670
                    uint aindex = value / SIZEOF_BIN_SEQ_OBJ;
 
671
 
 
672
                    max_array_index =
 
673
                        max(max_array_index, aindex + osize);
 
674
                    make_tasv_new(op, atype,
 
675
                                  attrs | a_all | icurrent_space,
 
676
                                  osize, refs, abase + aindex);
 
677
                }
 
678
                break;
 
679
            case BS_TYPE_DICTIONARY:    /* EXTENSION */
 
680
                if ((osize & 1) != 0 && osize != 1)
 
681
                    return_error(e_syntaxerror);
 
682
                atype = t_mixedarray;   /* mark as dictionary */
 
683
                goto arr;
 
684
            case BS_TYPE_MARK:
 
685
                if (osize | value) { /* unused */
 
686
                    scan_bos_error(pstate, "non-zero unused field");
 
687
                    return_error(e_syntaxerror);
 
688
                }
 
689
                make_mark(op);
 
690
                break;
 
691
            default:
 
692
                scan_bos_error(pstate, "invalid object type");
 
693
                return_error(e_syntaxerror);
 
694
        }
695
695
    }
696
696
    s_end_inline(s, p, rlimit);
697
697
    /* Shorten the objects to remove the space that turned out */
698
698
    /* to be used for strings. */
699
699
    pbs->index = max_array_index;
700
700
    iresize_ref_array(&pbs->bin_array, max_array_index,
701
 
                      "binary object sequence(objects)");
 
701
                      "binary object sequence(objects)");
702
702
    code = scan_bos_string_continue(i_ctx_p, pref, pstate);
703
703
    if (code == scan_Refill)
704
 
        pbs->cont = scan_bos_string_continue;
 
704
        pbs->cont = scan_bos_string_continue;
705
705
    return code;
706
706
}
707
707
 
709
709
/* adjusting all the pointers to them from objects. */
710
710
static byte *
711
711
scan_bos_resize(i_ctx_t *i_ctx_p, scanner_state * pstate, uint new_size,
712
 
                uint index)
 
712
                uint index)
713
713
{
714
714
    scan_binary_state *const pbs = &pstate->s_ss.binary;
715
715
    uint old_size = da_size(&pstate->s_da);
716
716
    byte *old_base = pstate->s_da.base;
717
717
    byte *new_base = iresize_string(old_base, old_size, new_size,
718
 
                                    "scan_bos_resize");
 
718
                                    "scan_bos_resize");
719
719
    byte *relocated_base = new_base + (new_size - old_size);
720
720
    uint i;
721
721
    ref *aptr = pbs->bin_array.value.refs;
722
722
 
723
723
    if (new_base == 0)
724
 
        return 0;
 
724
        return 0;
725
725
    /* Since the allocator normally extends strings downward, */
726
726
    /* it's quite possible that new and old addresses are the same. */
727
727
    if (relocated_base != old_base)
728
 
        for (i = index; i != 0; i--, aptr++)
729
 
            if (r_has_type(aptr, t_string) && r_size(aptr) != 0)
730
 
                aptr->value.bytes =
731
 
                    aptr->value.bytes - old_base + relocated_base;
 
728
        for (i = index; i != 0; i--, aptr++)
 
729
            if (r_has_type(aptr, t_string) && r_size(aptr) != 0)
 
730
                aptr->value.bytes =
 
731
                    aptr->value.bytes - old_base + relocated_base;
732
732
    return new_base;
733
733
}
734
734
 
735
735
/* Continue reading the strings for a binary object sequence. */
736
736
static int
737
737
scan_bos_string_continue(i_ctx_t *i_ctx_p, ref * pref,
738
 
                         scanner_state * pstate)
 
738
                         scanner_state * pstate)
739
739
{
740
740
    scan_binary_state *const pbs = &pstate->s_ss.binary;
741
741
    ref rstr;
746
746
    uint i;
747
747
 
748
748
    if (code != 0)
749
 
        return code;
 
749
        return code;
750
750
 
751
751
    /* Fix up names.  We must do this before creating dictionaries. */
752
752
 
753
753
    for (op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
754
 
         i != 0; i--, op++
755
 
         )
756
 
        switch (r_type(op)) {
757
 
            case t_string:
758
 
                if (r_has_attr(op, a_write))    /* a real string */
759
 
                    break;
760
 
                /* This is actually a name; look it up now. */
761
 
                {
762
 
                    uint attrs = r_type_attrs(op) & (a_read | a_executable);
763
 
 
764
 
                    code = name_ref(imemory, op->value.bytes, r_size(op), op, 1);
765
 
                    if (code < 0)
766
 
                        return code;
767
 
                    r_set_attrs(op, attrs);
768
 
                }
769
 
                /* falls through */
770
 
            case t_name:
771
 
                if (r_has_attr(op, a_read)) {   /* BS_TYPE_EVAL_NAME */
772
 
                    ref *defp = dict_find_name(op);
773
 
 
774
 
                    if (defp == 0)
775
 
                        return_error(e_undefined);
776
 
                    store_check_space(space, defp);
777
 
                    ref_assign(op, defp);
778
 
                }
779
 
                break;
780
 
            case t_mixedarray:  /* actually a dictionary */
781
 
                rescan = true;
782
 
        }
 
754
         i != 0; i--, op++
 
755
         )
 
756
        switch (r_type(op)) {
 
757
            case t_string:
 
758
                if (r_has_attr(op, a_write))    /* a real string */
 
759
                    break;
 
760
                /* This is actually a name; look it up now. */
 
761
                {
 
762
                    uint attrs = r_type_attrs(op) & (a_read | a_executable);
 
763
 
 
764
                    code = name_ref(imemory, op->value.bytes, r_size(op), op, 1);
 
765
                    if (code < 0)
 
766
                        return code;
 
767
                    r_set_attrs(op, attrs);
 
768
                }
 
769
                /* falls through */
 
770
            case t_name:
 
771
                if (r_has_attr(op, a_read)) {   /* BS_TYPE_EVAL_NAME */
 
772
                    ref *defp = dict_find_name(op);
 
773
 
 
774
                    if (defp == 0)
 
775
                        return_error(e_undefined);
 
776
                    store_check_space(space, defp);
 
777
                    ref_assign(op, defp);
 
778
                }
 
779
                break;
 
780
            case t_mixedarray:  /* actually a dictionary */
 
781
                rescan = true;
 
782
        }
783
783
 
784
784
    /* Create dictionaries, if any. */
785
785
 
786
786
    if (rescan) {
787
 
        rescan = false;
788
 
        for (op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
789
 
             i != 0; i--, op++
790
 
             )
791
 
            switch (r_type(op)) {
792
 
            case t_mixedarray:  /* actually a dictionary */
793
 
                {
794
 
                    uint count = r_size(op);
795
 
                    ref rdict;
 
787
        rescan = false;
 
788
        for (op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
 
789
             i != 0; i--, op++
 
790
             )
 
791
            switch (r_type(op)) {
 
792
            case t_mixedarray:  /* actually a dictionary */
 
793
                {
 
794
                    uint count = r_size(op);
 
795
                    ref rdict;
796
796
 
797
 
                    if (count == 1) {
798
 
                        /* Indirect reference. */
799
 
                        if (op->value.refs < op)
800
 
                            ref_assign(&rdict, op->value.refs);
801
 
                        else {
802
 
                            rescan = true;
803
 
                            continue;
804
 
                        }
805
 
                    } else {
806
 
                        code = dict_create(count >> 1, &rdict);
807
 
                        if (code < 0)
808
 
                            return code;
809
 
                        while (count) {
810
 
                            count -= 2;
811
 
                            code = idict_put(&rdict,
812
 
                                             &op->value.refs[count],
813
 
                                             &op->value.refs[count + 1]);
814
 
                            if (code < 0)
815
 
                                return code;
816
 
                        }
817
 
                    }
818
 
                    r_set_attrs(&rdict, a_all);
819
 
                    r_copy_attrs(&rdict, a_executable, op);
820
 
                    ref_assign(op, &rdict);
821
 
                }
822
 
                break;
823
 
            }
 
797
                    if (count == 1) {
 
798
                        /* Indirect reference. */
 
799
                        if (op->value.refs < op)
 
800
                            ref_assign(&rdict, op->value.refs);
 
801
                        else {
 
802
                            rescan = true;
 
803
                            continue;
 
804
                        }
 
805
                    } else {
 
806
                        code = dict_create(count >> 1, &rdict);
 
807
                        if (code < 0)
 
808
                            return code;
 
809
                        while (count) {
 
810
                            count -= 2;
 
811
                            code = idict_put(&rdict,
 
812
                                             &op->value.refs[count],
 
813
                                             &op->value.refs[count + 1]);
 
814
                            if (code < 0)
 
815
                                return code;
 
816
                        }
 
817
                    }
 
818
                    r_set_attrs(&rdict, a_all);
 
819
                    r_copy_attrs(&rdict, a_executable, op);
 
820
                    ref_assign(op, &rdict);
 
821
                }
 
822
                break;
 
823
            }
824
824
    }
825
825
 
826
826
    /* If there were any forward indirect references, fix them up now. */
827
827
 
828
828
    if (rescan)
829
 
        for (op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
830
 
             i != 0; i--, op++
831
 
            )
832
 
            if (r_has_type(op, t_mixedarray)) {
833
 
                const ref *piref = op->value.const_refs;
834
 
                ref rdict;
 
829
        for (op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
 
830
             i != 0; i--, op++
 
831
            )
 
832
            if (r_has_type(op, t_mixedarray)) {
 
833
                const ref *piref = op->value.const_refs;
 
834
                ref rdict;
835
835
 
836
 
                if (r_has_type(piref, t_mixedarray))    /* ref to indirect */
837
 
                    return_error(e_syntaxerror);
838
 
                ref_assign(&rdict, piref);
839
 
                r_copy_attrs(&rdict, a_executable, op);
840
 
                ref_assign(op, &rdict);
841
 
            }
 
836
                if (r_has_type(piref, t_mixedarray))    /* ref to indirect */
 
837
                    return_error(e_syntaxerror);
 
838
                ref_assign(&rdict, piref);
 
839
                r_copy_attrs(&rdict, a_executable, op);
 
840
                ref_assign(op, &rdict);
 
841
            }
842
842
 
843
843
    ref_assign(pref, &pbs->bin_array);
844
844
    r_set_size(pref, pbs->top_size);
854
854
 */
855
855
int
856
856
encode_binary_token(i_ctx_t *i_ctx_p, const ref *obj, int *ref_offset,
857
 
                    int *char_offset, byte *str)
 
857
                    int *char_offset, byte *str)
858
858
{
859
859
    bin_seq_type_t type;
860
860
    uint size = 0;
863
863
    ref nstr;
864
864
 
865
865
    switch (r_type(obj)) {
866
 
        case t_null:
867
 
            type = BS_TYPE_NULL;
868
 
            break;              /* always set all fields */
869
 
        case t_mark:
870
 
            type = BS_TYPE_MARK;
871
 
            break;              /* always set all fields */
872
 
        case t_integer:
873
 
            type = BS_TYPE_INTEGER;
874
 
            value = obj->value.intval;
875
 
            break;
876
 
        case t_real:
877
 
            type = BS_TYPE_REAL;
878
 
            if (sizeof(obj->value.realval) != sizeof(int)) {
879
 
                /* The PLRM allocates exactly 4 bytes for reals. */
880
 
                return_error(e_rangecheck);
881
 
            }
882
 
            value = *(const int *)&obj->value.realval;
 
866
        case t_null:
 
867
            type = BS_TYPE_NULL;
 
868
            break;              /* always set all fields */
 
869
        case t_mark:
 
870
            type = BS_TYPE_MARK;
 
871
            break;              /* always set all fields */
 
872
        case t_integer:
 
873
            type = BS_TYPE_INTEGER;
 
874
            value = obj->value.intval;
 
875
            break;
 
876
        case t_real:
 
877
            type = BS_TYPE_REAL;
 
878
            if (sizeof(obj->value.realval) != sizeof(int)) {
 
879
                /* The PLRM allocates exactly 4 bytes for reals. */
 
880
                return_error(e_rangecheck);
 
881
            }
 
882
            value = *(const int *)&obj->value.realval;
883
883
#if !(ARCH_FLOATS_ARE_IEEE && BYTE_SWAP_IEEE_NATIVE_REALS)
884
 
            if (format >= 3) {
885
 
                /* Never byte-swap native reals -- use native byte order. */
886
 
                format = 4 - ARCH_IS_BIG_ENDIAN;
887
 
            }
 
884
            if (format >= 3) {
 
885
                /* Never byte-swap native reals -- use native byte order. */
 
886
                format = 4 - ARCH_IS_BIG_ENDIAN;
 
887
            }
888
888
#endif
889
 
            break;
890
 
        case t_boolean:
891
 
            type = BS_TYPE_BOOLEAN;
892
 
            value = obj->value.boolval;
893
 
            break;
894
 
        case t_array:
895
 
            type = BS_TYPE_ARRAY;
896
 
            size = r_size(obj);
897
 
            goto aod;
898
 
        case t_dictionary:      /* EXTENSION */
899
 
            type = BS_TYPE_DICTIONARY;
900
 
            size = dict_length(obj) << 1;
901
 
          aod:value = *ref_offset;
902
 
            *ref_offset += size * SIZEOF_BIN_SEQ_OBJ;
903
 
            break;
904
 
        case t_string:
905
 
            type = BS_TYPE_STRING;
 
889
            break;
 
890
        case t_boolean:
 
891
            type = BS_TYPE_BOOLEAN;
 
892
            value = obj->value.boolval;
 
893
            break;
 
894
        case t_array:
 
895
            type = BS_TYPE_ARRAY;
 
896
            size = r_size(obj);
 
897
            goto aod;
 
898
        case t_dictionary:      /* EXTENSION */
 
899
            type = BS_TYPE_DICTIONARY;
 
900
            size = dict_length(obj) << 1;
 
901
          aod:value = *ref_offset;
 
902
            *ref_offset += size * SIZEOF_BIN_SEQ_OBJ;
 
903
            break;
 
904
        case t_string:
 
905
            type = BS_TYPE_STRING;
906
906
nos:
907
 
            size = r_size(obj);
908
 
            value = *char_offset;
909
 
            *char_offset += size;
910
 
            break;
911
 
        case t_name:
912
 
            type = BS_TYPE_NAME;
913
 
            name_string_ref(imemory, obj, &nstr);
914
 
            r_copy_attrs(&nstr, a_executable, obj);
915
 
            obj = &nstr;
916
 
            goto nos;
917
 
        default:
918
 
            return_error(e_rangecheck);
 
907
            size = r_size(obj);
 
908
            value = *char_offset;
 
909
            *char_offset += size;
 
910
            break;
 
911
        case t_name:
 
912
            type = BS_TYPE_NAME;
 
913
            name_string_ref(imemory, obj, &nstr);
 
914
            r_copy_attrs(&nstr, a_executable, obj);
 
915
            obj = &nstr;
 
916
            goto nos;
 
917
        default:
 
918
            return_error(e_rangecheck);
919
919
    }
920
920
    {
921
 
        byte s0 = (byte) size, s1 = (byte) (size >> 8);
922
 
        byte v0 = (byte) value, v1 = (byte) (value >> 8),
923
 
            v2 = (byte) (value >> 16), v3 = (byte) (value >> 24);
 
921
        byte s0 = (byte) size, s1 = (byte) (size >> 8);
 
922
        byte v0 = (byte) value, v1 = (byte) (value >> 8),
 
923
            v2 = (byte) (value >> 16), v3 = (byte) (value >> 24);
924
924
 
925
 
        if (format & 1) {
926
 
            /* Store big-endian */
927
 
            str[2] = s1, str[3] = s0;
928
 
            str[4] = v3, str[5] = v2, str[6] = v1, str[7] = v0;
929
 
        } else {
930
 
            /* Store little-endian */
931
 
            str[2] = s0, str[3] = s1;
932
 
            str[4] = v0, str[5] = v1, str[6] = v2, str[7] = v3;
933
 
        }
 
925
        if (format & 1) {
 
926
            /* Store big-endian */
 
927
            str[2] = s1, str[3] = s0;
 
928
            str[4] = v3, str[5] = v2, str[6] = v1, str[7] = v0;
 
929
        } else {
 
930
            /* Store little-endian */
 
931
            str[2] = s0, str[3] = s1;
 
932
            str[4] = v0, str[5] = v1, str[6] = v2, str[7] = v3;
 
933
        }
934
934
    }
935
935
    if (r_has_attr(obj, a_executable))
936
 
        type += BS_EXECUTABLE;
 
936
        type += BS_EXECUTABLE;
937
937
    str[0] = (byte) type;
938
938
    return 0;
939
939
}