📄 infocmp.c
字号:
{(char *) 0, (char *) 0}};static intskip_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 voidanalyze_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; int tp_lines = tp->Numbers[2]; if (cap == ABSENT_STRING || cap == CANCELLED_STRING) return; (void) printf("%s: ", name); buf[0] = '\0'; for (sp = cap; *sp; sp++) { int i; int csi; size_t len = 0; const char *expansion = 0; /* first, check other capabilities in this entry */ for (i = 0; i < STRCOUNT; i++) { char *cp = tp->Strings[i]; /* don't use soft-key capabilities */ if (strnames[i][0] == 'k' && strnames[i][0] == 'f') continue; if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp != cap) { len = strlen(cp); (void) strncpy(buf2, sp, len); buf2[len] = '\0'; if (_nc_capcmp(cp, buf2)) continue;#define ISRS(s) (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2)) /* * Theoretically we just passed the test for translation * (equality once the padding is stripped). However, there * are a few more hoops that need to be jumped so that * identical pairs of initialization and reset strings * don't just refer to each other. */ if (ISRS(name) || ISRS(strnames[i])) if (cap < cp) continue;#undef ISRS expansion = strnames[i]; break; } } /* now check the standard capabilities */ if (!expansion) { csi = skip_csi(sp); for (ap = std_caps; ap->from; ap++) { size_t adj = csi ? 2 : 0; len = strlen(ap->from); if (len > adj && strncmp(ap->from + adj, sp + csi, len - adj) == 0) { expansion = ap->to; len -= adj; len += csi; break; } } } /* now check for standard-mode sequences */ if (!expansion && (csi = skip_csi(sp)) != 0 && (len = strspn(sp + csi, "0123456789;")) && ((sp[csi + len] == 'h') || (sp[csi + len] == 'l'))) { char buf3[MAX_TERMINFO_LENGTH]; (void) strcpy(buf2, (sp[csi + len] == 'h') ? "ECMA+" : "ECMA-"); (void) strncpy(buf3, sp + csi, len); len += csi + 1; buf3[len] = '\0'; ep = strtok(buf3, ";"); do { bool found = FALSE; for (ap = std_modes; ap->from; ap++) { size_t tlen = strlen(ap->from); if (strncmp(ap->from, ep, tlen) == 0) { (void) strcat(buf2, ap->to); found = TRUE; break; } } if (!found) (void) strcat(buf2, ep); (void) strcat(buf2, ";"); } while ((ep = strtok((char *) 0, ";"))); buf2[strlen(buf2) - 1] = '\0'; expansion = buf2; } /* now check for private-mode sequences */ if (!expansion && (csi = skip_csi(sp)) != 0 && sp[csi] == '?' && (len = strspn(sp + csi + 1, "0123456789;")) && ((sp[csi + 1 + len] == 'h') || (sp[csi + 1 + len] == 'l'))) { char buf3[MAX_TERMINFO_LENGTH]; (void) strcpy(buf2, (sp[csi + 1 + len] == 'h') ? "DEC+" : "DEC-"); (void) strncpy(buf3, sp + csi + 1, len); len += csi + 2; 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) strcat(buf2, ap->to); found = TRUE; break; } } if (!found) (void) strcat(buf2, ep); (void) strcat(buf2, ";"); } while ((ep = strtok((char *) 0, ";"))); buf2[strlen(buf2) - 1] = '\0'; expansion = buf2; } /* now check for ECMA highlight sequences */ if (!expansion && (csi = skip_csi(sp)) != 0 && (len = strspn(sp + csi, "0123456789;")) != 0 && sp[csi + len] == 'm') { char buf3[MAX_TERMINFO_LENGTH]; (void) strcpy(buf2, "SGR:"); (void) strncpy(buf3, sp + csi, len); len += csi + 1; 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) strcat(buf2, ap->to); found = TRUE; break; } } if (!found) (void) strcat(buf2, ep); (void) strcat(buf2, ";"); } while ((ep = strtok((char *) 0, ";"))); buf2[strlen(buf2) - 1] = '\0'; expansion = buf2; } if (!expansion && (csi = skip_csi(sp)) != 0 && sp[csi] == 'm') { len = csi + 1; (void) strcpy(buf2, "SGR:"); strcat(buf2, ecma_highlights[0].to); 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) sprintf(buf2, "1;%dr", tp_lines); len = strlen(buf2); if (strncmp(buf2, sp + csi, len) == 0) expansion = "RSR"; } len += csi; } /* now check for home-down */ if (!expansion && (csi = skip_csi(sp)) != 0) { (void) sprintf(buf2, "%d;1H", tp_lines); len = strlen(buf2); if (strncmp(buf2, sp + csi, len) == 0) { expansion = "LL"; } else { (void) sprintf(buf2, "%dH", tp_lines); len = strlen(buf2); if (strncmp(buf2, sp + csi, len) == 0) { expansion = "LL"; } } len += csi; } /* now look at the expansion we got, if any */ if (expansion) { (void) sprintf(buf + strlen(buf), "{%s}", expansion); sp += len - 1; continue; } else { /* couldn't match anything */ buf2[0] = *sp; buf2[1] = '\0'; (void) strcat(buf, TIC_EXPAND(buf2)); } } (void) printf("%s\n", buf);}/*************************************************************************** * * File comparison * ***************************************************************************/static voidfile_comparison(int argc, char *argv[]){#define MAXCOMPARE 2 /* someday we may allow comparisons on more files */ int filecount = 0; ENTRY *heads[MAXCOMPARE]; ENTRY *qp, *rp; int i, n; dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, itrace, FALSE); for (n = 0; n < argc && n < MAXCOMPARE; n++) { if (freopen(argv[n], "r", stdin) == 0) _nc_err_abort("Can't open %s", argv[n]); _nc_head = _nc_tail = 0; /* 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]); for_entry_list(qp) { if (qp->nuses) { (void) fputs(qp->tterm.term_names, stderr); (void) fputc('\n', stderr); } } ExitProgram(EXIT_FAILURE); } heads[filecount] = _nc_head; filecount++; } /* OK, all entries are in core. Ready to do the comparison */ if (itrace) (void) fprintf(stderr, "Entries are now in core...\n"); /* The entry-matching loop. Sigh, this is intrinsically quadratic. */ for (qp = heads[0]; qp; qp = qp->next) { for (rp = heads[1]; rp; rp = rp->next) if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) { if (qp->ncrosslinks < MAX_CROSSLINKS) qp->crosslinks[qp->ncrosslinks] = rp; qp->ncrosslinks++; if (rp->ncrosslinks < MAX_CROSSLINKS) rp->crosslinks[rp->ncrosslinks] = qp; rp->ncrosslinks++; } } /* now we have two circular lists with crosslinks */ if (itrace) (void) fprintf(stderr, "Name matches are done...\n"); for (qp = heads[0]; qp; qp = qp->next) { if (qp->ncrosslinks > 1) { (void) fprintf(stderr, "%s in file 1 (%s) has %d matches in file 2 (%s):\n", _nc_first_name(qp->tterm.term_names), argv[0], qp->ncrosslinks, argv[1]); for (i = 0; i < qp->ncrosslinks; i++) (void) fprintf(stderr, "\t%s\n", _nc_first_name((qp->crosslinks[i])->tterm.term_names)); } } for (rp = heads[1]; rp; rp = rp->next) { if (rp->ncrosslinks > 1) { (void) fprintf(stderr, "%s in file 2 (%s) has %d matches in file 1 (%s):\n", _nc_first_name(rp->tterm.term_names), argv[1], rp->ncrosslinks, argv[0]); for (i = 0; i < rp->ncrosslinks; i++) (void) fprintf(stderr, "\t%s\n", _nc_first_name((rp->crosslinks[i])->tterm.term_names)); } } (void) printf("In file 1 (%s) only:\n", argv[0]); for (qp = heads[0]; qp; qp = qp->next) if (qp->ncrosslinks == 0) (void) printf("\t%s\n", _nc_first_name(qp->tterm.term_names)); (void) printf("In file 2 (%s) only:\n", argv[1]); for (rp = heads[1]; rp; rp = rp->next) if (rp->ncrosslinks == 0) (void) printf("\t%s\n", _nc_first_name(rp->tterm.term_names)); (void) printf("The following entries are equivalent:\n"); for (qp = heads[0]; qp; qp = qp->next) { rp = qp->crosslinks[0]; if (qp->ncrosslinks == 1) { rp = qp->crosslinks[0]; repair_acsc(&qp->tterm); repair_acsc(&rp->tterm);#if NCURSES_XNAMES _nc_align_termtype(&qp->tterm, &rp->tterm);#endif if (entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp)) { char name1[NAMESIZE], name2[NAMESIZE]; (void) canonical_name(qp->tterm.term_names, name1); (void) canonical_name(rp->tterm.term_names, name2); (void) printf("%s = %s\n", name1, name2); } } } (void) printf("Differing entries:\n"); termcount = 2; for (qp = heads[0]; qp; qp = qp->next) { if (qp->ncrosslinks == 1) { rp = qp->crosslinks[0];#if NCURSES_XNAMES /* sorry - we have to do this on each pass */ _nc_align_termtype(&qp->tterm, &rp->tterm);#endif if (!(entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp))) { char name1[NAMESIZE], name2[NAMESIZE]; entries[0] = *qp; entries[1] = *rp; (void) canonical_name(qp->tterm.term_names, name1); (void) canonical_name(rp->tterm.term_names, name2); switch (compare) { 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; 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; 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; } } } }}static voidusage(void){ static const char *tbl[] = { "Usage: infocmp [options] [-A directory] [-B directory] [termname...]" ,"" ,"Options:" ," -1 print single-column" ," -C use termcap-names" ," -F compare terminfo-files" ," -I use terminfo-names" ," -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"#endif ," -c list common capabilities" ," -d list different capabilities" ," -e format output for C initializer" ," -E format output as C tables" ," -f with -1, format complex strings" ," -G format %{number} to %'char'" ," -g format %'char' to %{number}" ," -i analyze initialization/reset" ," -l output terminfo names" ," -n list capabilities in neither" ," -p ignore padding specifiers" ," -q brief listing, removes headers" ," -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); const size_t left = (last - first + 1) / 2 + first; size_t n; for (n = 0; n < left; n++) { size_t m = (n < first) ? last : n + left - first; if (m < last) fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]); else fprintf(stderr, "%s\n", tbl[n]); } ExitProgram(EXIT_FAILURE);}static char *any_initializer(const char *fmt, const char *type){ static char *initializer; char *s; if (initializer == 0) initializer = (char *) malloc(strlen(entries->tterm.term_names) + strlen(type) + strlen(fmt)); (void) strcpy(initializer, entries->tterm.term_names); for (s = initializer; *s != 0 && *s != '|'; s++) { if (!isalnum(UChar(*s))) *s = '_'; } *s = 0; (void) sprintf(s, 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 voiddump_initializers(TERMTYPE *term){ unsigned n; int size; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -