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
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.
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]
23 * Copyright (c) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
37 #include <sys/param.h>
44 #if !defined(TEXT_DOMAIN)
45 #define TEXT_DOMAIN "SYS_TEST"
47 #define ITMSUFFIX ".bt"
48 #define ME_DEFAULT "geniconvtbl"
49 #define CPP_PATH "/usr/lib/cpp"
51 itmc_ref_t
*ref_first
[ITMC_OBJ_LAST
+ 1];
52 itmc_ref_t
*ref_last
[ITMC_OBJ_LAST
+ 1];
54 itmc_name_t
*name_first
;
55 itmc_name_t
*name_last
;
57 char *itm_input_file
; /* referred in itm_comp.l */
58 char *itm_output_file
;
64 itmc_name_t name_lookup_error
;
67 char *itm_name_type_name
[] = {
83 static void usage(int status
);
84 static int cpp_opt_append(char *opt
, char *arg
);
85 static void cpp_opt_trunc(int num
);
86 static int parse_opts(int argc
, char **argv
);
87 static char *prog_path_expand(const char *base_name
);
88 static void map_name_type_append(char *optarg
);
89 static char *map_type_name_str(itmc_map_type_t
);
90 static char *strdup_vital(const char *);
92 #if defined(ENABLE_TRACE)
93 static void trace_option(void);
94 #endif /* ENABLE_TRACE */
95 static FILE *cpp_open(void);
96 static void cpp_close(FILE *fp
);
97 static int itm_compile(char *file
);
98 static void wait_child(pid_t pid
);
99 static int fork_error(void);
105 main(int argc
, char **argv
)
110 (void) setlocale(LC_ALL
, "");
112 (void) textdomain(TEXT_DOMAIN
);
114 (void) parse_opts(argc
, argv
);
116 #if defined(ENABLE_TRACE)
118 #endif /* ENABLE_TRACE */
120 if (NULL
!= cmd_opt
.disassemble
) {
121 disassemble(cmd_opt
.disassemble
);
122 } else if (NULL
== cmd_opt
.input_file
) {
123 (void) itm_compile(NULL
);
125 if (1 < cmd_opt
.input_file_num
) {
126 for (pp
= cmd_opt
.input_file
; *pp
; pp
++) {
127 (void) printf("%s:\n", *pp
);
131 exit(itm_compile(*pp
));
141 (void) itm_compile(*(cmd_opt
.input_file
));
150 itm_compile(char *file
)
158 extern int yyparse();
162 itm_input_file
= gettext("*stdin*");
164 if (0 != access(file
, R_OK
)) {
167 gettext("%1$s: can not access %2$s: "),
168 cmd_opt
.my_name
, file
);
171 exit(ITMC_STATUS_CMD2
);
173 itm_input_file
= file
;
176 if ((NULL
== cmd_opt
.output_file
) &&
177 (0 == cmd_opt
.no_output
)) {
178 p
= strrchr(file
, '.');
180 length
= strlen(file
);
184 itm_output_file
= malloc_vital(length
+ 5);
185 (void) memcpy(itm_output_file
, file
, length
);
186 (void) memcpy(itm_output_file
+ length
, ITMSUFFIX
, 5);
188 itm_output_file
= cmd_opt
.output_file
;
191 if (0 != cmd_opt
.preprocess
) {
194 cmd_line
= cmd_opt
.preprocess
;
196 (void) cpp_opt_append(file
, NULL
);
201 p
= strchr(cmd_line
, ' ');
203 length
= strlen(cmd_line
);
205 length
= (p
- cmd_line
);
207 command
= malloc_vital((sizeof (char)) * (length
+ 1));
208 (void) memcpy(command
, cmd_line
, length
);
209 *(command
+ length
) = '\0';
212 gettext("%1$s: can not start %2$s on %3$s\n"),
213 cmd_opt
.my_name
, command
, itm_input_file
);
214 exit(ITMC_STATUS_SYS
);
220 if (NULL
== cmd_opt
.preprocess_specified
) {
224 if ((NULL
== file
) || (0 != strcmp("-", file
))) {
227 yyin
= fopen(file
, "r");
230 gettext("%1$s: can not open %2$s\n"),
231 cmd_opt
.my_name
, itm_input_file
);
232 exit(ITMC_STATUS_CMD2
);
241 return (ITMC_STATUS_SUCCESS
);
248 wait_child(pid_t pid
)
253 (void) waitpid(pid
, &stat_loc
, 0);
254 if (WTERMSIG(stat_loc
)) {
255 if (WCOREDUMP(stat_loc
)) {
256 msgstr
= gettext("signal received: %s, core dumped\n");
258 msgstr
= gettext("signal received: %s\n");
260 itm_error(msgstr
, strsignal(WTERMSIG(stat_loc
)));
268 PERROR(gettext("fork"));
269 exit(ITMC_STATUS_SYS
);
270 return (0); /* never return */
276 parse_opts(int argc
, char **argv
)
291 cmd_opt
.my_name
= basename(*(argv
+ 0));
292 if ('\0' == *(cmd_opt
.my_name
)) {
293 cmd_opt
.my_name
= ME_DEFAULT
;
296 cmd_opt
.preprocess_default
= CPP_PATH
;
297 cmd_opt
.preprocess
= cmd_opt
.preprocess_default
;
298 cmd_opt
.strip
= 1; /* stripped by default */
299 while ((c
= getopt(argc
, argv
, "d:i:p:W:D:I:U:fnsM:lo:qX:h")) != EOF
) {
302 cmd_opt
.disassemble
= optarg
;
305 cmd_opt
.interpreter
= optarg
;
308 if (NULL
!= cmd_opt
.preprocess_specified
) {
309 (void) fprintf(stderr
,
310 gettext("multiple -p options are specified\n"));
313 cmd_opt
.preprocess_specified
=
314 prog_path_expand(optarg
);
315 cmd_opt
.preprocess
= cmd_opt
.preprocess_specified
;
316 if (NULL
== cmd_opt
.preprocess
) {
317 (void) fprintf(stderr
,
318 gettext("cannot find preprocessor \"%s\"\n"),
322 (void) cpp_opt_append(NULL
, NULL
);
323 p
= basename(optarg
);
325 *(cmd_opt
.cpp_opt
+ 0) = strdup_vital(optarg
);
327 *(cmd_opt
.cpp_opt
+ 0) = strdup_vital(p
);
331 if (cpp_opt_append(optarg
, NULL
)) {
336 if (cpp_opt_append("-I", optarg
)) {
341 if (cpp_opt_append("-D", optarg
)) {
346 if (cpp_opt_append("-U", optarg
)) {
351 cmd_opt
.force_overwrite
= 1;
354 cmd_opt
.no_output
= 1;
357 map_name_type_append(optarg
);
360 cmd_opt
.large_table
= 1;
363 cmd_opt
.output_file
= optarg
;
371 #if defined(ENABLE_TRACE)
373 cmd_opt
.trace
= malloc_vital((sizeof (char)) * 128);
374 (void) memset(cmd_opt
.trace
, 0, (sizeof (char)) * 128);
375 for (p
= optarg
; *p
; p
++) {
376 *(cmd_opt
.trace
+ ((*p
) & 0x007f)) = 1;
379 if (TRACE('Y')) yydebug
= 1;
382 #endif /* ENABLE_TRACE */
384 usage(ITMC_STATUS_SUCCESS
);
387 usage(ITMC_STATUS_CMD
);
392 cmd_opt
.input_file_num
= (argc
- optind
);
394 malloc_vital((sizeof (char *)) *
395 (argc
- optind
+ 1));
396 *(cmd_opt
.input_file
+ (argc
- optind
)) = NULL
;
399 for (i
= 0; optind
< argc
; optind
++, i
++) {
400 *(cmd_opt
.input_file
+ i
) = argv
[optind
];
405 if ((1 < cmd_opt
.input_file_num
) && (NULL
!= cmd_opt
.output_file
)) {
406 itm_error(gettext("use -o with single input file\n"));
410 if ((cmd_opt
.input_file_num
<= 0) &&
411 (NULL
== cmd_opt
.output_file
) &&
412 (NULL
== cmd_opt
.disassemble
) &&
413 (0 == cmd_opt
.no_output
)) {
415 "output file is unnamed. "
416 "use -o to specify output file\n"));
420 if (cmd_opt
.disassemble
&&
421 (cmd_opt
.interpreter
||
423 cmd_opt
.preprocess_specified
||
424 cmd_opt
.input_file
||
425 cmd_opt
.force_overwrite
||
427 cmd_opt
.map_name_type
||
428 cmd_opt
.large_table
||
429 cmd_opt
.output_file
)) {
431 gettext("-d may not specified with other options\n"));
436 usage(ITMC_STATUS_CMD
);
441 * may conflict with -d option
443 if ((NULL
== cmd_opt
.preprocess_specified
) &&
444 (NULL
!= cmd_opt
.preprocess_default
)) {
445 (void) cpp_opt_append(NULL
, NULL
);
446 p
= basename(cmd_opt
.preprocess_default
);
448 *(cmd_opt
.cpp_opt
+ 0) =
449 strdup_vital(cmd_opt
.preprocess_default
);
451 *(cmd_opt
.cpp_opt
+ 0) = strdup_vital(p
);
465 for (i
= 0; i
< cmd_opt
.cpp_opt_num
; i
++) {
466 TRACE_MESSAGE('C', ("%s\n", *(cmd_opt
.cpp_opt
+ i
)));
470 PERROR(gettext("pipe"));
471 itm_error(gettext("failed to open pipe\n"));
472 exit(ITMC_STATUS_SYS
);
475 if (pid
== 0) { /* child */
476 (void) close(filedes
[0]);
478 (void) dup2(filedes
[1], 1);
479 (void) execv(cmd_opt
.preprocess
, cmd_opt
.cpp_opt
);
481 } else if (pid
== (pid_t
)(-1)) { /* error */
484 (void) close(filedes
[1]);
485 return (fdopen(filedes
[0], "r"));
487 return (NULL
); /* NEVER */
492 cpp_opt_append(char *opt
, char *arg
)
499 opt_len
= ((NULL
== opt
) ? 0 : strlen(opt
));
500 arg_len
= ((NULL
== arg
) ? 0 : strlen(arg
));
501 if (0 < (opt_len
+ arg_len
)) {
502 new_opt
= malloc_vital(opt_len
+ arg_len
+ 1);
504 (void) memcpy(new_opt
, opt
, opt_len
+ 1);
507 (void) memcpy(new_opt
+ opt_len
, arg
, arg_len
+ 1);
513 if (0 == cmd_opt
.cpp_opt_reserved
) {
514 cmd_opt
.cpp_opt_reserved
= 32;
515 cmd_opt
.cpp_opt
= malloc_vital((sizeof (char *)) * 32);
516 *(cmd_opt
.cpp_opt
+ 0) = "cpp";
517 cmd_opt
.cpp_opt_num
= 1;
518 } else if ((cmd_opt
.cpp_opt_reserved
- 2) <= cmd_opt
.cpp_opt_num
) {
519 cmd_opt
.cpp_opt_reserved
+= 32;
520 new_opt_list
= malloc_vital((sizeof (char *)) *
521 cmd_opt
.cpp_opt_reserved
);
522 (void) memcpy(new_opt_list
, cmd_opt
.cpp_opt
,
523 (sizeof (char *)) * cmd_opt
.cpp_opt_num
);
524 (void) memset(new_opt_list
+ cmd_opt
.cpp_opt_num
, 0, 32);
525 free(cmd_opt
.cpp_opt
);
526 cmd_opt
.cpp_opt
= new_opt_list
;
528 if (NULL
!= new_opt
) {
529 *(cmd_opt
.cpp_opt
+ cmd_opt
.cpp_opt_num
) = new_opt
;
530 cmd_opt
.cpp_opt_num
+= 1;
537 cpp_opt_trunc(int num
)
539 if (cmd_opt
.cpp_opt_num
< num
) {
540 num
= cmd_opt
.cpp_opt_num
;
542 for (; 0 < num
; --num
) {
543 free(cmd_opt
.cpp_opt
+ cmd_opt
.cpp_opt_num
);
544 --(cmd_opt
.cpp_opt_num
);
553 (void) wait_child(0);
560 prog_path_expand(const char *base_name
)
564 char path
[MAXPATHLEN
];
568 base_len
= strlen(base_name
);
571 if (NULL
!= strchr(base_name
, '/')) {
572 if (0 == access(base_name
, X_OK
)) {
573 return (strdup_vital(base_name
));
579 for (p
= getenv("PATH"); p
; ) {
581 dir_len
= ((NULL
== pe
) ? strlen(p
) : (pe
- p
));
582 (void) memcpy(path
, p
, dir_len
);
583 if ((0 != dir_len
) &&
584 ('/' != path
[dir_len
- 1])) {
588 if ((dir_len
+ base_len
) < MAXPATHLEN
) {
589 (void) memcpy(path
+ dir_len
, base_name
, base_len
+ 1);
590 if (0 == access(path
, X_OK
)) {
591 return (strdup_vital(path
));
594 p
= ((NULL
== pe
) ? NULL
: (pe
+ 1));
604 if (ITMC_STATUS_SUCCESS
== status
) {
605 (void) fprintf(stdout
,
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
);
613 gettext("Usage: %1$s [-n] [-f] [-q]\n"
614 " [-p preprocessor] [-W argument]\n"
615 " [-Dname] [-Dname=def] [-Idirectory] [-Uname]\n"
616 " [file ...]\n %2$s -h\n"),
617 cmd_opt
.my_name
, cmd_opt
.my_name
);
624 map_type_name_str(itmc_map_type_t type
)
627 for (i
= 0; NULL
!= map_type_name
[i
].name
; i
++) {
628 if (type
== map_type_name
[i
].type
) {
629 return (map_type_name
[i
].name
);
636 map_name_type_append(char *optarg
)
644 itmc_map_type_t type
;
645 itmc_map_name_type_t
*m
;
648 oa
= oa_save
= strdup_vital(optarg
);
650 while ((NULL
!= oa
) && ('\0' != *oa
)) {
652 oa
= strchr(oa
, ',');
656 p
= strchr(name
, '=');
658 type
= ITMC_MAP_AUTOMATIC
;
662 type
= ITMC_MAP_AUTOMATIC
;
664 phf
= strchr(p
, ':');
667 hash_factor
= atoi(phf
);
668 if (hash_factor
< 0) {
671 "invalid hash factor is "
679 NULL
!= map_type_name
[i
].name
; i
++) {
681 strcmp(p
, map_type_name
[i
].name
)) {
682 type
= map_type_name
[i
].type
;
686 if (NULL
== map_type_name
[i
].name
) {
689 "unknown map type is specified: %s\n"),
696 if (0 == strcmp(name
, "default")) {
699 m
= cmd_opt
.map_name_type
;
701 m
= malloc_vital(sizeof (itmc_map_name_type_t
));
702 m
->name
= strdup_vital(name
);
704 m
->hash_factor
= hash_factor
;
706 cmd_opt
.map_name_type
= m
;
709 for (; ; m
= m
->next
) {
710 if (0 == strcmp(name
, m
->name
)) {
711 if (type
== m
->type
) {
718 "multiple default types are specified:"
719 " \"%1$s\" and \"%2$s\"\n"),
720 map_type_name_str(type
),
721 map_type_name_str(m
->type
));
724 gettext("map \"%1$s\" is specified as "
725 "two types \"%2$s\" and \"%3$s\"\n"),
727 map_type_name_str(type
),
728 map_type_name_str(m
->type
));
734 if (NULL
== m
->next
) {
739 m
->next
= malloc_vital(sizeof (itmc_map_name_type_t
));
741 m
->name
= strdup_vital(name
);
743 m
->hash_factor
= hash_factor
;
754 malloc_vital(size_t size
)
758 TRACE_MESSAGE('M', ("malloc_vital: %d\n", size
));
760 size
= ITMROUNDUP(size
);
762 p
= (void*) malloc(size
);
764 PERROR(gettext("malloc"));
765 exit(ITMC_STATUS_SYS
);
768 (void) memset(p
, 0, size
);
775 strdup_vital(const char *str
)
784 len
= strlen(str
) + 1;
785 p
= malloc_vital(len
);
786 (void) memcpy(p
, str
, len
);
795 str_to_data(int size
, char *seq
)
799 data
= malloc_vital(sizeof (itm_data_t
));
802 if (size
<= sizeof (data
->place
)) {
803 (void) memmove(&(data
->place
), seq
, size
);
805 data
->place
.itm_ptr
= (itm_place2_t
)malloc_vital(size
);
806 (void) memmove((char *)(data
->place
.itm_ptr
), seq
, size
);
814 name_to_str(itm_data_t
*name
)
816 static char *ptr
= NULL
;
817 static size_t len
= 0;
822 p
= gettext("(no name)");
823 req_len
= strlen(p
) + 1;
825 req_len
= name
->size
+ 1;
828 if (len
<= req_len
) {
831 ptr
= malloc_vital(len
);
835 (void) memcpy(ptr
, p
, req_len
);
836 *(ptr
+ req_len
) = '\0';
837 } else if (name
->size
<= (sizeof (name
->place
))) {
838 (void) memcpy(ptr
, (char *)(&(name
->place
)), name
->size
);
839 *(ptr
+ name
->size
) = '\0';
841 (void) memcpy(ptr
, (char *)(name
->place
.itm_ptr
), name
->size
);
842 *(ptr
+ name
->size
) = '\0';
848 #define ARGUMENTSMAX (8)
850 data_to_hexadecimal(itm_data_t
*data
)
852 static int index
= 0;
853 static char *ptr
[ARGUMENTSMAX
] = { NULL
, NULL
, NULL
, NULL
,
854 NULL
, NULL
, NULL
, NULL
};
855 static long len
[ARGUMENTSMAX
] = { 0, 0, 0, 0, 0, 0, 0, 0};
862 if (ARGUMENTSMAX
<= index
) index
= 0;
863 req_len
= (2 * data
->size
) + 1;
864 if (len
[index
] <= req_len
) {
867 ptr
[index
] = malloc_vital(len
[index
]);
871 if (data
->size
<= (sizeof (itm_place_t
))) {
872 p
= (char *)&(data
->place
);
874 p
= (char *)(data
->place
.itm_ptr
);
877 for (i
= 0; i
< data
->size
; i
++, p
++) {
878 val
= ((*p
& 0x00f0) >> 4);
879 if ((0 <= val
) && (val
<= 9)) {
882 *hdp
= 'a' + val
- 10;
887 if ((0 <= val
) && (val
<= 9)) {
890 *hdp
= 'a' + val
- 10;
895 return (ptr
[index
++]);
903 itm_error(char *format
, ...)
906 va_start(ap
, format
);
908 if (0 == cmd_opt
.quiet
) {
909 (void) vfprintf(stderr
, format
, ap
);
914 #if defined(ENABLE_TRACE)
924 itm_error("my_name = %s\n", cmd_opt
.my_name
);
925 if (NULL
== cmd_opt
.input_file
) {
926 (void) fprintf(stdout
, "input_file = (stdin)\n");
928 for (pp
= cmd_opt
.input_file
; *pp
; pp
++) {
929 (void) fprintf(stdout
, "input_file = %s\n", *pp
);
932 itm_error("output_file = %s\n",
933 cmd_opt
.output_file
? cmd_opt
.output_file
: "(stdout)");
934 itm_error("interpreter = %s\n",
935 cmd_opt
.interpreter
? cmd_opt
.interpreter
: "(default)");
936 if (cmd_opt
.cpp_opt
) {
937 itm_error("cpp_opt = %s\n", *(cmd_opt
.cpp_opt
));
938 for (i
= 1; i
< cmd_opt
.cpp_opt_num
; i
++) {
939 itm_error("\t%s\n", *(cmd_opt
.cpp_opt
+ i
));
942 itm_error("cpp_opt = %s\n", "(none)");
944 itm_error("preprocess_default = %s\n",
945 cmd_opt
.preprocess_default
? cmd_opt
.preprocess_default
:
947 itm_error("preprocess_specified = %s\n",
948 cmd_opt
.preprocess_specified
? cmd_opt
.preprocess_specified
:
950 itm_error("preprocess = %s\n",
951 cmd_opt
.preprocess
? cmd_opt
.preprocess
: "(no)");
952 itm_error("disassemble = %s\n",
953 cmd_opt
.disassemble
? "yes" : "no");
954 itm_error("map type =");
955 if (NULL
== cmd_opt
.map_name_type
) {
958 itmc_map_name_type_t
*m
;
960 m
= cmd_opt
.map_name_type
;
962 (((NULL
== m
->name
) || ('\0' == *(m
->name
))) ?
963 "default" : m
->name
),
964 map_type_name_str(m
->type
));
965 if (0 != m
->hash_factor
) {
966 itm_error(":%ld\n", m
->hash_factor
);
968 (void) fputc('\n', stderr
);
970 for (m
= m
->next
; NULL
!= m
; m
= m
->next
) {
972 (((NULL
== m
->name
) || ('\0' == *(m
->name
))) ?
973 "default" : m
->name
),
974 map_type_name_str(m
->type
));
975 if (0 != m
->hash_factor
) {
976 itm_error(":%ld\n", m
->hash_factor
);
978 (void) fputc('\n', stderr
);
982 itm_error("large table = %s\n",
983 cmd_opt
.large_table
? "true" : "false");
984 itm_error("overwrite = %s\n",
985 cmd_opt
.force_overwrite
? "true" : "false");
986 itm_error("strip = %s\n",
987 cmd_opt
.strip
? "true" : "false");
988 itm_error("no_output = %s\n",
989 cmd_opt
.no_output
? "true" : "false");
990 itm_error("trace = ");
991 if (NULL
== cmd_opt
.trace
) {
994 for (i
= 0x21; i
< 0x7f; i
++) {
996 (void) fputc(i
, stderr
);
999 (void) fputc('\n', stderr
);
1002 #endif /* ENABLE_TRACE */
1004 #if defined(ENABLE_TRACE)
1006 trace_message(char *format
, ...)
1009 va_start(ap
, format
);
1011 (void) vfprintf(stderr
, format
, ap
);
1015 #endif /* ENABLE_TRACE */