=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/infocmp/infocmp.c,v retrieving revision 1.19 retrieving revision 1.20 diff -c -r1.19 -r1.20 *** src/usr.bin/infocmp/infocmp.c 2007/06/02 01:29:12 1.19 --- src/usr.bin/infocmp/infocmp.c 2010/01/12 23:22:13 1.20 *************** *** 1,7 **** ! /* $OpenBSD: infocmp.c,v 1.19 2007/06/02 01:29:12 pvalchev Exp $ */ /**************************************************************************** ! * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * --- 1,7 ---- ! /* $OpenBSD: infocmp.c,v 1.20 2010/01/12 23:22:13 nicm Exp $ */ /**************************************************************************** ! * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * *************** *** 31,54 **** /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * ****************************************************************************/ /* * infocmp.c -- decompile an entry, or compare two entries * written by Eric S. Raymond */ #include - #include #include ! MODULE_ID("$From: infocmp.c,v 1.60 2001/02/24 22:03:12 tom Exp $") #define L_CURL "{" #define R_CURL "}" - #define MAXTERMS 32 /* max # terminal arguments we can handle */ #define MAX_STRING 1024 /* maximum formatted string */ const char *_nc_progname = "infocmp"; --- 31,54 ---- /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* * infocmp.c -- decompile an entry, or compare two entries * written by Eric S. Raymond + * and Thomas E Dickey */ #include #include ! MODULE_ID("$Id: infocmp.c,v 1.20 2010/01/12 23:22:13 nicm Exp $") #define L_CURL "{" #define R_CURL "}" #define MAX_STRING 1024 /* maximum formatted string */ const char *_nc_progname = "infocmp"; *************** *** 62,73 **** * ***************************************************************************/ ! static char *tname[MAXTERMS]; /* terminal type names */ ! static ENTRY entries[MAXTERMS]; /* terminfo entries */ static int termcount; /* count of terminal entries */ static bool limited = TRUE; /* "-r" option is not set */ static bool quiet = FALSE; static const char *bool_sep = ":"; static const char *s_absent = "NULL"; static const char *s_cancel = "NULL"; --- 62,73 ---- * ***************************************************************************/ ! static ENTRY *entries; /* terminfo entries */ static int termcount; /* count of terminal entries */ static bool limited = TRUE; /* "-r" option is not set */ static bool quiet = FALSE; + static bool literal = FALSE; static const char *bool_sep = ":"; static const char *s_absent = "NULL"; static const char *s_cancel = "NULL"; *************** *** 89,104 **** #if NO_LEAKS #undef ExitProgram ! static void ! ExitProgram(int code) GCC_NORETURN; /* prototype is to get gcc to accept the noreturn attribute */ ! static void ! ExitProgram(int code) { while (termcount-- > 0) _nc_free_termtype(&entries[termcount].tterm); _nc_leaks_dump_entry(); ! _nc_free_and_exit(code); } #endif --- 89,104 ---- #if NO_LEAKS #undef ExitProgram ! static void ExitProgram(int code) GCC_NORETURN; /* prototype is to get gcc to accept the noreturn attribute */ ! static void ! ExitProgram(int code) { while (termcount-- > 0) _nc_free_termtype(&entries[termcount].tterm); _nc_leaks_dump_entry(); ! free(entries); ! _nc_free_tic(code); } #endif *************** *** 122,128 **** ***************************************************************************/ static int ! capcmp(int idx, const char *s, const char *t) /* capability comparison function */ { if (!VALID_STRING(s) && !VALID_STRING(t)) --- 122,128 ---- ***************************************************************************/ static int ! capcmp(PredIdx idx, const char *s, const char *t) /* capability comparison function */ { if (!VALID_STRING(s) && !VALID_STRING(t)) *************** *** 137,143 **** } static int ! use_predicate(int type, int idx) /* predicate function to use for use decompilation */ { ENTRY *ep; --- 137,143 ---- } static int ! use_predicate(unsigned type, PredIdx idx) /* predicate function to use for use decompilation */ { ENTRY *ep; *************** *** 223,229 **** useeq(ENTRY * e1, ENTRY * e2) /* are the use references in two entries equivalent? */ { ! int i, j; if (e1->nuses != e2->nuses) return (FALSE); --- 223,229 ---- useeq(ENTRY * e1, ENTRY * e2) /* are the use references in two entries equivalent? */ { ! unsigned i, j; if (e1->nuses != e2->nuses) return (FALSE); *************** *** 247,256 **** } static bool ! entryeq(TERMTYPE * t1, TERMTYPE * t2) /* are two entries equivalent? */ { ! int i; for (i = 0; i < NUM_BOOLEANS(t1); i++) if (t1->Booleans[i] != t2->Booleans[i]) --- 247,256 ---- } static bool ! entryeq(TERMTYPE *t1, TERMTYPE *t2) /* are two entries equivalent? */ { ! unsigned i; for (i = 0; i < NUM_BOOLEANS(t1); i++) if (t1->Booleans[i] != t2->Booleans[i]) *************** *** 261,267 **** return (FALSE); for (i = 0; i < NUM_STRINGS(t1); i++) ! if (capcmp(i, t1->Strings[i], t2->Strings[i])) return (FALSE); return (TRUE); --- 261,267 ---- return (FALSE); for (i = 0; i < NUM_STRINGS(t1); i++) ! if (capcmp((PredIdx) i, t1->Strings[i], t2->Strings[i])) return (FALSE); return (TRUE); *************** *** 270,279 **** #define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers) static void ! print_uses(ENTRY * ep, FILE * fp) /* print an entry's use references */ { ! int i; if (!ep->nuses) fputs("NULL", fp); --- 270,279 ---- #define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers) static void ! print_uses(ENTRY * ep, FILE *fp) /* print an entry's use references */ { ! unsigned i; if (!ep->nuses) fputs("NULL", fp); *************** *** 334,340 **** } static void ! compare_predicate(int type, int idx, const char *name) /* predicate function to use for entry difference reports */ { ENTRY *e1 = &entries[0]; --- 334,340 ---- } static void ! compare_predicate(PredType type, PredIdx idx, const char *name) /* predicate function to use for entry difference reports */ { ENTRY *e1 = &entries[0]; *************** *** 476,489 **** {"\033)A", "ISO UK G1"}, /* enable UK chars for G1 */ {"\033)B", "ISO US G1"}, /* enable US chars for G1 */ ! /* these are DEC private modes widely supported by emulators */ {"\033=", "DECPAM"}, /* application keypad mode */ {"\033>", "DECPNM"}, /* normal keypad mode */ {"\033<", "DECANSI"}, /* enter ANSI mode */ {(char *) 0, (char *) 0} }; static const assoc private_modes[] = /* DEC \E[ ... [hl] modes recognized by many emulators */ { --- 476,501 ---- {"\033)A", "ISO UK G1"}, /* enable UK chars for G1 */ {"\033)B", "ISO US G1"}, /* enable US chars for G1 */ ! /* these are DEC private controls widely supported by emulators */ {"\033=", "DECPAM"}, /* application keypad mode */ {"\033>", "DECPNM"}, /* normal keypad mode */ {"\033<", "DECANSI"}, /* enter ANSI mode */ + {"\033[!p", "DECSTR"}, /* soft reset */ + {"\033 F", "S7C1T"}, /* 7-bit controls */ {(char *) 0, (char *) 0} }; + static const assoc std_modes[] = + /* ECMA \E[ ... [hl] modes recognized by many emulators */ + { + {"2", "AM"}, /* keyboard action mode */ + {"4", "IRM"}, /* insert/replace mode */ + {"12", "SRM"}, /* send/receive mode */ + {"20", "LNM"}, /* linefeed mode */ + {(char *) 0, (char *) 0} + }; + static const assoc private_modes[] = /* DEC \E[ ... [hl] modes recognized by many emulators */ { *************** *** 534,556 **** {(char *) 0, (char *) 0} }; static void ! analyze_string(const char *name, const char *cap, TERMTYPE * tp) { - char buf[MAX_TERMINFO_LENGTH]; char buf2[MAX_TERMINFO_LENGTH]; ! const char *sp, *ep; const assoc *ap; if (cap == ABSENT_STRING || cap == CANCELLED_STRING) return; (void) printf("%s: ", name); - buf[0] = '\0'; for (sp = cap; *sp; sp++) { int i; size_t len = 0; const char *expansion = 0; /* first, check other capabilities in this entry */ for (i = 0; i < STRCOUNT; i++) { --- 546,627 ---- {(char *) 0, (char *) 0} }; + static int + skip_csi(const char *cap) + { + int result = 0; + if (cap[0] == '\033' && cap[1] == '[') + result = 2; + else if (UChar(cap[0]) == 0233) + result = 1; + return result; + } + + static bool + same_param(const char *table, const char *param, unsigned length) + { + bool result = FALSE; + if (strncmp(table, param, length) == 0) { + result = !isdigit(UChar(param[length])); + } + return result; + } + + static char * + lookup_params(const assoc * table, char *dst, char *src, size_t dstlen) + { + char *result = 0; + const char *ep = strtok(src, ";"); + + if (ep != 0) { + const assoc *ap; + + do { + bool found = FALSE; + + for (ap = table; ap->from; ap++) { + size_t tlen = strlen(ap->from); + + if (same_param(ap->from, ep, tlen)) { + (void) strlcat(dst, ap->to, dstlen); + found = TRUE; + break; + } + } + + if (!found) + (void) strlcat(dst, ep, dstlen); + (void) strlcat(dst, ";", dstlen); + } while + ((ep = strtok((char *) 0, ";"))); + + if (dst[0] != '\0' && dst[strlen(dst) - 1] == ';') + dst[strlen(dst) - 1] = '\0'; + + result = dst; + } + return result; + } + static void ! analyze_string(const char *name, const char *cap, TERMTYPE *tp) { char buf2[MAX_TERMINFO_LENGTH]; ! const char *sp; const assoc *ap; + int tp_lines = tp->Numbers[2]; if (cap == ABSENT_STRING || cap == CANCELLED_STRING) return; (void) printf("%s: ", name); for (sp = cap; *sp; sp++) { int i; + int csi; size_t len = 0; + size_t next; const char *expansion = 0; + char buf3[MAX_TERMINFO_LENGTH]; /* first, check other capabilities in this entry */ for (i = 0; i < STRCOUNT; i++) { *************** *** 588,706 **** } /* now check the standard capabilities */ ! if (!expansion) for (ap = std_caps; ap->from; ap++) { ! len = strlen(ap->from); ! if (strncmp(ap->from, sp, len) == 0) { expansion = ap->to; break; } } ! /* now check for private-mode sequences */ if (!expansion ! && sp[0] == '\033' && sp[1] == '[' && sp[2] == '?' ! && (len = strspn(sp + 3, "0123456789;")) ! && ((sp[3 + len] == 'h') || (sp[3 + len] == 'l'))) { ! char buf3[MAX_TERMINFO_LENGTH]; ! (void) strlcpy(buf2, (sp[3 + len] == 'h') ? "DEC+" : "DEC-", sizeof buf2); ! (void) strncpy(buf3, sp + 3, len); ! len += 4; buf3[len] = '\0'; ! ep = strtok(buf3, ";"); ! do { ! bool found = FALSE; ! for (ap = private_modes; ap->from; ap++) { ! size_t tlen = strlen(ap->from); ! if (strncmp(ap->from, ep, tlen) == 0) { ! (void) strlcat(buf2, ap->to, sizeof buf2); ! found = TRUE; ! break; ! } ! } ! if (!found) ! (void) strlcat(buf2, ep, sizeof buf2); ! (void) strlcat(buf2, ";", sizeof buf2); ! } while ! ((ep = strtok((char *) 0, ";"))); ! if (buf2[0] != '\0' && buf2[strlen(buf2) - 1] == ';') ! buf2[strlen(buf2) - 1] = '\0'; ! expansion = buf2; } /* now check for ECMA highlight sequences */ if (!expansion ! && sp[0] == '\033' && sp[1] == '[' ! && (len = strspn(sp + 2, "0123456789;")) ! && sp[2 + len] == 'm') { ! char buf3[MAX_TERMINFO_LENGTH]; (void) strlcpy(buf2, "SGR:", sizeof buf2); ! (void) strncpy(buf3, sp + 2, len); ! len += 3; buf3[len] = '\0'; ! ep = strtok(buf3, ";"); ! do { ! bool found = FALSE; ! for (ap = ecma_highlights; ap->from; ap++) { ! size_t tlen = strlen(ap->from); ! ! if (strncmp(ap->from, ep, tlen) == 0) { ! (void) strlcat(buf2, ap->to, sizeof buf2); ! found = TRUE; ! break; ! } ! } ! ! if (!found) ! (void) strlcat(buf2, ep, sizeof buf2); ! (void) strlcat(buf2, ";", sizeof buf2); ! } while ! ((ep = strtok((char *) 0, ";"))); ! ! if (buf2[0] != '\0' && buf2[strlen(buf2) - 1] == ';') ! buf2[strlen(buf2) - 1] = '\0'; expansion = buf2; } /* now check for scroll region reset */ ! if (!expansion) { ! (void) snprintf(buf2, sizeof buf2, "\033[1;%dr", tp->Numbers[2]); ! len = strlen(buf2); ! if (strncmp(buf2, sp, len) == 0) expansion = "RSR"; } /* now check for home-down */ ! if (!expansion) { ! (void) snprintf(buf2, sizeof buf2, "\033[%d;1H", tp->Numbers[2]); len = strlen(buf2); ! if (strncmp(buf2, sp, len) == 0) expansion = "LL"; } /* now look at the expansion we got, if any */ if (expansion) { ! (void) snprintf(buf + strlen(buf), sizeof buf - strlen(buf), ! "{%s}", expansion); sp += len - 1; - continue; } else { /* couldn't match anything */ buf2[0] = *sp; buf2[1] = '\0'; ! (void) strlcat(buf, TIC_EXPAND(buf2), sizeof buf); } } ! (void) printf("%s\n", buf); } /*************************************************************************** --- 659,786 ---- } /* now check the standard capabilities */ ! if (!expansion) { ! csi = skip_csi(sp); for (ap = std_caps; ap->from; ap++) { ! size_t adj = (size_t) (csi ? 2 : 0); ! len = strlen(ap->from); ! if (csi && skip_csi(ap->from) != csi) ! continue; ! if (len > adj ! && strncmp(ap->from + adj, sp + csi, len - adj) == 0) { expansion = ap->to; + len -= adj; + len += (size_t) csi; break; } } + } ! /* now check for standard-mode sequences */ if (!expansion ! && (csi = skip_csi(sp)) != 0 ! && (len = strspn(sp + csi, "0123456789;")) ! && (len < sizeof(buf3)) ! && (next = (size_t) csi + len) ! && ((sp[next] == 'h') || (sp[next] == 'l'))) { ! (void) strlcpy(buf2, (sp[next] == 'h') ? "ECMA+" : "ECMA-", sizeof buf2); ! (void) strncpy(buf3, sp + csi, len); buf3[len] = '\0'; + len += (size_t) csi + 1; ! expansion = lookup_params(std_modes, buf2, buf3, sizeof buf2); ! } ! /* now check for private-mode sequences */ ! if (!expansion ! && (csi = skip_csi(sp)) != 0 ! && sp[csi] == '?' ! && (len = strspn(sp + csi + 1, "0123456789;")) ! && (len < sizeof(buf3)) ! && (next = (size_t) csi + 1 + len) ! && ((sp[next] == 'h') || (sp[next] == 'l'))) { ! (void) strlcpy(buf2, (sp[next] == 'h') ? "DEC+" : "DEC-", ! sizeof buf2); ! (void) strncpy(buf3, sp + csi + 1, len); ! buf3[len] = '\0'; ! len += (size_t) csi + 2; ! expansion = lookup_params(private_modes, buf2, buf3, sizeof buf2); } /* now check for ECMA highlight sequences */ if (!expansion ! && (csi = skip_csi(sp)) != 0 ! && (len = strspn(sp + csi, "0123456789;")) != 0 ! && (len < sizeof(buf3)) ! && (next = (size_t) csi + len) ! && sp[next] == 'm') { (void) strlcpy(buf2, "SGR:", sizeof buf2); ! (void) strncpy(buf3, sp + csi, len); buf3[len] = '\0'; + len += (size_t) csi + 1; ! expansion = lookup_params(ecma_highlights, buf2, buf3, sizeof buf2); ! } ! if (!expansion ! && (csi = skip_csi(sp)) != 0 ! && sp[csi] == 'm') { ! len = (size_t) csi + 1; ! (void) strlcpy(buf2, "SGR:", sizeof buf2); ! strlcat(buf2, ecma_highlights[0].to, sizeof buf2); expansion = buf2; } + /* now check for scroll region reset */ ! if (!expansion ! && (csi = skip_csi(sp)) != 0) { ! if (sp[csi] == 'r') { expansion = "RSR"; + len = 1; + } else { + (void) snprintf(buf2, sizeof buf2, "1;%dr", tp_lines); + len = strlen(buf2); + if (strncmp(buf2, sp + csi, len) == 0) + expansion = "RSR"; + } + len += (size_t) csi; } /* now check for home-down */ ! if (!expansion ! && (csi = skip_csi(sp)) != 0) { ! (void) snprintf(buf2, sizeof buf2, "%d;1H", tp_lines); len = strlen(buf2); ! if (strncmp(buf2, sp + csi, len) == 0) { expansion = "LL"; + } else { + (void) snprintf(buf2, sizeof buf2, "%dH", tp_lines); + len = strlen(buf2); + if (strncmp(buf2, sp + csi, len) == 0) { + expansion = "LL"; + } + } + len += (size_t) csi; } /* now look at the expansion we got, if any */ if (expansion) { ! printf("{%s}", expansion); sp += len - 1; } else { /* couldn't match anything */ buf2[0] = *sp; buf2[1] = '\0'; ! fputs(TIC_EXPAND(buf2), stdout); } } ! putchar('\n'); } /*************************************************************************** *************** *** 719,724 **** --- 799,805 ---- ENTRY *qp, *rp; int i, n; + memset(heads, 0, sizeof(heads)); dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, itrace, FALSE); for (n = 0; n < argc && n < MAXCOMPARE; n++) { *************** *** 729,741 **** /* parse entries out of the source file */ _nc_set_source(argv[n]); ! _nc_read_entry_source(stdin, NULL, TRUE, FALSE, NULLHOOK); if (itrace) (void) fprintf(stderr, "Resolving file %d...\n", n - 0); /* maybe do use resolution */ ! if (!_nc_resolve_uses(!limited)) { (void) fprintf(stderr, "There are unresolved use entries in %s:\n", argv[n]); --- 810,822 ---- /* parse entries out of the source file */ _nc_set_source(argv[n]); ! _nc_read_entry_source(stdin, NULL, TRUE, literal, NULLHOOK); if (itrace) (void) fprintf(stderr, "Resolving file %d...\n", n - 0); /* maybe do use resolution */ ! if (!_nc_resolve_uses2(!limited, literal)) { (void) fprintf(stderr, "There are unresolved use entries in %s:\n", argv[n]); *************** *** 745,751 **** (void) fputc('\n', stderr); } } ! exit(EXIT_FAILURE); } heads[filecount] = _nc_head; --- 826,832 ---- (void) fputc('\n', stderr); } } ! ExitProgram(EXIT_FAILURE); } heads[filecount] = _nc_head; *************** *** 862,868 **** case C_DIFFERENCE: if (itrace) (void) fprintf(stderr, ! "infocmp: dumping differences\n"); (void) printf("comparing %s to %s.\n", name1, name2); compare_entry(compare_predicate, &entries->tterm, quiet); break; --- 943,950 ---- case C_DIFFERENCE: if (itrace) (void) fprintf(stderr, ! "%s: dumping differences\n", ! _nc_progname); (void) printf("comparing %s to %s.\n", name1, name2); compare_entry(compare_predicate, &entries->tterm, quiet); break; *************** *** 870,876 **** case C_COMMON: if (itrace) (void) fprintf(stderr, ! "infocmp: dumping common capabilities\n"); (void) printf("comparing %s to %s.\n", name1, name2); compare_entry(compare_predicate, &entries->tterm, quiet); break; --- 952,959 ---- case C_COMMON: if (itrace) (void) fprintf(stderr, ! "%s: dumping common capabilities\n", ! _nc_progname); (void) printf("comparing %s to %s.\n", name1, name2); compare_entry(compare_predicate, &entries->tterm, quiet); break; *************** *** 878,884 **** case C_NAND: if (itrace) (void) fprintf(stderr, ! "infocmp: dumping differences\n"); (void) printf("comparing %s to %s.\n", name1, name2); compare_entry(compare_predicate, &entries->tterm, quiet); break; --- 961,968 ---- case C_NAND: if (itrace) (void) fprintf(stderr, ! "%s: dumping differences\n", ! _nc_progname); (void) printf("comparing %s to %s.\n", name1, name2); compare_entry(compare_predicate, &entries->tterm, quiet); break; *************** *** 904,909 **** --- 988,994 ---- ," -L use long names" ," -R subset (see manpage)" ," -T eliminate size limits (test)" + ," -U eliminate post-processing of entries" ," -V print version" #if NCURSES_XNAMES ," -a with -F, list commented-out caps" *************** *** 923,931 **** --- 1008,1022 ---- ," -r with -C, output in termcap form" ," -r with -F, resolve use-references" ," -s [d|i|l|c] sort fields" + #if NCURSES_XNAMES + ," -t suppress commented-out capabilities" + #endif ," -u produce source with 'use='" ," -v number (verbose)" ," -w number (width)" + #if NCURSES_XNAMES + ," -x treat unknown capabilities as user-defined" + #endif }; const size_t first = 3; const size_t last = SIZEOF(tbl); *************** *** 939,976 **** else fprintf(stderr, "%s\n", tbl[n]); } ! exit(EXIT_FAILURE); } static char * ! name_initializer(const char *type) { static char *initializer; static size_t len; char *s; if (initializer == 0) { ! len = strlen(entries->tterm.term_names) + 20; initializer = (char *) malloc(len); } ! (void) snprintf(initializer, len, "%s_data_%s", type, entries->tterm.term_names); for (s = initializer; *s != 0 && *s != '|'; s++) { ! if (!isalnum(CharOf(*s))) *s = '_'; } *s = 0; return initializer; } /* dump C initializers for the terminal type */ static void ! dump_initializers(TERMTYPE * term) { ! int n; const char *str = 0; - int size; (void) printf("static char %s[] = %s\n", name_initializer("bool"), L_CURL); for_each_boolean(n, term) { --- 1030,1110 ---- else fprintf(stderr, "%s\n", tbl[n]); } ! ExitProgram(EXIT_FAILURE); } static char * ! any_initializer(const char *fmt, const char *type) { static char *initializer; static size_t len; char *s; if (initializer == 0) { ! len = strlen(entries->tterm.term_names) + strlen(type) + strlen(fmt); initializer = (char *) malloc(len); } ! (void) strlcpy(initializer, entries->tterm.term_names, len); for (s = initializer; *s != 0 && *s != '|'; s++) { ! if (!isalnum(UChar(*s))) *s = '_'; } *s = 0; + (void) snprintf(s, len - (s - initializer), fmt, type); return initializer; } + static char * + name_initializer(const char *type) + { + return any_initializer("_%s_data", type); + } + + static char * + string_variable(const char *type) + { + return any_initializer("_s_%s", type); + } + /* dump C initializers for the terminal type */ static void ! dump_initializers(TERMTYPE *term) { ! unsigned n; const char *str = 0; + printf("\nstatic char %s[] = \"%s\";\n\n", + name_initializer("alias"), entries->tterm.term_names); + + for_each_string(n, term) { + char buf[MAX_STRING], *sp, *tp; + + if (VALID_STRING(term->Strings[n])) { + tp = buf; + *tp++ = '"'; + for (sp = term->Strings[n]; + *sp != 0 && (tp - buf) < MAX_STRING - 6; + sp++) { + if (isascii(UChar(*sp)) + && isprint(UChar(*sp)) + && *sp != '\\' + && *sp != '"') + *tp++ = *sp; + else { + (void) snprintf(tp, buf + sizeof buf - tp, "\\%03o", + UChar(*sp)); + tp += strlen(tp); + } + } + *tp++ = '"'; + *tp = '\0'; + (void) printf("static char %-20s[] = %s;\n", + string_variable(ExtStrname(term, n, strnames)), buf); + } + } + printf("\n"); + (void) printf("static char %s[] = %s\n", name_initializer("bool"), L_CURL); for_each_boolean(n, term) { *************** *** 991,997 **** str = "CANCELLED_BOOLEAN"; break; } ! (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtBoolname(term, n, boolnames), str); } (void) printf("%s;\n", R_CURL); --- 1125,1131 ---- str = "CANCELLED_BOOLEAN"; break; } ! (void) printf("\t/* %3u: %-8s */\t%s,\n", n, ExtBoolname(term, n, boolnames), str); } (void) printf("%s;\n", R_CURL); *************** *** 1012,1075 **** str = buf; break; } ! (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtNumname(term, n, numnames), str); } (void) printf("%s;\n", R_CURL); - size = sizeof(TERMTYPE) - + (NUM_BOOLEANS(term) * sizeof(term->Booleans[0])) - + (NUM_NUMBERS(term) * sizeof(term->Numbers[0])); - (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL); for_each_string(n, term) { - char buf[MAX_STRING], *sp, *tp; if (term->Strings[n] == ABSENT_STRING) str = "ABSENT_STRING"; else if (term->Strings[n] == CANCELLED_STRING) str = "CANCELLED_STRING"; else { ! tp = buf; ! *tp++ = '"'; ! for (sp = term->Strings[n]; ! *sp != 0 && (tp - buf) < MAX_STRING - 6; ! sp++) { ! if (isascii(CharOf(*sp)) ! && isprint(CharOf(*sp)) ! && *sp != '\\' ! && *sp != '"') ! *tp++ = *sp; ! else { ! (void) snprintf(tp, buf + sizeof buf - tp, "\\%03o", CharOf(*sp)); ! tp += strlen(tp); ! } ! } ! *tp++ = '"'; ! *tp = '\0'; ! size += (strlen(term->Strings[n]) + 1); ! str = buf; } ! #if NCURSES_XNAMES ! if (n == STRCOUNT) { ! (void) printf("%s;\n", R_CURL); ! ! (void) printf("static char * %s[] = %s\n", ! name_initializer("string_ext"), L_CURL); ! } ! #endif ! (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtStrname(term, n, strnames), str); } (void) printf("%s;\n", R_CURL); } /* dump C initializers for the terminal type */ static void ! dump_termtype(TERMTYPE * term) { ! (void) printf("\t%s\n\t\t\"%s\",\n", L_CURL, term->term_names); (void) printf("\t\t(char *)0,\t/* pointer to string table */\n"); (void) printf("\t\t%s,\n", name_initializer("bool")); --- 1146,1200 ---- str = buf; break; } ! (void) printf("\t/* %3u: %-8s */\t%s,\n", n, ExtNumname(term, n, numnames), str); } (void) printf("%s;\n", R_CURL); (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL); for_each_string(n, term) { if (term->Strings[n] == ABSENT_STRING) str = "ABSENT_STRING"; else if (term->Strings[n] == CANCELLED_STRING) str = "CANCELLED_STRING"; else { ! str = string_variable(ExtStrname(term, n, strnames)); } ! (void) printf("\t/* %3u: %-8s */\t%s,\n", n, ExtStrname(term, n, strnames), str); } (void) printf("%s;\n", R_CURL); + + #if NCURSES_XNAMES + if ((NUM_BOOLEANS(term) != BOOLCOUNT) + || (NUM_NUMBERS(term) != NUMCOUNT) + || (NUM_STRINGS(term) != STRCOUNT)) { + (void) printf("static char * %s[] = %s\n", + name_initializer("string_ext"), L_CURL); + for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) { + (void) printf("\t/* %3u: bool */\t\"%s\",\n", + n, ExtBoolname(term, n, boolnames)); + } + for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) { + (void) printf("\t/* %3u: num */\t\"%s\",\n", + n, ExtNumname(term, n, numnames)); + } + for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) { + (void) printf("\t/* %3u: str */\t\"%s\",\n", + n, ExtStrname(term, n, strnames)); + } + (void) printf("%s;\n", R_CURL); + } + #endif } /* dump C initializers for the terminal type */ static void ! dump_termtype(TERMTYPE *term) { ! (void) printf("\t%s\n\t\t%s,\n", L_CURL, name_initializer("alias")); (void) printf("\t\t(char *)0,\t/* pointer to string table */\n"); (void) printf("\t\t%s,\n", name_initializer("bool")); *************** *** 1081,1087 **** (void) printf("#if NCURSES_XNAMES\n"); (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n"); (void) printf("\t\t%s,\t/* ...corresponding names */\n", ! (NUM_STRINGS(term) != STRCOUNT) ? name_initializer("string_ext") : "(char **)0"); --- 1206,1214 ---- (void) printf("#if NCURSES_XNAMES\n"); (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n"); (void) printf("\t\t%s,\t/* ...corresponding names */\n", ! ((NUM_BOOLEANS(term) != BOOLCOUNT) ! || (NUM_NUMBERS(term) != NUMCOUNT) ! || (NUM_STRINGS(term) != STRCOUNT)) ? name_initializer("string_ext") : "(char **)0"); *************** *** 1097,1102 **** --- 1224,1231 ---- NUM_STRINGS(term) - STRCOUNT); (void) printf("#endif /* NCURSES_XNAMES */\n"); + #else + (void) term; #endif /* NCURSES_XNAMES */ (void) printf("\t%s\n", R_CURL); } *************** *** 1109,1119 **** if (temp == 0 || temp == optarg || *temp != 0) { fprintf(stderr, "Expected a number, not \"%s\"\n", optarg); ! exit(EXIT_FAILURE); } return (int) value; } /*************************************************************************** * * Main sequence --- 1238,1262 ---- if (temp == 0 || temp == optarg || *temp != 0) { fprintf(stderr, "Expected a number, not \"%s\"\n", optarg); ! ExitProgram(EXIT_FAILURE); } return (int) value; } + static char * + terminal_env(void) + { + char *terminal; + + if ((terminal = getenv("TERM")) == 0) { + (void) fprintf(stderr, + "%s: environment variable TERM not set\n", + _nc_progname); + exit(EXIT_FAILURE); + } + return terminal; + } + /*************************************************************************** * * Main sequence *************** *** 1123,1177 **** int main(int argc, char *argv[]) { - char *terminal, *firstdir, *restdir; /* Avoid "local data >32k" error with mwcc */ /* Also avoid overflowing smaller stacks on systems like AmigaOS */ ! size_t tlen = sizeof(path) * MAXTERMS; ! path *tfile = (path *) malloc(tlen); int c, i, len; bool formatted = FALSE; bool filecompare = FALSE; int initdump = 0; bool init_analyze = FALSE; - if ((terminal = getenv("TERM")) == 0) { - (void) fprintf(stderr, - "infocmp: environment variable TERM not set\n"); - return EXIT_FAILURE; - } - /* where is the terminfo database location going to default to? */ restdir = firstdir = 0; ! while ((c = getopt(argc, argv, "adeEcCfFGgIinlLpqrR:s:uv:Vw:A:B:1T")) != -1) switch (c) { #if NCURSES_XNAMES case 'a': _nc_disable_period = TRUE; use_extended_names(TRUE); break; #endif ! case 'd': ! compare = C_DIFFERENCE; break; ! case 'e': ! initdump |= 1; break; case 'E': initdump |= 2; break; ! case 'c': ! compare = C_COMMON; break; ! case 'C': ! outform = F_TERMCAP; ! tversion = "BSD"; ! if (sortmode == S_DEFAULT) ! sortmode = S_TERMCAP; break; case 'f': --- 1266,1348 ---- int main(int argc, char *argv[]) { /* Avoid "local data >32k" error with mwcc */ /* Also avoid overflowing smaller stacks on systems like AmigaOS */ ! path *tfile = 0; ! char **tname = 0; ! int maxterms; ! ! char **myargv; ! ! char *firstdir, *restdir; int c, i, len; bool formatted = FALSE; bool filecompare = FALSE; int initdump = 0; bool init_analyze = FALSE; + bool suppress_untranslatable = FALSE; /* where is the terminfo database location going to default to? */ restdir = firstdir = 0; ! #if NCURSES_XNAMES ! use_extended_names(FALSE); ! #endif ! ! _nc_progname = _nc_rootname(argv[0]); ! ! /* make sure we have enough space to add two terminal entries */ ! myargv = typeCalloc(char *, (size_t) (argc + 3)); ! memcpy(myargv, argv, (sizeof(char *) * (size_t) argc)); ! argv = myargv; ! ! while ((c = getopt(argc, ! argv, ! "1A:aB:CcdEeFfGgIiLlnpqR:rs:TtUuVv:w:x")) != -1) { switch (c) { + case '1': + mwidth = 0; + break; + + case 'A': + firstdir = optarg; + break; + #if NCURSES_XNAMES case 'a': _nc_disable_period = TRUE; use_extended_names(TRUE); break; #endif ! case 'B': ! restdir = optarg; break; ! case 'C': ! outform = F_TERMCAP; ! tversion = "BSD"; ! if (sortmode == S_DEFAULT) ! sortmode = S_TERMCAP; break; + case 'c': + compare = C_COMMON; + break; + + case 'd': + compare = C_DIFFERENCE; + break; + case 'E': initdump |= 2; break; ! case 'e': ! initdump |= 1; break; ! case 'F': ! filecompare = TRUE; break; case 'f': *************** *** 1186,1195 **** numbers = -1; break; - case 'F': - filecompare = TRUE; - break; - case 'I': outform = F_TERMINFO; if (sortmode == S_DEFAULT) --- 1357,1362 ---- *************** *** 1201,1216 **** init_analyze = TRUE; break; - case 'l': - outform = F_TERMINFO; - break; - case 'L': outform = F_VARIABLE; if (sortmode == S_DEFAULT) sortmode = S_VARIABLE; break; case 'n': compare = C_NAND; break; --- 1368,1383 ---- init_analyze = TRUE; break; case 'L': outform = F_VARIABLE; if (sortmode == S_DEFAULT) sortmode = S_VARIABLE; break; + case 'l': + outform = F_TERMINFO; + break; + case 'n': compare = C_NAND; break; *************** *** 1226,1240 **** bool_sep = ", "; break; - case 'r': - tversion = 0; - limited = FALSE; - break; - case 'R': tversion = optarg; break; case 's': if (*optarg == 'd') sortmode = S_NOSORT; --- 1393,1406 ---- bool_sep = ", "; break; case 'R': tversion = optarg; break; + case 'r': + tversion = 0; + break; + case 's': if (*optarg == 'd') sortmode = S_NOSORT; *************** *** 1246,1292 **** sortmode = S_TERMCAP; else { (void) fprintf(stderr, ! "infocmp: unknown sort mode\n"); ! return EXIT_FAILURE; } break; case 'u': compare = C_USEALL; break; case 'v': itrace = optarg_to_number(); set_trace_level(itrace); break; - case 'V': - puts(curses_version()); - ExitProgram(EXIT_SUCCESS); - case 'w': mwidth = optarg_to_number(); break; ! case 'A': ! firstdir = optarg; break; - case 'B': - restdir = optarg; - break; - - case '1': - mwidth = 0; - break; - - case 'T': - limited = FALSE; - break; default: usage(); } /* by default, sort by terminfo name */ if (sortmode == S_DEFAULT) sortmode = S_TERMINFO; --- 1412,1478 ---- sortmode = S_TERMCAP; else { (void) fprintf(stderr, ! "%s: unknown sort mode\n", ! _nc_progname); ! ExitProgram(EXIT_FAILURE); } break; + case 'T': + limited = FALSE; + break; + + #if NCURSES_XNAMES + case 't': + _nc_disable_period = FALSE; + suppress_untranslatable = TRUE; + break; + #endif + + case 'U': + literal = TRUE; + break; + case 'u': compare = C_USEALL; break; + case 'V': + puts(curses_version()); + ExitProgram(EXIT_SUCCESS); + case 'v': itrace = optarg_to_number(); set_trace_level(itrace); break; case 'w': mwidth = optarg_to_number(); break; ! #if NCURSES_XNAMES ! case 'x': ! use_extended_names(TRUE); break; + #endif default: usage(); } + } + maxterms = (argc + 2 - optind); + tfile = typeMalloc(path, maxterms); + tname = typeCalloc(char *, maxterms); + entries = typeCalloc(ENTRY, maxterms); + + if (tfile == 0 + || tname == 0 + || entries == 0) { + fprintf(stderr, "%s: not enough memory\n", _nc_progname); + ExitProgram(EXIT_FAILURE); + } + /* by default, sort by terminfo name */ if (sortmode == S_DEFAULT) sortmode = S_TERMINFO; *************** *** 1296,1306 **** /* make sure we have at least one terminal name to work with */ if (optind >= argc) ! argv[argc++] = terminal; /* if user is after a comparison, make sure we have two entries */ if (compare != C_DEFAULT && optind >= argc - 1) ! argv[argc++] = terminal; /* exactly two terminal names with no options means do -d */ if (argc - optind == 2 && compare == C_DEFAULT) --- 1482,1492 ---- /* make sure we have at least one terminal name to work with */ if (optind >= argc) ! argv[argc++] = terminal_env(); /* if user is after a comparison, make sure we have two entries */ if (compare != C_DEFAULT && optind >= argc - 1) ! argv[argc++] = terminal_env(); /* exactly two terminal names with no options means do -d */ if (argc - optind == 2 && compare == C_DEFAULT) *************** *** 1310,1359 **** /* grab the entries */ termcount = 0; for (; optind < argc; optind++) { ! if (termcount >= MAXTERMS) { ! (void) fprintf(stderr, ! "infocmp: too many terminal type arguments\n"); ! return EXIT_FAILURE; ! } else { ! const char *directory = termcount ? restdir : firstdir; ! int status; ! tname[termcount] = argv[optind]; ! if (directory) { ! (void) snprintf(tfile[termcount], ! tlen - termcount, ! "%s/%c/%s", ! directory, ! *argv[optind], argv[optind]); ! if (itrace) ! (void) fprintf(stderr, ! "infocmp: reading entry %s from file %s\n", ! argv[optind], tfile[termcount]); ! status = _nc_read_file_entry(tfile[termcount], ! &entries[termcount].tterm); ! } else { ! if (itrace) ! (void) fprintf(stderr, ! "infocmp: reading entry %s from system directories %s\n", ! argv[optind], tname[termcount]); ! status = _nc_read_entry(tname[termcount], ! tfile[termcount], ! &entries[termcount].tterm); ! directory = TERMINFO; /* for error message */ ! } ! if (status <= 0) { ! (void) fprintf(stderr, ! "infocmp: couldn't open terminfo file %s.\n", ! tfile[termcount]); ! return EXIT_FAILURE; ! } ! repair_acsc(&entries[termcount].tterm); ! termcount++; } } #if NCURSES_XNAMES --- 1496,1551 ---- /* grab the entries */ termcount = 0; for (; optind < argc; optind++) { ! const char *directory = termcount ? restdir : firstdir; ! int status; ! tname[termcount] = argv[optind]; ! if (directory) { ! #if USE_DATABASE ! #if MIXEDCASE_FILENAMES ! #define LEAF_FMT "%c" ! #else ! #define LEAF_FMT "%02x" ! #endif ! (void) snprintf(tfile[termcount], sizeof (path), ! "%s/" LEAF_FMT "/%s", directory, ! UChar(*argv[optind]), argv[optind]); ! if (itrace) ! (void) fprintf(stderr, ! "%s: reading entry %s from file %s\n", ! _nc_progname, ! argv[optind], tfile[termcount]); ! status = _nc_read_file_entry(tfile[termcount], ! &entries[termcount].tterm); ! #else ! (void) fprintf(stderr, "%s: terminfo files not supported\n", ! _nc_progname); ! ExitProgram(EXIT_FAILURE); ! #endif ! } else { ! if (itrace) ! (void) fprintf(stderr, ! "%s: reading entry %s from database\n", ! _nc_progname, ! tname[termcount]); ! status = _nc_read_entry(tname[termcount], ! tfile[termcount], ! &entries[termcount].tterm); ! directory = TERMINFO; /* for error message */ ! } ! if (status <= 0) { ! (void) fprintf(stderr, ! "%s: couldn't open terminfo file %s.\n", ! _nc_progname, ! tfile[termcount]); ! ExitProgram(EXIT_FAILURE); } + repair_acsc(&entries[termcount].tterm); + termcount++; } #if NCURSES_XNAMES *************** *** 1367,1377 **** dump_termtype(&entries[0].tterm); if (initdump & 2) dump_initializers(&entries[0].tterm); - ExitProgram(EXIT_SUCCESS); } /* analyze the init strings */ ! if (init_analyze) { #undef CUR #define CUR entries[0].tterm. analyze_string("is1", init_1string, &entries[0].tterm); --- 1559,1568 ---- dump_termtype(&entries[0].tterm); if (initdump & 2) dump_initializers(&entries[0].tterm); } /* analyze the init strings */ ! else if (init_analyze) { #undef CUR #define CUR entries[0].tterm. analyze_string("is1", init_1string, &entries[0].tterm); *************** *** 1383,1442 **** analyze_string("smcup", enter_ca_mode, &entries[0].tterm); analyze_string("rmcup", exit_ca_mode, &entries[0].tterm); #undef CUR ! ExitProgram(EXIT_SUCCESS); ! } ! /* ! * Here's where the real work gets done ! */ ! switch (compare) { ! case C_DEFAULT: ! if (itrace) ! (void) fprintf(stderr, ! "infocmp: about to dump %s\n", ! tname[0]); ! (void) printf("#\tReconstructed via infocmp from file: %s\n", ! tfile[0]); ! len = dump_entry(&entries[0].tterm, limited, numbers, NULL); ! putchar('\n'); ! if (itrace) ! (void) fprintf(stderr, "infocmp: length %d\n", len); ! break; ! case C_DIFFERENCE: ! if (itrace) ! (void) fprintf(stderr, "infocmp: dumping differences\n"); ! (void) printf("comparing %s to %s.\n", tname[0], tname[1]); ! compare_entry(compare_predicate, &entries->tterm, quiet); ! break; ! case C_COMMON: ! if (itrace) ! (void) fprintf(stderr, ! "infocmp: dumping common capabilities\n"); ! (void) printf("comparing %s to %s.\n", tname[0], tname[1]); ! compare_entry(compare_predicate, &entries->tterm, quiet); ! break; ! case C_NAND: ! if (itrace) ! (void) fprintf(stderr, ! "infocmp: dumping differences\n"); ! (void) printf("comparing %s to %s.\n", tname[0], tname[1]); ! compare_entry(compare_predicate, &entries->tterm, quiet); ! break; ! case C_USEALL: ! if (itrace) ! (void) fprintf(stderr, "infocmp: dumping use entry\n"); ! len = dump_entry(&entries[0].tterm, limited, numbers, use_predicate); ! for (i = 1; i < termcount; i++) ! len += dump_uses(tname[i], !(outform == F_TERMCAP || outform ! == F_TCONVERR)); ! putchar('\n'); ! if (itrace) ! (void) fprintf(stderr, "infocmp: length %d\n", len); ! break; } } else if (compare == C_USEALL) (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n"); --- 1574,1644 ---- analyze_string("smcup", enter_ca_mode, &entries[0].tterm); analyze_string("rmcup", exit_ca_mode, &entries[0].tterm); #undef CUR ! } else { ! /* ! * Here's where the real work gets done ! */ ! switch (compare) { ! case C_DEFAULT: ! if (itrace) ! (void) fprintf(stderr, ! "%s: about to dump %s\n", ! _nc_progname, ! tname[0]); ! (void) printf("#\tReconstructed via infocmp from file: %s\n", ! tfile[0]); ! dump_entry(&entries[0].tterm, ! suppress_untranslatable, ! limited, ! numbers, ! NULL); ! len = show_entry(); ! if (itrace) ! (void) fprintf(stderr, "%s: length %d\n", _nc_progname, len); ! break; ! case C_DIFFERENCE: ! if (itrace) ! (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname); ! (void) printf("comparing %s to %s.\n", tname[0], tname[1]); ! compare_entry(compare_predicate, &entries->tterm, quiet); ! break; ! case C_COMMON: ! if (itrace) ! (void) fprintf(stderr, ! "%s: dumping common capabilities\n", ! _nc_progname); ! (void) printf("comparing %s to %s.\n", tname[0], tname[1]); ! compare_entry(compare_predicate, &entries->tterm, quiet); ! break; ! case C_NAND: ! if (itrace) ! (void) fprintf(stderr, ! "%s: dumping differences\n", ! _nc_progname); ! (void) printf("comparing %s to %s.\n", tname[0], tname[1]); ! compare_entry(compare_predicate, &entries->tterm, quiet); ! break; ! case C_USEALL: ! if (itrace) ! (void) fprintf(stderr, "%s: dumping use entry\n", _nc_progname); ! dump_entry(&entries[0].tterm, ! suppress_untranslatable, ! limited, ! numbers, ! use_predicate); ! for (i = 1; i < termcount; i++) ! dump_uses(tname[i], !(outform == F_TERMCAP ! || outform == F_TCONVERR)); ! len = show_entry(); ! if (itrace) ! (void) fprintf(stderr, "%s: length %d\n", _nc_progname, len); ! break; ! } } } else if (compare == C_USEALL) (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n"); *************** *** 1448,1453 **** --- 1650,1660 ---- else file_comparison(argc - optind, argv + optind); + #if NO_LEAKS + free(myargv); + free(tfile); + free(tname); + #endif ExitProgram(EXIT_SUCCESS); }