1 /* ``Licensed under the Apache License, Version 2.0 (the "License");
2 * you may not use this file except in compliance with the License.
3 * You may obtain a copy of the License at
4 *
5 * http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 *
13 * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
14 * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
15 * AB. All Rights Reserved.''
16 *
17 * $Id$
18 */
19
20 #include "erl_driver.h"
21 #include <stdio.h>
22 #include <errno.h>
23 #include <string.h>
24
25 static ErlDrvPort erlang_port;
26 static ErlDrvData send_term_drv_start(ErlDrvPort port, char *command);
27 static void send_term_drv_stop(ErlDrvData drv_data);
28 static void send_term_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
29
30
31 static int make_ext_term_list(ErlDrvTermData *td, int bad);
32
33 #define FAIL_TERM(M, L) fail_term((M), (L), __LINE__)
34
35 static ErlDrvEntry send_term_drv_entry = {
36 NULL,
37 send_term_drv_start,
38 send_term_drv_stop,
39 send_term_drv_run,
40 NULL,
41 NULL,
42 "send_term_drv",
43 NULL,
44 NULL, /* handle */
45 NULL, /* control */
46 NULL, /* timeout */
47 NULL, /* outputv */
48 NULL, /* ready_async */
49 NULL,
50 NULL,
51 NULL,
52 ERL_DRV_EXTENDED_MARKER,
53 ERL_DRV_EXTENDED_MAJOR_VERSION,
54 ERL_DRV_EXTENDED_MINOR_VERSION,
55 0,
56 NULL,
57 NULL,
58 NULL,
59 };
60
DRIVER_INIT(send_term_drv)61 DRIVER_INIT(send_term_drv)
62 {
63 erlang_port = (ErlDrvPort)-1;
64 return &send_term_drv_entry;
65 }
66
send_term_drv_start(ErlDrvPort port,char * buf)67 static ErlDrvData send_term_drv_start(ErlDrvPort port, char *buf)
68 {
69 if (erlang_port != (ErlDrvPort)-1) {
70 return ERL_DRV_ERROR_GENERAL;
71 }
72
73 erlang_port = port;
74 return (ErlDrvData)port;
75 }
76
send_term_drv_stop(ErlDrvData drv_data)77 static void send_term_drv_stop(ErlDrvData drv_data)
78 {
79 }
80
81 static void output_term(ErlDrvTermData* msg, int len);
82 static void fail_term(ErlDrvTermData* msg, int len, int line);
83
send_term_drv_run(ErlDrvData port,char * buf,ErlDrvSizeT count)84 static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count)
85 {
86 char buf7[1024];
87 ErlDrvTermData spec[1024];
88 ErlDrvTermData* msg = spec;
89 ErlDrvBinary* bins[15];
90 int bin_ix = 0;
91 ErlDrvSInt64 s64[15];
92 int s64_ix = 0;
93 ErlDrvUInt64 u64[15];
94 int u64_ix = 0;
95 int i = 0;
96
97 for (i=0; i<count; i++) switch (buf[i]) {
98 case 0:
99 msg[0] = ERL_DRV_NIL;
100 msg += 1;
101 break;
102
103 case 1: /* Most term types inside a tuple. */
104 {
105 double f = 3.1416;
106
107 msg[0] = ERL_DRV_ATOM;
108 msg[1] = driver_mk_atom("blurf");
109 msg[2] = ERL_DRV_INT;
110 msg[3] = (ErlDrvTermData) 42;
111 msg[4] = ERL_DRV_NIL;
112 msg[5] = ERL_DRV_INT;
113 msg[6] = (ErlDrvTermData) -42;
114 msg[7] = ERL_DRV_TUPLE;
115 msg[8] = (ErlDrvTermData) 0;
116 msg[9] = ERL_DRV_PORT;
117 msg[10] = driver_mk_port(erlang_port);
118 msg[11] = ERL_DRV_STRING_CONS;
119 msg[12] = (ErlDrvTermData) "abc";
120 msg[13] = (ErlDrvTermData) 3;
121 msg[14] = ERL_DRV_LIST;
122 msg[15] = (ErlDrvTermData) 3;
123 msg[16] = ERL_DRV_STRING;
124 msg[17] = (ErlDrvTermData) "kalle";
125 msg[18] = (ErlDrvTermData) 5;
126 msg[19] = ERL_DRV_FLOAT;
127 msg[20] = (ErlDrvTermData) &f;
128 msg[21] = ERL_DRV_PID;
129 msg[22] = driver_connected(erlang_port);
130 msg[23] = ERL_DRV_MAP;
131 msg[24] = (ErlDrvTermData) 0;
132 msg[25] = ERL_DRV_TUPLE;
133 msg[26] = (ErlDrvTermData) 8;
134 msg += 27;
135 }
136 break;
137
138 case 2: /* Deep stack */
139 {
140 int i;
141
142 for (i = 0; i < 400; i += 2) {
143 msg[i] = ERL_DRV_INT;
144 msg[i+1] = (ErlDrvTermData) (i / 2);
145 }
146 msg[i] = ERL_DRV_NIL;
147 msg[i+1] = ERL_DRV_LIST;
148 msg[i+2] = (ErlDrvTermData) 201;
149 msg += i+3;
150 }
151 break;
152
153 case 3: /* Binaries */
154 {
155 ErlDrvBinary* bin;
156 int i;
157
158 bin = bins[bin_ix++] = driver_alloc_binary(256);
159 for (i = 0; i < 256; i++) {
160 bin->orig_bytes[i] = i;
161 }
162 msg[0] = ERL_DRV_BINARY;
163 msg[1] = (ErlDrvTermData) bin;
164 msg[2] = (ErlDrvTermData) 256;
165 msg[3] = (ErlDrvTermData) 0;
166 msg[4] = ERL_DRV_BINARY;
167 msg[5] = (ErlDrvTermData) bin;
168 msg[6] = (ErlDrvTermData) 256-23-17;
169 msg[7] = (ErlDrvTermData) 23;
170 msg[8] = ERL_DRV_TUPLE;
171 msg[9] = (ErlDrvTermData) 2;
172 msg += 10;
173 }
174 break;
175
176 case 4: /* Pids */
177 msg[0] = ERL_DRV_PID;
178 msg[1] = driver_connected(erlang_port);
179 msg[2] = ERL_DRV_PID;
180 msg[3] = driver_caller(erlang_port);
181 msg[4] = ERL_DRV_TUPLE;
182 msg[5] = (ErlDrvTermData) 2;
183 msg += 6;
184 break;
185
186 case 5:
187 msg += make_ext_term_list(msg, 0);
188 break;
189
190 case 6:
191 msg[0] = ERL_DRV_INT;
192 msg[1] = ~((ErlDrvTermData) 0);
193 msg[2] = ERL_DRV_UINT;
194 msg[3] = ~((ErlDrvTermData) 0);
195 msg[4] = ERL_DRV_TUPLE;
196 msg[5] = (ErlDrvTermData) 2;
197 msg += 6;
198 break;
199
200 case 7: {
201 int len = 0;
202 memset(buf7, 17, sizeof(buf7));
203 /* empty heap binary */
204 msg[len++] = ERL_DRV_BUF2BINARY;
205 msg[len++] = (ErlDrvTermData) NULL; /* NULL is ok if size == 0 */
206 msg[len++] = (ErlDrvTermData) 0;
207 /* empty heap binary again */
208 msg[len++] = ERL_DRV_BUF2BINARY;
209 msg[len++] = (ErlDrvTermData) buf7; /* ptr is ok if size == 0 */
210 msg[len++] = (ErlDrvTermData) 0;
211 /* heap binary */
212 msg[len++] = ERL_DRV_BUF2BINARY;
213 msg[len++] = (ErlDrvTermData) buf7;
214 msg[len++] = (ErlDrvTermData) 17;
215 /* off heap binary */
216 msg[len++] = ERL_DRV_BUF2BINARY;
217 msg[len++] = (ErlDrvTermData) buf7;
218 msg[len++] = (ErlDrvTermData) sizeof(buf7);
219
220 msg[len++] = ERL_DRV_TUPLE;
221 msg[len++] = (ErlDrvTermData) 4;
222
223 msg += len;
224 break;
225 }
226
227 case 8:
228 msg[0] = ERL_DRV_NIL;
229 msg += 1;
230 break;
231
232 case 9:
233 msg[0] = ERL_DRV_ATOM;
234 msg[1] = (ErlDrvTermData) driver_mk_atom("");
235 msg += 2;
236 break;
237
238 case 10:
239 msg[0] = ERL_DRV_ATOM;
240 msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom");
241 msg += 2;
242 break;
243
244 case 11:
245 msg[0] = ERL_DRV_INT;
246 msg[1] = (ErlDrvTermData) -4711;
247 msg += 2;
248 break;
249
250 case 12:
251 msg[0] = ERL_DRV_UINT;
252 msg[1] = (ErlDrvTermData) 4711;
253 msg += 2;
254
255 break;
256 case 13:
257 msg[0] = ERL_DRV_PORT;
258 msg[1] = driver_mk_port(erlang_port);
259 msg += 2;
260 break;
261
262 case 14: {
263 ErlDrvBinary *dbin = bins[bin_ix++] = driver_alloc_binary(0);
264 msg[0] = ERL_DRV_BINARY;
265 msg[1] = (ErlDrvTermData) dbin;
266 msg[2] = (ErlDrvTermData) 0;
267 msg[3] = (ErlDrvTermData) 0;
268 msg += 4;
269 break;
270 }
271
272 case 15: {
273 static const char buf[] = "hejsan";
274 ErlDrvBinary *dbin = bins[bin_ix++] = driver_alloc_binary(sizeof(buf)-1);
275 if (dbin)
276 memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1);
277 msg[0] = ERL_DRV_BINARY;
278 msg[1] = (ErlDrvTermData) dbin;
279 msg[2] = (ErlDrvTermData) (dbin ? sizeof(buf)-1 : 0);
280 msg[3] = (ErlDrvTermData) 0;
281 msg += 4;
282 break;
283 }
284
285 case 16:
286 msg[0] = ERL_DRV_BUF2BINARY;
287 msg[1] = (ErlDrvTermData) NULL;
288 msg[2] = (ErlDrvTermData) 0;
289 msg += 3;
290 break;
291
292 case 17: {
293 static const char buf[] = "";
294 msg[0] = ERL_DRV_BUF2BINARY;
295 msg[1] = (ErlDrvTermData) buf;
296 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
297 msg += 3;
298 break;
299 }
300
301 case 18: {
302 static const char buf[] = "hoppsan";
303 msg[0] = ERL_DRV_BUF2BINARY;
304 msg[1] = (ErlDrvTermData) buf;
305 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
306 msg += 3;
307 break;
308 }
309
310 case 19:
311 msg[0] = ERL_DRV_STRING;
312 msg[1] = (ErlDrvTermData) buf;
313 msg[2] = (ErlDrvTermData) 0;
314 msg += 3;
315 break;
316
317 case 20: {
318 static const char buf[] = "";
319 msg[0] = ERL_DRV_STRING;
320 msg[1] = (ErlDrvTermData) buf;
321 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
322 msg += 3;
323 break;
324 }
325
326 case 21: {
327 static const char buf[] = "hippsan";
328 msg[0] = ERL_DRV_STRING;
329 msg[1] = (ErlDrvTermData) buf;
330 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
331 msg += 3;
332 break;
333 }
334
335 case 22:
336 msg[0] = ERL_DRV_TUPLE;
337 msg[1] = (ErlDrvTermData) 0;
338 msg += 2;
339 break;
340
341 case 23:
342 msg[0] = ERL_DRV_NIL;
343 msg[1] = ERL_DRV_LIST;
344 msg[2] = (ErlDrvTermData) 1;
345 msg += 3;
346 break;
347
348 case 24:
349 msg[0] = ERL_DRV_PID;
350 msg[1] = driver_connected(erlang_port);
351 msg += 2;
352 break;
353
354 case 25:
355 msg[0] = ERL_DRV_NIL;
356 msg[1] = ERL_DRV_STRING_CONS;
357 msg[2] = (ErlDrvTermData) "";
358 msg[3] = (ErlDrvTermData) 0;
359 msg += 4;
360 break;
361
362 case 26: {
363 static double my_float = 0.0;
364 msg[0] = ERL_DRV_FLOAT;
365 msg[1] = (ErlDrvTermData) &my_float;
366 msg += 2;
367 break;
368 }
369
370 case 27: {
371 static char buf[] = {131, 106}; /* [] */
372 msg[0] = ERL_DRV_EXT2TERM;
373 msg[1] = (ErlDrvTermData) buf;
374 msg[2] = (ErlDrvTermData) sizeof(buf);
375 msg += 3;
376 break;
377 }
378
379 case 28: {
380 ErlDrvUInt64* x = &u64[u64_ix++];
381 *x = ~((ErlDrvUInt64) 0);
382 msg[0] = ERL_DRV_UINT64;
383 msg[1] = (ErlDrvTermData) x;
384 msg += 2;
385 break;
386 }
387
388 case 29: {
389 ErlDrvUInt64* x = &u64[u64_ix++];
390 *x = ((ErlDrvUInt64) 4711) << 32;
391 msg[0] = ERL_DRV_UINT64;
392 msg[1] = (ErlDrvTermData) x;
393 msg += 2;
394 break;
395 }
396
397 case 30: {
398 ErlDrvUInt64* x = &u64[u64_ix++];
399 *x = 4711;
400 msg[0] = ERL_DRV_UINT64;
401 msg[1] = (ErlDrvTermData) x;
402 msg += 2;
403 break;
404 }
405
406 case 31: {
407 ErlDrvUInt64* x = &u64[u64_ix++];
408 *x = 0;
409 msg[0] = ERL_DRV_UINT64;
410 msg[1] = (ErlDrvTermData) x;
411 msg += 2;
412 break;
413 }
414
415 case 32: {
416 ErlDrvSInt64* x = &s64[s64_ix++];
417 *x = ((((ErlDrvUInt64) 0x7fffffff) << 32) | ((ErlDrvUInt64) 0xffffffff));
418 msg[0] = ERL_DRV_INT64;
419 msg[1] = (ErlDrvTermData) x;
420 msg += 2;
421 break;
422 }
423
424 case 33: {
425 ErlDrvSInt64* x = &s64[s64_ix++];
426 *x = (ErlDrvSInt64) (((ErlDrvUInt64) 4711) << 32);
427 msg[0] = ERL_DRV_INT64;
428 msg[1] = (ErlDrvTermData) x;
429 msg += 2;
430 break;
431 }
432
433 case 34: {
434 ErlDrvSInt64* x = &s64[s64_ix++];
435 *x = 4711;
436 msg[0] = ERL_DRV_INT64;
437 msg[1] = (ErlDrvTermData) x;
438 msg += 2;
439 break;
440 }
441
442 case 35: {
443 ErlDrvSInt64* x = &s64[s64_ix++];
444 *x = 0;
445 msg[0] = ERL_DRV_INT64;
446 msg[1] = (ErlDrvTermData) x;
447 msg += 2;
448 break;
449 }
450
451 case 36: {
452 ErlDrvSInt64* x = &s64[s64_ix++];
453 *x = -1;
454 msg[0] = ERL_DRV_INT64;
455 msg[1] = (ErlDrvTermData) x;
456 msg += 2;
457 break;
458 }
459
460 case 37: {
461 ErlDrvSInt64* x = &s64[s64_ix++];
462 *x = -4711;
463 msg[0] = ERL_DRV_INT64;
464 msg[1] = (ErlDrvTermData) x;
465 msg += 2;
466 break;
467 }
468
469 case 38: {
470 ErlDrvSInt64* x = &s64[s64_ix++];
471 *x = ((ErlDrvSInt64) ((ErlDrvUInt64) 4711) << 32)*-1;
472 msg[0] = ERL_DRV_INT64;
473 msg[1] = (ErlDrvTermData) x;
474 msg += 2;
475 break;
476 }
477
478 case 39: {
479 ErlDrvSInt64* x = &s64[s64_ix++];
480 *x = ((ErlDrvSInt64) 1) << 63;
481 msg[0] = ERL_DRV_INT64;
482 msg[1] = (ErlDrvTermData) x;
483 msg += 2;
484 break;
485 }
486
487 case 40: {
488 msg[0] = ERL_DRV_MAP;
489 msg[1] = (ErlDrvTermData) 0;
490 msg += 2;
491 break;
492 }
493
494 case 41: /* Most term types inside a map */
495 case 42: {
496 double f = 3.1416;
497
498 if (buf[i] == 41) {
499 *msg++ = ERL_DRV_ATOM;
500 *msg++ = driver_mk_atom("blurf");
501 }
502 *msg++ = ERL_DRV_INT;
503 *msg++ = (ErlDrvTermData)42;
504 *msg++ = ERL_DRV_NIL;
505 *msg++ = ERL_DRV_INT;
506 *msg++ = (ErlDrvTermData)-42;
507 *msg++ = ERL_DRV_TUPLE;
508 *msg++ = (ErlDrvTermData)0;
509 *msg++ = ERL_DRV_PORT;
510 *msg++ = driver_mk_port(erlang_port);
511 *msg++ = ERL_DRV_STRING_CONS;
512 *msg++ = (ErlDrvTermData)"abc";
513 *msg++ = (ErlDrvTermData)3;
514 *msg++ = ERL_DRV_LIST;
515 *msg++ = (ErlDrvTermData)3;
516 *msg++ = ERL_DRV_STRING;
517 *msg++ = (ErlDrvTermData)"kalle";
518 *msg++ = (ErlDrvTermData)5;
519 *msg++ = ERL_DRV_FLOAT;
520 *msg++ = (ErlDrvTermData)&f;
521 *msg++ = ERL_DRV_PID;
522 *msg++ = driver_connected(erlang_port);
523 *msg++ = ERL_DRV_MAP;
524 *msg++ = (ErlDrvTermData)0;
525 if (buf[i] == 42) {
526 *msg++ = ERL_DRV_ATOM;
527 *msg++ = driver_mk_atom("blurf");
528 }
529 *msg++ = ERL_DRV_MAP;
530 *msg++ = (ErlDrvTermData)4;
531 break;
532 }
533
534 case 127: /* Error cases */
535 {
536 long refc;
537 ErlDrvBinary* bin = bins[bin_ix++] = driver_alloc_binary(256);
538
539 FAIL_TERM(msg, 0);
540
541 msg[0] = ERL_DRV_LIST;
542 msg[1] = (ErlDrvTermData) 0;
543 FAIL_TERM(msg, 2);
544
545 /* Not an atom */
546 msg[0] = ERL_DRV_ATOM;
547 msg[1] = (ErlDrvTermData) driver_connected(erlang_port);
548 FAIL_TERM(msg, 2);
549 msg[0] = ERL_DRV_ATOM;
550 msg[1] = driver_term_nil;
551 FAIL_TERM(msg, 2);
552
553 /* Not a pid */
554 msg[0] = ERL_DRV_PID;
555 msg[1] = (ErlDrvTermData) driver_mk_atom("blurf");
556 FAIL_TERM(msg, 2);
557 msg[0] = ERL_DRV_PID;
558 msg[1] = driver_term_nil;
559 FAIL_TERM(msg, 2);
560
561 /* Not a port */
562 msg[0] = ERL_DRV_PORT;
563 msg[1] = (ErlDrvTermData) driver_mk_atom("blurf");
564 FAIL_TERM(msg, 2);
565 msg[0] = ERL_DRV_PORT;
566 msg[1] = driver_term_nil;
567 FAIL_TERM(msg, 2);
568
569 /* Missing parameter on stack */
570 msg[0] = ERL_DRV_STRING_CONS;
571 msg[1] = (ErlDrvTermData) "abc";
572 msg[2] = (ErlDrvTermData) 3;
573 FAIL_TERM(msg, 3);
574
575 /*
576 * The first binary reference is correct, the second is incorrect.
577 * There should not be any "binary leak".
578 */
579 msg[0] = ERL_DRV_BINARY;
580 msg[1] = (ErlDrvTermData) bin;
581 msg[2] = (ErlDrvTermData) 256;
582 msg[3] = (ErlDrvTermData) 0;
583 msg[4] = ERL_DRV_BINARY;
584 msg[5] = (ErlDrvTermData) bin;
585 msg[6] = (ErlDrvTermData) 257;
586 msg[7] = (ErlDrvTermData) 0;
587 msg[8] = ERL_DRV_TUPLE;
588 msg[9] = (ErlDrvTermData) 2;
589 FAIL_TERM(msg, 10);
590
591 msg[0] = ERL_DRV_BINARY;
592 msg[1] = (ErlDrvTermData) bin;
593 msg[2] = (ErlDrvTermData) 256;
594 msg[3] = (ErlDrvTermData) 0;
595 msg[4] = ERL_DRV_BINARY;
596 msg[5] = (ErlDrvTermData) bin;
597 msg[6] = (ErlDrvTermData) 256;
598 msg[7] = (ErlDrvTermData) 50;
599 msg[8] = ERL_DRV_TUPLE;
600 msg[9] = (ErlDrvTermData) 2;
601 FAIL_TERM(msg, 10);
602
603 /*
604 * We have succefully built two binaries. We expect the ref count
605 * to be 1 (SMP) or 3 (non-SMP).
606 */
607 refc = driver_binary_get_refc(bin);
608 if (refc > 3) {
609 char sbuf[128];
610 sprintf(sbuf, "bad_refc:%ld", refc);
611 driver_failure_atom(erlang_port, sbuf);
612 }
613 driver_free_binary(bin);
614
615
616 FAIL_TERM(msg, make_ext_term_list(msg, 1));
617
618
619 /*
620 * Check that we fail for missing args.
621 *
622 * We setup valid terms but pass a too small size. We
623 * want valid terms since we want to verify that the
624 * failure really is due to the small size.
625 */
626 msg[0] = ERL_DRV_ATOM;
627 msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom");
628 FAIL_TERM(msg, 1);
629
630 msg[0] = ERL_DRV_INT;
631 msg[1] = (ErlDrvTermData) -4711;
632 FAIL_TERM(msg, 1);
633
634 msg[0] = ERL_DRV_UINT;
635 msg[1] = (ErlDrvTermData) 4711;
636 FAIL_TERM(msg, 1);
637
638 msg[0] = ERL_DRV_PORT;
639 msg[1] = driver_mk_port(erlang_port);
640 FAIL_TERM(msg, 1);
641
642 {
643 char buf[] = "hejsan";
644 ErlDrvBinary *dbin = driver_alloc_binary(sizeof(buf)-1);
645 if (!dbin)
646 driver_failure_posix(erlang_port, ENOMEM);
647 else {
648 memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1);
649 msg[0] = ERL_DRV_BINARY;
650 msg[1] = (ErlDrvTermData) dbin;
651 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
652 msg[3] = (ErlDrvTermData) 0;
653 FAIL_TERM(msg, 1);
654 FAIL_TERM(msg, 2);
655 FAIL_TERM(msg, 3);
656 driver_free_binary(dbin);
657 }
658 }
659
660 {
661 char buf[] = "hoppsan";
662 msg[0] = ERL_DRV_BUF2BINARY;
663 msg[1] = (ErlDrvTermData) buf;
664 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
665 FAIL_TERM(msg, 1);
666 FAIL_TERM(msg, 2);
667 }
668
669 {
670 char buf[] = "hippsan";
671 msg[0] = ERL_DRV_STRING;
672 msg[1] = (ErlDrvTermData) buf;
673 msg[2] = (ErlDrvTermData) sizeof(buf)-1;
674 FAIL_TERM(msg, 1);
675 FAIL_TERM(msg, 2);
676 }
677
678 msg[0] = ERL_DRV_TUPLE;
679 msg[1] = (ErlDrvTermData) 0;
680 FAIL_TERM(msg, 1);
681
682 msg[0] = ERL_DRV_NIL;
683 msg[1] = ERL_DRV_LIST;
684 msg[2] = (ErlDrvTermData) 1;
685 FAIL_TERM(msg, 2);
686
687 msg[0] = ERL_DRV_PID;
688 msg[1] = driver_connected(erlang_port);
689 FAIL_TERM(msg, 1);
690
691 msg[0] = ERL_DRV_NIL;
692 msg[1] = ERL_DRV_STRING_CONS;
693 msg[2] = (ErlDrvTermData) "";
694 msg[3] = (ErlDrvTermData) 0;
695 FAIL_TERM(msg, 2);
696 FAIL_TERM(msg, 3);
697
698 {
699 double my_float = 0.0;
700 msg[0] = ERL_DRV_FLOAT;
701 msg[1] = (ErlDrvTermData) &my_float;
702 FAIL_TERM(msg, 1);
703 }
704
705 {
706 char buf[] = {131, 106}; /* [] */
707 msg[0] = ERL_DRV_EXT2TERM;
708 msg[1] = (ErlDrvTermData) buf;
709 msg[2] = (ErlDrvTermData) sizeof(buf);
710 FAIL_TERM(msg, 1);
711 FAIL_TERM(msg, 2);
712 }
713
714 msg[0] = ERL_DRV_MAP;
715 msg[1] = (ErlDrvTermData) 0;
716 FAIL_TERM(msg, 1);
717
718 /* map with duplicate key */
719 msg[0] = ERL_DRV_ATOM;
720 msg[1] = driver_mk_atom("key");
721 msg[2] = ERL_DRV_NIL;
722 msg[3] = ERL_DRV_ATOM;
723 msg[4] = driver_mk_atom("key");
724 msg[5] = ERL_DRV_INT;
725 msg[6] = (ErlDrvTermData) -4711;
726 msg[7] = ERL_DRV_MAP;
727 msg[8] = 2;
728 FAIL_TERM(msg, 9);
729
730 /* Signal end of test case */
731 msg[0] = ERL_DRV_NIL;
732 erl_drv_output_term(driver_mk_port(erlang_port), msg, 1);
733 return;
734 }
735 break;
736
737 default:
738 driver_failure_atom(erlang_port, "bad_request");
739 break;
740 }
741 if (count > 1) {
742 *msg++ = ERL_DRV_NIL;
743 *msg++ = ERL_DRV_LIST;
744 *msg++ = count + 1;
745 }
746 output_term(spec, msg-spec);
747 if ((bin_ix|s64_ix|u64_ix) > 15) abort();
748 while (bin_ix) {
749 driver_free_binary(bins[--bin_ix]);
750 }
751 }
752
output_term(ErlDrvTermData * msg,int len)753 static void output_term(ErlDrvTermData* msg, int len)
754 {
755 if (erl_drv_output_term(driver_mk_port(erlang_port), msg, len) <= 0) {
756 driver_failure_atom(erlang_port, "erl_drv_output_term_failed");
757 }
758 }
759
fail_term(ErlDrvTermData * msg,int len,int line)760 static void fail_term(ErlDrvTermData* msg, int len, int line)
761 {
762 int status = erl_drv_output_term(driver_mk_port(erlang_port), msg, len);
763
764 if (status == 1) {
765 char buf[1024];
766 sprintf(buf, "%s:%d: unexpected success", __FILE__, line);
767 driver_failure_atom(erlang_port, buf);
768 } else if (status == 0) {
769 char buf[1024];
770 sprintf(buf, "%s:%d: unexpected port error", __FILE__, line);
771 driver_failure_atom(erlang_port, buf);
772 }
773 }
774
775 #include "ext_terms.h"
776
777 /*
778 * <<131,103,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,36,0,0,0,0,1>>
779 * is a valid pid: <0.36.0>
780 *
781 * We replace the nodename tag (atom tag: 100) with a pid tag (103) to get an
782 * invalid pid.
783 */
784 static unsigned char bad_ext_term[] = {
785 131,103,103,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,36,0,0,0,0,1
786 /* ^
787 * |
788 * The bad tag.
789 */
790 };
791
make_ext_term_list(ErlDrvTermData * td,int bad)792 static int make_ext_term_list(ErlDrvTermData *td, int bad)
793 {
794 int tdix = 0;
795 int i;
796 for (i = 0; i < NO_OF_EXT_TERMS; i++) {
797 td[tdix++] = ERL_DRV_EXT2TERM;
798 td[tdix++] = (ErlDrvTermData) &ext_terms[i].ext[0];
799 td[tdix++] = (ErlDrvTermData) ext_terms[i].ext_size;
800 td[tdix++] = ERL_DRV_EXT2TERM;
801 td[tdix++] = (ErlDrvTermData) &ext_terms[i].cext[0];
802 td[tdix++] = (ErlDrvTermData) ext_terms[i].cext_size;
803 td[tdix++] = ERL_DRV_TUPLE;
804 td[tdix++] = (ErlDrvTermData) 2;
805 }
806 if (bad) { /* Include a bad ext term */
807 td[tdix++] = ERL_DRV_EXT2TERM;
808 td[tdix++] = (ErlDrvTermData) &bad_ext_term[0];
809 td[tdix++] = (ErlDrvTermData) sizeof(bad_ext_term);
810 }
811 td[tdix++] = ERL_DRV_NIL;
812 td[tdix++] = ERL_DRV_LIST;
813 td[tdix++] = (ErlDrvTermData) (NO_OF_EXT_TERMS + (bad ? 2 : 1));
814 return tdix;
815 }
816