+ bool code = FALSE;
+ size_t n;
+
+ if (needle != 0) {
+ for (n = 0; needle[n] != 0; n++) {
+ if (_nc_name_match(haystack, needle[n], "|")) {
+ code = TRUE;
+ break;
+ }
+ }
+ } else
+ code = TRUE;
+ return (code);
+}
+
+static FILE *
+open_tempfile(char *name)
+{
+ FILE *result = 0;
+#if HAVE_MKSTEMP
+ int fd = mkstemp(name);
+ if (fd >= 0)
+ result = fdopen(fd, "w");
+#else
+ if (tmpnam(name) != 0)
+ result = fopen(name, "w");
+#endif
+ return result;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char my_tmpname[PATH_MAX];
+ int v_opt = -1, debug_level;
+ int smart_defaults = TRUE;
+ char *termcap;
+ ENTRY *qp;
+
+ int this_opt, last_opt = '?';
+
+ int outform = F_TERMINFO; /* output format */
+ int sortmode = S_TERMINFO; /* sort_mode */
+
+ int width = 60;
+ bool formatted = FALSE; /* reformat complex strings? */
+ bool literal = FALSE; /* suppress post-processing? */
+ int numbers = 0; /* format "%'char'" to/from "%{number}" */
+ bool forceresolve = FALSE; /* force resolution */
+ bool limited = TRUE;
+ char *tversion = (char *) NULL;
+ const char *source_file = "terminfo";
+ char **namelst = 0;
+ char *outdir = (char *) NULL;
+ bool check_only = FALSE;
+ bool suppress_untranslatable = FALSE;
+
+ log_fp = stderr;
+
+ _nc_progname = _nc_rootname(argv[0]);
+
+ if ((infodump = same_program(_nc_progname, PROG_CAPTOINFO)) != FALSE) {
+ outform = F_TERMINFO;
+ sortmode = S_TERMINFO;
+ }
+ if ((capdump = same_program(_nc_progname, PROG_INFOTOCAP)) != FALSE) {
+ outform = F_TERMCAP;
+ sortmode = S_TERMCAP;
+ }
+#if NCURSES_XNAMES
+ use_extended_names(FALSE);
+#endif
+
+ /*
+ * Processing arguments is a little complicated, since someone made a
+ * design decision to allow the numeric values for -w, -v options to
+ * be optional.
+ */
+ while ((this_opt = getopt(argc, argv,
+ "0123456789CILNR:TUVace:fGgo:rstvwx")) != -1) {
+ if (isdigit(this_opt)) {
+ switch (last_opt) {
+ case 'v':
+ v_opt = (v_opt * 10) + (this_opt - '0');
+ break;
+ case 'w':
+ width = (width * 10) + (this_opt - '0');
+ break;
+ default:
+ if (this_opt != '1')
+ usage();
+ last_opt = this_opt;
+ width = 0;
+ }
+ continue;
+ }
+ switch (this_opt) {
+ case 'C':
+ capdump = TRUE;
+ outform = F_TERMCAP;
+ sortmode = S_TERMCAP;
+ break;
+ case 'I':
+ infodump = TRUE;
+ outform = F_TERMINFO;
+ sortmode = S_TERMINFO;
+ break;
+ case 'L':
+ infodump = TRUE;
+ outform = F_VARIABLE;
+ sortmode = S_VARIABLE;
+ break;
+ case 'N':
+ smart_defaults = FALSE;
+ literal = TRUE;
+ break;
+ case 'R':
+ tversion = optarg;
+ break;
+ case 'T':
+ limited = FALSE;
+ break;
+ case 'U':
+ literal = TRUE;
+ break;
+ case 'V':
+ puts(curses_version());
+ cleanup(namelst);
+ ExitProgram(EXIT_SUCCESS);
+ case 'c':
+ check_only = TRUE;
+ break;
+ case 'e':
+ namelst = make_namelist(optarg);
+ break;
+ case 'f':
+ formatted = TRUE;
+ break;
+ case 'G':
+ numbers = 1;
+ break;
+ case 'g':
+ numbers = -1;
+ break;
+ case 'o':
+ outdir = optarg;
+ break;
+ case 'r':
+ forceresolve = TRUE;
+ break;
+ case 's':
+ showsummary = TRUE;
+ break;
+ case 'v':
+ v_opt = 0;
+ break;
+ case 'w':
+ width = 0;
+ break;
+#if NCURSES_XNAMES
+ case 't':
+ _nc_disable_period = FALSE;
+ suppress_untranslatable = TRUE;
+ break;
+ case 'a':
+ _nc_disable_period = TRUE;
+ /* FALLTHRU */
+ case 'x':
+ use_extended_names(TRUE);
+ break;
+#endif
+ default:
+ usage();
+ }
+ last_opt = this_opt;
+ }
+
+ debug_level = (v_opt > 0) ? v_opt : (v_opt == 0);
+ set_trace_level(debug_level);
+
+ if (_nc_tracing) {
+ save_check_termtype = _nc_check_termtype2;
+ _nc_check_termtype2 = check_termtype;
+ }
+#if !HAVE_BIG_CORE
+ /*
+ * Aaargh! immedhook seriously hoses us!
+ *
+ * One problem with immedhook is it means we can't do -e. Problem
+ * is that we can't guarantee that for each terminal listed, all the
+ * terminals it depends on will have been kept in core for reference
+ * resolution -- in fact it's certain the primitive types at the end
+ * of reference chains *won't* be in core unless they were explicitly
+ * in the select list themselves.
+ */
+ if (namelst && (!infodump && !capdump)) {
+ (void) fprintf(stderr,
+ "Sorry, -e can't be used without -I or -C\n");
+ cleanup(namelst);
+ ExitProgram(EXIT_FAILURE);
+ }
+#endif /* HAVE_BIG_CORE */
+
+ if (optind < argc) {
+ source_file = argv[optind++];
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: Too many file names. Usage:\n\t%s %s",
+ _nc_progname,
+ _nc_progname,
+ usage_string);
+ ExitProgram(EXIT_FAILURE);
+ }
+ } else {
+ if (infodump == TRUE) {
+ /* captoinfo's no-argument case */
+ source_file = "/etc/termcap";
+ if ((termcap = getenv("TERMCAP")) != 0
+ && (namelst = make_namelist(getenv("TERM"))) != 0) {
+ if (access(termcap, F_OK) == 0) {
+ /* file exists */
+ source_file = termcap;
+ } else if ((tmp_fp = open_tempfile(strcpy(my_tmpname,
+ "/tmp/XXXXXX")))
+ != 0) {
+ source_file = my_tmpname;
+ fprintf(tmp_fp, "%s\n", termcap);
+ fclose(tmp_fp);
+ tmp_fp = open_input(source_file);
+ to_remove = source_file;
+ } else {
+ failed("tmpnam");
+ }
+ }
+ } else {
+ /* tic */
+ fprintf(stderr,
+ "%s: File name needed. Usage:\n\t%s %s",
+ _nc_progname,
+ _nc_progname,
+ usage_string);
+ cleanup(namelst);
+ ExitProgram(EXIT_FAILURE);
+ }
+ }
+
+ if (tmp_fp == 0)
+ tmp_fp = open_input(source_file);
+
+ if (infodump)
+ dump_init(tversion,
+ smart_defaults
+ ? outform
+ : F_LITERAL,
+ sortmode, width, debug_level, formatted);
+ else if (capdump)
+ dump_init(tversion,
+ outform,
+ sortmode, width, debug_level, FALSE);
+
+ /* parse entries out of the source file */
+ _nc_set_source(source_file);
+#if !HAVE_BIG_CORE
+ if (!(check_only || infodump || capdump))
+ _nc_set_writedir(outdir);
+#endif /* HAVE_BIG_CORE */
+ _nc_read_entry_source(tmp_fp, (char *) NULL,
+ !smart_defaults || literal, FALSE,
+ ((check_only || infodump || capdump)
+ ? NULLHOOK
+ : immedhook));
+
+ /* do use resolution */
+ if (check_only || (!infodump && !capdump) || forceresolve) {
+ if (!_nc_resolve_uses2(TRUE, literal) && !check_only) {
+ cleanup(namelst);
+ ExitProgram(EXIT_FAILURE);
+ }
+ }
+
+ /* length check */
+ if (check_only && (capdump || infodump)) {
+ for_entry_list(qp) {
+ if (matches(namelst, qp->tterm.term_names)) {
+ int len = fmt_entry(&qp->tterm, NULL, FALSE, TRUE, infodump, numbers);
+
+ if (len > (infodump ? MAX_TERMINFO_LENGTH : MAX_TERMCAP_LENGTH))
+ (void) fprintf(stderr,
+ "warning: resolved %s entry is %d bytes long\n",
+ _nc_first_name(qp->tterm.term_names),
+ len);
+ }
+ }
+ }
+
+ /* write or dump all entries */
+ if (!check_only) {
+ if (!infodump && !capdump) {
+ _nc_set_writedir(outdir);
+ for_entry_list(qp) {
+ if (matches(namelst, qp->tterm.term_names))
+ write_it(qp);
+ }
+ } else {
+ /* this is in case infotocap() generates warnings */
+ _nc_curr_col = _nc_curr_line = -1;
+
+ for_entry_list(qp) {
+ if (matches(namelst, qp->tterm.term_names)) {
+ int j = qp->cend - qp->cstart;
+ int len = 0;
+
+ /* this is in case infotocap() generates warnings */
+ _nc_set_type(_nc_first_name(qp->tterm.term_names));
+
+ (void) fseek(tmp_fp, qp->cstart, SEEK_SET);
+ while (j-- > 0) {
+ if (infodump)
+ (void) putchar(fgetc(tmp_fp));
+ else
+ put_translate(fgetc(tmp_fp));
+ }
+
+ repair_acsc(&qp->tterm);
+ dump_entry(&qp->tterm, suppress_untranslatable,
+ limited, numbers, NULL);
+ for (j = 0; j < (int) qp->nuses; j++)
+ dump_uses(qp->uses[j].name, !capdump);
+ len = show_entry();
+ if (debug_level != 0 && !limited)
+ printf("# length=%d\n", len);
+ }
+ }
+ if (!namelst && _nc_tail) {
+ int c, oldc = '\0';
+ bool in_comment = FALSE;
+ bool trailing_comment = FALSE;
+
+ (void) fseek(tmp_fp, _nc_tail->cend, SEEK_SET);
+ while ((c = fgetc(tmp_fp)) != EOF) {
+ if (oldc == '\n') {
+ if (c == '#') {
+ trailing_comment = TRUE;
+ in_comment = TRUE;
+ } else {
+ in_comment = FALSE;