112044Slayer #ifndef LINT 2*13250Slayer static char *sccsid="@(#)showtc.c 1.6 (Berkeley) 06/22/83"; 312044Slayer #endif 412044Slayer 512031Slayer /* 612031Slayer ** show termcap entries 712031Slayer ** 812031Slayer ** where: 912458Slayer ** -D look for duplicate names and print termcap file 1012031Slayer ** -S sort entries before display 1112458Slayer ** -T trace (-DDEBUG only) 12*13250Slayer ** -U print unknown capabilities 1312044Slayer ** -b show bare entries 1412458Slayer ** -d -D and stop 1512044Slayer ** -f following arg is FULL PATHNAME of termcap file 1612044Slayer ** -g sort on generic names 1712044Slayer ** -s don't print two char name at the front of every line 1812044Slayer ** -x expand tc= capabilities 1912031Slayer ** [ent] display specific entry. tc= will be expanded. 2012031Slayer ** 2112031Slayer ** David L. Wasley, U.C.Berkeley 2212446Slayer ** Kevin Layer: modified for 4.1c and misc changes. 2312446Slayer ** Kevin Layer: added the printing of terminal capabilities 2412446Slayer ** in `human' readable form (like that in "man 5 termcap"). 2512031Slayer */ 2612031Slayer 2712031Slayer #include <stdio.h> 2812031Slayer #include <sys/file.h> 2912031Slayer #include <ctype.h> 3012031Slayer #include <sys/types.h> 3112031Slayer #include <sys/stat.h> 3212031Slayer 3312031Slayer #define NO 0 3412031Slayer #define YES 1 3512031Slayer #define CNULL '\0' 3612031Slayer #define NOENTRIES 1024 3712044Slayer #define USAGE "usage: %s [-Sxdngb] [-f termcapfile] [entry] ...\n" 3812031Slayer 3912031Slayer struct TcName { 4012031Slayer char name_buf[124]; 4112031Slayer long file_pos; 4212031Slayer } tcNames[NOENTRIES]; 4312031Slayer 44*13250Slayer #define NOCAPS 105 4512446Slayer 4612446Slayer struct Caps { 4712446Slayer char *cap; 4812446Slayer char *desc; 4912446Slayer } capList[NOCAPS] = 5012446Slayer { 5112446Slayer "ae", "End alternate character set", 5212446Slayer "al", "Add new blank line", 5312446Slayer "am", "Has automatic margins", 5412446Slayer "as", "Start alternate character set", 5512446Slayer "bc", "Backspace if not ^H", 56*13250Slayer "bl", "Audible Bell", 5712446Slayer "bs", "Can backspace with ^H", 5812446Slayer "bt", "Back tab", 5912446Slayer "bw", "Backspace wraps from col 0 to last col", 6012446Slayer "CC", "Command char in prototype if settable", 6112446Slayer "cd", "Clear to end of display", 6212446Slayer "ce", "Clear to end of line", 6312446Slayer "ch", "Like cm, but horizontal motion only", 6412446Slayer "cl", "Clear screen", 6512446Slayer "cm", "Cursor motion", 6612446Slayer "co", "Number of columns in a line", 6712446Slayer "cr", "Carriage return, (default ^M)", 6812446Slayer "cs", "Change scrolling region (vt100), like cm", 6912446Slayer "cv", "Like ch but vertical only.", 7012446Slayer "da", "Display may be retained above", 7112446Slayer "dB", "Number of millisec of bs delay needed", 7212446Slayer "db", "Display may be retained below", 7312446Slayer "dC", "Number of millisec of cr delay needed", 7412446Slayer "dc", "Delete character", 7512446Slayer "dF", "Number of millisec of ff delay needed", 7612446Slayer "dl", "Delete line", 7712446Slayer "dm", "Start Delete mode", 7812446Slayer "dN", "Number of millisec of nl delay needed", 7912446Slayer "do", "Down one line", 8012461Slayer "ds", "Disable status display", 8112446Slayer "dT", "Number of millisec of tab delay needed", 8212446Slayer "ed", "End delete mode", 8312446Slayer "ei", "End insert mode;give \":ei=:\" if ic", 8412446Slayer "eo", "Can erase overstrikes with a blank", 8512461Slayer "es", "Escape seq's ok on status line", 8612446Slayer "ff", "Hardcopy page eject (default ^L)", 8712446Slayer "fs", "From status line sequence", 8812446Slayer "hc", "Hardcopy terminal", 8912446Slayer "hd", "Half-line down (forward 1/2 lf)", 9012446Slayer "ho", "Home cursor (if no cm)", 9112446Slayer "hs", "Has 25th status line", 9212446Slayer "hu", "Half-line up (reverse 1/2 lf)", 9312446Slayer "hz", "Hazeltine; can't print ~'s", 9412446Slayer "ic", "Insert character", 9512446Slayer "if", "Name of file containing is", 9612446Slayer "im", "Start insert mode;give \":im=:\" if ic", 9712446Slayer "in", "Insert mode distinguishes nulls on display", 9812446Slayer "ip", "Insert pad after character inserted", 9912446Slayer "is", "Initialization string", 10012461Slayer "i2", "Initialization string (used by sysline(1))", 10112446Slayer "kb", "Sent by backspace key", 10212446Slayer "kd", "Sent down arrow key", 10312446Slayer "ke", "Out of \"keypad transmit\" mode", 10412446Slayer "kh", "Sent by home key", 10512446Slayer "kl", "Sent by left arrow key", 10612446Slayer "kn", "Number of \"other\" keys", 10712446Slayer "ko", "Tc entries for other non-function keys", 10812446Slayer "kr", "Sent by right arrow key", 10912446Slayer "ks", "Put in \"keypad transmit\" mode", 11012446Slayer "ku", "Sent by up arrow key", 111*13250Slayer "le", "Move left", 11212446Slayer "li", "Number of lines on screen or page", 11312446Slayer "ll", "Last line, first column (if no cm)", 11412446Slayer "ma", "Arrow key map, used by vi V2 only", 115*13250Slayer "mb", "Enter blinking mode", 116*13250Slayer "md", "Enter bold mode", 117*13250Slayer "me", "Reset video attributes", 118*13250Slayer "mh", "Enter halfbright mode", 11912446Slayer "mi", "Safe to move while in insert mode", 120*13250Slayer "mk", "Enter protected mode", 12112446Slayer "ml", "Memory lock on above cursor.", 122*13250Slayer "mr", "Enter reverse video mode", 12312446Slayer "ms", "Ok to move while in standout/underline mode", 12412446Slayer "mu", "Memory unlock (turn off memory lock).", 12512446Slayer "nc", "No working CR (DM2500,H2000)", 12612446Slayer "nd", "Non-destructive space (cursor right)", 12712446Slayer "nl", "Newline character (default \\n)", 12812446Slayer "ns", "Is a CRT but doesn't scroll.", 12912446Slayer "os", "Terminal overstrikes", 13012446Slayer "pc", "Pad character (rather than null)", 13112446Slayer "pt", "Has hardware tabs (may need to use is)", 13212446Slayer "se", "End stand out mode", 13312446Slayer "sf", "Scroll forwards", 13412446Slayer "sg", "Number of blank chars left by so/se", 13512446Slayer "so", "Begin stand out mode", 13612446Slayer "sr", "Scroll reverse (backwards)", 13712446Slayer "ta", "Tab (other than ^I or with padding)", 13812446Slayer "tc", "Entry of similar terminal - must be last", 13912446Slayer "te", "String to end programs that use cm", 14012446Slayer "ti", "String to begin programs that use cm", 14112446Slayer "ts", "To status line sequence", 14212446Slayer "uc", "Underscore one char and move past it", 14312446Slayer "ue", "End underscore mode", 14412446Slayer "ug", "Number of blank chars left by us or ue", 14512446Slayer "ul", "Underlines, though no overstrike", 14612446Slayer "up", "Upline (cursor up)", 14712446Slayer "us", "Start underscore mode", 14812446Slayer "vb", "Visible bell (may not move cursor)", 14912446Slayer "ve", "Sequence to end open/visual mode", 15012446Slayer "vs", "Sequence to start open/visual mode", 15112446Slayer "xb", "Beehive (f1=escape, f2=ctrl C)", 15212446Slayer "xn", "A newline is ignored after a wrap (Concept)", 15312446Slayer "xr", "Return acts like ce \\r \\n (Delta Data)", 15412446Slayer "xs", "Standout not erased by writing over it (HP 264?)", 15512446Slayer "xt", "Destructive tabs, magic so char (Teleray 1061)" 15612446Slayer }; 15712446Slayer 15812031Slayer #ifdef DEBUG 15912031Slayer int Dflag = NO; 16012031Slayer #endif 16112031Slayer int xflag = NO; 16212044Slayer int Sflag = YES; 16312044Slayer int sflag = NO; 16412031Slayer int dflag = NO; 16512031Slayer int nflag = NO; 16612031Slayer int gflag = NO; 16712031Slayer int bflag = NO; 168*13250Slayer int Uflag = NO; 16912031Slayer int tc_loopc; /* loop counter */ 17012031Slayer char *tcfile; /* termcap database pathname */ 17112031Slayer char tcbuf[1024]; /* buffer for termcap description */ 17212031Slayer char *lastchar(); 17312031Slayer int name_cmp(); 17412031Slayer int ent_cmp(); 17512031Slayer struct TcName *find_name(); 17612031Slayer char *getenv(); 17712031Slayer char *ctime(); 17812031Slayer char *strncpy(); 17912031Slayer long ftell(); 18012031Slayer 18112031Slayer main(argc, argv, envp) 18212031Slayer int argc; 18312031Slayer char **argv; 18412031Slayer char **envp; 18512031Slayer { 18612031Slayer char *av; 18712031Slayer struct TcName *tn; 18812031Slayer register char *bp; 18912031Slayer long pos; 19012031Slayer int n; 19112031Slayer struct stat st; 19212031Slayer char envbuf[256]; 19312031Slayer FILE *tcfp; 19412031Slayer 19512031Slayer if ((bp = getenv("TERMCAP")) && *bp == '/') 19612031Slayer tcfile = bp; 19712031Slayer else 19812031Slayer tcfile = "/etc/termcap"; 19912031Slayer 20012031Slayer while (--argc > 0) 20112031Slayer { 20212031Slayer if (*(av = *++argv) == '-') 20312031Slayer { 20412031Slayer while (*++av) 20512031Slayer { 20612031Slayer switch (*av) 20712031Slayer { 20812031Slayer /* use alternate termcap file */ 20912031Slayer case 'f': 21012031Slayer if (argc-- <= 0) 21112031Slayer { 21212031Slayer fprintf(stderr, 21312031Slayer "-f needs a filename\n"); 21412031Slayer exit(1); 21512031Slayer } 21612031Slayer tcfile = *++argv; 21712031Slayer break; 21812031Slayer 21912031Slayer /* only check for dup names */ 22012458Slayer case 'd': 22112031Slayer nflag = YES; 22212031Slayer /* fall thru */ 22312031Slayer 22412031Slayer /* look for duplicated names */ 22512458Slayer case 'D': 22612031Slayer dflag = YES; 22712031Slayer continue; 22812031Slayer 229*13250Slayer case 'U': 230*13250Slayer Uflag = YES; 231*13250Slayer continue; 232*13250Slayer 23312044Slayer /* strip the two name off */ 23412044Slayer case 's': 23512044Slayer sflag = YES; 23612044Slayer continue; 23712044Slayer 23812031Slayer /* sort the name array */ 23912031Slayer case 'S': 24012044Slayer Sflag = NO; 24112031Slayer continue; 24212031Slayer 24312031Slayer #ifdef DEBUG 24412458Slayer case 'T': 24512031Slayer Dflag = YES; 24612031Slayer continue; 24712031Slayer #endif 24812031Slayer 24912031Slayer /* sort on generic names */ 25012031Slayer case 'g': 25112031Slayer gflag = YES; 25212031Slayer continue; 25312031Slayer 25412031Slayer /* expand entries in 'full mode' */ 25512031Slayer case 'x': 25612031Slayer xflag = YES; 25712031Slayer continue; 25812031Slayer 25912031Slayer /* show bare entry */ 26012031Slayer case 'b': 26112031Slayer bflag = YES; 26212031Slayer continue; 26312031Slayer 26412031Slayer default: 26512031Slayer fprintf(stderr, "showtc: unknown flag: -%c\n", *av); 26612031Slayer fprintf(stderr, USAGE, argv[0]); 26712031Slayer exit(1); 26812031Slayer } 26912031Slayer } 27012031Slayer } 27112031Slayer else 27212031Slayer break; 27312031Slayer } 27412031Slayer 27512031Slayer /* 27612031Slayer * insert the specified TERMCAP file into the environment 27712031Slayer */ 27812031Slayer (void) sprintf(envbuf, "TERMCAP=%s", tcfile); 27912031Slayer while (*envp) 28012031Slayer { 28112031Slayer if (strncmp(*envp, "TERMCAP=", 8) == 0) 28212031Slayer { 28312031Slayer *envp = envbuf; 28412031Slayer break; 28512031Slayer } 28612031Slayer envp++; 28712031Slayer } 28812031Slayer if (! *envp) 28912031Slayer *envp = envbuf; /* this may be dangerous */ 29012031Slayer 29112031Slayer /* 29212031Slayer ** if user specified type(s), do only those 29312031Slayer */ 29412031Slayer if (argc > 0) 29512031Slayer { 29612031Slayer /* 29712031Slayer ** look for the users specified term types 29812031Slayer */ 29912031Slayer while (argc > 0) 30012031Slayer { 30112031Slayer switch (n = tgetent(tcbuf, *argv)) 30212031Slayer { 30312031Slayer case 1: 30412031Slayer if (bflag) 30512031Slayer (void) prnt_raw(tcbuf); 30612031Slayer else 30712031Slayer (void) prnt_ent(tcbuf); 30812031Slayer break; 30912031Slayer 31012031Slayer case 0: 31112031Slayer fprintf(stderr, 31212031Slayer "showtc: bad entry: %s\n", *argv); 31312031Slayer break; 31412031Slayer 31512031Slayer case -1: 31612031Slayer fputs("showtc: ", stderr); 31712031Slayer perror(tcfile); 31812031Slayer exit(1); 31912031Slayer 32012031Slayer default: 32112031Slayer fprintf(stderr, "bad return from tgetent: %d\n", n); 32212031Slayer exit(1); 32312031Slayer } 32412031Slayer argc--; 32512031Slayer argv++; 32612031Slayer } 32712031Slayer exit(0); 32812031Slayer } 32912031Slayer 33012031Slayer if (bflag) 33112031Slayer { 33212031Slayer fprintf(stderr, "showtc: -b flag with no entries makes no sense.\n"); 33312031Slayer exit(1); 33412031Slayer } 33512031Slayer 33612031Slayer 33712031Slayer /* 33812031Slayer ** if no type was specified, do the whole file 33912031Slayer */ 34012031Slayer if ((tcfp = fopen(tcfile, "r")) == NULL) 34112031Slayer { 34212031Slayer perror(tcfile); 34312031Slayer exit(1); 34412031Slayer } 34512031Slayer 34612031Slayer /* 34712031Slayer ** identify database, for the record 34812031Slayer */ 34912031Slayer if (stat(tcfile, &st)) 35012031Slayer { 35112031Slayer perror(tcfile); 35212031Slayer exit(1); 35312031Slayer } 35412031Slayer printf("File: %s, last modified: %s\n", tcfile, ctime(&st.st_mtime)); 35512031Slayer 35612031Slayer 35712031Slayer /* 35812031Slayer ** build termcap entry table 35912031Slayer */ 36012031Slayer tn = tcNames; 36112031Slayer pos = ftell(tcfp); 36212031Slayer bp = tcbuf; 36312031Slayer while (fgets(bp, sizeof (tcbuf), tcfp) != NULL) 36412031Slayer { 36512031Slayer if (tcbuf[0] == '#') 36612031Slayer { 36712031Slayer pos = ftell(tcfp); 36812031Slayer bp = tcbuf; 36912031Slayer continue; 37012031Slayer } 37112031Slayer 37212031Slayer tn->file_pos = pos; 37312031Slayer 37412031Slayer /* 37512031Slayer ** get full entry 37612031Slayer */ 37712031Slayer while (*(bp = lastchar(bp)) == '\\' && fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp)) 37812031Slayer ; 37912031Slayer /* 38012031Slayer ** save the names 38112031Slayer */ 38212031Slayer for (bp = tcbuf; *bp && *bp != ':'; bp++) 38312031Slayer ; 38412031Slayer *bp = '\0'; 38512031Slayer (void) strncpy(tn->name_buf, tcbuf, 38612031Slayer sizeof tcNames[0].name_buf); 38712031Slayer 38812031Slayer pos = ftell(tcfp); 38912031Slayer bp = tcbuf; 39012031Slayer tn++; 39112031Slayer } 39212031Slayer tn->file_pos = -1; 39312031Slayer 39412031Slayer /* 39512031Slayer ** Look for duplicate names 39612031Slayer */ 39712031Slayer if (dflag) 39812031Slayer check_dup(); 39912031Slayer if (nflag) 40012031Slayer exit(0); 40112031Slayer 40212031Slayer #ifdef DEBUG 40312031Slayer if (Dflag) 40412031Slayer { 40512031Slayer for (tn = tcNames; tn->file_pos >= 0; tn++) 40612031Slayer { 40712031Slayer printf("Entry #%d:\n\t%s\n\tfile_pos = %ld\n", 40812031Slayer tn - tcNames, tn->name_buf, tn->file_pos); 40912031Slayer } 41012031Slayer exit(0); 41112031Slayer } 41212031Slayer #endif 41312031Slayer 41412031Slayer /* 41512031Slayer ** Order the list 41612031Slayer */ 41712044Slayer if (Sflag) 41812031Slayer qsort((char *)tcNames, tn - tcNames, 41912031Slayer sizeof (struct TcName), name_cmp); 42012031Slayer 42112031Slayer /* 42212031Slayer ** List termcap entry for each name in table 42312031Slayer */ 42412031Slayer for (tn = tcNames; tn->file_pos >= 0; tn++) 42512031Slayer { 42612031Slayer tc_loopc = 0; 42712031Slayer /*** working toward this ... 42812031Slayer (void) prnt_ent(tn); 42912031Slayer ***/ 43012031Slayer (void) fseek(tcfp, tn->file_pos, 0); 43112031Slayer bp = tcbuf; 43212031Slayer while (fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp) 43312031Slayer && *(bp = lastchar(bp)) == '\\') 43412031Slayer ; 43512031Slayer (void) prnt_ent(tcbuf); 43612031Slayer } 43712031Slayer } 43812031Slayer 43912031Slayer char * 44012031Slayer lastchar(b) 44112031Slayer char *b; 44212031Slayer { 44312031Slayer register char *p; 44412031Slayer 44512031Slayer p = b + strlen(b) - 1; 44612031Slayer while (*p == '\n' || *p == ' ') 44712031Slayer p--; 44812031Slayer return(p); 44912031Slayer } 45012031Slayer 45112031Slayer name_cmp(a, b) 45212031Slayer char *a, *b; 45312031Slayer { 45412031Slayer if (gflag) /* sort on generic names */ 45512031Slayer { 45612031Slayer a += 3; 45712031Slayer b += 3; 45812031Slayer while (*a && *b && *a != '|' && *a == *b) 45912031Slayer { 46012031Slayer a++; 46112031Slayer b++; 46212031Slayer } 46312031Slayer if (*a == '|' || *a == CNULL) 46412031Slayer return((*b == '|' || *b == CNULL)? 0:-1); 46512031Slayer if (*b == '|' || *b == CNULL) 46612031Slayer return(1); 46712031Slayer return(*a - *b); 46812031Slayer } 46912031Slayer return(strncmp(a, b, 2)); 47012031Slayer } 47112031Slayer 47212031Slayer prnt_ent(buf) 47312031Slayer register char *buf; 47412031Slayer { 47512031Slayer register char *name; 47612446Slayer char *getdesc(); 47712031Slayer char *caps[256]; 47812031Slayer register char **cp; 47912031Slayer register char **tp; 48012031Slayer char tname[3]; 48112031Slayer 48212031Slayer cp = caps; 48312031Slayer name = buf; 48412031Slayer tname[3] = '\0'; 48512031Slayer 48612031Slayer while (*buf) 48712031Slayer { 48812031Slayer switch (*buf) 48912031Slayer { 49012031Slayer case ':': 49112031Slayer *buf++ = '\0'; 49212031Slayer while (*buf && !isalnum(*buf)) 49312031Slayer buf++; 49412031Slayer if (*buf) 49512031Slayer { 49612031Slayer /* 49712031Slayer * ignore duplicate cap entries 49812031Slayer */ 49912031Slayer for (tp = caps; tp < cp; tp++) 50012031Slayer if (strncmp(buf, *tp, 2) == 0) 50112031Slayer goto skip; 50212031Slayer *cp++ = buf; 50312031Slayer skip: 50412031Slayer /* 50512031Slayer * does user want tc= expanded? 50612031Slayer */ 50712031Slayer if (xflag && strncmp(buf, "tc=", 3) == 0) 50812031Slayer { 50912031Slayer /* 51012031Slayer * find end of tc= 51112031Slayer */ 51212031Slayer while (*buf != ':') 51312031Slayer buf++; 51412031Slayer *buf = '\0'; 51512031Slayer /* 51612031Slayer * save term name 51712031Slayer */ 51812031Slayer tname[0] = name[0]; 51912031Slayer tname[1] = name[1]; 52012031Slayer printf("%s: expanding %s\n", 52112031Slayer tname, cp[-1]); 52212031Slayer /* 52312031Slayer * let tgetent do the work 52412031Slayer */ 52512031Slayer tgetent(tcbuf, tname); 52612031Slayer prnt_ent(tcbuf); 52712031Slayer return; 52812031Slayer } 52912031Slayer } 53012031Slayer continue; 53112031Slayer 53212031Slayer case '|': 53312031Slayer *buf++ = ','; 53412031Slayer continue; 53512031Slayer 53612031Slayer default: 53712031Slayer buf++; 53812031Slayer } 53912031Slayer } 54012031Slayer *cp = CNULL; /* was (char *)0 */ 54112031Slayer 54212044Slayer if (Sflag) 54312031Slayer qsort((char *) caps, cp - caps, sizeof (char *), ent_cmp); 54412031Slayer 54512031Slayer printf("%s\n", name); 54612031Slayer for (cp = caps; *cp; cp++) 547*13250Slayer if (Uflag) { 548*13250Slayer if (unknowncap(*cp)) { 549*13250Slayer printf("%3.3s\n", *cp); 550*13250Slayer } 551*13250Slayer } else if (sflag) { 55212446Slayer printf("%-45s %s\n", getdesc(*cp), *cp); 553*13250Slayer } else { 55412446Slayer printf("%2.2s %-45s %s\n", name, getdesc(*cp), *cp); 55512446Slayer } 55612031Slayer (void) putchar('\n'); 55712031Slayer } 55812031Slayer 55912031Slayer prnt_raw(buf) 56012031Slayer char *buf; 56112031Slayer { 56212031Slayer register char *b; 56312031Slayer register int len; 56412031Slayer register int n; 56512031Slayer char *index(); 56612031Slayer 56712031Slayer len = 0; 56812031Slayer b = buf; 56912031Slayer while (*b) 57012031Slayer { 57112031Slayer if ((n = index(b, ':') - b + 1) <= 0) 57212031Slayer n = strlen(b); 57312031Slayer if (len == 0) /* first part */ 57412031Slayer { 57512031Slayer printf("%.*s\\\n\t:", n, b); 57612031Slayer len = 9 - n; 57712031Slayer } 57812031Slayer else 57912031Slayer { 58012031Slayer if ((len + n) >= 75) 58112031Slayer { 58212031Slayer printf("\\\n\t:"); 58312031Slayer len = 9; 58412031Slayer } 58512031Slayer printf("%.*s", n, b); 58612031Slayer } 58712031Slayer len += n; 58812031Slayer b += n; 58912031Slayer while (*b && index(" \t:\n", *b)) 59012031Slayer b++; 59112031Slayer } 59212031Slayer if (b[-1] != ':') 59312031Slayer (void) putchar(':'); 59412031Slayer (void) putchar('\n'); 59512031Slayer } 59612031Slayer 59712031Slayer ent_cmp(a, b) 59812031Slayer char **a, **b; 59912031Slayer { 60012031Slayer return(strncmp(*a, *b, 2)); 60112031Slayer } 60212031Slayer 60312031Slayer check_dup() 60412031Slayer { 60512031Slayer /* 60612031Slayer ** Look for duplicated names 60712031Slayer */ 60812031Slayer register char *p; 60912031Slayer register char *q; 61012031Slayer register struct TcName *tn; 61112031Slayer register struct TcName *tm; 61212031Slayer 61312031Slayer tn = tcNames; 61412031Slayer while (tn->file_pos >= 0) 61512031Slayer { 61612031Slayer p = q = tn->name_buf; 61712031Slayer while (*q) 61812031Slayer { 61912031Slayer while (*p && *p != '|') 62012031Slayer p++; 62112031Slayer if (p != q && (tm = find_name(q, tn + 1, p - q))) 62212031Slayer { 62312031Slayer fputs("Duplicate name: ", stdout); 62412031Slayer while (q != p) 62512031Slayer (void) putchar(*q++); 62612031Slayer (void) putchar('\n'); 62712031Slayer puts(tn->name_buf); 62812031Slayer puts(tm->name_buf); 62912031Slayer puts("---\n"); 63012031Slayer } 63112031Slayer if (*p == '|') 63212031Slayer p++; 63312031Slayer q = p; 63412031Slayer } 63512031Slayer tn++; 63612031Slayer } 63712031Slayer } 63812031Slayer 63912031Slayer struct TcName * 64012031Slayer find_name(name, tn, len) 64112031Slayer register char *name; 64212031Slayer register struct TcName *tn; 64312031Slayer register int len; 64412031Slayer { 64512031Slayer /* 64612031Slayer ** find name of length len in tcname structure buffers. 64712031Slayer */ 64812031Slayer register char *p; 64912031Slayer register char *buf; 65012031Slayer register int n; 65112031Slayer 65212031Slayer while (tn->file_pos >= 0) 65312031Slayer { 65412031Slayer buf = tn->name_buf; 65512031Slayer while (*buf) 65612031Slayer { 65712031Slayer p = name; 65812031Slayer n = len; 65912031Slayer if (*buf == '|') 66012031Slayer buf++; 66112031Slayer 66212031Slayer while (*buf && *buf != '|') 66312031Slayer { 66412031Slayer if (*p != *buf) 66512031Slayer { 66612031Slayer while (*buf && *buf != '|') 66712031Slayer buf++; 66812031Slayer break; 66912031Slayer } 67012031Slayer 67112031Slayer if (--n <= 0) 67212031Slayer { 67312031Slayer buf++; 67412031Slayer if (*buf == '|' || *buf == '\0') 67512031Slayer return(tn); 67612031Slayer while (*buf && *buf != '|') 67712031Slayer buf++; 67812031Slayer break; 67912031Slayer } 68012031Slayer buf++; 68112031Slayer p++; 68212031Slayer } 68312031Slayer } 68412031Slayer tn++; 68512031Slayer } 68612031Slayer return((struct TcName *)0); 68712031Slayer } 68812446Slayer 68912446Slayer char * 69012446Slayer getdesc(key) 69112446Slayer char *key; 69212446Slayer { 69312446Slayer register int i; 69412446Slayer 69512446Slayer for (i = 0; i <= NOCAPS; i++) 69612446Slayer if (strncmp(key, capList[i].cap, 2) == 0) 69712446Slayer return (capList[i].desc); 69812458Slayer return(""); 69912446Slayer } 700*13250Slayer 701*13250Slayer unknowncap(key) 702*13250Slayer char *key; 703*13250Slayer { 704*13250Slayer register int i; 705*13250Slayer 706*13250Slayer for (i = 0; i <= NOCAPS; i++) 707*13250Slayer if (strncmp(key, capList[i].cap, 2) == 0) 708*13250Slayer return (0); 709*13250Slayer return(1); 710*13250Slayer } 711