~ubuntu-branches/ubuntu/lucid/erlang/lucid-proposed

1.1.14 by Sergei Golovan
Import upstream version 13.a-dfsg
1
/*
2
 * %CopyrightBegin%
3
 * 
4
 * Copyright Ericsson AB 1996-2009. All Rights Reserved.
5
 * 
6
 * The contents of this file are subject to the Erlang Public License,
1 by Brent A. Fulgham
Import upstream version 9.2.2
7
 * Version 1.1, (the "License"); you may not use this file except in
8
 * compliance with the License. You should have received a copy of the
9
 * Erlang Public License along with this software. If not, it can be
1.1.14 by Sergei Golovan
Import upstream version 13.a-dfsg
10
 * retrieved online at http://www.erlang.org/.
1 by Brent A. Fulgham
Import upstream version 9.2.2
11
 * 
12
 * Software distributed under the License is distributed on an "AS IS"
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
 * the License for the specific language governing rights and limitations
15
 * under the License.
16
 * 
1.1.14 by Sergei Golovan
Import upstream version 13.a-dfsg
17
 * %CopyrightEnd%
1 by Brent A. Fulgham
Import upstream version 9.2.2
18
 */
19
/*
20
 * Purpose: Decoding and encoding Erlang terms.
21
 */  
22
#include "eidef.h"
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <ctype.h>
27
#include <sys/types.h>
28
#include <string.h>
29
30
#include "erl_interface.h"
31
#include "erl_marshal.h"
32
#include "erl_eterm.h"
33
#include "erl_malloc.h"
34
#include "erl_error.h"
35
#include "erl_internal.h"
36
37
#include "eiext.h" /* replaces external.h */
38
#include "putget.h"
39
40
static int is_string(ETERM* term);
41
#if defined(VXWORKS) && CPU == PPC860
1.1.2 by Francois-Denis Gonthier
Import upstream version 10.b.5
42
int erl_fp_compare(unsigned *a, unsigned *b);
1 by Brent A. Fulgham
Import upstream version 9.2.2
43
static void erl_long_to_fp(long l, unsigned *d);
44
#endif
45
46
/* Used when comparing two encoded byte arrays */
47
/* this global data is ok (from threading point of view) since it is
48
 * initialized once and never changed
49
 */
50
51
#define CMP_ARRAY_SIZE 256
52
/* FIXME problem for threaded ? */
53
static char cmp_array[CMP_ARRAY_SIZE]; 
54
static int init_cmp_array_p=1; /* initialize array, the first time */
55
56
#if defined(VXWORKS) && CPU == PPC860
57
#include <limits.h>
58
#endif
59
60
#if defined(__GNUC__)
61
#  define INLINE __inline__
62
#elif defined(__WIN32__)
63
#  define INLINE __inline
64
#else
65
#  define INLINE
66
#endif
67
1.1.9 by Soren Hansen
Import upstream version 11.b.4
68
static int cmp_floats(double f1, double f2);
1 by Brent A. Fulgham
Import upstream version 9.2.2
69
static INLINE double to_float(long l);
70
71
#define ERL_NUM_CMP 1
72
#define ERL_REF_CMP 3
73
74
#define IS_ERL_NUM(t) (cmp_array[t]==ERL_NUM_CMP)
75
76
#define CMP_NUM_CLASS_SIZE 256
77
static unsigned char cmp_num_class[CMP_NUM_CLASS_SIZE]; 
78
static int init_cmp_num_class_p=1; /* initialize array, the first time */
79
80
#define MK_CMP_NUM_CODE(x,y)    (((x)<<2)|(y))
81
#define CMP_NUM_CLASS(x)        (cmp_num_class[x] & 0x03)
82
#define CMP_NUM_CODE(x,y)       (MK_CMP_NUM_CODE(CMP_NUM_CLASS(x),CMP_NUM_CLASS(y)))
83
84
#define SMALL 1
85
#define FLOAT 2
86
#define BIG   3
87
88
#define SMALL_SMALL    MK_CMP_NUM_CODE(SMALL,SMALL)
89
#define SMALL_FLOAT    MK_CMP_NUM_CODE(SMALL,FLOAT)
90
#define SMALL_BIG      MK_CMP_NUM_CODE(SMALL,BIG)
91
#define FLOAT_SMALL    MK_CMP_NUM_CODE(FLOAT,SMALL)
92
#define FLOAT_FLOAT    MK_CMP_NUM_CODE(FLOAT,FLOAT)
93
#define FLOAT_BIG      MK_CMP_NUM_CODE(FLOAT,BIG)
94
#define BIG_SMALL      MK_CMP_NUM_CODE(BIG,SMALL)
95
#define BIG_FLOAT      MK_CMP_NUM_CODE(BIG,FLOAT)
96
#define BIG_BIG        MK_CMP_NUM_CODE(BIG,BIG)
97
98
void erl_init_marshal(void)
99
{
100
  if (init_cmp_array_p) {
101
    memset(cmp_array, 0, CMP_ARRAY_SIZE);
102
    cmp_array[ERL_SMALL_INTEGER_EXT] = 1;
103
    cmp_array[ERL_INTEGER_EXT]       = 1;
104
    cmp_array[ERL_FLOAT_EXT]         = 1;
105
    cmp_array[ERL_SMALL_BIG_EXT]     = 1;
106
    cmp_array[ERL_LARGE_BIG_EXT]     = 1;
107
    cmp_array[ERL_ATOM_EXT]          = 2;
108
    cmp_array[ERL_REFERENCE_EXT]     = 3;
109
    cmp_array[ERL_NEW_REFERENCE_EXT] = 3;
110
    cmp_array[ERL_FUN_EXT]           = 4;
111
    cmp_array[ERL_NEW_FUN_EXT]       = 4;
112
    cmp_array[ERL_PORT_EXT]          = 5;
113
    cmp_array[ERL_PID_EXT]           = 6;
114
    cmp_array[ERL_SMALL_TUPLE_EXT]   = 7;
115
    cmp_array[ERL_LARGE_TUPLE_EXT]   = 7;
116
    cmp_array[ERL_NIL_EXT]           = 8;
117
    cmp_array[ERL_STRING_EXT]        = 9;
118
    cmp_array[ERL_LIST_EXT]          = 9;
119
    cmp_array[ERL_BINARY_EXT]        = 10;
120
    init_cmp_array_p = 0;
121
  }
122
  if (init_cmp_num_class_p) {
123
    memset(cmp_num_class, 0, CMP_NUM_CLASS_SIZE);
124
    cmp_num_class[ERL_SMALL_INTEGER_EXT] = SMALL;
125
    cmp_num_class[ERL_INTEGER_EXT]       = SMALL;
126
    cmp_num_class[ERL_FLOAT_EXT]         = FLOAT;
127
    cmp_num_class[ERL_SMALL_BIG_EXT]     = BIG;
128
    cmp_num_class[ERL_LARGE_BIG_EXT]     = BIG;
129
    init_cmp_num_class_p = 0;
130
  }
131
}
132
133
/*==============================================================
134
 * Marshalling routines.
135
 *==============================================================
136
 */
137
138
/* 
139
 * The actual ENCODE engine.
140
 * Returns 0 on success, otherwise 1.
141
 */
142
int erl_encode_it(ETERM *ep, unsigned char **ext, int dist)
143
{
144
    int i;
145
    unsigned int u;
146
    
147
    switch(ERL_TYPE(ep)) 
148
    {
149
    case ERL_ATOM:
150
	i =  ep->uval.aval.len;
151
	*(*ext)++ = ERL_ATOM_EXT;
152
	*(*ext)++ = (i >>8) &0xff;
153
	*(*ext)++ = i &0xff;
154
	memcpy((void *) *ext, (const void *) ep->uval.aval.a, i);
155
	*ext += i;
156
	return 0;
157
158
    case ERL_INTEGER:
159
	i = ep->uval.ival.i;
160
	/* ERL_SMALL_BIG */
161
	if ((i > ERL_MAX) || (i < ERL_MIN)) { 
162
	    *(*ext)++ = ERL_SMALL_BIG_EXT;
163
	    *(*ext)++ = 4;		/* four bytes */
164
	    if ((*(*ext)++ = ((i>>31) & 0x01))) /* sign byte  */ 
165
	      i = -i;
166
	    *(*ext)++ = i  & 0xff;	/* LSB first  */
167
	    *(*ext)++ = (i >> 8) & 0xff;
168
	    *(*ext)++ = (i >> 16) & 0xff;
169
	    *(*ext)++ = (i >> 24) & 0x7f; /* Don't include the sign bit */
170
	    return 0;
171
	} 
172
	/* SMALL_INTEGER */
173
	if ((i < 256) && (i >= 0)) {
174
	    *(*ext)++ = ERL_SMALL_INTEGER_EXT;
175
	    *(*ext)++ = i & 0xff;
176
	    return 0;
177
	}
178
	/* INTEGER */
179
	*(*ext)++ = ERL_INTEGER_EXT;
180
	*(*ext)++ = (i >> 24) & 0xff;
181
	*(*ext)++ = (i >> 16) & 0xff;
182
	*(*ext)++ = (i >> 8) & 0xff;
183
	*(*ext)++ = i  & 0xff;
184
	return 0;
185
186
    case ERL_U_INTEGER:
187
	u = ep->uval.uival.u;
188
	/* ERL_U_SMALL_BIG */
189
	if (u > ERL_MAX) {
190
	*(*ext)++ = ERL_SMALL_BIG_EXT;
191
	*(*ext)++ = 4;		/* four bytes */
192
	*(*ext)++ = 0;		/* sign byte  */ 
193
	*(*ext)++ = u  & 0xff;	/* LSB first  */
194
	*(*ext)++ = (u >> 8) & 0xff;
195
	*(*ext)++ = (u >> 16) & 0xff;
196
	*(*ext)++ = (u >> 24) & 0xff; 
197
	return 0;
198
	}
199
	/* SMALL_INTEGER */
200
	if ((u < 256) && (u >= 0)) {
201
	    *(*ext)++ = ERL_SMALL_INTEGER_EXT;
202
	    *(*ext)++ = u & 0xff;
203
	    return 0;
204
	}
205
	/* INTEGER */
206
	*(*ext)++ = ERL_INTEGER_EXT;
207
	*(*ext)++ = (u >> 24) & 0xff;
208
	*(*ext)++ = (u >> 16) & 0xff;
209
	*(*ext)++ = (u >> 8) & 0xff;
210
	*(*ext)++ = u  & 0xff;
211
	return 0;
212
213
    case ERL_PID:
214
	*(*ext)++ = ERL_PID_EXT;    
215
	/* First poke in node as an atom */    
216
	i = strlen(ERL_PID_NODE(ep));
217
	*(*ext)++ = ERL_ATOM_EXT;
218
	*(*ext)++ = (i >>8) &0xff;
219
	*(*ext)++ = i &0xff;
220
	memcpy(*ext, ERL_PID_NODE(ep), i);
221
	*ext += i;
222
	/* And then fill in the integer fields */
223
	i = ERL_PID_NUMBER(ep);
224
	*(*ext)++ = (i >>24) &0xff;
225
	*(*ext)++ = (i >>16) &0xff;
226
	*(*ext)++ = (i >>8) &0xff;
227
	*(*ext)++ = i &0xff;
228
	i = ERL_PID_SERIAL(ep);
229
	*(*ext)++ = (i >>24) &0xff;
230
	*(*ext)++ = (i >>16) &0xff;
231
	*(*ext)++ = (i >>8) &0xff;
232
	*(*ext)++ = i &0xff;
233
	*(*ext)++ = ERL_PID_CREATION(ep);
234
	return 0;
235
    case ERL_REF: {
236
	    int len, j;
237
238
	    /* Always encode as an extended reference; all
239
	       participating parties are now expected to be
240
	       able to decode extended references. */
241
242
	    *(*ext)++ = ERL_NEW_REFERENCE_EXT;
243
244
	    i = strlen(ERL_REF_NODE(ep));
245
	    len = ERL_REF_LEN(ep);
246
	    *(*ext)++ = (len >>8) &0xff;
247
	    *(*ext)++ = len &0xff;
248
249
	    *(*ext)++ = ERL_ATOM_EXT;
250
	    *(*ext)++ = (i >>8) &0xff;
251
	    *(*ext)++ = i &0xff;
252
	    memcpy(*ext, ERL_REF_NODE(ep), i);
253
	    *ext += i;
254
	    *(*ext)++ = ERL_REF_CREATION(ep);
255
	    /* Then the integer fields */
256
	    for (j = 0; j < ERL_REF_LEN(ep); j++) {
257
		i = ERL_REF_NUMBERS(ep)[j];
258
		*(*ext)++ = (i >>24) &0xff;
259
		*(*ext)++ = (i >>16) &0xff;
260
		*(*ext)++ = (i >>8) &0xff;
261
		*(*ext)++ = i &0xff;
262
	    }
263
	}
264
	return 0;
265
    case ERL_PORT:
266
	*(*ext)++ = ERL_PORT_EXT;
267
	/* First poke in node as an atom */
268
	i = strlen(ERL_PORT_NODE(ep));
269
	*(*ext)++ = ERL_ATOM_EXT;
270
	*(*ext)++ = (i >>8) &0xff;
271
	*(*ext)++ = i &0xff;
272
	memcpy(*ext, ERL_PORT_NODE(ep), i);
273
	*ext += i;
274
	/* Then the integer fields */
275
	i = ERL_PORT_NUMBER(ep);
276
	*(*ext)++ = (i >>24) &0xff;
277
	*(*ext)++ = (i >>16) &0xff;
278
	*(*ext)++ = (i >>8) &0xff;
279
	*(*ext)++ = i &0xff;
280
	*(*ext)++ = ERL_PORT_CREATION(ep);
281
	return 0;
282
    case ERL_EMPTY_LIST:
283
	*(*ext)++ = ERL_NIL_EXT;
284
	break;
285
    case ERL_LIST:
286
	i = is_string(ep);
287
	if (0 < i && i < 0x10000) { /* String. */
288
	    *(*ext)++ = ERL_STRING_EXT;
289
	    *(*ext)++ = (i >>8) &0xff;
290
	    *(*ext)++ = i &0xff;
291
	    while (ERL_TYPE(ep) == ERL_LIST) {
292
		*(*ext)++ = HEAD(ep)->uval.ival.i;
293
		ep = TAIL(ep);
294
	    }
295
	    break;
296
	} else {		/* List. */
297
	    i = erl_length(ep);
298
	    *(*ext)++ = ERL_LIST_EXT;
299
	    *(*ext)++ = (i >>24) &0xff;
300
	    *(*ext)++ = (i >>16) &0xff;
301
	    *(*ext)++ = (i >>8) &0xff;
302
	    *(*ext)++ = i &0xff;
303
	    while (ERL_TYPE(ep) == ERL_LIST) {
304
		if (erl_encode_it(HEAD(ep), ext, dist))
305
		    return 1;
306
		ep = TAIL(ep);
307
	    }
308
	    i = erl_encode_it(ep, ext, dist);
309
	    return i;
310
	}
311
    case ERL_TUPLE:
312
	i = ep->uval.tval.size;
313
	if (i <= 0xff) {
314
	    *(*ext)++ = ERL_SMALL_TUPLE_EXT;
315
	    *(*ext)++ = i & 0xff;
316
	}
317
	else {
318
	    *(*ext)++ = ERL_LARGE_TUPLE_EXT;
319
	    *(*ext)++ = (i >> 24) & 0xff;
320
	    *(*ext)++ = (i >> 16 ) & 0xff;
321
	    *(*ext)++ = (i >> 8) & 0xff;
322
	    *(*ext)++ = i & 0xff;
323
	}
324
	for (i=0; i<ep->uval.tval.size; i++)
325
	    if (erl_encode_it(ep->uval.tval.elems[i], ext, dist))
326
		return 1;
327
	break;
328
    case ERL_FLOAT:
329
	*(*ext)++ = ERL_FLOAT_EXT;
330
	memset(*ext, 0, 31);
331
	sprintf((char *) *ext, "%.20e", ep->uval.fval.f);
332
	*ext += 31;
333
	break;
334
    case ERL_BINARY:
335
	*(*ext)++ = ERL_BINARY_EXT;
336
	i = ep->uval.bval.size;
337
	*(*ext)++ = (i >> 24) & 0xff;
338
	*(*ext)++ = (i >> 16) & 0xff;
339
	*(*ext)++ = (i >> 8) & 0xff;
340
	*(*ext)++ = i  & 0xff;
341
	memcpy((char *) *ext, (char*) ep->uval.bval.b, i);
342
	*ext += i;
343
	break;
344
    case ERL_FUNCTION:
345
	if (ERL_FUN_ARITY(ep) != -1) {
346
	    unsigned char *size_p = *ext + 1;
347
	    *(*ext)++ = ERL_NEW_FUN_EXT;
348
	    *ext += 4;
349
	    i = ERL_FUN_ARITY(ep);
350
	    put8(*ext, i);
351
	    memcpy(*ext, ERL_FUN_MD5(ep), 16);
352
	    *ext += 16;
353
	    i = ERL_FUN_NEW_INDEX(ep);
354
	    put32be(*ext, i);
355
	    i = ERL_CLOSURE_SIZE(ep);
356
	    put32be(*ext, i);
357
	    erl_encode_it(ERL_FUN_MODULE(ep), ext, dist);
358
	    erl_encode_it(ERL_FUN_INDEX(ep), ext, dist);
359
	    erl_encode_it(ERL_FUN_UNIQ(ep), ext, dist);
360
	    erl_encode_it(ERL_FUN_CREATOR(ep), ext, dist);
361
	    for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
362
		erl_encode_it(ep->uval.funcval.closure[i], ext, dist);
363
	    if (size_p != NULL) {
364
		i = *ext - size_p;
365
		put32be(size_p, i);
366
	    }
367
	} else {
368
	    *(*ext)++ = ERL_FUN_EXT;
369
	    i = ERL_CLOSURE_SIZE(ep);
370
	    *(*ext)++ = (i >> 24) & 0xff;
371
	    *(*ext)++ = (i >> 16) & 0xff;
372
	    *(*ext)++ = (i >> 8) & 0xff;
373
	    *(*ext)++ = i  & 0xff;
374
	    erl_encode_it(ERL_FUN_CREATOR(ep), ext, dist);
375
	    erl_encode_it(ERL_FUN_MODULE(ep), ext, dist);
376
	    erl_encode_it(ERL_FUN_INDEX(ep), ext, dist);
377
	    erl_encode_it(ERL_FUN_UNIQ(ep), ext, dist);
378
	    for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
379
		erl_encode_it(ep->uval.funcval.closure[i], ext, dist);
380
	}
381
	break;
382
    default:
383
	return 1;
384
    }
385
    return 0;
386
}
387
388
/* 
389
 * ENCODE an ETERM into a BUFFER, assuming BUFFER is of 
390
 * enough size. At success return number of bytes written 
391
 * into it, otherwise return 0.
392
 */
393
static int erl_encode3(ETERM *ep, unsigned char *t, int dist)
394
{
395
  unsigned char *x = t;
396
  
397
  *x++ = ERL_VERSION_MAGIC;
398
  if (erl_encode_it(ep, &x, dist)) {
399
#ifdef DEBUG
400
    erl_err_msg("<ERROR> erl_encode: Error while encoding");
401
#endif
402
    return 0;
403
  }
404
  return (x - t);
405
406
}
407
408
/* API */
409
410
int erl_encode(ETERM *ep, unsigned char *t)
411
{
412
    return erl_encode3(ep, t, 4);
413
}
414
415
/* determine the buffer size that will be required for the eterm */
416
static int erl_term_len_helper(ETERM *ep, int dist);
417
418
/* FIXME hard coded dist version */
419
int erl_term_len(ETERM *ep)
420
{
421
  return 1+erl_term_len_helper(ep, 4);
422
}
423
424
static int erl_term_len_helper(ETERM *ep, int dist)
425
{
426
  int len = 0;
427
  int i;
428
  unsigned int u;
429
430
  if (ep) {
431
    switch (ERL_TYPE(ep)) {
432
    case ERL_ATOM:
433
      i = ep->uval.aval.len;
434
      len = i + 3;
435
      break;
436
437
    case ERL_INTEGER:
438
      i = ep->uval.ival.i;
439
      if ((i > ERL_MAX) || (i < ERL_MIN)) len = 7;
440
      else if ((i < 256) && (i >= 0)) len = 2; 
441
      else len = 5;
442
      break;
443
444
    case ERL_U_INTEGER:
445
      u = ep->uval.uival.u;
446
      if (u > ERL_MAX) len = 7;
447
      else if (u  < 256) len = 2;
448
      else len = 5;
449
      break;
450
451
    case ERL_PID:
452
      /* 1 + N + 4 + 4 + 1 where N = 3 + strlen */
453
      i = strlen(ERL_PID_NODE(ep));
454
      len = 13 + i;
455
      break;
456
457
    case ERL_REF:
458
      i = strlen(ERL_REF_NODE(ep));
459
      if (dist >= 4 && ERL_REF_LEN(ep) > 1) {
460
	  len = 1 + 2 + (i+3) + 1 + ERL_REF_LEN(ep) * 4;
461
      } else {
462
	  /* 1 + N + 4 + 1 where N = 3 + strlen */
463
	  len = 9 + i;
464
      }
465
      break;
466
467
    case ERL_PORT:
468
      /* 1 + N + 4 + 1 where N = 3 + strlen */
469
      i = strlen(ERL_PORT_NODE(ep));
470
      len = 9 + i;
471
      break;
472
473
    case ERL_EMPTY_LIST:
474
      len = 1;
475
      break;
476
477
    case ERL_LIST:
478
      i = is_string(ep);
479
      if ((i > 0) && (i < 0x10000)) { /* string: 3 + strlen */
480
	for (len = 3; ERL_TYPE(ep) == ERL_LIST; ep =  TAIL(ep)) {
481
	  len++;
482
	}
483
      }
484
      else { /* list: 5 + len(elem1) + len(elem2) ... */
485
	for (len = 5; ERL_TYPE(ep) == ERL_LIST; ep =  TAIL(ep)) {
486
	  len += erl_term_len_helper(HEAD(ep), dist);
487
	}
488
	len += erl_term_len_helper(ep, dist); /* last element */
489
      }
490
      break;
491
492
    case ERL_TUPLE:
493
      /* (2 or 5) + len(elem1) + len(elem2) ... */
494
      i = ep->uval.tval.size;
495
      if (i <= 0xff) len = 2;
496
      else len = 5;
497
      
498
      for (i=0; i<ep->uval.tval.size; i++) {
499
	len += erl_term_len_helper(ep->uval.tval.elems[i], dist);
500
      }
501
      break;
502
503
    case ERL_FLOAT:
504
      len = 32;
505
      break;
506
507
    case ERL_BINARY:
508
      i = ep->uval.bval.size;
509
      len = 5 + i;
510
      break;
511
512
    case ERL_FUNCTION:
513
      if (ERL_FUN_ARITY(ep) == -1) {
514
	  len = 1 + 4;
515
	  len += erl_term_len_helper(ERL_FUN_CREATOR(ep),dist);
516
	  len += erl_term_len_helper(ERL_FUN_MODULE(ep),dist);
517
	  len += erl_term_len_helper(ERL_FUN_INDEX(ep),dist);
518
	  len += erl_term_len_helper(ERL_FUN_UNIQ(ep),dist);
519
	  for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
520
	      len += erl_term_len_helper(ERL_CLOSURE_ELEMENT(ep,i), dist);
521
      } else {
522
	  len = 1 + 4 + 16 + 4 + 4;
523
	  len += erl_term_len_helper(ERL_FUN_MODULE(ep),dist);
524
	  len += erl_term_len_helper(ERL_FUN_INDEX(ep),dist);
525
	  len += erl_term_len_helper(ERL_FUN_UNIQ(ep),dist);
526
	  len += erl_term_len_helper(ERL_FUN_CREATOR(ep),dist);
527
	  for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
528
	      len += erl_term_len_helper(ERL_CLOSURE_ELEMENT(ep,i), dist);
529
      }
530
      break;
531
532
    default:
533
#ifdef DEBUG
534
	fprintf(stderr, "Shouldn't happen: erl_term_len, unknown term type: '%c'\n",ERL_TYPE(ep));
535
#endif
536
      erl_errno = EINVAL;
537
      exit(1);
538
    }
539
  }
540
541
  return len;
542
}
543
544
/* 
545
 * This one makes it easy to ENCODE several CONSECUTIVE
546
 * ETERM's into the same buffer. 
547
 */
548
int erl_encode_buf(ETERM *ep, unsigned char **ext)
549
{
550
  unsigned char *start=*ext;
551
  
552
  *(*ext)++ = ERL_VERSION_MAGIC;
553
  if (erl_encode_it(ep, ext, 0)) {
554
#ifdef DEBUG
555
    erl_err_msg("<ERROR> erl_encode_buf: Error while encoding\n");
556
#endif
557
    return 0;
558
  }
559
  return (*ext - start);
560
561
} /* erl_encode_buf */
562
563
/*
564
 * A nice macro to make it look cleaner in the 
565
 * cases of PID's,PORT's and REF's below. 
566
 * It reads the NODE name from a buffer.
567
 */
568
#define READ_THE_NODE(ext,cp,len,i) \
569
/* eat first atom, repr. the node */ \
570
if (**ext != ERL_ATOM_EXT) \
571
  return (ETERM *) NULL; \
572
*ext += 1; \
573
i = (**ext << 8) | (*ext)[1]; \
574
cp = (char *) *(ext) + 2; \
575
*ext += (i + 2); \
576
len = i
577
1.1.9 by Soren Hansen
Import upstream version 11.b.4
578
#define STATIC_NODE_BUF_SZ 30
579
580
#define SET_NODE(node,node_buf,cp,len) \
581
if (len >= STATIC_NODE_BUF_SZ) node = malloc(len+1); \
582
else node = node_buf; \
583
memcpy(node, cp, len); \
584
node[len] = '\0'
585
586
#define RESET_NODE(node,len) \
587
if (len >= STATIC_NODE_BUF_SZ) free(node)
588
1 by Brent A. Fulgham
Import upstream version 9.2.2
589
/*
590
 * The actual DECODE engine.
591
 * Returns NULL in case of failure.
592
 */
593
static ETERM *erl_decode_it(unsigned char **ext)
594
{
595
    char *cp;
596
    ETERM *ep,*tp,*np;
597
    unsigned int u,sign;
598
    int i,j,len,arity;
599
    double ff;
600
    
601
    /* Assume we are going to decode an integer */
602
    ep = erl_alloc_eterm(ERL_INTEGER);
603
    ERL_COUNT(ep) = 1;
604
    
605
    switch (*(*ext)++) 
606
    {
607
    case ERL_INTEGER_EXT:
608
	i = (int) (**ext << 24) | ((*ext)[1] << 16) |
609
	    ((*ext)[2] << 8) | (*ext)[3];
610
	*ext += 4;
611
	ep->uval.ival.i = i;
612
	return ep;
613
614
    case ERL_SMALL_INTEGER_EXT:
615
	i = *(*ext)++;
616
	ep->uval.ival.i = i;
617
	return ep;
618
619
        /* NOTE: The arity below for bigs is not really the arity (= number of digits) */
620
        /*       It is the byte count and this might cause problems in other parts...  */
621
    case ERL_SMALL_BIG_EXT:
622
        arity = *(*ext)++; 
623
	goto big_cont;
624
    case ERL_LARGE_BIG_EXT:
625
	arity = (**ext << 24) | ((*ext)[1])<< 16 | 
626
	    ((*ext)[2]) << 8 |((*ext)[3]); 
627
	*ext += 4;
628
    big_cont:
629
	sign = *(*ext)++; 
630
	if (arity != 4)             
631
	    goto big_truncate;
632
	if ((*ext)[3] & 0x80) { 
633
	    /* MSB already occupied ! */
634
	    if (sign)
635
		goto big_truncate;
636
	    else {                
637
		/* It will fit into an unsigned int !! */
638
		u = (((*ext)[3] << 24)|((*ext)[2])<< 16|((*ext)[1]) << 8 |(**ext));
639
		ERL_TYPE(ep) = ERL_U_INTEGER;
640
		ep->uval.uival.u = u;
641
		/* *ext += i; */
642
		*ext += arity;
643
		return ep;
644
	    }
645
	}
646
	else {       
647
	    /* It will fit into an int !! 
648
	     * Note: It comes in "one's-complement notation" 
649
	     */
650
	    if (sign)
651
		i = (int) (~(((*ext)[3] << 24) | ((*ext)[2])<< 16 |
652
			     ((*ext)[1]) << 8 | (**ext)) | (unsigned int) sign);
653
	    else
654
		i = (int) (((*ext)[3] << 24) | ((*ext)[2])<< 16 |
655
			   ((*ext)[1]) << 8 | (**ext));
656
	    ep->uval.ival.i = i;
657
	    *ext += arity;
658
	    return ep;
659
	}
660
    big_truncate: 
661
	/* truncate to: (+/-) 1 */
662
#ifdef DEBUG
663
	erl_err_msg("<WARNING> erl_decode_it: Integer truncated...");
664
#endif
665
	ep->uval.ival.i = sign?-1:1;
666
	*ext += arity;
667
	return ep;
668
      
669
    case ERL_ATOM_EXT:
670
	ERL_TYPE(ep) = ERL_ATOM;
671
	i = (**ext << 8) | (*ext)[1];
672
	cp = (char *) *(ext) + 2;
673
	*ext += (i + 2);
674
	ep->uval.aval.len = i;
675
	ep->uval.aval.a = (char *) erl_malloc(i+1);
676
	memcpy(ep->uval.aval.a, cp, i);
677
	ep->uval.aval.a[i]='\0';
678
	return ep;
679
      
680
    case ERL_PID_EXT:
681
	erl_free_term(ep);
682
	{			/* Why not use the constructors? */
1.1.9 by Soren Hansen
Import upstream version 11.b.4
683
	    char *node;
684
	    char node_buf[STATIC_NODE_BUF_SZ];
1 by Brent A. Fulgham
Import upstream version 9.2.2
685
	    unsigned int number, serial;
686
	    unsigned char creation;
1.1.9 by Soren Hansen
Import upstream version 11.b.4
687
	    ETERM *eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
688
689
	    READ_THE_NODE(ext,cp,len,i);
1.1.9 by Soren Hansen
Import upstream version 11.b.4
690
	    SET_NODE(node,node_buf,cp,len);
1 by Brent A. Fulgham
Import upstream version 9.2.2
691
692
	    /* get the integers */
693
#if 0
694
	    /* FIXME: Remove code or whatever....
695
               Ints on the wire are big-endian (== network byte order)
696
               so use ntoh[sl]. (But some are little-endian! Arrrgh!)
697
               Also, the libc authors can be expected to optimize them
698
               heavily. However, the marshalling makes no guarantees
699
               about alignments -- so it won't work at all. */
700
	    number = ntohl(*((unsigned int *)*ext)++);
701
	    serial = ntohl(*((unsigned int *)*ext)++);
702
#else
703
	    number = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | 
704
		((*ext)[2]) << 8 | ((*ext)[3]);	
705
	    *ext += 4;
706
	    serial = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | 
707
		((*ext)[2]) << 8 | ((*ext)[3]);	
708
	    *ext += 4;
709
#endif
710
	    creation =  *(*ext)++; 
1.1.9 by Soren Hansen
Import upstream version 11.b.4
711
	    eterm_p = erl_mk_pid(node, number, serial, creation);
712
	    RESET_NODE(node,len);
713
	    return eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
714
	}
715
    case ERL_REFERENCE_EXT:
716
	erl_free_term(ep);
717
	{
1.1.9 by Soren Hansen
Import upstream version 11.b.4
718
	    char *node;
719
	    char node_buf[STATIC_NODE_BUF_SZ];
1 by Brent A. Fulgham
Import upstream version 9.2.2
720
	    unsigned int number;
721
	    unsigned char creation;
1.1.9 by Soren Hansen
Import upstream version 11.b.4
722
	    ETERM *eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
723
724
	    READ_THE_NODE(ext,cp,len,i);
1.1.9 by Soren Hansen
Import upstream version 11.b.4
725
	    SET_NODE(node,node_buf,cp,len);
1 by Brent A. Fulgham
Import upstream version 9.2.2
726
727
	    /* get the integers */
728
#if 0
729
	    number = ntohl(*((unsigned int *)*ext)++);
730
#else
731
	    number = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | 
732
		((*ext)[2]) << 8 | ((*ext)[3]);	
733
	    *ext += 4;
734
#endif
735
	    creation =  *(*ext)++; 
1.1.9 by Soren Hansen
Import upstream version 11.b.4
736
	    eterm_p = erl_mk_ref(node, number, creation);
737
	    RESET_NODE(node,len);
738
	    return eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
739
	}
740
741
    case ERL_NEW_REFERENCE_EXT: 
742
	erl_free_term(ep);
743
	{
1.1.9 by Soren Hansen
Import upstream version 11.b.4
744
	    char *node;
745
	    char node_buf[STATIC_NODE_BUF_SZ];
1 by Brent A. Fulgham
Import upstream version 9.2.2
746
	    size_t cnt, i;
747
	    unsigned int n[3];
748
	    unsigned char creation;
1.1.9 by Soren Hansen
Import upstream version 11.b.4
749
	    ETERM *eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
750
751
#if 0
752
	    cnt = ntohs(*((unsigned short *)*ext)++);
753
#else
754
	    cnt = ((*ext)[0] << 8) | (*ext)[1];
755
	    *ext += 2;
756
#endif
757
758
	    READ_THE_NODE(ext,cp,len,i);
1.1.9 by Soren Hansen
Import upstream version 11.b.4
759
	    SET_NODE(node,node_buf,cp,len);
1 by Brent A. Fulgham
Import upstream version 9.2.2
760
761
	    /* get the integers */
762
	    creation =  *(*ext)++; 
763
	    for(i = 0; i < cnt; i++)
764
	    {
765
#if 0
766
		n[i] = ntohl(*((unsigned int *)*ext)++);
767
#else
768
		n[i] = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | 
769
		    ((*ext)[2]) << 8 | ((*ext)[3]);	
770
		*ext += 4;
771
#endif
772
	    }
1.1.9 by Soren Hansen
Import upstream version 11.b.4
773
	    eterm_p = __erl_mk_reference(node, cnt, n, creation);
774
	    RESET_NODE(node,len);
775
	    return eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
776
	}
777
778
    case ERL_PORT_EXT:
779
	erl_free_term(ep);
780
	{
1.1.9 by Soren Hansen
Import upstream version 11.b.4
781
	    char *node;
782
	    char node_buf[STATIC_NODE_BUF_SZ];
1 by Brent A. Fulgham
Import upstream version 9.2.2
783
	    unsigned int number;
784
	    unsigned char creation;
1.1.9 by Soren Hansen
Import upstream version 11.b.4
785
	    ETERM *eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
786
787
	    READ_THE_NODE(ext,cp,len,i);
1.1.9 by Soren Hansen
Import upstream version 11.b.4
788
	    SET_NODE(node,node_buf,cp,len);
1 by Brent A. Fulgham
Import upstream version 9.2.2
789
790
	    /* get the integers */
791
#if 0
792
	    number = ntohl(*((unsigned int *)*ext)++);
793
#else
794
	    number = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | 
795
		((*ext)[2]) << 8 | ((*ext)[3]);	
796
	    *ext += 4;
797
#endif
798
	    creation =  *(*ext)++; 
1.1.9 by Soren Hansen
Import upstream version 11.b.4
799
	    eterm_p = erl_mk_port(node, number, creation);
800
	    RESET_NODE(node,len);
801
	    return eterm_p;
1 by Brent A. Fulgham
Import upstream version 9.2.2
802
	}
803
804
    case ERL_NIL_EXT:
805
	ERL_TYPE(ep) = ERL_EMPTY_LIST;
806
	return ep;
807
808
    case ERL_LIST_EXT:
809
	ERL_TYPE(ep) = ERL_LIST;
810
	i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3];
811
	*ext += 4;	
812
	/* ASSERT(i != 0);	*/	/* Should be represented by ERL_NIL_EXT. */
813
	tp = ep;
814
	for (j = 0; j < i; j++) 
815
	    if ((HEAD(tp) = erl_decode_it(ext)) == NULL) 
816
		goto failure;
817
	    else if (j + 1 < i) {
818
		/* We have to watch out for how we allocates the
819
		 * last tail element since we may encounter non-
820
		 * well formed lists.
821
		 */
822
		np = erl_alloc_eterm(ERL_LIST);
823
		ERL_COUNT(np) = 1;
1.1.13 by Sergei Golovan
Import upstream version 12.b.5-dfsg
824
                TAIL(np) = NULL; /* in case of failure */
1 by Brent A. Fulgham
Import upstream version 9.2.2
825
		TAIL(tp) = np;
826
		tp = np;
827
	    }
828
	if ((TAIL(tp) = erl_decode_it(ext)) == NULL) 
829
	    goto failure;
830
	return ep;
831
832
    case ERL_STRING_EXT:
833
	{
834
	    unsigned char* s;
835
	  
836
	    ERL_TYPE(ep) = ERL_EMPTY_LIST;
837
	    i = (**ext << 8) | ((*ext)[1]);
838
	    *ext += 2;
839
	    s = *ext+i;
840
841
	    while (*ext < s) {
842
		ETERM* integer;
843
		ETERM* cons;
844
845
		integer = erl_alloc_eterm(ERL_INTEGER);
846
		ERL_COUNT(integer) = 1;
847
		integer->uval.ival.i = *--s;
848
849
		cons = erl_alloc_eterm(ERL_LIST);
850
		ERL_COUNT(cons) = 1;
851
		HEAD(cons) = integer;
852
		TAIL(cons) = ep;
853
		ep = cons;
854
	    }
855
	    *ext += i;
856
	    return ep;
857
	}
858
859
    case ERL_SMALL_TUPLE_EXT:
860
	ERL_TYPE(ep) = ERL_TUPLE;
861
	i = *(*ext)++;
862
	goto decode_tuple;
863
864
    case ERL_LARGE_TUPLE_EXT:
865
	i = (**ext << 24) | ((*ext)[1]) << 16 | 
866
	    ((*ext)[2]) << 8 | ((*ext)[3]) ;	
867
	*ext += 4;
868
    decode_tuple:
869
	ep->uval.tval.size = i;
870
	j = (i + 1) * sizeof(ETERM*);
871
	ep->uval.tval.elems = (ETERM**) erl_malloc(j);
872
	memset(ep->uval.tval.elems, 0, j); /* in case of failure below... */
873
	for (i=0; i<ep->uval.tval.size; i++)
874
	    if ((tp = erl_decode_it(ext)) == NULL)
875
		goto failure;
876
	    else
877
		ep->uval.tval.elems[i] = tp;
878
	return ep;
879
880
    case ERL_FLOAT_EXT:
881
	ERL_TYPE(ep) = ERL_FLOAT;
882
	if (sscanf((char *) *ext, "%lf", &ff) != 1)
883
	    goto failure;
884
	*ext += 31;
885
	ep->uval.fval.f = ff;
886
	return ep;
887
888
    case ERL_BINARY_EXT:
889
	ERL_TYPE(ep) = ERL_BINARY;
890
	i = (**ext << 24) | ((*ext)[1] << 16) |
891
	    ((*ext)[2] << 8) | (*ext)[3];
892
	*ext += 4;
893
	ep->uval.bval.size = i;
894
	ep->uval.bval.b = (unsigned char *) erl_malloc(i);
895
	memcpy(ep->uval.bval.b, *ext, i);
896
	*ext += i;
897
	return ep;
898
899
    case ERL_FUN_EXT:		/* FIXME: error checking */
900
	ERL_TYPE(ep) = ERL_FUNCTION;
901
	i = get32be(*ext);
902
	/*i = *(**ext << 24) | ((*ext)[1] << 16) | ((*ext)[2] << 8) | (*ext)[3];
903
	 *ext += 4; */
904
	ERL_FUN_ARITY(ep) = -1;
905
	ERL_CLOSURE_SIZE(ep) = i;
906
	ERL_FUN_CREATOR(ep) = erl_decode_it(ext);
907
	ERL_FUN_MODULE(ep) = erl_decode_it(ext);
908
	ERL_FUN_INDEX(ep) = erl_decode_it(ext);
909
	ERL_FUN_UNIQ(ep) = erl_decode_it(ext);
910
	j = i * sizeof(ETERM*);
911
	ERL_CLOSURE(ep) = (ETERM**) erl_malloc(j);
912
	memset(ERL_CLOSURE(ep), 0, j);
913
	for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
914
	    ERL_CLOSURE_ELEMENT(ep,i) = erl_decode_it(ext);
915
	return ep;
916
917
    case ERL_NEW_FUN_EXT:	/* FIXME: error checking */
918
	ERL_TYPE(ep) = ERL_FUNCTION;
919
	i = get32be(*ext);	/* size, we don't use it here */
920
	ERL_FUN_ARITY(ep) = get8(*ext);
921
	memcpy(ERL_FUN_MD5(ep), *ext, 16);
922
	*ext += 16;
923
	ERL_FUN_NEW_INDEX(ep) = get32be(*ext);
924
	i = get32be(*ext);
925
	ERL_CLOSURE_SIZE(ep) = i;
926
	ERL_FUN_MODULE(ep) = erl_decode_it(ext);
927
	ERL_FUN_INDEX(ep) = erl_decode_it(ext);
928
	ERL_FUN_UNIQ(ep) = erl_decode_it(ext);
929
	ERL_FUN_CREATOR(ep) = erl_decode_it(ext);
930
	j = i * sizeof(ETERM*);
931
	ERL_CLOSURE(ep) = (ETERM**) erl_malloc(j);
932
	memset(ERL_CLOSURE(ep), 0, j);
933
	for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
934
	    ERL_CLOSURE_ELEMENT(ep,i) = erl_decode_it(ext);
935
	return ep;
936
937
    } /* switch */
