xref: /illumos-gate/usr/src/cmd/geniconvtbl/itmcomp.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <libgen.h>
31 #include <fcntl.h>
32 #include <locale.h>
33 #include <string.h>
34 #include <sys/wait.h>
35 #include <sys/param.h>
36 #include <stdarg.h>
37 #include <errno.h>
38 
39 #include "itmcomp.h"
40 #include "maptype.h"
41 
42 #if !defined(TEXT_DOMAIN)
43 #define	TEXT_DOMAIN	"SYS_TEST"
44 #endif
45 #define	ITMSUFFIX	".bt"
46 #define	ME_DEFAULT	"geniconvtbl"
47 #define	CPP_PATH	"/usr/lib/cpp"
48 
49 itmc_ref_t	*ref_first[ITMC_OBJ_LAST + 1];
50 itmc_ref_t	*ref_last[ITMC_OBJ_LAST + 1];
51 
52 itmc_name_t	*name_first;
53 itmc_name_t	*name_last;
54 
55 char		*itm_input_file;		/* referred in itm_comp.l */
56 char		*itm_output_file;
57 
58 cmd_opt_t	cmd_opt;
59 itm_num_t	name_id;
60 itm_num_t	reg_id;
61 
62 itmc_name_t	name_lookup_error;
63 int		error_deferred;
64 
65 char *itm_name_type_name[] = {
66 	"UNKNOWN",
67 	"ITM",
68 	"STRING",
69 	"DIRECTION",
70 	"CONDITION",
71 	"MAP",
72 	"OPERATION",
73 	"EXPRESSION",
74 	"DATA",
75 	"NAME",
76 	"RANGE",
77 	"REGISTER",
78 };
79 
80 
81 static void	usage(int status);
82 static int	cpp_opt_append(char	*opt, char	*arg);
83 static void	cpp_opt_trunc(int num);
84 static int	parse_opts(int argc, char	**argv);
85 static char	*prog_path_expand(const char	*base_name);
86 static void	map_name_type_append(char	*optarg);
87 static char	*map_type_name_str(itmc_map_type_t);
88 static char	*strdup_vital(const char *);
89 
90 #if defined(ENABLE_TRACE)
91 static void	trace_option(void);
92 #endif /* ENABLE_TRACE */
93 static FILE	*cpp_open(void);
94 static void	cpp_close(FILE		*fp);
95 static int	itm_compile(char	*file);
96 static void	wait_child(pid_t pid);
97 static int	fork_error(void);
98 
99 
100 
101 
102 int
103 main(int argc, char **argv)
104 {
105 	char	**pp;
106 	pid_t	pid;
107 
108 	(void) setlocale(LC_ALL, "");
109 
110 	(void) textdomain(TEXT_DOMAIN);
111 
112 	(void) parse_opts(argc, argv);
113 
114 #if defined(ENABLE_TRACE)
115 	trace_option();
116 #endif /* ENABLE_TRACE */
117 
118 	if (NULL != cmd_opt.disassemble) {
119 		disassemble(cmd_opt.disassemble);
120 	} else if (NULL == cmd_opt.input_file) {
121 		(void) itm_compile(NULL);
122 	} else {
123 		if (1 < cmd_opt.input_file_num) {
124 			for (pp = cmd_opt.input_file; *pp; pp++) {
125 				(void) printf("%s:\n", *pp);
126 				pid = fork();
127 				switch (pid) {
128 				case 0:
129 					exit(itm_compile(*pp));
130 					break;
131 				case -1:
132 					(void) fork_error();
133 					break;
134 				default:
135 					wait_child(pid);
136 				}
137 			}
138 		} else {
139 			(void) itm_compile(*(cmd_opt.input_file));
140 		}
141 	}
142 
143 	return (0);
144 }
145 
146 
147 static int
148 itm_compile(char *file)
149 {
150 	char	*cmd_line;
151 	char	*command;
152 	char	*p;
153 	size_t	length;
154 	FILE	*fp;
155 
156 	extern int	yyparse();
157 	extern FILE *yyin;
158 
159 	if (NULL == file) {
160 		itm_input_file = gettext("*stdin*");
161 	} else {
162 		if (0 != access(file, R_OK)) {
163 			int	e = errno;
164 			itm_error(gettext("%1$s: can not access %2$s: "),
165 			    cmd_opt.my_name, file);
166 			errno = e;
167 			PERROR(NULL);
168 			exit(ITMC_STATUS_CMD2);
169 		}
170 		itm_input_file = file;
171 	}
172 
173 	if ((NULL == cmd_opt.output_file) &&
174 	    (0 == cmd_opt.no_output)) {
175 		p = strrchr(file, '.');
176 		if (NULL == p) {
177 			length = strlen(file);
178 		} else {
179 			length = p - file;
180 		}
181 		itm_output_file = malloc_vital(length + 5);
182 		(void) memcpy(itm_output_file, file, length);
183 		(void) memcpy(itm_output_file + length, ITMSUFFIX, 5);
184 	} else {
185 		itm_output_file = cmd_opt.output_file;
186 	}
187 
188 	if (0 != cmd_opt.preprocess) {
189 		if (NULL == file) {
190 			fp = cpp_open();
191 			cmd_line = cmd_opt.preprocess;
192 		} else {
193 			(void) cpp_opt_append(file, NULL);
194 			fp = cpp_open();
195 			cpp_opt_trunc(1);
196 		}
197 		if (NULL == fp) {
198 			p = strchr(cmd_line, ' ');
199 			if (NULL == p) {
200 				length = strlen(cmd_line);
201 			} else {
202 				length = (p - cmd_line);
203 			}
204 			command = malloc_vital((sizeof (char)) * (length + 1));
205 			(void) memcpy(command, cmd_line, length);
206 			*(command + length) = '\0';
207 			PERROR(command);
208 			itm_error(gettext("%1$s: can not start "
209 			    "%2$s on %3$s\n"), cmd_opt.my_name, command,
210 			    itm_input_file);
211 			exit(ITMC_STATUS_SYS);
212 		} else {
213 			yyin = fp;
214 		}
215 
216 		(void) yyparse();
217 		if (NULL == cmd_opt.preprocess_specified) {
218 			cpp_close(fp);
219 		}
220 	} else {
221 		if ((NULL == file) || (0 != strcmp("-", file))) {
222 			yyin = stdin;
223 		} else {
224 			yyin = fopen(file, "r");
225 			if (NULL == yyin) {
226 				itm_error(gettext("%1$s: can not open %2$s\n"),
227 				    cmd_opt.my_name, itm_input_file);
228 				exit(ITMC_STATUS_CMD2);
229 			}
230 		}
231 		(void) yyparse();
232 		if (stdin != yyin) {
233 			(void) fclose(yyin);
234 		}
235 	}
236 
237 	return (ITMC_STATUS_SUCCESS);
238 }
239 
240 
241 
242 
243 static void
244 wait_child(pid_t pid)
245 {
246 	int	stat_loc;
247 	char *msgstr;
248 
249 	(void) waitpid(pid, &stat_loc, 0);
250 	if (WTERMSIG(stat_loc)) {
251 		if (WCOREDUMP(stat_loc)) {
252 			msgstr = gettext("signal received: %s, core dumped\n");
253 		} else {
254 			msgstr = gettext("signal received: %s\n");
255 		}
256 		itm_error(msgstr, strsignal(WTERMSIG(stat_loc)));
257 	}
258 }
259 
260 
261 static int
262 fork_error(void)
263 {
264 	PERROR(gettext("fork"));
265 	exit(ITMC_STATUS_SYS);
266 	return (0); /* never return */
267 }
268 
269 
270 
271 static int
272 parse_opts(int argc, char **argv)
273 {
274 	int		c;
275 	int		i;
276 	char		*p;
277 	int		error_num = 0;
278 
279 #ifdef YYDEBUG
280 	extern int	yydebug;
281 #endif /* YYDEBUG */
282 
283 	extern char	*optarg;
284 	extern int	optind;
285 
286 
287 	cmd_opt.my_name = basename(*(argv + 0));
288 	if ('\0' == *(cmd_opt.my_name)) {
289 		cmd_opt.my_name = ME_DEFAULT;
290 	}
291 
292 	cmd_opt.preprocess_default = CPP_PATH;
293 	cmd_opt.preprocess = cmd_opt.preprocess_default;
294 	cmd_opt.strip = 1; /* stripped by default */
295 	while ((c = getopt(argc, argv, "d:i:p:W:D:I:U:fnsM:lo:qX:h")) != EOF) {
296 		switch (c) {
297 		case 'd':
298 			cmd_opt.disassemble = optarg;
299 			break;
300 		case 'i':
301 			cmd_opt.interpreter = optarg;
302 			break;
303 		case 'p':
304 			if (NULL != cmd_opt.preprocess_specified) {
305 				(void) fprintf(stderr,
306 				gettext("multiple -p options are specified\n"));
307 				error_num += 1;
308 			}
309 			cmd_opt.preprocess_specified =
310 			    prog_path_expand(optarg);
311 			cmd_opt.preprocess = cmd_opt.preprocess_specified;
312 			if (NULL == cmd_opt.preprocess) {
313 				(void) fprintf(stderr,
314 				gettext("cannot find preprocessor \"%s\"\n"),
315 				    optarg);
316 				error_num += 1;
317 			}
318 			(void) cpp_opt_append(NULL, NULL);
319 			p = basename(optarg);
320 			if (NULL == p) {
321 				*(cmd_opt.cpp_opt + 0) = strdup_vital(optarg);
322 			} else {
323 				*(cmd_opt.cpp_opt + 0) = strdup_vital(p);
324 			}
325 			break;
326 		case 'W':
327 			if (cpp_opt_append(optarg, NULL)) {
328 				error_num += 1;
329 			}
330 			break;
331 		case 'I':
332 			if (cpp_opt_append("-I", optarg)) {
333 				error_num += 1;
334 			}
335 			break;
336 		case 'D':
337 			if (cpp_opt_append("-D", optarg)) {
338 				error_num += 1;
339 			}
340 			break;
341 		case 'U':
342 			if (cpp_opt_append("-U", optarg)) {
343 				error_num += 1;
344 			}
345 			break;
346 		case 'f':
347 			cmd_opt.force_overwrite = 1;
348 			break;
349 		case 'n':
350 			cmd_opt.no_output = 1;
351 			break;
352 		case 'M':
353 			map_name_type_append(optarg);
354 			break;
355 		case 'l':
356 			cmd_opt.large_table = 1;
357 			break;
358 		case 'o':
359 			cmd_opt.output_file = optarg;
360 			break;
361 		case 's':
362 			cmd_opt.strip = 0;
363 			break;
364 		case 'q':
365 			cmd_opt.quiet = 1;
366 			break;
367 #if defined(ENABLE_TRACE)
368 		case 'X':
369 			cmd_opt.trace = malloc_vital((sizeof (char)) * 128);
370 			(void) memset(cmd_opt.trace, 0, (sizeof (char)) * 128);
371 			for (p = optarg; *p; p++) {
372 				*(cmd_opt.trace + ((*p) & 0x007f)) = 1;
373 			}
374 #ifdef YYDEBUG
375 			if (TRACE('Y'))	yydebug = 1;
376 #endif /* YYDEBUG */
377 			break;
378 #endif /* ENABLE_TRACE */
379 		case 'h':
380 			usage(ITMC_STATUS_SUCCESS);
381 			break;
382 		default:
383 			usage(ITMC_STATUS_CMD);
384 		}
385 	}
386 
387 	if (optind < argc) {
388 		cmd_opt.input_file_num = (argc - optind);
389 		cmd_opt.input_file =
390 		    malloc_vital((sizeof (char *)) * (argc - optind + 1));
391 		*(cmd_opt.input_file + (argc - optind)) = NULL;
392 	}
393 
394 	for (i = 0; optind < argc; optind++, i++) {
395 		*(cmd_opt.input_file + i) = argv[optind];
396 	}
397 
398 	/* check conflict */
399 
400 	if ((1 < cmd_opt.input_file_num) && (NULL != cmd_opt.output_file)) {
401 		itm_error(gettext("use -o with single input file\n"));
402 		error_num++;
403 	}
404 
405 	if ((cmd_opt.input_file_num <= 0) &&
406 	    (NULL == cmd_opt.output_file) &&
407 	    (NULL == cmd_opt.disassemble) &&
408 	    (0 == cmd_opt.no_output)) {
409 		itm_error(gettext("output file is unnamed. "
410 		    "use -o to specify output file\n"));
411 		error_num++;
412 	}
413 
414 	if (cmd_opt.disassemble &&
415 	    (cmd_opt.interpreter ||
416 	    cmd_opt.cpp_opt ||
417 	    cmd_opt.preprocess_specified ||
418 	    cmd_opt.input_file ||
419 	    cmd_opt.force_overwrite ||
420 	    cmd_opt.no_output ||
421 	    cmd_opt.map_name_type ||
422 	    cmd_opt.large_table ||
423 	    cmd_opt.output_file)) {
424 		itm_error(gettext("-d may not be specified with "
425 		    "other options\n"));
426 		error_num++;
427 	}
428 
429 	if (error_num) {
430 		usage(ITMC_STATUS_CMD);
431 	}
432 
433 	/*
434 	 * do not move upward
435 	 * may conflict with -d option
436 	 */
437 	if ((NULL == cmd_opt.preprocess_specified) &&
438 	    (NULL != cmd_opt.preprocess_default)) {
439 		(void) cpp_opt_append(NULL, NULL);
440 		p = basename(cmd_opt.preprocess_default);
441 		if (NULL == p) {
442 			*(cmd_opt.cpp_opt + 0) =
443 			    strdup_vital(cmd_opt.preprocess_default);
444 		} else {
445 			*(cmd_opt.cpp_opt + 0) = strdup_vital(p);
446 		}
447 	}
448 	return (0);
449 }
450 
451 
452 static FILE *
453 cpp_open(void)
454 {
455 	pid_t	pid;
456 	int	filedes[2];
457 	int	i;
458 
459 	for (i = 0; i < cmd_opt.cpp_opt_num; i++) {
460 		TRACE_MESSAGE('C', ("%s\n", *(cmd_opt.cpp_opt + i)));
461 	}
462 
463 	if (pipe(filedes)) {
464 		PERROR(gettext("pipe"));
465 		itm_error(gettext("failed to open pipe\n"));
466 		exit(ITMC_STATUS_SYS);
467 	}
468 	pid = fork();
469 	if (pid == 0) {	/* child */
470 		(void) close(filedes[0]);
471 		(void) close(1);
472 		(void) dup2(filedes[1], 1);
473 		(void) execv(cmd_opt.preprocess, cmd_opt.cpp_opt);
474 		exit(0);
475 	} else if (pid == (pid_t)(-1)) {	/* error */
476 		return	(NULL);
477 	} else {
478 		(void) close(filedes[1]);
479 		return (fdopen(filedes[0], "r"));
480 	}
481 	return	(NULL); /* NEVER */
482 }
483 
484 
485 static int
486 cpp_opt_append(char	*opt, char	*arg)
487 {
488 	size_t	opt_len;
489 	size_t	arg_len;
490 	char	*new_opt;
491 	char	**new_opt_list;
492 
493 	opt_len = ((NULL == opt) ? 0 : strlen(opt));
494 	arg_len = ((NULL == arg) ? 0 : strlen(arg));
495 	if (0 < (opt_len + arg_len)) {
496 		new_opt = malloc_vital(opt_len + arg_len + 1);
497 		if (NULL != opt) {
498 			(void) memcpy(new_opt, opt, opt_len + 1);
499 		}
500 		if (NULL != arg) {
501 			(void) memcpy(new_opt + opt_len, arg, arg_len + 1);
502 		}
503 	} else {
504 		new_opt = NULL;
505 	}
506 
507 	if (0 == cmd_opt.cpp_opt_reserved) {
508 		cmd_opt.cpp_opt_reserved = 32;
509 		cmd_opt.cpp_opt = malloc_vital((sizeof (char *)) * 32);
510 		*(cmd_opt.cpp_opt + 0) = strdup_vital("cpp");
511 		cmd_opt.cpp_opt_num = 1;
512 	} else if ((cmd_opt.cpp_opt_reserved - 2) <= cmd_opt.cpp_opt_num) {
513 		cmd_opt.cpp_opt_reserved += 32;
514 		new_opt_list = malloc_vital((sizeof (char *)) *
515 		    cmd_opt.cpp_opt_reserved);
516 		(void) memcpy(new_opt_list, cmd_opt.cpp_opt,
517 		    (sizeof (char *)) * cmd_opt.cpp_opt_num);
518 		(void) memset(new_opt_list + cmd_opt.cpp_opt_num, 0, 32);
519 		free(cmd_opt.cpp_opt);
520 		cmd_opt.cpp_opt = new_opt_list;
521 	}
522 	if (NULL != new_opt) {
523 		*(cmd_opt.cpp_opt + cmd_opt.cpp_opt_num) = new_opt;
524 		cmd_opt.cpp_opt_num += 1;
525 	}
526 	return (0);
527 }
528 
529 
530 static void
531 cpp_opt_trunc(int num)
532 {
533 	if (cmd_opt.cpp_opt_num < num) {
534 		num = cmd_opt.cpp_opt_num;
535 	}
536 	for (; 0 < num; --num) {
537 		free(*(cmd_opt.cpp_opt + cmd_opt.cpp_opt_num - 1));
538 		--(cmd_opt.cpp_opt_num);
539 	}
540 }
541 
542 
543 static void
544 cpp_close(FILE *fp)
545 {
546 	(void) fclose(fp);
547 	(void) wait_child(0);
548 }
549 
550 
551 
552 
553 static char *
554 prog_path_expand(const char *base_name)
555 {
556 	size_t	base_len;
557 	size_t	dir_len;
558 	char	path[MAXPATHLEN];
559 	char	*p;
560 	char	*pe;
561 
562 	base_len = strlen(base_name);
563 	path[0] = '\0';
564 
565 	if (NULL != strchr(base_name, '/')) {
566 		if (0 == access(base_name, X_OK)) {
567 			return (strdup_vital(base_name));
568 		} else {
569 			return (NULL);
570 		}
571 	}
572 
573 	for (p = getenv("PATH"); p; ) {
574 		pe = strchr(p, ':');
575 		dir_len = ((NULL == pe) ? strlen(p) : (pe - p));
576 		(void) memcpy(path, p, dir_len);
577 		if ((0 != dir_len) &&
578 		    ('/' != path[dir_len - 1])) {
579 			path[dir_len] = '/';
580 			dir_len += 1;
581 		}
582 		if ((dir_len + base_len) < MAXPATHLEN) {
583 			(void) memcpy(path + dir_len, base_name, base_len + 1);
584 			if (0 == access(path, X_OK)) {
585 				return (strdup_vital(path));
586 			}
587 		}
588 		p = ((NULL == pe) ? NULL : (pe + 1));
589 	}
590 	return	(NULL);
591 }
592 
593 
594 static void
595 usage(int status)
596 {
597 	if (ITMC_STATUS_SUCCESS == status) {
598 		(void) fprintf(stdout,
599 		gettext("Usage: %1$s [-n] [-f] [-q]\n"
600 		    "	     [-p preprocessor] [-W argument]\n"
601 		    "	     [-Dname] [-Dname=def] [-Idirectory] [-Uname]\n"
602 		    "	     [file ...]\n	%2$s -h\n"),
603 		    cmd_opt.my_name, cmd_opt.my_name);
604 	} else {
605 		(void) itm_error(
606 		gettext("Usage: %1$s [-n] [-f] [-q]\n"
607 		    "	     [-p preprocessor] [-W argument]\n"
608 		    "	     [-Dname] [-Dname=def] [-Idirectory] [-Uname]\n"
609 		    "	     [file ...]\n	%2$s -h\n"),
610 		    cmd_opt.my_name, cmd_opt.my_name);
611 	}
612 	exit(status);
613 }
614 
615 
616 static char *
617 map_type_name_str(itmc_map_type_t type)
618 {
619 	int	i;
620 	for (i = 0; NULL != map_type_name[i].name; i++) {
621 		if (type == map_type_name[i].type) {
622 			return (map_type_name[i].name);
623 		}
624 	}
625 	return ("");
626 }
627 
628 static void
629 map_name_type_append(char *optarg)
630 {
631 	char			*oa;
632 	char			*oa_save;
633 	char			*name;
634 	char			*p;
635 	char			*phf;
636 	int			hash_factor = 0;
637 	itmc_map_type_t		type;
638 	itmc_map_name_type_t	*m;
639 	int			i;
640 
641 	oa = oa_save = strdup_vital(optarg);
642 
643 	while ((NULL != oa) && ('\0' != *oa)) {
644 		name = oa;
645 		oa = strchr(oa, ',');
646 		if (NULL != oa) {
647 			*(oa++) = '\0';
648 		}
649 		p = strchr(name, '=');
650 		if (NULL == p) {
651 			type = ITMC_MAP_AUTOMATIC;
652 		} else {
653 			*(p++) = '\0';
654 			if ('\0' == *p) {
655 				type = ITMC_MAP_AUTOMATIC;
656 			} else {
657 				phf = strchr(p, ':');
658 				if (NULL != phf) {
659 					*(phf++) = '\0';
660 					hash_factor = atoi(phf);
661 					if (hash_factor < 0) {
662 						itm_error(gettext("invalid "
663 						    "hash factor is "
664 						    "specified: %s\n"), phf);
665 						hash_factor = 0;
666 						error_deferred += 1;
667 					}
668 				}
669 				for (i = 0; NULL != map_type_name[i].name;
670 				    i++) {
671 					if (0 ==
672 					    strcmp(p, map_type_name[i].name)) {
673 						type = map_type_name[i].type;
674 						break;
675 					}
676 				}
677 				if (NULL == map_type_name[i].name) {
678 					itm_error(gettext("unknown map type "
679 					    "is specified: %s\n"), p);
680 					error_deferred += 1;
681 					continue;
682 				}
683 			}
684 		}
685 		if (0 == strcmp(name, "default")) {
686 			*name = '\0';
687 		}
688 		m = cmd_opt.map_name_type;
689 		if (NULL == m) {
690 			m = malloc_vital(sizeof (itmc_map_name_type_t));
691 			m->name = strdup_vital(name);
692 			m->type = type;
693 			m->hash_factor = hash_factor;
694 			m->next = NULL;
695 			cmd_opt.map_name_type = m;
696 			continue;
697 		}
698 		for (; ; m = m->next) {
699 			if (0 == strcmp(name, m->name)) {
700 				if (type == m->type) {
701 					m = NULL;
702 					break;
703 				}
704 				if ('\0' == *name) {
705 					itm_error(gettext("multiple default "
706 					    "types are specified:"
707 					    " \"%1$s\" and \"%2$s\"\n"),
708 					    map_type_name_str(type),
709 					    map_type_name_str(m->type));
710 				} else {
711 					itm_error(gettext("map \"%1$s\" is "
712 					    "specified as two types \"%2$s\" "
713 					    "and \"%3$s\"\n"), name,
714 					    map_type_name_str(type),
715 					    map_type_name_str(m->type));
716 				}
717 				error_deferred += 1;
718 				m = NULL;
719 				break;
720 			}
721 			if (NULL == m->next) {
722 				break;
723 			}
724 		}
725 		if (NULL != m) {
726 			m->next = malloc_vital(sizeof (itmc_map_name_type_t));
727 			m = m->next;
728 			m->name = strdup_vital(name);
729 			m->type = type;
730 			m->hash_factor = hash_factor;
731 			m->next = NULL;
732 
733 		}
734 	}
735 	free(oa_save);
736 }
737 
738 
739 
740 void *
741 malloc_vital(size_t size)
742 {
743 	void	*p;
744 
745 	TRACE_MESSAGE('M', ("malloc_vital: %d\n", size));
746 
747 	size = ITMROUNDUP(size);
748 
749 	p = (void*) malloc(size);
750 	if (NULL == p) {
751 		PERROR(gettext("malloc"));
752 		exit(ITMC_STATUS_SYS);
753 	}
754 
755 	(void) memset(p, 0, size);
756 
757 	return	(p);
758 }
759 
760 
761 static char *
762 strdup_vital(const char		*str)
763 {
764 	char	*p;
765 	size_t	len;
766 
767 	if (NULL == str) {
768 		return	(NULL);
769 	}
770 
771 	len = strlen(str) + 1;
772 	p = malloc_vital(len);
773 	(void) memcpy(p, str, len);
774 	return	(p);
775 }
776 
777 
778 
779 
780 
781 itm_data_t *
782 str_to_data(int size, char *seq)
783 {
784 	itm_data_t *data;
785 
786 	data = malloc_vital(sizeof (itm_data_t));
787 
788 	data->size = size;
789 	if (size <= sizeof (data->place)) {
790 		(void) memmove(&(data->place), seq, size);
791 	} else {
792 		data->place.itm_ptr = (itm_place2_t)malloc_vital(size);
793 		(void) memmove((char *)(data->place.itm_ptr), seq, size);
794 	}
795 
796 	return	(data);
797 }
798 
799 
800 char *
801 name_to_str(itm_data_t *name)
802 {
803 	static char	*ptr = NULL;
804 	static size_t	len = 0;
805 	size_t		req_len;
806 	char		*p;
807 
808 	if (NULL == name) {
809 		p = gettext("(no name)");
810 		req_len = strlen(p) + 1;
811 	} else {
812 		req_len = name->size + 1;
813 	}
814 
815 	if (len <= req_len) {
816 		len += 512;
817 		free(ptr);
818 		ptr = malloc_vital(len);
819 	}
820 
821 	if (NULL == name) {
822 		(void) memcpy(ptr, p, req_len);
823 		*(ptr + req_len) = '\0';
824 	} else if (name->size <= (sizeof (name->place))) {
825 		(void) memcpy(ptr, (char *)(&(name->place)), name->size);
826 		*(ptr + name->size) = '\0';
827 	} else {
828 		(void) memcpy(ptr, (char *)(name->place.itm_ptr), name->size);
829 		*(ptr + name->size) = '\0';
830 	}
831 
832 	return	(ptr);
833 }
834 
835 #define	ARGUMENTSMAX (8)
836 char *
837 data_to_hexadecimal(itm_data_t		*data)
838 {
839 	static int index = 0;
840 	static char	*ptr[ARGUMENTSMAX] = { NULL, NULL, NULL, NULL,
841 						NULL, NULL, NULL, NULL};
842 	static long	len[ARGUMENTSMAX] = { 0, 0, 0, 0, 0, 0, 0, 0};
843 	char		*hdp;
844 	char		*p;
845 	long		i;
846 	int		val;
847 	size_t		req_len;
848 
849 	if (ARGUMENTSMAX <= index) index = 0;
850 	req_len = (2 * data->size) + 1;
851 	if (len[index] <= req_len) {
852 		len[index] += 512;
853 		free(ptr[index]);
854 		ptr[index] = malloc_vital(len[index]);
855 	}
856 	hdp = ptr[index];
857 
858 	if (data->size <= (sizeof (itm_place_t))) {
859 		p = (char *)&(data->place);
860 	} else {
861 		p = (char *)(data->place.itm_ptr);
862 	}
863 
864 	for (i = 0; i < data->size; i++, p++) {
865 		val = ((*p & 0x00f0) >> 4);
866 		if ((0 <= val) && (val <= 9)) {
867 			*hdp = '0' + val;
868 		} else {
869 			*hdp = 'a' + val - 10;
870 		}
871 		hdp++;
872 
873 		val = (*p & 0x000f);
874 		if ((0 <= val) && (val <= 9)) {
875 			*hdp = '0' + val;
876 		} else {
877 			*hdp = 'a' + val - 10;
878 		}
879 		hdp++;
880 	}
881 	*hdp = '\0';
882 	return (ptr[index++]);
883 }
884 
885 
886 
887 
888 
889 void
890 itm_error(char *format, ...)
891 {
892 	va_list		ap;
893 	va_start(ap, format);
894 
895 	if (0 == cmd_opt.quiet) {
896 		(void) vfprintf(stderr, format, ap);
897 	}
898 	va_end(ap);
899 }
900 
901 #if defined(ENABLE_TRACE)
902 static void
903 trace_option(void)
904 {
905 	char **pp;
906 	int	i;
907 
908 	if (!(TRACE('o')))
909 		return;
910 
911 	itm_error("my_name	   = %s\n", cmd_opt.my_name);
912 	if (NULL == cmd_opt.input_file) {
913 		(void) fprintf(stdout, "input_file   = (stdin)\n");
914 	} else {
915 		for (pp = cmd_opt.input_file; *pp; pp++) {
916 			(void) fprintf(stdout, "input_file   = %s\n", *pp);
917 		}
918 	}
919 	itm_error("output_file  = %s\n",
920 	    cmd_opt.output_file ? cmd_opt.output_file : "(stdout)");
921 	itm_error("interpreter  = %s\n",
922 	    cmd_opt.interpreter ? cmd_opt.interpreter : "(default)");
923 	if (cmd_opt.cpp_opt) {
924 		itm_error("cpp_opt	   = %s\n", *(cmd_opt.cpp_opt));
925 		for (i = 1; i < cmd_opt.cpp_opt_num; i++) {
926 			itm_error("\t%s\n", *(cmd_opt.cpp_opt + i));
927 		}
928 	} else {
929 		itm_error("cpp_opt	   = %s\n", "(none)");
930 	}
931 	itm_error("preprocess_default = %s\n",
932 	    cmd_opt.preprocess_default ? cmd_opt.preprocess_default :
933 	    "(no)");
934 	itm_error("preprocess_specified = %s\n",
935 	    cmd_opt.preprocess_specified ? cmd_opt.preprocess_specified :
936 	    "(no)");
937 	itm_error("preprocess   = %s\n",
938 	    cmd_opt.preprocess ? cmd_opt.preprocess : "(no)");
939 	itm_error("disassemble  = %s\n",
940 	    cmd_opt.disassemble ? "yes" : "no");
941 	itm_error("map type	   =");
942 	if (NULL == cmd_opt.map_name_type) {
943 		itm_error("\n");
944 	} else {
945 		itmc_map_name_type_t *m;
946 		itm_error(" ");
947 		m = cmd_opt.map_name_type;
948 		itm_error("%s=%s",
949 		    (((NULL == m->name) || ('\0' == *(m->name))) ?
950 		    "default" : m->name),
951 		    map_type_name_str(m->type));
952 		if (0 != m->hash_factor) {
953 			itm_error(":%ld\n", m->hash_factor);
954 		} else {
955 			(void) fputc('\n', stderr);
956 		}
957 		for (m = m->next; NULL != m; m = m->next) {
958 			itm_error("		%s=%s",
959 			    (((NULL == m->name) || ('\0' == *(m->name))) ?
960 			    "default" : m->name),
961 			    map_type_name_str(m->type));
962 			if (0 != m->hash_factor) {
963 				itm_error(":%ld\n", m->hash_factor);
964 			} else {
965 				(void) fputc('\n', stderr);
966 			}
967 		}
968 	}
969 	itm_error("large table  = %s\n",
970 	    cmd_opt.large_table ? "true" : "false");
971 	itm_error("overwrite	   = %s\n",
972 	    cmd_opt.force_overwrite ? "true" : "false");
973 	itm_error("strip	      = %s\n",
974 	    cmd_opt.strip ? "true" : "false");
975 	itm_error("no_output	   = %s\n",
976 	    cmd_opt.no_output ? "true" : "false");
977 	itm_error("trace	      = ");
978 	if (NULL == cmd_opt.trace) {
979 		itm_error("(no)\n");
980 	} else {
981 		for (i = 0x21; i < 0x7f; i++) {
982 			if (TRACE(i)) {
983 				(void) fputc(i, stderr);
984 			}
985 		}
986 		(void) fputc('\n', stderr);
987 	}
988 }
989 #endif /* ENABLE_TRACE */
990 
991 #if defined(ENABLE_TRACE)
992 extern void
993 trace_message(char *format, ...)
994 {
995 	va_list	ap;
996 	va_start(ap, format);
997 
998 	(void) vfprintf(stderr, format, ap);
999 
1000 	va_end(ap);
1001 }
1002 #endif /* ENABLE_TRACE */
1003