xref: /netbsd-src/external/mpl/dhcp/dist/keama/print.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
1 /*	$NetBSD: print.c,v 1.3 2022/04/03 01:10:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  *   Internet Systems Consortium, Inc.
19  *   PO Box 360
20  *   Newmarket, NH 03857 USA
21  *   <info@isc.org>
22  *   https://www.isc.org/
23  *
24  */
25 
26 #include <sys/cdefs.h>
27 __RCSID("$NetBSD: print.c,v 1.3 2022/04/03 01:10:59 christos Exp $");
28 
29 #include "keama.h"
30 
31 #include <sys/errno.h>
32 #include <sys/types.h>
33 #include <arpa/inet.h>
34 #include <ctype.h>
35 #include <netdb.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 static void debug(const char* fmt, ...);
42 
43 const char *
print_expression(struct element * expr,isc_boolean_t * lose)44 print_expression(struct element *expr, isc_boolean_t *lose)
45 {
46 	if (expr->type == ELEMENT_BOOLEAN)
47 		return print_boolean_expression(expr, lose);
48 	if (expr->type == ELEMENT_INTEGER)
49 		return print_numeric_expression(expr, lose);
50 	if (expr->type == ELEMENT_STRING)
51 		return print_data_expression(expr, lose);
52 
53 	if (is_boolean_expression(expr))
54 		return print_boolean_expression(expr, lose);
55 	if (is_numeric_expression(expr))
56 		return print_numeric_expression(expr, lose);
57 	if (is_data_expression(expr))
58 		return print_data_expression(expr, lose);
59 	*lose = ISC_TRUE;
60 	return "???";
61 }
62 
63 const char *
print_boolean_expression(struct element * expr,isc_boolean_t * lose)64 print_boolean_expression(struct element *expr, isc_boolean_t *lose)
65 {
66 	struct string *result;
67 
68 	if (expr->type == ELEMENT_BOOLEAN) {
69 		if (boolValue(expr))
70 			return "true";
71 		else
72 			return "false";
73 	}
74 
75 	/*
76 	 * From is_boolean_expression
77 	 */
78 	if (expr->type != ELEMENT_MAP) {
79 		*lose = ISC_TRUE;
80 		return "???";
81 	}
82 	result = allocString();
83 
84 	/* check */
85 	if (mapContains(expr, "check")) {
86 		struct element *name;
87 
88 		appendString(result, "check ");
89 		name = mapGet(expr, "check");
90 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
91 			*lose = ISC_TRUE;
92 			appendString(result, "???");
93 		} else
94 			concatString(result, stringValue(name));
95 		return result->content;
96 	}
97 
98 	/* exists */
99 	if (mapContains(expr, "exists")) {
100 		struct element *arg;
101 		struct element *universe;
102 		struct element *name;
103 
104 		appendString(result, "exists ");
105 		arg = mapGet(expr, "exists");
106 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
107 			*lose = ISC_TRUE;
108 			appendString(result, "???");
109 			return result->content;
110 		}
111 		universe = mapGet(arg, "universe");
112 		if ((universe == NULL) || (universe->type != ELEMENT_STRING)) {
113 			*lose = ISC_TRUE;
114 			appendString(result, "???");
115 			return result->content;
116 		}
117 		concatString(result, stringValue(universe));
118 		appendString(result, ".");
119 		name = mapGet(arg, "name");
120 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
121 			*lose = ISC_TRUE;
122 			appendString(result, "???");
123 			return result->content;
124 		}
125 		concatString(result, stringValue(name));
126 		return result->content;
127 	}
128 
129 	/* variable-exists */
130 	if (mapContains(expr, "variable-exists")) {
131 		struct element *name;
132 
133 		appendString(result, "variable-exists ");
134 		name = mapGet(expr, "variable-exists");
135 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
136 			*lose = ISC_TRUE;
137 			appendString(result, "???");
138 		} else
139 			concatString(result, stringValue(name));
140 		return result->content;
141 	}
142 
143 	/* equal */
144 	if (mapContains(expr, "equal")) {
145 		struct element *arg;
146 		struct element *left;
147 		struct element *right;
148 		isc_boolean_t add_parenthesis;
149 
150 		appendString(result, "equal ");
151 		arg = mapGet(expr, "equal");
152 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
153 			*lose = ISC_TRUE;
154 			appendString(result, "???");
155 			return result->content;
156 		}
157 		left = mapGet(arg, "left");
158 		if (left == NULL) {
159 			*lose = ISC_TRUE;
160 			appendString(result, "???");
161 			return result->content;
162 		}
163 		result = allocString();
164 		add_parenthesis = ISC_TF(expr_precedence(expr_equal,
165 							 left) < 0);
166 		if (add_parenthesis)
167 			appendString(result, "(");
168 		appendString(result, print_expression(left, lose));
169 		if (add_parenthesis)
170 			appendString(result, ")");
171 		appendString(result, " = ");
172 		right = mapGet(arg, "right");
173 		if (right == NULL) {
174 			*lose = ISC_TRUE;
175 			appendString(result, "???");
176 			return result->content;
177 		}
178 		add_parenthesis = ISC_TF(expr_precedence(expr_equal,
179 							 right) < 0);
180 		if (add_parenthesis)
181 			appendString(result, "(");
182 		appendString(result, print_expression(right, lose));
183 		if (add_parenthesis)
184 			appendString(result, ")");
185 		return result->content;
186 	}
187 
188 	/* not-equal */
189 	if (mapContains(expr, "not-equal")) {
190 		struct element *arg;
191 		struct element *left;
192 		struct element *right;
193 		isc_boolean_t add_parenthesis;
194 
195 		appendString(result, "not-equal ");
196 		arg = mapGet(expr, "not-equal");
197 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
198 			*lose = ISC_TRUE;
199 			appendString(result, "???");
200 			return result->content;
201 		}
202 		left = mapGet(arg, "left");
203 		if (left == NULL) {
204 			*lose = ISC_TRUE;
205 			appendString(result, "???");
206 			return result->content;
207 		}
208 		result = allocString();
209 		add_parenthesis = ISC_TF(expr_precedence(expr_not_equal,
210 							 left) < 0);
211 		if (add_parenthesis)
212 			appendString(result, "(");
213 		appendString(result, print_expression(left, lose));
214 		if (add_parenthesis)
215 			appendString(result, ")");
216 		appendString(result, " != ");
217 		right = mapGet(arg, "right");
218 		if (right == NULL) {
219 			*lose = ISC_TRUE;
220 			appendString(result, "???");
221 			return result->content;
222 		}
223 		add_parenthesis = ISC_TF(expr_precedence(expr_not_equal,
224 							 right) < 0);
225 		if (add_parenthesis)
226 			appendString(result, "(");
227 		appendString(result, print_expression(right, lose));
228 		if (add_parenthesis)
229 			appendString(result, ")");
230 		return result->content;
231 	}
232 
233 	/* regex-match */
234 	if (mapContains(expr, "regex-match")) {
235 		struct element *arg;
236 		struct element *left;
237 		struct element *right;
238 		isc_boolean_t add_parenthesis;
239 
240 		appendString(result, "regex-match ");
241 		arg = mapGet(expr, "regex-match");
242 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
243 			*lose = ISC_TRUE;
244 			appendString(result, "???");
245 			return result->content;
246 		}
247 		left = mapGet(arg, "left");
248 		if (left == NULL) {
249 			*lose = ISC_TRUE;
250 			appendString(result, "???");
251 			return result->content;
252 		}
253 		result = allocString();
254 		add_parenthesis = ISC_TF(expr_precedence(expr_regex_match,
255 							 left) < 0);
256 		if (add_parenthesis)
257 			appendString(result, "(");
258 		appendString(result, print_expression(left, lose));
259 		if (add_parenthesis)
260 			appendString(result, ")");
261 		appendString(result, " ~= ");
262 		right = mapGet(arg, "right");
263 		if (right == NULL) {
264 			*lose = ISC_TRUE;
265 			appendString(result, "???");
266 			return result->content;
267 		}
268 		appendString(result, print_expression(right, lose));
269 		return result->content;
270 	}
271 
272 	/* iregex-match */
273 	if (mapContains(expr, "iregex-match")) {
274 		struct element *arg;
275 		struct element *left;
276 		struct element *right;
277 		isc_boolean_t add_parenthesis;
278 
279 		appendString(result, "iregex-match ");
280 		arg = mapGet(expr, "iregex-match");
281 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
282 			*lose = ISC_TRUE;
283 			appendString(result, "???");
284 			return result->content;
285 		}
286 		left = mapGet(arg, "left");
287 		if (left == NULL) {
288 			*lose = ISC_TRUE;
289 			appendString(result, "???");
290 			return result->content;
291 		}
292 		result = allocString();
293 		add_parenthesis = ISC_TF(expr_precedence(expr_iregex_match,
294 							 left) < 0);
295 		if (add_parenthesis)
296 			appendString(result, "(");
297 		appendString(result, print_expression(left, lose));
298 		if (add_parenthesis)
299 			appendString(result, ")");
300 		appendString(result, " ~~ ");
301 		right = mapGet(arg, "right");
302 		if (right == NULL) {
303 			*lose = ISC_TRUE;
304 			appendString(result, "???");
305 			return result->content;
306 		}
307 		appendString(result, print_expression(right, lose));
308 		return result->content;
309 	}
310 
311 	/* and */
312 	if (mapContains(expr, "and")) {
313 		struct element *arg;
314 		struct element *left;
315 		struct element *right;
316 		isc_boolean_t add_parenthesis;
317 
318 		appendString(result, "and ");
319 		arg = mapGet(expr, "and");
320 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
321 			*lose = ISC_TRUE;
322 			appendString(result, "???");
323 			return result->content;
324 		}
325 		left = mapGet(arg, "left");
326 		if (left == NULL) {
327 			*lose = ISC_TRUE;
328 			appendString(result, "???");
329 			return result->content;
330 		}
331 		result = allocString();
332 		add_parenthesis = ISC_TF(expr_precedence(expr_and,
333 							 left) < 0);
334 		if (add_parenthesis)
335 			appendString(result, "(");
336 		appendString(result, print_expression(left, lose));
337 		if (add_parenthesis)
338 			appendString(result, ")");
339 		appendString(result, " and ");
340 		right = mapGet(arg, "right");
341 		if (right == NULL) {
342 			*lose = ISC_TRUE;
343 			appendString(result, "???");
344 			return result->content;
345 		}
346 		add_parenthesis = ISC_TF(expr_precedence(expr_and,
347 							 right) < 0);
348 		if (add_parenthesis)
349 			appendString(result, "(");
350 		appendString(result, print_expression(right, lose));
351 		if (add_parenthesis)
352 			appendString(result, ")");
353 		return result->content;
354 	}
355 
356 	/* or */
357 	if (mapContains(expr, "or")) {
358 		struct element *arg;
359 		struct element *left;
360 		struct element *right;
361 		isc_boolean_t add_parenthesis;
362 
363 		appendString(result, "or ");
364 		arg = mapGet(expr, "or");
365 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
366 			*lose = ISC_TRUE;
367 			appendString(result, "???");
368 			return result->content;
369 		}
370 		left = mapGet(arg, "left");
371 		if (left == NULL) {
372 			*lose = ISC_TRUE;
373 			appendString(result, "???");
374 			return result->content;
375 		}
376 		result = allocString();
377 		add_parenthesis = ISC_TF(expr_precedence(expr_or,
378 							 left) < 0);
379 		if (add_parenthesis)
380 			appendString(result, "(");
381 		appendString(result, print_expression(left, lose));
382 		if (add_parenthesis)
383 			appendString(result, ")");
384 		appendString(result, " or ");
385 		right = mapGet(arg, "right");
386 		if (right == NULL) {
387 			*lose = ISC_TRUE;
388 			appendString(result, "???");
389 			return result->content;
390 		}
391 		add_parenthesis = ISC_TF(expr_precedence(expr_or,
392 							 right) < 0);
393 		if (add_parenthesis)
394 			appendString(result, "(");
395 		appendString(result, print_expression(right, lose));
396 		if (add_parenthesis)
397 			appendString(result, ")");
398 		return result->content;
399 	}
400 
401 	/* not */
402 	if (mapContains(expr, "not")) {
403 		struct element *arg;
404 		isc_boolean_t add_parenthesis;
405 
406 		appendString(result, "not ");
407 		arg = mapGet(expr, "not");
408 		if (arg == NULL) {
409 			*lose = ISC_TRUE;
410 			appendString(result, "???");
411 			return result->content;
412 		}
413 		add_parenthesis = ISC_TF(expr_precedence(expr_not,
414 							 arg) < 0);
415 		if (add_parenthesis)
416 			appendString(result, "(");
417 		appendString(result, print_expression(arg, lose));
418 		if (add_parenthesis)
419 			appendString(result, ")");
420 		return result->content;
421 	}
422 
423 	/* known */
424 	if (mapContains(expr, "known")) {
425 		return "known";
426 	}
427 
428 	/* static */
429 	if (mapContains(expr, "static")) {
430 		return "static";
431 	}
432 
433 	/* variable-reference */
434 	if (mapContains(expr, "variable-reference")) {
435 		struct element *name;
436 
437 		appendString(result, "variable-reference ");
438 		name = mapGet(expr, "variable-reference");
439 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
440 			*lose = ISC_TRUE;
441 			appendString(result, "???");
442 			return result->content;
443 		}
444 		return stringValue(name)->content;
445 	}
446 
447 	/* funcall */
448 	if (mapContains(expr, "funcall")) {
449 		struct element *arg;
450 		struct element *name;
451 		struct element *args;
452 		size_t i;
453 
454 		appendString(result, "funcall ");
455 		arg = mapGet(expr, "funcall");
456 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
457 			*lose = ISC_TRUE;
458 			appendString(result, "???");
459 			return result->content;
460 		}
461 		name = mapGet(arg, "name");
462 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
463 			*lose = ISC_TRUE;
464 			appendString(result, "???");
465 			return result->content;
466 		}
467 		result = allocString();
468 		concatString(result, stringValue(name));
469 		appendString(result, "(");
470 		args = mapGet(arg, "arguments");
471 		if ((args == NULL) || (args->type != ELEMENT_LIST)) {
472 			*lose = ISC_TRUE;
473 			appendString(result, "???" ")");
474 			return result->content;
475 		}
476 		for (i = 0; i < listSize(args); i++) {
477 			struct element *item;
478 
479 			if (i != 0)
480 				appendString(result, ", ");
481 			item = listGet(args, i);
482 			if (item == NULL) {
483 				debug("funcall null argument %u",
484 				      (unsigned)i);
485 				*lose = ISC_TRUE;
486 				appendString(result, "???");
487 				continue;
488 			}
489 			appendString(result, print_expression(item, lose));
490 		}
491 		appendString(result, ")");
492 		return result->content;
493 	}
494 
495 	*lose = ISC_TRUE;
496 	appendString(result, "???");
497 	return result->content;
498 }
499 
500 const char *
print_data_expression(struct element * expr,isc_boolean_t * lose)501 print_data_expression(struct element *expr, isc_boolean_t *lose)
502 {
503 	struct string *result;
504 
505 	if (expr->type == ELEMENT_STRING)
506 		return quote(stringValue(expr))->content;
507 
508 	/*
509 	 * From is_data_expression
510 	 */
511 	if (expr->type != ELEMENT_MAP) {
512 		*lose = ISC_TRUE;
513 		return "???";
514 	}
515 	result = allocString();
516 
517 	/* substring */
518 	if (mapContains(expr, "substring")) {
519 		struct element *arg;
520 		struct element *string;
521 		struct element *offset;
522 		struct element *length;
523 
524 		appendString(result, "substring(");
525 		arg = mapGet(expr, "substring");
526 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
527 			*lose = ISC_TRUE;
528 			appendString(result, "???" ")");
529 			return result->content;
530 		}
531 		string = mapGet(arg, "expression");
532 		if (string == NULL) {
533 			*lose = ISC_TRUE;
534 			appendString(result, "???" ")");
535 			return result->content;
536 		}
537 		appendString(result, print_data_expression(string, lose));
538 		appendString(result, ", ");
539 		offset = mapGet(arg, "offset");
540 		if (offset  == NULL) {
541 			*lose = ISC_TRUE;
542 			appendString(result, "???" ")");
543 			return result->content;
544 		}
545 		appendString(result, print_numeric_expression(offset, lose));
546 		appendString(result, ", ");
547 		length = mapGet(arg, "length");
548 		if (length  == NULL) {
549 			*lose = ISC_TRUE;
550 			appendString(result, "???" ")");
551 			return result->content;
552 		}
553 		appendString(result, print_numeric_expression(length, lose));
554 		appendString(result, ")");
555 		return result->content;
556 	}
557 
558 	/* suffix */
559 	if (mapContains(expr, "suffix")) {
560 		struct element *arg;
561 		struct element *string;
562 		struct element *length;
563 
564 		appendString(result, "suffix(");
565 		arg = mapGet(expr, "suffix");
566 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
567 			*lose = ISC_TRUE;
568 			appendString(result, "???" ")");
569 			return result->content;
570 		}
571 		string = mapGet(arg, "expression");
572 		if (string == NULL) {
573 			*lose = ISC_TRUE;
574 			appendString(result, "???" ")");
575 			return result->content;
576 		}
577 		appendString(result, print_data_expression(string, lose));
578 		appendString(result, ", ");
579 		length = mapGet(arg, "length");
580 		if (length  == NULL) {
581 			*lose = ISC_TRUE;
582 			appendString(result, "???" ")");
583 			return result->content;
584 		}
585 		appendString(result, print_numeric_expression(length, lose));
586 		appendString(result, ")");
587 		return result->content;
588 	}
589 
590 	/* lowercase */
591 	if (mapContains(expr, "lowercase")) {
592 		struct element *arg;
593 
594 		appendString(result, "lowercase(");
595 		arg = mapGet(expr, "lowercase");
596 		if (arg == NULL) {
597 			*lose = ISC_TRUE;
598 			appendString(result, "???" ")");
599 			return result->content;
600 		}
601 		appendString(result, print_data_expression(arg, lose));
602 		appendString(result, ")");
603 		return result->content;
604 	}
605 
606 	/* uppercase */
607 	if (mapContains(expr, "uppercase")) {
608 		struct element *arg;
609 
610 		appendString(result, "uppercase(");
611 		arg = mapGet(expr, "uppercase");
612 		if (arg == NULL) {
613 			*lose = ISC_TRUE;
614 			appendString(result, "???" ")");
615 			return result->content;
616 		}
617 		appendString(result, print_data_expression(arg, lose));
618 		appendString(result, ")");
619 		return result->content;
620 	}
621 
622 	/* option */
623 	if (mapContains(expr, "option")) {
624 		struct element *arg;
625 		struct element *universe;
626 		struct element *name;
627 
628 		appendString(result, "option ");
629 		arg = mapGet(expr, "option");
630 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
631 			*lose = ISC_TRUE;
632 			appendString(result, "???");
633 			return result->content;
634 		}
635 		universe = mapGet(arg, "universe");
636 		if ((universe == NULL) || (universe->type != ELEMENT_STRING)) {
637 			*lose = ISC_TRUE;
638 			appendString(result, "???");
639 			return result->content;
640 		}
641 		concatString(result, stringValue(universe));
642 		appendString(result, ".");
643 		name = mapGet(arg, "name");
644 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
645 			*lose = ISC_TRUE;
646 			appendString(result, "???");
647 			return result->content;
648 		}
649 		concatString(result, stringValue(name));
650 		return result->content;
651 	}
652 
653 	/* hardware */
654 	if (mapContains(expr, "hardware"))
655 		return "hardware";
656 
657 	/* hw-type */
658 	if (mapContains(expr, "hw-type"))
659 		return "hw-type";
660 
661 	/* hw-address */
662 	if (mapContains(expr, "hw-address"))
663 		return "hw-address";
664 
665 	/* const-data */
666 	if (mapContains(expr, "const-data")) {
667 		struct element *arg;
668 
669 		arg = mapGet(expr, "const-data");
670 		if ((arg == NULL) || (arg->type != ELEMENT_STRING)) {
671 			*lose = ISC_TRUE;
672 			appendString(result, "???");
673 			return result->content;
674 		}
675 		concatString(result, stringValue(arg));
676 		return result->content;
677 	}
678 
679 	/* packet */
680 	if (mapContains(expr, "packet")) {
681 		struct element *arg;
682 		struct element *offset;
683 		struct element *length;
684 
685 		appendString(result, "packet(");
686 		arg = mapGet(expr, "packet");
687 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
688 			*lose = ISC_TRUE;
689 			appendString(result, "???" ")");
690 			return result->content;
691 		}
692 		offset = mapGet(arg, "offset");
693 		if (offset  == NULL) {
694 			*lose = ISC_TRUE;
695 			appendString(result, "???" ")");
696 			return result->content;
697 		}
698 		appendString(result, print_numeric_expression(offset, lose));
699 		appendString(result, ", ");
700 		length = mapGet(arg, "length");
701 		if (length  == NULL) {
702 			*lose = ISC_TRUE;
703 			appendString(result, "???" ")");
704 			return result->content;
705 		}
706 		appendString(result, print_numeric_expression(length, lose));
707 		appendString(result, ")");
708 		return result->content;
709 	}
710 
711 	/* concat */
712 	if (mapContains(expr, "concat")) {
713 		struct element *arg;
714 		struct element *left;
715 		struct element *right;
716 
717 		appendString(result, "concat(");
718 		arg = mapGet(expr, "concat");
719 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
720 			*lose = ISC_TRUE;
721 			appendString(result, "???" ")");
722 			return result->content;
723 		}
724 		left = mapGet(arg, "left");
725 		if (left == NULL) {
726 			*lose = ISC_TRUE;
727 			appendString(result, "???" ")");
728 			return result->content;
729 		}
730 		appendString(result, print_data_expression(left, lose));
731 		appendString(result, ", ");
732 		right = mapGet(arg, "right");
733 		if (right == NULL) {
734 			*lose = ISC_TRUE;
735 			appendString(result, "???" ")");
736 			return result->content;
737 		}
738 		appendString(result, print_data_expression(right, lose));
739 		appendString(result, ")");
740 		return result->content;
741 	}
742 
743 	/* encapsulate */
744 	if (mapContains(expr, "encapsulate")) {
745 		struct element *arg;
746 
747 		appendString(result, "encapsulate ");
748 		arg = mapGet(expr, "encapsulate");
749 		if (arg == NULL) {
750 			*lose = ISC_TRUE;
751 			appendString(result, "???");
752 			return result->content;
753 		}
754 		appendString(result, print_data_expression(arg, lose));
755 		return result->content;
756 	}
757 
758 	/* encode-int8 */
759 	if (mapContains(expr, "encode-int8")) {
760 		struct element *arg;
761 
762 		appendString(result, "encode-int(");
763 		arg = mapGet(expr, "encode-int8");
764 		if (arg == NULL) {
765 			*lose = ISC_TRUE;
766 			appendString(result, "???, 8)");
767 			return result->content;
768 		}
769 		appendString(result, print_numeric_expression(arg, lose));
770 		appendString(result, ", 8)");
771 		return result->content;
772 	}
773 
774 	/* encode-int16 */
775 	if (mapContains(expr, "encode-int16")) {
776 		struct element *arg;
777 
778 		appendString(result, "encode-int(");
779 		arg = mapGet(expr, "encode-int16");
780 		if (arg == NULL) {
781 			*lose = ISC_TRUE;
782 			appendString(result, "???, 16)");
783 			return result->content;
784 		}
785 		appendString(result, print_numeric_expression(arg, lose));
786 		appendString(result, ", 16)");
787 		return result->content;
788 	}
789 
790 	/* encode-int32 */
791 	if (mapContains(expr, "encode-int32")) {
792 		struct element *arg;
793 
794 		appendString(result, "encode-int(");
795 		arg = mapGet(expr, "encode-int32");
796 		if (arg == NULL) {
797 			*lose = ISC_TRUE;
798 			appendString(result, "???, 32)");
799 			return result->content;
800 		}
801 		appendString(result, print_numeric_expression(arg, lose));
802 		appendString(result, ", 32)");
803 		return result->content;
804 	}
805 
806 	/* gethostbyname */
807 	if (mapContains(expr, "gethostbyname")) {
808 		struct element *arg;
809 
810 		appendString(result, "gethostbyname(");
811 		arg = mapGet(expr, "gethostbyname");
812 		if (arg == NULL) {
813 			*lose = ISC_TRUE;
814 			appendString(result, "???");
815 			return result->content;
816 		}
817 		appendString(result, print_data_expression(arg, lose));
818 		appendString(result, ")");
819 		return result->content;
820 	}
821 
822 	/* binary-to-ascii */
823 	if (mapContains(expr, "binary-to-ascii")) {
824 		struct element *arg;
825 		struct element *base;
826 		struct element *width;
827 		struct element *separator;
828 		struct element *buffer;
829 
830 		appendString(result, "binary-to-ascii(");
831 		arg = mapGet(expr, "binary-to-ascii");
832 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
833 			*lose = ISC_TRUE;
834 			appendString(result, "???" ")");
835 			return result->content;
836 		}
837 		base = mapGet(arg, "base");
838 		if (base == NULL) {
839 			*lose = ISC_TRUE;
840 			appendString(result, "???" ")");
841 			return result->content;
842 		}
843 		appendString(result, print_numeric_expression(base, lose));
844 		appendString(result, ", ");
845 		width = mapGet(arg, "width");
846 		if (width == NULL) {
847 			*lose = ISC_TRUE;
848 			appendString(result, "???" ")");
849 			return result->content;
850 		}
851 		appendString(result, print_numeric_expression(width, lose));
852 		appendString(result, ", ");
853 		separator = mapGet(arg, "separator");
854 		if (separator == NULL) {
855 			*lose = ISC_TRUE;
856 			appendString(result, "???" ")");
857 			return result->content;
858 		}
859 		appendString(result, print_data_expression(separator, lose));
860 		appendString(result, ", ");
861 		buffer = mapGet(arg, "buffer");
862 		if (buffer == NULL) {
863 			*lose = ISC_TRUE;
864 			appendString(result, "???" ")");
865 			return result->content;
866 		}
867 		appendString(result, print_data_expression(buffer, lose));
868 		appendString(result, ")");
869 		return result->content;
870 	}
871 
872 	/* filename */
873 	if (mapContains(expr, "filename"))
874 		return "filename";
875 
876 	/* server-name */
877 	if (mapContains(expr, "server-name"))
878 		return "server-name";
879 
880 	/* reverse */
881 	if (mapContains(expr, "reverse")) {
882 		struct element *arg;
883 		struct element *width;
884 		struct element *buffer;
885 
886 		appendString(result, "reverse(");
887 		arg = mapGet(expr, "reverse");
888 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
889 			*lose = ISC_TRUE;
890 			appendString(result, "???" ")");
891 			return result->content;
892 		}
893 		width = mapGet(arg, "width");
894 		if (width == NULL) {
895 			*lose = ISC_TRUE;
896 			appendString(result, "???" ")");
897 			return result->content;
898 		}
899 		appendString(result, print_numeric_expression(width, lose));
900 		appendString(result, ", ");
901 		buffer = mapGet(arg, "buffer");
902 		if (buffer == NULL) {
903 			*lose = ISC_TRUE;
904 			appendString(result, "???" ")");
905 			return result->content;
906 		}
907 		appendString(result, print_data_expression(buffer, lose));
908 		appendString(result, ")");
909 		return result->content;
910 	}
911 
912 	/* pick-first-value */
913 	if (mapContains(expr, "pick-first-value")) {
914 		struct element *arg;
915 		size_t i;
916 
917 		appendString(result, "pick-first-value(");
918 		arg = mapGet(expr, "pick-first-value");
919 		if ((arg == NULL) || (arg->type != ELEMENT_LIST)) {
920 			*lose = ISC_TRUE;
921 			appendString(result, "???" ")");
922 			return result->content;
923 		}
924 		for (i = 0; i < listSize(arg); i++) {
925 			struct element *item;
926 
927 			if (i != 0)
928 				appendString(result, ", ");
929 			item = listGet(arg, i);
930 			if (item == NULL) {
931 				*lose = ISC_TRUE;
932 				appendString(result, "???");
933 				continue;
934 			}
935 			appendString(result,
936 				     print_data_expression(item, lose));
937 		}
938 		appendString(result, ")");
939 		return result->content;
940 	}
941 
942 	/* host-decl-name */
943 	if (mapContains(expr, "host-decl-name"))
944 		return "host-decl-name";
945 
946 	/* leased-address */
947 	if (mapContains(expr, "leased-address"))
948 		return "leased-address";
949 
950 	/* config-option */
951 	if (mapContains(expr, "config-option")) {
952 		struct element *arg;
953 		struct element *universe;
954 		struct element *name;
955 
956 		appendString(result, "config-option ");
957 		arg = mapGet(expr, "config-option");
958 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
959 			*lose = ISC_TRUE;
960 			appendString(result, "???");
961 			return result->content;
962 		}
963 		universe = mapGet(arg, "universe");
964 		if ((universe == NULL) || (universe->type != ELEMENT_STRING)) {
965 			*lose = ISC_TRUE;
966 			appendString(result, "???");
967 			return result->content;
968 		}
969 		concatString(result, stringValue(universe));
970 		appendString(result, ".");
971 		name = mapGet(arg, "name");
972 		if ((name == NULL) || (name->type != ELEMENT_STRING)) {
973 			*lose = ISC_TRUE;
974 			appendString(result, "???");
975 			return result->content;
976 		}
977 		concatString(result, stringValue(name));
978 		return result->content;
979 	}
980 
981 	/* null */
982 	if (mapContains(expr, "null"))
983 		return "null";
984 
985 	/* gethostname */
986 	if (mapContains(expr, "gethostname"))
987 		return "gethostname";
988 
989 	/* v6relay */
990 	if (mapContains(expr, "v6relay")) {
991 		struct element *arg;
992 		struct element *relay;
993 		struct element *option;
994 
995 
996 		appendString(result, "v6relay(");
997 		arg = mapGet(expr, "v6relay");
998 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
999 			*lose = ISC_TRUE;
1000 			appendString(result, "???" ")");
1001 			return result->content;
1002 		}
1003 		relay = mapGet(arg, "relay");
1004 		if (relay == NULL) {
1005 			*lose = ISC_TRUE;
1006 			appendString(result, "???" ")");
1007 			return result->content;
1008 		}
1009 		appendString(result, print_numeric_expression(relay, lose));
1010 		appendString(result, ", ");
1011 		option = mapGet(arg, "relay-option");
1012 		if (option == NULL) {
1013 			*lose = ISC_TRUE;
1014 			appendString(result, "???" ")");
1015 			return result->content;
1016 		}
1017 		appendString(result, print_data_expression(option, lose));
1018 		appendString(result, ")");
1019 		return result->content;
1020 	}
1021 
1022 	*lose = ISC_TRUE;
1023 	appendString(result, "???");
1024 	return result->content;
1025 }
1026 
1027 const char *
print_numeric_expression(struct element * expr,isc_boolean_t * lose)1028 print_numeric_expression(struct element *expr, isc_boolean_t *lose)
1029 {
1030 	struct string *result;
1031 
1032 	if (expr->type == ELEMENT_INTEGER) {
1033 		char buf[20];
1034 
1035 		snprintf(buf, sizeof(buf), "%lld", (long long)intValue(expr));
1036 		result = makeString(-1, buf);
1037 		return result->content;
1038 	}
1039 
1040 	/*
1041 	 * From is_numeric_expression
1042 	 */
1043 	if (expr->type != ELEMENT_MAP) {
1044 		*lose = ISC_TRUE;
1045 		return "???";
1046 	}
1047 	result = allocString();
1048 
1049 	/* extract-int8 */
1050 	if (mapContains(expr, "extract-int8")) {
1051 		struct element *arg;
1052 
1053 		appendString(result, "extract-int(");
1054 		arg = mapGet(expr, "extract-int8");
1055 		if (arg == NULL) {
1056 			*lose = ISC_TRUE;
1057 			appendString(result, "???, 8)");
1058 			return result->content;
1059 		}
1060 		appendString(result, print_data_expression(arg, lose));
1061 		appendString(result, ", 8)");
1062 		return result->content;
1063 	}
1064 
1065 	/* extract-int16 */
1066 	if (mapContains(expr, "extract-int16")) {
1067 		struct element *arg;
1068 
1069 		appendString(result, "extract-int(");
1070 		arg = mapGet(expr, "extract-int16");
1071 		if (arg == NULL) {
1072 			*lose = ISC_TRUE;
1073 			appendString(result, "???, 16)");
1074 			return result->content;
1075 		}
1076 		appendString(result, print_data_expression(arg, lose));
1077 		appendString(result, ", 16)");
1078 		return result->content;
1079 	}
1080 
1081 	/* extract-int32 */
1082 	if (mapContains(expr, "extract-int32")) {
1083 		struct element *arg;
1084 
1085 		appendString(result, "extract-int(");
1086 		arg = mapGet(expr, "extract-int32");
1087 		if (arg == NULL) {
1088 			*lose = ISC_TRUE;
1089 			appendString(result, "???, 32)");
1090 			return result->content;
1091 		}
1092 		appendString(result, print_data_expression(arg, lose));
1093 		appendString(result, ", 32)");
1094 		return result->content;
1095 	}
1096 
1097 	/* const-int */
1098 	if (mapContains(expr, "const-int")) {
1099 		struct element *arg;
1100 		char buf[20];
1101 
1102 		arg = mapGet(expr, "const-int");
1103 		if ((arg == NULL) || (arg->type != ELEMENT_INTEGER)) {
1104 			*lose = ISC_TRUE;
1105 			appendString(result, "???");
1106 			return result->content;
1107 		}
1108 		snprintf(buf, sizeof(buf), "%lld", (long long)intValue(arg));
1109 		result = makeString(-1, buf);
1110 		return result->content;
1111 	}
1112 
1113 	/* lease-time */
1114 	if (mapContains(expr, "lease-time"))
1115 		return "lease-time";
1116 
1117 	/* add */
1118 	if (mapContains(expr, "add")) {
1119 		struct element *arg;
1120 		struct element *left;
1121 		struct element *right;
1122 		isc_boolean_t add_parenthesis;
1123 
1124 		appendString(result, "add ");
1125 		arg = mapGet(expr, "add");
1126 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1127 			*lose = ISC_TRUE;
1128 			appendString(result, "???");
1129 			return result->content;
1130 		}
1131 		left = mapGet(arg, "left");
1132 		if (left == NULL) {
1133 			*lose = ISC_TRUE;
1134 			appendString(result, "???");
1135 			return result->content;
1136 		}
1137 		result = allocString();
1138 		add_parenthesis = ISC_TF(expr_precedence(expr_add,
1139 							 left) < 0);
1140 		if (add_parenthesis)
1141 			appendString(result, "(");
1142 		appendString(result, print_expression(left, lose));
1143 		if (add_parenthesis)
1144 			appendString(result, ")");
1145 		appendString(result, " + ");
1146 		right = mapGet(arg, "right");
1147 		if (right == NULL) {
1148 			*lose = ISC_TRUE;
1149 			appendString(result, "???");
1150 			return result->content;
1151 		}
1152 		add_parenthesis = ISC_TF(expr_precedence(expr_add,
1153 							 right) < 0);
1154 		if (add_parenthesis)
1155 			appendString(result, "(");
1156 		appendString(result, print_expression(right, lose));
1157 		if (add_parenthesis)
1158 			appendString(result, ")");
1159 		return result->content;
1160 	}
1161 
1162 	/* subtract */
1163 	if (mapContains(expr, "subtract")) {
1164 		struct element *arg;
1165 		struct element *left;
1166 		struct element *right;
1167 		isc_boolean_t add_parenthesis;
1168 
1169 		appendString(result, "subtract ");
1170 		arg = mapGet(expr, "subtract");
1171 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1172 			*lose = ISC_TRUE;
1173 			appendString(result, "???");
1174 			return result->content;
1175 		}
1176 		left = mapGet(arg, "left");
1177 		if (left == NULL) {
1178 			*lose = ISC_TRUE;
1179 			appendString(result, "???");
1180 			return result->content;
1181 		}
1182 		result = allocString();
1183 		add_parenthesis = ISC_TF(expr_precedence(expr_subtract,
1184 							 left) < 0);
1185 		if (add_parenthesis)
1186 			appendString(result, "(");
1187 		appendString(result, print_expression(left, lose));
1188 		if (add_parenthesis)
1189 			appendString(result, ")");
1190 		appendString(result, " - ");
1191 		right = mapGet(arg, "right");
1192 		if (right == NULL) {
1193 			*lose = ISC_TRUE;
1194 			appendString(result, "???");
1195 			return result->content;
1196 		}
1197 		add_parenthesis = ISC_TF(expr_precedence(expr_subtract,
1198 							 right) < 0);
1199 		if (add_parenthesis)
1200 			appendString(result, "(");
1201 		appendString(result, print_expression(right, lose));
1202 		if (add_parenthesis)
1203 			appendString(result, ")");
1204 		return result->content;
1205 	}
1206 
1207 	/* multiply */
1208 	if (mapContains(expr, "multiply")) {
1209 		struct element *arg;
1210 		struct element *left;
1211 		struct element *right;
1212 		isc_boolean_t add_parenthesis;
1213 
1214 		appendString(result, "multiply ");
1215 		arg = mapGet(expr, "multiply");
1216 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1217 			*lose = ISC_TRUE;
1218 			appendString(result, "???");
1219 			return result->content;
1220 		}
1221 		left = mapGet(arg, "left");
1222 		if (left == NULL) {
1223 			*lose = ISC_TRUE;
1224 			appendString(result, "???");
1225 			return result->content;
1226 		}
1227 		result = allocString();
1228 		add_parenthesis = ISC_TF(expr_precedence(expr_multiply,
1229 							 left) < 0);
1230 		if (add_parenthesis)
1231 			appendString(result, "(");
1232 		appendString(result, print_expression(left, lose));
1233 		if (add_parenthesis)
1234 			appendString(result, ")");
1235 		appendString(result, " * ");
1236 		right = mapGet(arg, "right");
1237 		if (right == NULL) {
1238 			*lose = ISC_TRUE;
1239 			appendString(result, "???");
1240 			return result->content;
1241 		}
1242 		add_parenthesis = ISC_TF(expr_precedence(expr_multiply,
1243 							 right) < 0);
1244 		if (add_parenthesis)
1245 			appendString(result, "(");
1246 		appendString(result, print_expression(right, lose));
1247 		if (add_parenthesis)
1248 			appendString(result, ")");
1249 		return result->content;
1250 	}
1251 
1252 	/* divide */
1253 	if (mapContains(expr, "divide")) {
1254 		struct element *arg;
1255 		struct element *left;
1256 		struct element *right;
1257 		isc_boolean_t add_parenthesis;
1258 
1259 		appendString(result, "divide ");
1260 		arg = mapGet(expr, "divide");
1261 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1262 			*lose = ISC_TRUE;
1263 			appendString(result, "???");
1264 			return result->content;
1265 		}
1266 		left = mapGet(arg, "left");
1267 		if (left == NULL) {
1268 			*lose = ISC_TRUE;
1269 			appendString(result, "???");
1270 			return result->content;
1271 		}
1272 		result = allocString();
1273 		add_parenthesis = ISC_TF(expr_precedence(expr_divide,
1274 							 left) < 0);
1275 		if (add_parenthesis)
1276 			appendString(result, "(");
1277 		appendString(result, print_expression(left, lose));
1278 		if (add_parenthesis)
1279 			appendString(result, ")");
1280 		appendString(result, " / ");
1281 		right = mapGet(arg, "right");
1282 		if (right == NULL) {
1283 			*lose = ISC_TRUE;
1284 			appendString(result, "???");
1285 			return result->content;
1286 		}
1287 		add_parenthesis = ISC_TF(expr_precedence(expr_divide,
1288 							 right) < 0);
1289 		if (add_parenthesis)
1290 			appendString(result, "(");
1291 		appendString(result, print_expression(right, lose));
1292 		if (add_parenthesis)
1293 			appendString(result, ")");
1294 		return result->content;
1295 	}
1296 
1297 	/* remainder */
1298 	if (mapContains(expr, "remainder")) {
1299 		struct element *arg;
1300 		struct element *left;
1301 		struct element *right;
1302 		isc_boolean_t add_parenthesis;
1303 
1304 		appendString(result, "remainder ");
1305 		arg = mapGet(expr, "remainder");
1306 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1307 			*lose = ISC_TRUE;
1308 			appendString(result, "???");
1309 			return result->content;
1310 		}
1311 		left = mapGet(arg, "left");
1312 		if (left == NULL) {
1313 			*lose = ISC_TRUE;
1314 			appendString(result, "???");
1315 			return result->content;
1316 		}
1317 		result = allocString();
1318 		add_parenthesis = ISC_TF(expr_precedence(expr_remainder,
1319 							 left) < 0);
1320 		if (add_parenthesis)
1321 			appendString(result, "(");
1322 		appendString(result, print_expression(left, lose));
1323 		if (add_parenthesis)
1324 			appendString(result, ")");
1325 		appendString(result, " % ");
1326 		right = mapGet(arg, "right");
1327 		if (right == NULL) {
1328 			*lose = ISC_TRUE;
1329 			appendString(result, "???");
1330 			return result->content;
1331 		}
1332 		add_parenthesis = ISC_TF(expr_precedence(expr_remainder,
1333 							 right) < 0);
1334 		if (add_parenthesis)
1335 			appendString(result, "(");
1336 		appendString(result, print_expression(right, lose));
1337 		if (add_parenthesis)
1338 			appendString(result, ")");
1339 		return result->content;
1340 	}
1341 
1342 	/* binary-and */
1343 	if (mapContains(expr, "binary-and")) {
1344 		struct element *arg;
1345 		struct element *left;
1346 		struct element *right;
1347 		isc_boolean_t add_parenthesis;
1348 
1349 		appendString(result, "binary-and ");
1350 		arg = mapGet(expr, "binary-and");
1351 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1352 			*lose = ISC_TRUE;
1353 			appendString(result, "???");
1354 			return result->content;
1355 		}
1356 		left = mapGet(arg, "left");
1357 		if (left == NULL) {
1358 			*lose = ISC_TRUE;
1359 			appendString(result, "???");
1360 			return result->content;
1361 		}
1362 		result = allocString();
1363 		add_parenthesis = ISC_TF(expr_precedence(expr_binary_and,
1364 							 left) < 0);
1365 		if (add_parenthesis)
1366 			appendString(result, "(");
1367 		appendString(result, print_expression(left, lose));
1368 		if (add_parenthesis)
1369 			appendString(result, ")");
1370 		appendString(result, " & ");
1371 		right = mapGet(arg, "right");
1372 		if (right == NULL) {
1373 			*lose = ISC_TRUE;
1374 			appendString(result, "???");
1375 			return result->content;
1376 		}
1377 		add_parenthesis = ISC_TF(expr_precedence(expr_binary_and,
1378 							 right) < 0);
1379 		if (add_parenthesis)
1380 			appendString(result, "(");
1381 		appendString(result, print_expression(right, lose));
1382 		if (add_parenthesis)
1383 			appendString(result, ")");
1384 		return result->content;
1385 	}
1386 
1387 	/* binary-or */
1388 	if (mapContains(expr, "binary-or")) {
1389 		struct element *arg;
1390 		struct element *left;
1391 		struct element *right;
1392 		isc_boolean_t add_parenthesis;
1393 
1394 		appendString(result, "binary-or ");
1395 		arg = mapGet(expr, "binary-or");
1396 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1397 			*lose = ISC_TRUE;
1398 			appendString(result, "???");
1399 			return result->content;
1400 		}
1401 		left = mapGet(arg, "left");
1402 		if (left == NULL) {
1403 			*lose = ISC_TRUE;
1404 			appendString(result, "???");
1405 			return result->content;
1406 		}
1407 		result = allocString();
1408 		add_parenthesis = ISC_TF(expr_precedence(expr_binary_or,
1409 							 left) < 0);
1410 		if (add_parenthesis)
1411 			appendString(result, "(");
1412 		appendString(result, print_expression(left, lose));
1413 		if (add_parenthesis)
1414 			appendString(result, ")");
1415 		appendString(result, " | ");
1416 		right = mapGet(arg, "right");
1417 		if (right == NULL) {
1418 			*lose = ISC_TRUE;
1419 			appendString(result, "???");
1420 			return result->content;
1421 		}
1422 		add_parenthesis = ISC_TF(expr_precedence(expr_binary_or,
1423 							 right) < 0);
1424 		if (add_parenthesis)
1425 			appendString(result, "(");
1426 		appendString(result, print_expression(right, lose));
1427 		if (add_parenthesis)
1428 			appendString(result, ")");
1429 		return result->content;
1430 	}
1431 
1432 	/* binary-xor */
1433 	if (mapContains(expr, "binary-xor")) {
1434 		struct element *arg;
1435 		struct element *left;
1436 		struct element *right;
1437 		isc_boolean_t add_parenthesis;
1438 
1439 		appendString(result, "binary-xor ");
1440 		arg = mapGet(expr, "binary-xor");
1441 		if ((arg == NULL) || (arg->type != ELEMENT_MAP)) {
1442 			*lose = ISC_TRUE;
1443 			appendString(result, "???");
1444 			return result->content;
1445 		}
1446 		left = mapGet(arg, "left");
1447 		if (left == NULL) {
1448 			*lose = ISC_TRUE;
1449 			appendString(result, "???");
1450 			return result->content;
1451 		}
1452 		result = allocString();
1453 		add_parenthesis = ISC_TF(expr_precedence(expr_binary_xor,
1454 							 left) < 0);
1455 		if (add_parenthesis)
1456 			appendString(result, "(");
1457 		appendString(result, print_expression(left, lose));
1458 		if (add_parenthesis)
1459 			appendString(result, ")");
1460 		appendString(result, " ^ ");
1461 		right = mapGet(arg, "right");
1462 		if (right == NULL) {
1463 			*lose = ISC_TRUE;
1464 			appendString(result, "???");
1465 			return result->content;
1466 		}
1467 		add_parenthesis = ISC_TF(expr_precedence(expr_binary_xor,
1468 							 right) < 0);
1469 		if (add_parenthesis)
1470 			appendString(result, "(");
1471 		appendString(result, print_expression(right, lose));
1472 		if (add_parenthesis)
1473 			appendString(result, ")");
1474 		return result->content;
1475 	}
1476 
1477 	/* client-state */
1478 	if (mapContains(expr, "client-state"))
1479 		return "client-state";
1480 
1481 	*lose = ISC_TRUE;
1482 	appendString(result, "???");
1483 	return result->content;
1484 }
1485 
1486 static void
debug(const char * fmt,...)1487 debug(const char* fmt, ...)
1488 {
1489 	va_list list;
1490 
1491 	va_start(list, fmt);
1492 	vfprintf(stderr, fmt, list);
1493 	fprintf(stderr, "\n");
1494 	va_end(list);
1495 }
1496