938
    
939
 failure:
940
    erl_free_term(ep);
941
    return (ETERM *) NULL;
942
    
943
} /* erl_decode_it */
944
945
/*
946
 * DECODE a buffer of BYTES into an ETERM.
947
 * Returns NULL in case of failure.
948
 */
949
ETERM *erl_decode(unsigned char *t) 
950
{
951
  ETERM *ep;
952
  unsigned char *ext;
953
954
  ext = t;
955
956
  /* We ignore the version magic since it might be
957
   * possible that the buffer has been manipulated
958
   * with erl_peek_ext.
959
   */
960
  if (*ext == ERL_VERSION_MAGIC) 
961
    ext++;  
962
963
  ep = NULL;
964
  ep = erl_decode_it(&ext);
965
#ifdef DEBUG
966
  if (!ep) erl_err_msg("<ERROR> erl_decode: Error while decoding");
967
#endif
968
  return ep;
969
970
} /* erl_decode */
971
972
/* 
973
 * This one makes it possible to DECODE two CONSECUTIVE 
974
 * ETERM's in the same buffer. 
975
 */
976
ETERM *erl_decode_buf(unsigned char **ext) 
977
{
978
  ETERM *ep;
979
  
980
  /* We ignore the version magic since it might be
981
   * possible that the buffer has been manipulated
982
   * with erl_peek_ext.
983
   */
984
  if (**ext == ERL_VERSION_MAGIC) 
985
    (*ext)++;
986
987
  ep = NULL;
988
  ep = erl_decode_it(ext);
989
#ifdef DEBUG
990
    if (!ep) erl_err_msg("<ERROR> erl_decode_buf: Error while decoding");
991
#endif
992
  return ep;
993
994
} /* erl_decode_buf */
995
996
997
/*==============================================================
998
 * Ok, here comes routines for inspecting/manipulating 
999
 * an encoded buffer of bytes.
1000
 *==============================================================
1001
 */
1002
1003
/*
1004
 * Return 1 if the VERSION MAGIC in the BUFFER is the
1005
 * same as the this library version.
1006
 */
1007
int erl_verify_magic(unsigned char *ext)
1008
{
1009
1010
  if (*ext == ERL_VERSION_MAGIC) 
1011
    return 1;
1012
  else
1013
    return 0;
1014
1015
} /* erl_verify_magic */
1016
1017
/*
1018
 * Return the TYPE of an ENCODED ETERM.
1019
 * At failure, return 0.
1020
 */ 
1021
unsigned char erl_ext_type(unsigned char *ext)
1022
{
1023
    /* FIXME old code could skip multiple magic */
1024
1025
    /* Move over magic number if any */
1026
    if (*ext == ERL_VERSION_MAGIC) ext++;
1027
  
1028
    switch (*ext) {
1029
    case ERL_SMALL_INTEGER_EXT:
1030
    case ERL_INTEGER_EXT:
1031
	return ERL_INTEGER;
1032
    case ERL_ATOM_EXT:
1033
	return ERL_ATOM;
1034
    case ERL_PID_EXT:
1035
	return ERL_PID;
1036
    case ERL_PORT_EXT:
1037
	return ERL_PORT;
1038
    case ERL_REFERENCE_EXT:
1039
    case ERL_NEW_REFERENCE_EXT:
1040
	return ERL_REF;
1041
    case ERL_NIL_EXT: 
1042
	return ERL_EMPTY_LIST;
1043
    case ERL_LIST_EXT:
1044
	return ERL_LIST;
1045
    case ERL_SMALL_TUPLE_EXT:
1046
    case ERL_LARGE_TUPLE_EXT:
1047
	return ERL_TUPLE;
1048
    case ERL_FLOAT_EXT:
1049
	return ERL_FLOAT;
1050
    case ERL_BINARY_EXT:
1051
	return ERL_BINARY;
1052
    case ERL_FUN_EXT:
1053
    case ERL_NEW_FUN_EXT:
1054
	return ERL_FUNCTION;
1055
    case ERL_SMALL_BIG_EXT:
1056
    case ERL_LARGE_BIG_EXT:
1057
        return ERL_BIG;
1058
    default:
1059
	return 0;
1060
1061
    } /* switch */
1062
1063
} /* erl_ext_type */
1064
1065
/* 
1066
 * Returns the number of elements in compund
1067
 * terms. For other kind of terms zero is returned.
1068
 * At failure -1 is returned.
1069
 */
1070
int erl_ext_size(unsigned char *t)
1071
{
1072
    int i;
1073
    unsigned char *v;
1074
1075
    if (*t == ERL_VERSION_MAGIC) 
1076
	return erl_ext_size(t+1);
1077
 
1078
    v = t+1;
1079
    switch(*t) {
1080
    case ERL_SMALL_INTEGER_EXT:
1081
    case ERL_INTEGER_EXT:
1082
    case ERL_ATOM_EXT:
1083
    case ERL_PID_EXT:
1084
    case ERL_PORT_EXT:
1085
    case ERL_REFERENCE_EXT:
1086
    case ERL_NEW_REFERENCE_EXT:
1087
    case ERL_NIL_EXT: 
1088
    case ERL_BINARY_EXT:
1089
    case ERL_STRING_EXT:
1090
    case ERL_FLOAT_EXT:
1091
    case ERL_SMALL_BIG_EXT:
1092
    case ERL_LARGE_BIG_EXT:
1093
	return 0;
1094
	break;
1095
    case ERL_SMALL_TUPLE_EXT:
1096
	i = v[0];
1097
	return i;
1098
	break;
1099
    case ERL_LIST_EXT:
1100
    case ERL_LARGE_TUPLE_EXT:
1101
	i = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
1102
	return i;
1103
	break;
1104
    case ERL_FUN_EXT:
1105
	i = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
1106
	return i+4;
1107
	break;
1108
    case ERL_NEW_FUN_EXT:
1109
        v += 4 + 1 + 16 + 4;
1110
	i = get32be(v);
1111
	return i + 4;
1112
	break;
1113
    default:
1114
	return -1;
1115
	break;
1116
    } /* switch */
1117
1118
} /* ext_size */
1119
1120
/*
1121
 * A nice macro that eats up the atom pointed to.
1122
 */
1123
#define JUMP_ATOM(ext,i) \
1124
if (**ext != ERL_ATOM_EXT) \
1125
  return 0; \
1126
*ext += 1; \
1127
i = (**ext << 8) | (*ext)[1]; \
1128
*ext += (i + 2)
1129
1130
/*
1131
 * MOVE the POINTER PAST the ENCODED ETERM we
1132
 * are currently pointing at. Returns 1 at
1133
 * success, otherwise 0.
1134
 */
1135
static int jump(unsigned char **ext) 
1136
{
1137
    int j,k,i=0;
1138
    int n;
1139
    
1140
    switch (*(*ext)++) {
1141
    case ERL_VERSION_MAGIC:
1142
	return jump(ext);
1143
    case ERL_INTEGER_EXT:
1144
	*ext += 4;
1145
	break;
1146
    case ERL_SMALL_INTEGER_EXT:
1147
	*ext += 1;
1148
	break;
1149
    case ERL_ATOM_EXT:
1150
	i = (**ext << 8) | (*ext)[1];
1151
	*ext += (i + 2);
1152
	break;
1153
    case ERL_PID_EXT:
1154
	/* eat first atom */
1155
	JUMP_ATOM(ext,i);
1156
	*ext += 9;		/* Two int's and the creation field */
1157
	break;
1158
    case ERL_REFERENCE_EXT:
1159
    case ERL_PORT_EXT:
1160
	/* first field is an atom */
1161
	JUMP_ATOM(ext,i);
1162
	*ext += 5;		/* One int and the creation field */
1163
	break;
1164
    case ERL_NEW_REFERENCE_EXT:
1165
	n = (**ext << 8) | (*ext)[1];
1166
	*ext += 2;
1167
	/* first field is an atom */
1168
	JUMP_ATOM(ext,i);
1169
	*ext += 4*n+1;
1170
	break;
1171
    case ERL_NIL_EXT:
1172
	/* We just passed it... */
1173
	break;
1174
    case ERL_LIST_EXT:
1175
	i = j = 0;
1176
	j = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3];
1177
	*ext += 4;	
1178
	for(k=0; k<j; k++) 
1179
	    if ((i = jump(ext)) == 0)
1180
		return(0);
1181
	if (**ext == ERL_NIL_EXT) {
1182
	    *ext += 1;
1183
	    break;
1184
	}
1185
	if (jump(ext) == 0) return 0;
1186
	break;
1187
    case ERL_STRING_EXT:
1188
	i = **ext << 8 | (*ext)[1];
1189
	*ext += 2 + i;
1190
	break;
1191
    case ERL_SMALL_TUPLE_EXT:
1192
	i = *(*ext)++;
1193
	goto jump_tuple;
1194
    case ERL_LARGE_TUPLE_EXT:
1195
	i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3];
1196
	*ext += 4;
1197
    jump_tuple:
1198
	for (j = 0; j < i; j++) 
1199
	    if ((k = jump(ext)) == 0)
1200
		return(0);
1201
	break;
1202
    case ERL_FLOAT_EXT:
1203
	*ext += 31;
1204
	break;
1205
    case ERL_BINARY_EXT:
1206
	i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3];
1207
	*ext += 4+i;
1208
	break;
1209
    case ERL_FUN_EXT:
1210
	i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3];
1211
	*ext += 4;
1212
	i += 4;
1213
	for (j = 0; j < i; j++)
1214
	    if ((k = jump(ext)) == 0)
1215
		return(0);
1216
	break;
1217
    case ERL_NEW_FUN_EXT:
1218
	i = get32be(*ext);
1219
	*ext += i + 4;
1220
	break;
1221
    case ERL_SMALL_BIG_EXT:
1222
        i = *(*ext);
1223
        *ext += i + 1;
1224
        break;
1225
    case ERL_LARGE_BIG_EXT:
1226
	i = get32be(*ext);
1227
        *ext += i + 4;
1228
        break;
1229
    default:
1230
	return 0;
1231
    } /* switch */
1232
1233
    return 1;
1234
1235
} /* jump */
1236
1237
/* 
1238
 * The actual PEEK engine.
1239
 */
1240
static unsigned char *peek_ext(unsigned char **ext, int jumps)
1241
{
1242
  int i;
1243
1244
  switch (*(*ext)++) 
1245
    {
1246
    case ERL_VERSION_MAGIC:
1247
      return peek_ext(ext, jumps);
1248
    case ERL_SMALL_TUPLE_EXT:
1249
      i = *(*ext)++;
1250
      goto do_the_peek_stuff;
1251
    case ERL_LARGE_TUPLE_EXT:
1252
    case ERL_LIST_EXT:
1253
      i = (**ext << 24) | ((*ext)[1]) << 16| ((*ext)[2]) << 8| ((*ext)[3]) ;  
1254
      *ext += 4;
1255
    do_the_peek_stuff:
1256
      if (i <= jumps)   {
1257
#ifdef DEBUG
1258
	erl_err_msg("<ERROR> peek_ext: Out of range"); 
1259
#endif
1260
	return NULL;
1261
      }
1262
      for(i=0; i<jumps; i++)
1263
	if (!jump(ext)) {
1264
#ifdef DEBUG
1265
	  erl_err_msg("<ERROR> peek_ext: Bad data"); 
1266
#endif
1267
	  return NULL;
1268
	}
1269
      return *ext;
1270
    default:
1271
#ifdef DEBUG
1272
      erl_err_msg("<ERROR> peek_ext: Can't peek in non list/tuple type");
1273
#endif
1274
      return NULL;
1275
    } /* switch */
1276
1277
} /* peek_ext */
1278
	
1279
/*
1280
 * Return a POINTER TO the N:TH ELEMENT in a
1281
 * COMPUND ENCODED ETERM.
1282
 */
1283
unsigned char *erl_peek_ext(unsigned char *ext, int jumps)
1284
{
1285
  unsigned char *x=ext;
1286
1287
  return peek_ext(&x, jumps);  
1288
1289
} /* erl_peek_ext */
1290
1291
/* 
1292
 * Lexically compare two strings of bytes,
1293
 * (string s1 length l1 and s2 l2).
1294
 * Return: -1 if s1 < s2
1295
 *	    0 if s1 = s2
1296
 *	    1 if s1 > s2 
1297
 */
1298
static int cmpbytes(unsigned char* s1,int l1,unsigned char* s2,int l2)
1299
{
1300
  int i;
1301
  i = 0;
1302
  while((i < l1) && (i < l2)) {
1303
    if (s1[i] < s2[i]) return(-1);
1304
    if (s1[i] > s2[i]) return(1);
1305
    i++;
1306
  }
1307
  if (l1 < l2) return(-1);
1308
  if (l1 > l2) return(1);
1309
  return(0);
1310
1311
} /* cmpbytes */
1312
1313
#define CMP_EXT_ERROR_CODE 4711
1314
1315
#define CMP_EXT_INT32_BE(AP, BP)				\
1316
do {								\
1317
    if ((AP)[0] != (BP)[0]) return (AP)[0] < (BP)[0] ? -1 : 1;	\
1318
    if ((AP)[1] != (BP)[1]) return (AP)[1] < (BP)[1] ? -1 : 1;	\
1319
    if ((AP)[2] != (BP)[2]) return (AP)[2] < (BP)[2] ? -1 : 1;	\
1320
    if ((AP)[3] != (BP)[3]) return (AP)[3] < (BP)[3] ? -1 : 1;	\
1321
} while (0)
1322
1323
#define CMP_EXT_SKIP_ATOM(EP)					\
1324
do {								\
1325
    if ((EP)[0] != ERL_ATOM_EXT)				\
1326
	return CMP_EXT_ERROR_CODE;				\
1327
    (EP) += 3 + ((EP)[1] << 8 | (EP)[2]);			\
1328
} while (0)
1329
1330
/* 
1331
 * We now know that both byte arrays are of the same type.
1332
 */
1333
static int compare_top_ext(unsigned char**, unsigned char **); /* forward */
1334
static int cmp_exe2(unsigned char **e1, unsigned char **e2);
1335
1336
static int cmp_refs(unsigned char **e1, unsigned char **e2)
1337
{
1338
    int tmp, n1, n2;
1339
    unsigned char *node1, *node2, *id1, *id2, cre1, cre2;
1340
1341
    if (*((*e1)++) == ERL_REFERENCE_EXT) {
1342
	node1 = *e1;
1343
	CMP_EXT_SKIP_ATOM(*e1);
1344
	n1 = 1;
1345
	id1 = *e1;
1346
	cre1 = (*e1)[4];
1347
	*e1 += 5;
1348
    } else {
1349
	n1 = get16be(*e1);
1350
	node1 = *e1;
1351
	CMP_EXT_SKIP_ATOM(*e1);
1352
	cre1 = **e1;
1353
	id1 = (*e1) + 1 + (n1 - 1)*4;
1354
	*e1 = id1 + 4;
1355
    }
1356
1357
    if (*((*e2)++) == ERL_REFERENCE_EXT) {
1358
	node2 = *e2;
1359
	CMP_EXT_SKIP_ATOM(*e2);
1360
	n2 = 1;
1361
	id2 = *e2;
1362
	cre2 = (*e2)[4];
1363
	*e2 += 5;
1364
    } else {
1365
	n2 = get16be(*e2);
1366
	node2 = *e2;
1367
	CMP_EXT_SKIP_ATOM(*e2);
1368
	cre2 = **e2;
1369
	id2 = (*e2) + 1 + (n2 - 1)*4;
1370
	*e2 = id2 + 4;
1371
    }
1372
1373
    /* First compare node names... */
1374
    tmp = cmp_exe2(&node1, &node2);
1375
    if (tmp != 0)
1376
	return tmp;
1377
1378
    /* ... then creations ... */
1379
    if (cre1 != cre2)
1380
	return cre1 < cre2 ? -1 : 1;
1381
1382
    /* ... and then finaly ids. */
1383
    if (n1 != n2) {
1384
	unsigned char zero[] = {0, 0, 0, 0};
1385
	if (n1 > n2)
1386
	    do {
1387
		CMP_EXT_INT32_BE(id1, zero);
1388
		id1 -= 4;
1389
		n1--;
1390
	    } while (n1 > n2);
1391
	else
1392
	    do {
1393
		CMP_EXT_INT32_BE(zero, id2);
1394
		id2 -= 4;
1395
		n2--;
1396
	    } while (n2 > n1);
1397
    }
1398
    
1399
    for (; n1 > 0; n1--, id1 -= 4, id2 -= 4)
1400
	CMP_EXT_INT32_BE(id1, id2);
1401
1402
    return 0;
1403
}
1404
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1405
static int cmp_string_list(unsigned char **e1, unsigned char **e2) {
1406
  
1407
  /* we need to compare a string in **e1 and a list in **e2               */
1408
  /* convert the string to list representation and convert that with e2   */
1409
  /* we need a temporary buffer of:                                       */
1410
  /* 5 (list tag + length) + 2*string length + 1 (end of list tag)        */
1411
  /* for short lists we use a stack allocated buffer, otherwise we malloc */
1412
1413
  unsigned char *bp;
1414
  unsigned char buf[5+2*255+1]; /* used for short lists */
1415
  int i,e1_len;
1416
  int res;
1417
  
1418
  e1_len = ((*e1)[1] << 8) | ((*e1)[2]);
1419
  if ( e1_len < 256 ) {
1420
    bp = buf;
1421
  } else {
1422
    bp = malloc(5+(2*e1_len)+1);
1423
  }
1424
1425
  bp[0] = ERL_LIST_EXT;
1426
  bp[1] = bp[2] = 0;
1427
  bp[3] = (*e1)[1];
1428
  bp[4] = (*e1)[2];
1429
1430
  for(i=0;i<e1_len;i++) {
1431
    bp[5+2*i] = ERL_SMALL_INTEGER_EXT;
1432
    bp[5+2*i+1] = (*e1)[3+i];
1433
  }
1434
1435
  bp[5+2*e1_len] = ERL_NIL_EXT;
1436
1437
  res = cmp_exe2(&bp, e2);
1438
1439
  if ( e1_len >= 256 ) free(bp);
1440
1441
  return res;
1442
}
1443
1 by Brent A. Fulgham
Import upstream version 9.2.2
1444
static int cmp_exe2(unsigned char **e1, unsigned char **e2)
1445
{
1446
  int min,  ret,i,j,k;
1447
  double ff1, ff2;
1448
  unsigned char *tmp1, *tmp2;
1449
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1450
  if ( ((*e1)[0] == ERL_STRING_EXT) && ((*e2)[0] == ERL_LIST_EXT) ) {
1451
    return cmp_string_list(e1, e2);
1452
  } else if ( ((*e1)[0] == ERL_LIST_EXT) && ((*e2)[0] == ERL_STRING_EXT) ) {
1453
    return -cmp_string_list(e2, e1);
1454
  }
1455
1 by Brent A. Fulgham
Import upstream version 9.2.2
1456
  *e2 += 1;
1457
  switch (*(*e1)++) 
1458
    {
1459
    case ERL_SMALL_INTEGER_EXT:
1460
      if (**e1 < **e2) ret = -1;
1461
      else if (**e1 > **e2) ret = 1;
1462
      else ret = 0;
1463
      *e1 += 1; *e2 += 1;
1464
      return ret;
1465
    case ERL_INTEGER_EXT:
1466
      i = (int) (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3];
1467
      j = (int) (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3];
1468
      if ( i < j) 
1469
	ret = -1;
1470
      else if ( i > j) 
1471
	ret = 1;
1472
      else 
1473
	ret = 0;
1474
      *e1 += 4; *e2 += 4;
1475
      return ret;
1476
    case ERL_ATOM_EXT:
1477
      i = (**e1 << 8) | (*e1)[1];
1478
      j = (**e2 << 8) | (*e2)[1];
1479
      ret = cmpbytes(*e1 +2, i, *e2 +2, j);
1480
      *e1 += (i + 2);
1481
      *e2 += (j + 2);
1482
      return ret;
1483
    case ERL_PID_EXT: {
1484
      unsigned char *n1 = *e1;
1485
      unsigned char *n2 = *e2;
1486
      CMP_EXT_SKIP_ATOM(*e1); CMP_EXT_SKIP_ATOM(*e2);
1487
      *e1 += 9; *e2 += 9;
1488
1489
      /* First compare serials ... */
1490
      tmp1 = *e1 - 5; tmp2 = *e2 - 5;
1491
      CMP_EXT_INT32_BE(tmp1, tmp2);
1492
1493
      /* ... then ids ... */
1494
      tmp1 -= 4; tmp2 -= 4;
1495
      CMP_EXT_INT32_BE(tmp1, tmp2);
1496
1497
      /* ... then node names ... */
1498
      ret = cmp_exe2(&n1, &n2);
1499
      if (ret != 0)
1500
	  return ret;
1501
1502
      /* ... and then finaly creations. */
1503
      tmp1 += 8; tmp2 += 8;
1504
      if (*tmp1 != *tmp2)
1505
	  return *tmp1 < *tmp2 ? -1 : 1;
1506
      return 0;
1507
    }
1508
    case ERL_PORT_EXT:
1509
      /* First compare node names ... */
1510
      if (**e1 != ERL_ATOM_EXT || **e2 != ERL_ATOM_EXT)
1511
	  return CMP_EXT_ERROR_CODE;
1512
      ret = cmp_exe2(e1, e2);
1513
      *e1 += 5; *e2 += 5;
1514
      if (ret != 0)
1515
	  return ret;
1516
      /* ... then creations ... */
1517
      tmp1 = *e1 - 1; tmp2 = *e2 - 1;
1518
      if (*tmp1 != *tmp2)
1519
	  return *tmp1 < *tmp2 ? -1 : 1;
1520
      /* ... and then finaly ids. */
1521
      tmp1 -= 4; tmp2 -= 4;
1522
      CMP_EXT_INT32_BE(tmp1, tmp2);
1523
      return 0;
1524
    case ERL_NIL_EXT: return 0;
1525
    case ERL_LIST_EXT:
1526
      i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3];
1527
      *e1 += 4;
1528
      j = (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3];
1529
      *e2 += 4;
1530
      if ( i == j && j == 0 ) return 0;
1531
      min = (i < j) ? i : j;
1532
      k = 0;
1533
      while (1) {
1534
	if (k++ == min)
1535
	  return compare_top_ext(e1 , e2);
1536
	if ((ret = compare_top_ext(e1 , e2)) == 0) 
1537
	  continue;
1538
	return ret;
1539
      }
1540
    case ERL_STRING_EXT:
1541
      i = (**e1 << 8) | ((*e1)[1]);
1542
      *e1 += 2;
1543
      j = (**e2 << 8) | ((*e2)[1]);
1544
      *e2 += 2;
1545
      ret = cmpbytes(*e1, i, *e2, j);
1546
      *e1 += i;
1547
      *e2 += j;
1548
      return ret;
1549
    case ERL_SMALL_TUPLE_EXT:
1550
      i = *(*e1)++; 	j = *(*e2)++;
1551
      if (i < j) return -1;
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1552
      if (i > j ) return 1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1553
      while (i--) {
1554
	if ((j = compare_top_ext(e1, e2))) return j;
1555
      }
1556
      return 0;
1557
    case ERL_LARGE_TUPLE_EXT:
1558
      i = (**e1 << 24) | ((*e1)[1]) << 16| ((*e1)[2]) << 8| ((*e1)[3]) ;	
1559
      *e1 += 4;
1560
      j = (**e2 << 24) | ((*e2)[1]) << 16| ((*e2)[2]) << 8| ((*e2)[3]) ;	
1561
      *e2 += 4;
1562
      if (i < j) return -1;
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1563
      if (i > j ) return 1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1564
      while (i--) {
1565
	if ((j = compare_top_ext(e1, e2))) return j;
1566
      }
1567
      return 0;
1568
    case ERL_FLOAT_EXT:
1569
      if (sscanf((char *) *e1, "%lf", &ff1) != 1)
1570
	return -1;
1571
      *e1 += 31;
1572
      if (sscanf((char *) *e2, "%lf", &ff2) != 1)
1573
	return -1;
1574
      *e2 += 31;
1575
      return cmp_floats(ff1,ff2);
1576
1577
    case ERL_BINARY_EXT:
1578
      i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3];
1579
      *e1 += 4;
1580
      j = (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3];
1581
      *e2 += 4;
1582
      ret = cmpbytes(*e1, i , *e2 , j);
1583
      *e1 += i; *e2 += j;
1584
      return ret;
1585
1586
    case ERL_FUN_EXT:  /* FIXME: */
1587
    case ERL_NEW_FUN_EXT:  /* FIXME: */
1588
      return -1;
1589
1590
    default:
1591
      return cmpbytes(*e1, 1, *e2, 1);
1592
1593
    } /* switch */
1594
  
1595
} /* cmp_exe2 */
1596
1597
/* Number compare */
1598
1.1.9 by Soren Hansen
Import upstream version 11.b.4
1599
static int cmp_floats(double f1, double f2)
1 by Brent A. Fulgham
Import upstream version 9.2.2
1600
{
1601
#if defined(VXWORKS) && CPU == PPC860
1602
      return erl_fp_compare((unsigned *) &f1, (unsigned *) &f2);
1603
#else
1604
      if (f1<f2) return -1;
1605
      else if (f1>f2) return 1;
1606
      else return 0;
1607
#endif
1608
}
1609
1610
static INLINE double to_float(long l) 
1611
{
1612
    double f;
1613
#if defined(VXWORKS) && CPU == PPC860
1614
    erl_long_to_fp(l, (unsigned *) &f);
1615
#else
1616
    f = l;
1617
#endif
1618
    return f;
1619
}
1620
1621
1622
static int cmp_small_big(unsigned char**e1, unsigned char **e2)
1623
{
1624
    int i1,i2;
1625
    int t2;
1626
    int n2;
1627
    long l1;
1628
    int res;
1629
1630
    erlang_big *b1,*b2;
1631
1632
    i1 = i2 = 0;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1633
    if ( ei_decode_long((char *)*e1,&i1,&l1) < 0 ) return -1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1634
    
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1635
    ei_get_type((char *)*e2,&i2,&t2,&n2);
1 by Brent A. Fulgham
Import upstream version 9.2.2
1636
    
1637
    /* any small will fit in two digits */
1638
    if ( (b1 = ei_alloc_big(2)) == NULL ) return -1;
1639
    if ( ei_small_to_big(l1,b1) < 0 ) {
1640
        ei_free_big(b1);
1641
        return -1;
1642
    }
1643
    
1644
    if ( (b2 = ei_alloc_big(n2)) == NULL ) {
1645
        ei_free_big(b1);
1646
        return 1;
1647
    }
1648
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1649
    if ( ei_decode_big((char *)*e2,&i2,b2) < 0 ) {
1 by Brent A. Fulgham
Import upstream version 9.2.2
1650
        ei_free_big(b1);
1651
        ei_free_big(b2);
1652
        return 1;
1653
    }
1654
    
1655
    res = ei_big_comp(b1,b2);
1656
    
1657
    ei_free_big(b1);
1658
    ei_free_big(b2);
1659
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1660
    *e1 += i1;
1661
    *e2 += i2;
1662
1 by Brent A. Fulgham
Import upstream version 9.2.2
1663
    return res;
1664
}
1665
1666
static int cmp_small_float(unsigned char**e1, unsigned char **e2)
1667
{
1668
    int i1,i2;
1669
    long l1;
1670
    double f1,f2;
1671
1672
    /* small -> float -> float_comp */
1673
1674
    i1 = i2 = 0;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1675
    if ( ei_decode_long((char *)*e1,&i1,&l1) < 0 ) return -1;
1676
    if ( ei_decode_double((char *)*e2,&i2,&f2) < 0 ) return 1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1677
    
1678
    f1 = to_float(l1);
1679
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1680
    *e1 += i1;
1681
    *e2 += i2;
1682
1 by Brent A. Fulgham
Import upstream version 9.2.2
1683
    return cmp_floats(f1,f2);
1684
}
1685
1686
static int cmp_float_big(unsigned char**e1, unsigned char **e2)
1687
{
1688
    int res;
1689
    int i1,i2;
1690
    int t2,n2;
1691
    double f1,f2;
1692
    erlang_big *b2;
1693
    
1694
    /* big -> float if overflow return big sign else float_comp */
1695
    
1696
    i1 = i2 = 0;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1697
    if ( ei_decode_double((char *)*e1,&i1,&f1) < 0 ) return -1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1698
    
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1699
    if (ei_get_type((char *)*e2,&i2,&t2,&n2) < 0) return 1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1700
    if ((b2 = ei_alloc_big(n2)) == NULL) return 1;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1701
    if (ei_decode_big((char *)*e2,&i2,b2) < 0) return 1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1702
    
1703
    /* convert the big to float */
1704
    if ( ei_big_to_double(b2,&f2) < 0 ) {
1705
        /* exception look at the sign */
1706
        res = b2->is_neg ? 1 : -1;
1707
        ei_free_big(b2);
1708
        return res;
1709
    }
1710
    
1711
    ei_free_big(b2);
1712
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1713
    *e1 += i1;
1714
    *e2 += i2;
1715
1 by Brent A. Fulgham
Import upstream version 9.2.2
1716
    return cmp_floats(f1,f2);
1717
}
1718
1719
static int cmp_small_small(unsigned char**e1, unsigned char **e2)
1720
{
1721
    int i1,i2;
1722
    long l1,l2;
1723
1724
    i1 = i2 = 0;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1725
    if ( ei_decode_long((char *)*e1,&i1,&l1) < 0 ) {
1 by Brent A. Fulgham
Import upstream version 9.2.2
1726
        fprintf(stderr,"Failed to decode 1\r\n");
1727
        return -1;
1728
    }
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1729
    if ( ei_decode_long((char *)*e2,&i2,&l2) < 0 ) {
1 by Brent A. Fulgham
Import upstream version 9.2.2
1730
        fprintf(stderr,"Failed to decode 2\r\n");
1731
        return 1;
1732
    }
1733
    
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1734
    *e1 += i1;
1735
    *e2 += i2;
1736
    
1 by Brent A. Fulgham
Import upstream version 9.2.2
1737
    if ( l1 < l2 ) return -1;
1738
    else if ( l1 > l2 ) return 1;
1739
    else return 0;
1740
}
1741
1742
static int cmp_float_float(unsigned char**e1, unsigned char **e2)
1743
{
1744
    int i1,i2;
1745
    double f1,f2;
1746
1747
    i1 = i2 = 0;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1748
    if ( ei_decode_double((char *)*e1,&i1,&f1) < 0 ) return -1;
1749
    if ( ei_decode_double((char *)*e2,&i2,&f2) < 0 ) return 1;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1750
    
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1751
    *e1 += i1;
1752
    *e2 += i2;
1753
    
1 by Brent A. Fulgham
Import upstream version 9.2.2
1754
    return cmp_floats(f1,f2);
1755
}
1756
1757
static int cmp_big_big(unsigned char**e1, unsigned char **e2)
1758
{
1759
    int res;
1760
    int i1,i2;
1761
    int t1,t2;
1762
    int n1,n2;
1763
    erlang_big *b1,*b2;
1764
1765
    i1 = i2 = 0;
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1766
    ei_get_type((char *)*e1,&i1,&t1,&n1);
1767
    ei_get_type((char *)*e2,&i2,&t2,&n2);
1 by Brent A. Fulgham
Import upstream version 9.2.2
1768
    
1769
    b1 = ei_alloc_big(n1);
1770
    b2 = ei_alloc_big(n2);
1771
    
1.2.2 by Sergei Golovan
Import upstream version 13.b.1-dfsg
1772
    ei_decode_big((char *)*e1,&i1,b1);
1773
    ei_decode_big((char *)*e2,&i2,b2);
1 by Brent A. Fulgham
Import upstream version 9.2.2
1774
    
1775
    res = ei_big_comp(b1,b2);
1776
    
1777
    ei_free_big(b1);
1778
    ei_free_big(b2);
1.1.12 by Sergei Golovan
Import upstream version 12.b.3-dfsg
1779
    
1780
    *e1 += i1;
1781
    *e2 += i2;
1 by Brent A. Fulgham
Import upstream version 9.2.2
1782
1783
    return res;
1784
}
1785
1786
static int cmp_number(unsigned char**e1, unsigned char **e2)
1787
{
1788
    switch (CMP_NUM_CODE(**e1,**e2)) {
1789
1790
      case SMALL_BIG:
1791
        /* fprintf(stderr,"compare small_big\r\n"); */
1792
        return cmp_small_big(e1,e2);
1793
1794
      case BIG_SMALL:
1795
        /* fprintf(stderr,"compare sbig_small\r\n"); */
1796
        return -cmp_small_big(e2,e1);
1797
1798
      case SMALL_FLOAT:
1799
        /* fprintf(stderr,"compare small_float\r\n"); */
1800
        return cmp_small_float(e1,e2);
1801
        
1802
      case FLOAT_SMALL:
1803
        /* fprintf(stderr,"compare float_small\r\n"); */
1804
        return -cmp_small_float(e2,e1);
1805
1806
      case FLOAT_BIG:
1807
        /* fprintf(stderr,"compare float_big\r\n"); */
1808
        return cmp_float_big(e1,e2);
1809
1810
      case BIG_FLOAT:
1811
        /* fprintf(stderr,"compare big_float\r\n"); */
1812
        return -cmp_float_big(e2,e1);
1813
1814
      case SMALL_SMALL:
1815
        /* fprintf(stderr,"compare small_small\r\n"); */
1816
        return cmp_small_small(e1,e2);
1817
1818
      case FLOAT_FLOAT:
1819
        /* fprintf(stderr,"compare float_float\r\n"); */
1820
        return cmp_float_float(e1,e2);
1821
1822
      case BIG_BIG:
1823
        /* fprintf(stderr,"compare big_big\r\n"); */
1824
        return cmp_big_big(e1,e2);
1825
1826
      default:
1827
        /* should never get here ... */
1828
        /* fprintf(stderr,"compare standard\r\n"); */
1829
        return cmp_exe2(e1,e2);
1830
    }
1831
1832
}
1833
1834
/* 
1835
 * If the arrays are of the same type, then we
1836
 * have to do a real compare.
1837
 */
