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 "/opt/gcc/4.4.4/bin/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 *(cmd_opt
.cpp_opt
+ 0) = strdup_vital(optarg
);
326 if (cpp_opt_append(optarg
, NULL
)) {
331 if (cpp_opt_append("-I", optarg
)) {
336 if (cpp_opt_append("-D", optarg
)) {
341 if (cpp_opt_append("-U", optarg
)) {
346 cmd_opt
.force_overwrite
= 1;
349 cmd_opt
.no_output
= 1;
352 map_name_type_append(optarg
);
355 cmd_opt
.large_table
= 1;
358 cmd_opt
.output_file
= optarg
;
366 #if defined(ENABLE_TRACE)
368 cmd_opt
.trace
= malloc_vital((sizeof (char)) * 128);
369 (void) memset(cmd_opt
.trace
, 0, (sizeof (char)) * 128);
370 for (p
= optarg
; *p
; p
++) {
371 *(cmd_opt
.trace
+ ((*p
) & 0x007f)) = 1;
374 if (TRACE('Y')) yydebug
= 1;
377 #endif /* ENABLE_TRACE */
379 usage(ITMC_STATUS_SUCCESS
);
382 usage(ITMC_STATUS_CMD
);
387 cmd_opt
.input_file_num
= (argc
- optind
);
389 malloc_vital((sizeof (char *)) *
390 (argc
- optind
+ 1));
391 *(cmd_opt
.input_file
+ (argc
- optind
)) = NULL
;
394 for (i
= 0; optind
< argc
; optind
++, i
++) {
395 *(cmd_opt
.input_file
+ i
) = argv
[optind
];
400 if ((1 < cmd_opt
.input_file_num
) && (NULL
!= cmd_opt
.output_file
)) {
401 itm_error(gettext("use -o with single input file\n"));
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
)) {
410 "output file is unnamed. "
411 "use -o to specify output file\n"));
415 if (cmd_opt
.disassemble
&&
416 (cmd_opt
.interpreter
||
418 cmd_opt
.preprocess_specified
||
419 cmd_opt
.input_file
||
420 cmd_opt
.force_overwrite
||
422 cmd_opt
.map_name_type
||
423 cmd_opt
.large_table
||
424 cmd_opt
.output_file
)) {
426 gettext("-d may not specified with other options\n"));
431 usage(ITMC_STATUS_CMD
);
436 * may conflict with -d option
438 if ((NULL
== cmd_opt
.preprocess_specified
) &&
439 (NULL
!= cmd_opt
.preprocess_default
)) {
440 (void) cpp_opt_append(NULL
, NULL
);
441 *(cmd_opt
.cpp_opt
+ 0) =
442 strdup_vital(cmd_opt
.preprocess_default
);
455 for (i
= 0; i
< cmd_opt
.cpp_opt_num
; i
++) {
456 TRACE_MESSAGE('C', ("%s\n", *(cmd_opt
.cpp_opt
+ i
)));
460 PERROR(gettext("pipe"));
461 itm_error(gettext("failed to open pipe\n"));
462 exit(ITMC_STATUS_SYS
);
465 if (pid
== 0) { /* child */
466 (void) close(filedes
[0]);
468 (void) dup2(filedes
[1], 1);
469 (void) execv(cmd_opt
.preprocess
, cmd_opt
.cpp_opt
);
471 } else if (pid
== (pid_t
)(-1)) { /* error */
474 (void) close(filedes
[1]);
475 return (fdopen(filedes
[0], "r"));
477 return (NULL
); /* NEVER */
482 cpp_opt_append(char *opt
, char *arg
)
489 opt_len
= ((NULL
== opt
) ? 0 : strlen(opt
));
490 arg_len
= ((NULL
== arg
) ? 0 : strlen(arg
));
491 if (0 < (opt_len
+ arg_len
)) {
492 new_opt
= malloc_vital(opt_len
+ arg_len
+ 1);
494 (void) memcpy(new_opt
, opt
, opt_len
+ 1);
497 (void) memcpy(new_opt
+ opt_len
, arg
, arg_len
+ 1);
503 if (0 == cmd_opt
.cpp_opt_reserved
) {
504 cmd_opt
.cpp_opt_reserved
= 32;
505 cmd_opt
.cpp_opt
= malloc_vital((sizeof (char *)) * 32);
506 *(cmd_opt
.cpp_opt
+ 0) = cmd_opt
.preprocess
;
507 cmd_opt
.cpp_opt_num
= 1;
508 } else if ((cmd_opt
.cpp_opt_reserved
- 2) <= cmd_opt
.cpp_opt_num
) {
509 cmd_opt
.cpp_opt_reserved
+= 32;
510 new_opt_list
= malloc_vital((sizeof (char *)) *
511 cmd_opt
.cpp_opt_reserved
);
512 (void) memcpy(new_opt_list
, cmd_opt
.cpp_opt
,
513 (sizeof (char *)) * cmd_opt
.cpp_opt_num
);
514 (void) memset(new_opt_list
+ cmd_opt
.cpp_opt_num
, 0, 32);
515 free(cmd_opt
.cpp_opt
);
516 cmd_opt
.cpp_opt
= new_opt_list
;
518 if (NULL
!= new_opt
) {
519 *(cmd_opt
.cpp_opt
+ cmd_opt
.cpp_opt_num
) = new_opt
;
520 cmd_opt
.cpp_opt_num
+= 1;
527 cpp_opt_trunc(int num
)
529 if (cmd_opt
.cpp_opt_num
< num
) {
530 num
= cmd_opt
.cpp_opt_num
;
532 for (; 0 < num
; --num
) {
533 free(cmd_opt
.cpp_opt
+ cmd_opt
.cpp_opt_num
);
534 --(cmd_opt
.cpp_opt_num
);
543 (void) wait_child(0);
550 prog_path_expand(const char *base_name
)
554 char path
[MAXPATHLEN
];
558 base_len
= strlen(base_name
);
561 if (NULL
!= strchr(base_name
, '/')) {
562 if (0 == access(base_name
, X_OK
)) {
563 return (strdup_vital(base_name
));
569 for (p
= getenv("PATH"); p
; ) {
571 dir_len
= ((NULL
== pe
) ? strlen(p
) : (pe
- p
));
572 (void) memcpy(path
, p
, dir_len
);
573 if ((0 != dir_len
) &&
574 ('/' != path
[dir_len
- 1])) {
578 if ((dir_len
+ base_len
) < MAXPATHLEN
) {
579 (void) memcpy(path
+ dir_len
, base_name
, base_len
+ 1);
580 if (0 == access(path
, X_OK
)) {
581 return (strdup_vital(path
));
584 p
= ((NULL
== pe
) ? NULL
: (pe
+ 1));
594 if (ITMC_STATUS_SUCCESS
== status
) {
595 (void) fprintf(stdout
,
596 gettext("Usage: %1$s [-n] [-f] [-q]\n"
597 " [-p preprocessor] [-W argument]\n"
598 " [-Dname] [-Dname=def] [-Idirectory] [-Uname]\n"
599 " [file ...]\n %2$s -h\n"),
600 cmd_opt
.my_name
, cmd_opt
.my_name
);
603 gettext("Usage: %1$s [-n] [-f] [-q]\n"
604 " [-p preprocessor] [-W argument]\n"
605 " [-Dname] [-Dname=def] [-Idirectory] [-Uname]\n"
606 " [file ...]\n %2$s -h\n"),
607 cmd_opt
.my_name
, cmd_opt
.my_name
);
614 map_type_name_str(itmc_map_type_t type
)
617 for (i
= 0; NULL
!= map_type_name
[i
].name
; i
++) {
618 if (type
== map_type_name
[i
].type
) {
619 return (map_type_name
[i
].name
);
626 map_name_type_append(char *optarg
)
634 itmc_map_type_t type
;
635 itmc_map_name_type_t
*m
;
638 oa
= oa_save
= strdup_vital(optarg
);
640 while ((NULL
!= oa
) && ('\0' != *oa
)) {
642 oa
= strchr(oa
, ',');
646 p
= strchr(name
, '=');
648 type
= ITMC_MAP_AUTOMATIC
;
652 type
= ITMC_MAP_AUTOMATIC
;
654 phf
= strchr(p
, ':');
657 hash_factor
= atoi(phf
);
658 if (hash_factor
< 0) {
661 "invalid hash factor is "
669 NULL
!= map_type_name
[i
].name
; i
++) {
671 strcmp(p
, map_type_name
[i
].name
)) {
672 type
= map_type_name
[i
].type
;
676 if (NULL
== map_type_name
[i
].name
) {
679 "unknown map type is specified: %s\n"),
686 if (0 == strcmp(name
, "default")) {
689 m
= cmd_opt
.map_name_type
;
691 m
= malloc_vital(sizeof (itmc_map_name_type_t
));
692 m
->name
= strdup_vital(name
);
694 m
->hash_factor
= hash_factor
;
696 cmd_opt
.map_name_type
= m
;
699 for (; ; m
= m
->next
) {
700 if (0 == strcmp(name
, m
->name
)) {
701 if (type
== m
->type
) {
708 "multiple default types are specified:"
709 " \"%1$s\" and \"%2$s\"\n"),
710 map_type_name_str(type
),
711 map_type_name_str(m
->type
));
714 gettext("map \"%1$s\" is specified as "
715 "two types \"%2$s\" and \"%3$s\"\n"),
717 map_type_name_str(type
),
718 map_type_name_str(m
->type
));
724 if (NULL
== m
->next
) {
729 m
->next
= malloc_vital(sizeof (itmc_map_name_type_t
));
731 m
->name
= strdup_vital(name
);
733 m
->hash_factor
= hash_factor
;
744 malloc_vital(size_t size
)
748 TRACE_MESSAGE('M', ("malloc_vital: %d\n", size
));
750 size
= ITMROUNDUP(size
);
752 p
= (void*) malloc(size
);
754 PERROR(gettext("malloc"));
755 exit(ITMC_STATUS_SYS
);
758 (void) memset(p
, 0, size
);
765 strdup_vital(const char *str
)
774 len
= strlen(str
) + 1;
775 p
= malloc_vital(len
);
776 (void) memcpy(p
, str
, len
);
785 str_to_data(int size
, char *seq
)
789 data
= malloc_vital(sizeof (itm_data_t
));
792 if (size
<= sizeof (data
->place
)) {
793 (void) memmove(&(data
->place
), seq
, size
);
795 data
->place
.itm_ptr
= (itm_place2_t
)malloc_vital(size
);
796 (void) memmove((char *)(data
->place
.itm_ptr
), seq
, size
);
804 name_to_str(itm_data_t
*name
)
806 static char *ptr
= NULL
;
807 static size_t len
= 0;
812 p
= gettext("(no name)");
813 req_len
= strlen(p
) + 1;
815 req_len
= name
->size
+ 1;
818 if (len
<= req_len
) {
821 ptr
= malloc_vital(len
);
825 (void) memcpy(ptr
, p
, req_len
);
826 *(ptr
+ req_len
) = '\0';
827 } else if (name
->size
<= (sizeof (name
->place
))) {
828 (void) memcpy(ptr
, (char *)(&(name
->place
)), name
->size
);
829 *(ptr
+ name
->size
) = '\0';
831 (void) memcpy(ptr
, (char *)(name
->place
.itm_ptr
), name
->size
);
832 *(ptr
+ name
->size
) = '\0';
838 #define ARGUMENTSMAX (8)
840 data_to_hexadecimal(itm_data_t
*data
)
842 static int index
= 0;
843 static char *ptr
[ARGUMENTSMAX
] = { NULL
, NULL
, NULL
, NULL
,
844 NULL
, NULL
, NULL
, NULL
};
845 static long len
[ARGUMENTSMAX
] = { 0, 0, 0, 0, 0, 0, 0, 0};
852 if (ARGUMENTSMAX
<= index
) index
= 0;
853 req_len
= (2 * data
->size
) + 1;
854 if (len
[index
] <= req_len
) {
857 ptr
[index
] = malloc_vital(len
[index
]);
861 if (data
->size
<= (sizeof (itm_place_t
))) {
862 p
= (char *)&(data
->place
);
864 p
= (char *)(data
->place
.itm_ptr
);
867 for (i
= 0; i
< data
->size
; i
++, p
++) {
868 val
= ((*p
& 0x00f0) >> 4);
869 if ((0 <= val
) && (val
<= 9)) {
872 *hdp
= 'a' + val
- 10;
877 if ((0 <= val
) && (val
<= 9)) {
880 *hdp
= 'a' + val
- 10;
885 return (ptr
[index
++]);
893 itm_error(char *format
, ...)
896 va_start(ap
, format
);
898 if (0 == cmd_opt
.quiet
) {
899 (void) vfprintf(stderr
, format
, ap
);
904 #if defined(ENABLE_TRACE)
914 itm_error("my_name = %s\n", cmd_opt
.my_name
);
915 if (NULL
== cmd_opt
.input_file
) {
916 (void) fprintf(stdout
, "input_file = (stdin)\n");
918 for (pp
= cmd_opt
.input_file
; *pp
; pp
++) {
919 (void) fprintf(stdout
, "input_file = %s\n", *pp
);
922 itm_error("output_file = %s\n",
923 cmd_opt
.output_file
? cmd_opt
.output_file
: "(stdout)");
924 itm_error("interpreter = %s\n",
925 cmd_opt
.interpreter
? cmd_opt
.interpreter
: "(default)");
926 if (cmd_opt
.cpp_opt
) {
927 itm_error("cpp_opt = %s\n", *(cmd_opt
.cpp_opt
));
928 for (i
= 1; i
< cmd_opt
.cpp_opt_num
; i
++) {
929 itm_error("\t%s\n", *(cmd_opt
.cpp_opt
+ i
));
932 itm_error("cpp_opt = %s\n", "(none)");
934 itm_error("preprocess_default = %s\n",
935 cmd_opt
.preprocess_default
? cmd_opt
.preprocess_default
:
937 itm_error("preprocess_specified = %s\n",
938 cmd_opt
.preprocess_specified
? cmd_opt
.preprocess_specified
:
940 itm_error("preprocess = %s\n",
941 cmd_opt
.preprocess
? cmd_opt
.preprocess
: "(no)");
942 itm_error("disassemble = %s\n",
943 cmd_opt
.disassemble
? "yes" : "no");
944 itm_error("map type =");
945 if (NULL
== cmd_opt
.map_name_type
) {
948 itmc_map_name_type_t
*m
;
950 m
= cmd_opt
.map_name_type
;
952 (((NULL
== m
->name
) || ('\0' == *(m
->name
))) ?
953 "default" : m
->name
),
954 map_type_name_str(m
->type
));
955 if (0 != m
->hash_factor
) {
956 itm_error(":%ld\n", m
->hash_factor
);
958 (void) fputc('\n', stderr
);
960 for (m
= m
->next
; NULL
!= m
; m
= m
->next
) {
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
);
972 itm_error("large table = %s\n",
973 cmd_opt
.large_table
? "true" : "false");
974 itm_error("overwrite = %s\n",
975 cmd_opt
.force_overwrite
? "true" : "false");
976 itm_error("strip = %s\n",
977 cmd_opt
.strip
? "true" : "false");
978 itm_error("no_output = %s\n",
979 cmd_opt
.no_output
? "true" : "false");
980 itm_error("trace = ");
981 if (NULL
== cmd_opt
.trace
) {
984 for (i
= 0x21; i
< 0x7f; i
++) {
986 (void) fputc(i
, stderr
);
989 (void) fputc('\n', stderr
);
992 #endif /* ENABLE_TRACE */
994 #if defined(ENABLE_TRACE)
996 trace_message(char *format
, ...)
999 va_start(ap
, format
);
1001 (void) vfprintf(stderr
, format
, ap
);
1005 #endif /* ENABLE_TRACE */