1838
/* 
1839
 * COMPARE TWO encoded BYTE ARRAYS e1 and e2.
1840
 * Return: -1 if e1 < e2
1841
 *          0 if e1 == e2 
1842
 *          1 if e2 > e1   
1843
 */
1844
static int compare_top_ext(unsigned char**e1, unsigned char **e2)
1845
{
1846
  if (**e1 == ERL_VERSION_MAGIC) (*e1)++;
1847
  if (**e2 == ERL_VERSION_MAGIC) (*e2)++;
1848
1849
  if (cmp_array[**e1] < cmp_array[**e2]) return -1;
1850
  if (cmp_array[**e1] > cmp_array[**e2]) return 1;
1851
  
1852
  if (IS_ERL_NUM(**e1)) 
1853
      return cmp_number(e1,e2);
1854
1855
  if (cmp_array[**e1] == ERL_REF_CMP)
1856
      return cmp_refs(e1, e2);
1857
1858
  return cmp_exe2(e1, e2);
1859
}
1860
1861
int erl_compare_ext(unsigned char *e1, unsigned char *e2)
1862
{
1863
  return compare_top_ext(&e1, &e2); 
1864
} /* erl_compare_ext */
1865
1866
#if defined(VXWORKS) && CPU == PPC860
1867
/* FIXME we have no floating point but don't we have emulation?! */
1.1.2 by Francois-Denis Gonthier
Import upstream version 10.b.5
1868
int erl_fp_compare(unsigned *a, unsigned *b) 
1 by Brent A. Fulgham
Import upstream version 9.2.2
1869
{
1870
    /* Big endian mode of powerPC, IEEE floating point. */
1871
    unsigned a_split[4] = {a[0] >> 31,             /* Sign bit */
1872
                           (a[0] >> 20) & 0x7FFU,  /* Exponent */
1873
                           a[0] & 0xFFFFFU,        /* Mantissa MS bits */
1874
                           a[1]};                  /* Mantissa LS bits */
1875
    unsigned b_split[4] = {b[0] >> 31,
1876
                           (b[0] >> 20) & 0x7FFU,
1877
                           b[0] & 0xFFFFFU,
1878
                           b[1]};
1879
    int a_is_infinite, b_is_infinite;
1880
    int res;
1881
1882
1883
    /* Make -0 be +0 */
1884
    if (a_split[1] == 0 && a_split[2] == 0 && a_split[3] == 0)
1885
        a_split[0] = 0;
1886
    if (b_split[1] == 0 && b_split[2] == 0 && b_split[3] == 0)
1887
        b_split[0] = 0;
1888
    /* Check for infinity */
1889
    a_is_infinite = (a_split[1] == 0x7FFU && a_split[2] == 0 && 
1890
                     a_split[3] == 0);
1891
    b_is_infinite = (b_split[1] == 0x7FFU && b_split[2] == 0 && 
1892
                     b_split[3] == 0);
1893
1894
    if (a_is_infinite && !b_is_infinite)
1895
        return (a_split[0]) ? -1 : 1;
1896
    if (b_is_infinite && !a_is_infinite)
1897
        return (b_split[0]) ? 1 : -1;
1898
    if (a_is_infinite && b_is_infinite)
1899
        return b[0] - a[0]; 
1900
    /* Check for indeterminate or nan, infinite is already handled, 
1901
     so we only check the exponent. */
1902
    if((a_split[1] == 0x7FFU) || (b_split[1] == 0x7FFU))
1903
        return INT_MAX; /* Well, they are not equal anyway, 
1904
                           abort() could be an alternative... */
1905
1906
    if (a_split[0] && !b_split[0])
1907
        return -1;
1908
    if (b_split[0] && !a_split[0])
1909
        return 1;
1910
    /* Compare */
1911
    res = memcmp(a_split + 1, b_split + 1, 3 * sizeof(unsigned));
1912
    /* Make -1, 0 or 1 */
1913
    res = (!!res) * ((res < 0) ? -1 : 1); 
1914
    /* Turn sign if negative values */
1915
    if (a_split[0]) /* Both are negative */
1916
        res = -1 * res;
1917
    return res;
1918
}
1919
1920
static void join(unsigned d_split[4], unsigned *d)
1921
{
1922
    d[0] = (d_split[0] << 31) |         /* Sign bit */
1923
	((d_split[1] & 0x7FFU) << 20) | /* Exponent */
1924
	(d_split[2] & 0xFFFFFU);        /* Mantissa MS bits */
1925
    d[1] = d_split[3];                  /* Mantissa LS bits */
1926
}
1927
1928
static int blength(unsigned long l)
1929
{
1930
    int i;
1931
    for(i = 0; l; ++i)
1932
	l >>= 1;
1933
    return i;
1934
}
1935
1936
static void erl_long_to_fp(long l, unsigned *d) 
1937
{
1938
    unsigned d_split[4];
1939
    unsigned x;
1940
    if (l < 0) {
1941
	d_split[0] = 1;
1942
	x = -l;
1943
    } else {
1944
	d_split[0] = 0;
1945
	x = l;
1946
    }
1947
1948
    if (!l) {
1949
	memset(d_split,0,sizeof(d_split));
1950
    } else {
1951
	int len = blength(x);
1952
	x <<= (33 - len);
1953
	d_split[2] = (x >> 12);
1954
	d_split[3] = (x << 20);
1955
	d_split[1] = 1023 + len - 1;
1956
    }
1957
    join(d_split,d);
1958
}
1959
1960
#endif
1961
1962
1963
/* 
1964
 * Checks if a term is a "string": a flat list of byte-sized integers.
1965
 *
1966
 * Returns: 0 if the term is not a string, otherwise the length is returned.
1967
 */
1968
1969
static int is_string(ETERM* term)
1970
{
1971
    int len = 0;
1972
1973
    while (ERL_TYPE(term) == ERL_LIST) {
1974
	ETERM* head = HEAD(term);
1975
1976
	if (!ERL_IS_INTEGER(head) || ((unsigned)head->uval.ival.i) > 255) {
1977
	    return 0;
1978
	}
1979
	len++;
1980
	term = TAIL(term);
1981
    }
1982
1983
    if (ERL_IS_EMPTY_LIST(term)) {
1984
	return len;
1985
    }
1986
    return 0;
1987
}