captoinfo.c revision 381:1a7f0e46092a
1251881Speter/* 2251881Speter * CDDL HEADER START 3251881Speter * 4251881Speter * The contents of this file are subject to the terms of the 5251881Speter * Common Development and Distribution License, Version 1.0 only 6251881Speter * (the "License"). You may not use this file except in compliance 7251881Speter * with the License. 8251881Speter * 9251881Speter * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10251881Speter * or http://www.opensolaris.org/os/licensing. 11251881Speter * See the License for the specific language governing permissions 12251881Speter * and limitations under the License. 13251881Speter * 14251881Speter * When distributing Covered Code, include this CDDL HEADER in each 15251881Speter * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16251881Speter * If applicable, add the following below this CDDL HEADER, with the 17251881Speter * fields enclosed by brackets "[]" replaced with your own identifying 18251881Speter * information: Portions Copyright [yyyy] [name of copyright owner] 19251881Speter * 20251881Speter * CDDL HEADER END 21251881Speter */ 22251881Speter/* 23251881Speter * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24251881Speter * Use is subject to license terms. 25251881Speter */ 26251881Speter 27251881Speter/* Copyright (c) 1988 AT&T */ 28251881Speter/* All Rights Reserved */ 29251881Speter 30251881Speter#pragma ident "%Z%%M% %I% %E% SMI" 31251881Speter 32251881Speter/* 33251881Speter * NAME 34251881Speter * captoinfo - convert a termcap description to a terminfo description 35251881Speter * 36251881Speter * SYNOPSIS 37251881Speter * captoinfo [-1vV] [-w width] [ filename ... ] 38251881Speter * 39251881Speter * AUTHOR 40251881Speter * Tony Hansen, January 22, 1984. 41251881Speter */ 42251881Speter 43251881Speter#include "curses.h" 44251881Speter#include <ctype.h> 45251881Speter#include <stdlib.h> 46251881Speter#include <unistd.h> 47251881Speter#include <string.h> 48251881Speter#include "otermcap.h" 49251881Speter#include "print.h" 50251881Speter 51251881Speter#define trace stderr /* send trace messages to stderr */ 52251881Speter 53251881Speter/* extra termcap variables no longer in terminfo */ 54251881Speterchar *oboolcodes[] = 55251881Speter { 56251881Speter "bs", /* Terminal can backspace with "^H" */ 57251881Speter "nc", /* No correctly working carriage return (DM2500,H2000) */ 58251881Speter "ns", /* Terminal is a CRT but does not scroll. */ 59251881Speter "pt", /* Has hardware tabs (may need to be set with "is") */ 60251881Speter "MT", /* Has meta key, alternate code. */ 61251881Speter "xr", /* Return acts like ce \r \n (Delta Data) */ 62251881Speter 0 63251881Speter}; 64251881Speterint cap_bs = 0, cap_nc = 1, cap_ns = 2, cap_pt = 3, cap_MT = 4, cap_xr = 5; 65251881Speterchar *onumcodes[] = 66251881Speter { 67251881Speter "dB", /* Number of millisec of bs delay needed */ 68251881Speter "dC", /* Number of millisec of cr delay needed */ 69251881Speter "dF", /* Number of millisec of ff delay needed */ 70251881Speter "dN", /* Number of millisec of nl delay needed */ 71251881Speter "dT", /* Number of millisec of tab delay needed */ 72251881Speter "ug", /* Number of blank chars left by us or ue */ 73251881Speter/* Ignore the 'kn' number. It was ill-defined and never used. */ 74251881Speter "kn", /* Number of "other" keys */ 75251881Speter 0 76251881Speter}; 77251881Speterint cap_dB = 0, cap_dC = 1, cap_dF = 2, cap_dN = 3, cap_dT = 4, cap_ug = 5; 78251881Speter 79251881Speterchar *ostrcodes[] = 80251881Speter { 81251881Speter "bc", /* Backspace if not "^H" */ 82251881Speter "ko", /* Termcap entries for other non-function keys */ 83251881Speter "ma", /* Arrow key map, used by vi version 2 only */ 84251881Speter "nl", /* Newline character (default "\n") */ 85251881Speter "rs", /* undocumented reset string, like is (info is2) */ 86251881Speter/* Ignore the 'ml' and 'mu' strings. */ 87251881Speter "ml", /* Memory lock on above cursor. */ 88251881Speter "mu", /* Memory unlock (turn off memory lock). */ 89251881Speter 0 90251881Speter}; 91251881Speterint cap_bc = 0, cap_ko = 1, cap_ma = 2, cap_nl = 3, cap_rs = 4; 92251881Speter 93251881Speter#define numelements(x) (sizeof (x)/sizeof (x[0])) 94251881Speterchar oboolval[2][numelements(oboolcodes)]; 95251881Spetershort onumval[2][numelements(onumcodes)]; 96251881Speterchar *ostrval[2][numelements(ostrcodes)]; 97251881Speter 98251881Speter/* externs from libcurses.a */ 99251881Speterextern char *boolnames[], *boolcodes[]; 100251881Speterextern char *numnames[], *numcodes[]; 101251881Speterextern char *strnames[], *strcodes[]; 102251881Speter 103251881Speter/* globals for this file */ 104251881Speterchar *progname; /* argv [0], the name of the program */ 105251881Speterstatic char *term_name; /* the name of the terminal being worked on */ 106251881Speterstatic int uselevel; /* whether we're dealing with use= info */ 107251881Speterstatic int boolcount, /* the maximum numbers of each name array */ 108251881Speter numcount, 109251881Speter strcount; 110251881Speter 111251881Speter/* globals dealing with the environment */ 112251881Speterextern char **environ; 113251881Speterstatic char TERM[100]; 114251881Speter#if defined(SYSV) || defined(USG) /* handle both Sys Vr2 and Vr3 curses */ 115251881Speterstatic char dirname[BUFSIZ]; 116251881Speter#else 117251881Speter#include <sys/param.h> 118251881Speterstatic char dirname[MAXPATHLEN]; 119251881Speter#endif /* SYSV || USG */ 120251881Speterstatic char TERMCAP[BUFSIZ+15]; 121251881Speterstatic char *newenviron[] = { &TERM[0], &TERMCAP[0], 0 }; 122251881Speter 123251881Speter/* dynamic arrays */ 124251881Speterstatic char *boolval[2]; /* dynamic array of boolean values */ 125251881Speterstatic short *numval[2]; /* dynamic array of numeric values */ 126251881Speterstatic char **strval[2]; /* dynamic array of string pointers */ 127251881Speter 128251881Speter/* data buffers */ 129251881Speterstatic char *capbuffer; /* string table, pointed at by strval */ 130251881Speterstatic char *nextstring; /* pointer into string table */ 131251881Speterstatic char *bp; /* termcap raw string table */ 132251881Speterstatic char *buflongname; /* place to copy the long names */ 133251881Speter 134251881Speter/* flags */ 135251881Speterstatic int verbose = 0; /* debugging printing level */ 136251881Speterstatic int copycomments = 0; /* copy comments from tercap source */ 137251881Speter 138251881Speter#define ispadchar(c) (isdigit(c) || (c) == '.' || (c) == '*') 139251881Speter 140251881Speterstatic void getlongname(void); 141251881Speterstatic void handleko(void); 142251881Speterstatic void handlema(void); 143251881Speterstatic void print_no_use_entry(void); 144251881Speterstatic void print_use_entry(char *); 145251881Speterstatic void captoinfo(void); 146251881Speterstatic void use_etc_termcap(void); 147251881Speterstatic void initdirname(void); 148251881Speterstatic void setfilename(char *); 149251881Speterstatic void setterm_name(void); 150251881Speterstatic void use_file(char *); 151251881Speterstatic void sorttable(char *[], char *[]); 152251881Speterstatic void inittables(void); 153251881Speter 154251881Speter/* 155251881Speter * Verify that the names given in the termcap entry are all valid. 156251881Speter */ 157251881Speter 158251881Speterint 159251881Spetercapsearch(char *codes[], char *ocodes[], char *cap) 160251881Speter{ 161251881Speter for (; *codes; codes++) 162251881Speter if (((*codes)[0] == cap[0]) && ((*codes)[1] == cap[1])) 163251881Speter return (1); 164251881Speter 165251881Speter for (; *ocodes; ocodes++) 166251881Speter if (((*ocodes)[0] == cap[0]) && ((*ocodes)[1] == cap[1])) 167251881Speter return (1); 168251881Speter 169251881Speter return (0); 170251881Speter} 171251881Speter 172251881Spetervoid 173251881Speterchecktermcap() 174251881Speter{ 175251881Speter char *tbuf = bp; 176251881Speter enum { tbool, tnum, tstr, tcancel, tunknown } type; 177251881Speter 178251881Speter for (;;) { 179251881Speter tbuf = tskip(tbuf); 180251881Speter while (*tbuf == '\t' || *tbuf == ' ' || *tbuf == ':') 181251881Speter tbuf++; 182251881Speter 183251881Speter if (*tbuf == 0) 184251881Speter return; 185251881Speter 186251881Speter /* commented out entry? */ 187251881Speter if (*tbuf == '.') { 188251881Speter if (verbose) 189251881Speter (void) fprintf(trace, "termcap string '%c%c' " 190251881Speter "commented out.\n", tbuf[1], tbuf[2]); 191251881Speter if (!capsearch(boolcodes, oboolcodes, tbuf + 1) && 192251881Speter !capsearch(numcodes, onumcodes, tbuf + 1) && 193251881Speter !capsearch(strcodes, ostrcodes, tbuf + 1)) 194251881Speter (void) fprintf(stderr, 195251881Speter "%s: TERM=%s: commented out code '%.2s' " 196251881Speter "is unknown.\n", progname, term_name, 197251881Speter tbuf+1); 198251881Speter continue; 199251881Speter } 200251881Speter 201251881Speter if (verbose) 202251881Speter (void) fprintf(trace, "looking at termcap string " 203251881Speter "'%.2s'.\n", tbuf); 204251881Speter 205251881Speter switch (tbuf[2]) { 206251881Speter case ':': case '\0': type = tbool; break; 207251881Speter case '#': type = tnum; break; 208251881Speter case '=': type = tstr; break; 209251881Speter case '@': type = tcancel; break; 210251881Speter default: 211251881Speter (void) fprintf(stderr, 212251881Speter "%s: TERM=%s: unknown type given for the " 213251881Speter "termcap code '%.2s'.\n", progname, 214251881Speter term_name, tbuf); 215251881Speter type = tunknown; 216251881Speter } 217251881Speter 218251881Speter if (verbose > 1) 219251881Speter (void) fprintf(trace, "type of '%.2s' is %s.\n", tbuf, 220251881Speter (type == tbool) ? "boolean" : 221251881Speter (type == tnum) ? "numeric" : 222251881Speter (type = tstr) ? "string" : 223251881Speter (type = tcancel) ? "canceled" : "unknown"); 224251881Speter 225251881Speter /* look for the name in bools */ 226251881Speter if (capsearch(boolcodes, oboolcodes, tbuf)) { 227251881Speter if (type != tbool && type != tcancel) 228251881Speter (void) fprintf(stderr, 229251881Speter "%s: TERM=%s: wrong type given for the " 230251881Speter "boolean termcap code '%.2s'.\n", progname, 231251881Speter term_name, tbuf); 232251881Speter continue; 233251881Speter } 234251881Speter 235251881Speter /* look for the name in nums */ 236251881Speter if (capsearch(numcodes, onumcodes, tbuf)) { 237251881Speter if (type != tnum && type != tcancel) 238251881Speter (void) fprintf(stderr, 239251881Speter "%s: TERM=%s: wrong type given for the " 240251881Speter "numeric termcap code '%.2s'.\n", progname, 241251881Speter term_name, tbuf); 242251881Speter continue; 243251881Speter } 244251881Speter 245251881Speter /* look for the name in strs */ 246251881Speter if (capsearch(strcodes, ostrcodes, tbuf)) { 247251881Speter if (type != tstr && type != tcancel) 248251881Speter (void) fprintf(stderr, 249251881Speter "%s: TERM=%s: wrong type given for the " 250251881Speter "string termcap code '%.2s'.\n", progname, 251251881Speter term_name, tbuf); 252251881Speter continue; 253251881Speter } 254251881Speter 255251881Speter (void) fprintf(stderr, 256251881Speter "%s: TERM=%s: the %s termcap code '%.2s' is not a valid " 257251881Speter "name.\n", progname, term_name, 258251881Speter (type == tbool) ? "boolean" : 259251881Speter (type == tnum) ? "numeric" : 260251881Speter (type = tstr) ? "string" : 261251881Speter (type = tcancel) ? "canceled" : "(unknown type)", tbuf); 262251881Speter } 263251881Speter} 264251881Speter 265251881Speter/* 266251881Speter * Fill up the termcap tables. 267251881Speter */ 268251881Speterint 269251881Speterfilltables(void) 270251881Speter{ 271251881Speter int i, tret; 272251881Speter 273251881Speter /* Retrieve the termcap entry. */ 274251881Speter if ((tret = otgetent(bp, term_name)) != 1) { 275251881Speter (void) fprintf(stderr, 276251881Speter "%s: TERM=%s: tgetent failed with return code %d (%s).\n", 277251881Speter progname, term_name, tret, 278251881Speter (tret == 0) ? "non-existent or invalid entry" : 279251881Speter (tret == -1) ? "cannot open $TERMCAP" : "unknown reason"); 280251881Speter return (0); 281251881Speter } 282251881Speter 283251881Speter if (verbose) { 284251881Speter (void) fprintf(trace, "bp="); 285251881Speter (void) cpr(trace, bp); 286251881Speter (void) fprintf(trace, ".\n"); 287251881Speter } 288251881Speter 289251881Speter if (uselevel == 0) 290251881Speter checktermcap(); 291251881Speter 292251881Speter /* Retrieve the values that are in terminfo. */ 293251881Speter 294251881Speter /* booleans */ 295251881Speter for (i = 0; boolcodes[i]; i++) { 296251881Speter boolval[uselevel][i] = otgetflag(boolcodes[i]); 297251881Speter if (verbose > 1) { 298251881Speter (void) fprintf(trace, "boolcodes=%s, ", boolcodes[i]); 299251881Speter (void) fprintf(trace, "boolnames=%s, ", boolnames[i]); 300251881Speter (void) fprintf(trace, 301251881Speter "flag=%d.\n", boolval[uselevel][i]); 302251881Speter } 303251881Speter } 304251881Speter 305251881Speter /* numbers */ 306251881Speter for (i = 0; numcodes[i]; i++) { 307251881Speter numval[uselevel][i] = otgetnum(numcodes[i]); 308251881Speter if (verbose > 1) { 309251881Speter (void) fprintf(trace, "numcodes=%s, ", numcodes[i]); 310251881Speter (void) fprintf(trace, "numnames=%s, ", numnames[i]); 311251881Speter (void) fprintf(trace, "num=%d.\n", numval[uselevel][i]); 312251881Speter } 313251881Speter } 314251881Speter 315251881Speter if (uselevel == 0) 316251881Speter nextstring = capbuffer; 317251881Speter 318251881Speter /* strings */ 319251881Speter for (i = 0; strcodes[i]; i++) { 320251881Speter strval[uselevel][i] = otgetstr(strcodes[i], &nextstring); 321251881Speter if (verbose > 1) { 322251881Speter (void) fprintf(trace, "strcodes=%s, ", strcodes [i]); 323251881Speter (void) fprintf(trace, "strnames=%s, ", strnames [i]); 324251881Speter if (strval[uselevel][i]) { 325251881Speter (void) fprintf(trace, "str="); 326251881Speter tpr(trace, strval[uselevel][i]); 327251881Speter (void) fprintf(trace, ".\n"); 328251881Speter } 329251881Speter else 330251881Speter (void) fprintf(trace, "str=NULL.\n"); 331251881Speter } 332251881Speter /* remove zero length strings */ 333251881Speter if (strval[uselevel][i] && (strval[uselevel][i][0] == '\0')) { 334251881Speter (void) fprintf(stderr, 335251881Speter "%s: TERM=%s: cap %s (info %s) is NULL: REMOVED\n", 336251881Speter progname, term_name, strcodes[i], strnames[i]); 337251881Speter strval[uselevel][i] = NULL; 338251881Speter } 339251881Speter } 340251881Speter 341251881Speter /* Retrieve the values not found in terminfo anymore. */ 342251881Speter 343251881Speter /* booleans */ 344251881Speter for (i = 0; oboolcodes[i]; i++) { 345251881Speter oboolval[uselevel][i] = otgetflag(oboolcodes[i]); 346251881Speter if (verbose > 1) { 347251881Speter (void) fprintf(trace, "oboolcodes=%s, ", 348251881Speter oboolcodes[i]); 349251881Speter (void) fprintf(trace, "flag=%d.\n", 350251881Speter oboolval[uselevel][i]); 351251881Speter } 352251881Speter } 353251881Speter 354251881Speter /* numbers */ 355251881Speter for (i = 0; onumcodes[i]; i++) { 356251881Speter onumval[uselevel][i] = otgetnum(onumcodes[i]); 357251881Speter if (verbose > 1) { 358251881Speter (void) fprintf(trace, "onumcodes=%s, ", onumcodes[i]); 359251881Speter (void) fprintf(trace, "num=%d.\n", 360251881Speter onumval[uselevel][i]); 361251881Speter } 362251881Speter } 363251881Speter 364251881Speter /* strings */ 365251881Speter for (i = 0; ostrcodes[i]; i++) { 366251881Speter ostrval[uselevel][i] = otgetstr(ostrcodes[i], &nextstring); 367251881Speter if (verbose > 1) { 368251881Speter (void) fprintf(trace, "ostrcodes=%s, ", ostrcodes[i]); 369251881Speter if (ostrval[uselevel][i]) { 370251881Speter (void) fprintf(trace, "ostr="); 371251881Speter tpr(trace, ostrval[uselevel][i]); 372251881Speter (void) fprintf(trace, ".\n"); 373251881Speter } 374251881Speter else 375251881Speter (void) fprintf(trace, "ostr=NULL.\n"); 376251881Speter } 377251881Speter /* remove zero length strings */ 378251881Speter if (ostrval[uselevel][i] && (ostrval[uselevel][i][0] == '\0')) { 379251881Speter (void) fprintf(stderr, 380251881Speter "%s: TERM=%s: cap %s (no terminfo name) is NULL: " 381251881Speter "REMOVED\n", progname, term_name, ostrcodes[i]); 382251881Speter ostrval[uselevel][i] = NULL; 383251881Speter } 384251881Speter } 385251881Speter return (1); 386251881Speter} 387251881Speter 388251881Speter/* 389251881Speter * This routine copies the set of names from the termcap entry into 390251881Speter * a separate buffer, getting rid of the old obsolete two character 391251881Speter * names. 392251881Speter */ 393251881Speterstatic void 394251881Spetergetlongname(void) 395251881Speter{ 396251881Speter char *b = &bp[0], *l = buflongname; 397251881Speter 398251881Speter /* Skip the two character name */ 399251881Speter if (bp[2] == '|') 400251881Speter b = &bp[3]; 401251881Speter 402251881Speter /* Copy the rest of the names */ 403251881Speter while (*b && *b != ':') 404251881Speter *l++ = *b++; 405251881Speter *l = '\0'; 406251881Speter 407251881Speter if (b != &bp[0]) { 408251881Speter (void) fprintf(stderr, "%s: obsolete 2 character name " 409251881Speter "'%2.2s' removed.\n", progname, bp); 410251881Speter (void) fprintf(stderr, "\tsynonyms are: '%s'\n", buflongname); 411251881Speter } 412251881Speter} 413251881Speter 414251881Speter/* 415251881Speter * Return the value of the termcap string 'capname' as stored in our list. 416251881Speter */ 417251881Speterchar * 418251881Spetergetcapstr(char *capname) 419251881Speter{ 420251881Speter int i; 421251881Speter 422251881Speter if (verbose > 1) 423251881Speter (void) fprintf(trace, "looking for termcap value of %s.\n", 424251881Speter capname); 425251881Speter 426251881Speter /* Check the old termcap list. */ 427251881Speter for (i = 0; ostrcodes[i]; i++) 428251881Speter if (strcmp(ostrcodes[i], capname) == 0) { 429251881Speter if (verbose > 1) { 430251881Speter (void) fprintf(trace, "\tvalue is:"); 431251881Speter tpr(trace, ostrval[uselevel][i]); 432251881Speter (void) fprintf(trace, ".\n"); 433251881Speter } 434251881Speter return (ostrval[uselevel][i]); 435251881Speter } 436251881Speter 437251881Speter if (verbose > 1) 438251881Speter (void) fprintf(trace, "termcap name '%s' not found in " 439251881Speter "ostrcodes.\n", capname); 440251881Speter 441251881Speter /* Check the terminfo list. */ 442251881Speter for (i = 0; strcodes[i]; i++) 443251881Speter if (strcmp(strcodes[i], capname) == 0) { 444251881Speter if (verbose > 1) { 445251881Speter (void) fprintf(trace, "\tvalue is:"); 446251881Speter tpr(trace, strval[uselevel][i]); 447251881Speter (void) fprintf(trace, ".\n"); 448251881Speter } 449251881Speter return (strval[uselevel][i]); 450251881Speter } 451251881Speter 452251881Speter (void) fprintf(stderr, "%s: TERM=%s: termcap name '%s' not found.\n", 453251881Speter progname, term_name, capname); 454251881Speter 455251881Speter return ((char *)NULL); 456251881Speter} 457251881Speter 458251881Speter/* 459251881Speter * Search for a name in the given table and 460251881Speter * return the index. 461251881Speter * Someday I'll redo this to use bsearch(). 462251881Speter */ 463251881Speter/* ARGSUSED */ 464251881Speterint 465251881Spetersearch(char *names[], int max, char *infoname) 466251881Speter{ 467251881Speter#ifndef BSEARCH 468251881Speter int i; 469251881Speter for (i = 0; names [i] != NULL; i++) 470251881Speter if (strcmp(names [i], infoname) == 0) 471251881Speter return (i); 472251881Speter return (-1); 473251881Speter#else /* this doesn't work for some reason */ 474251881Speter char **bret; 475251881Speter 476251881Speter bret = (char **)bsearch(infoname, (char *)names, max, 477251881Speter sizeof (char *), strcmp); 478251881Speter (void) fprintf(trace, "search looking for %s.\n", infoname); 479251881Speter (void) fprintf(trace, "base=%#x, bret=%#x, nel=%d.\n", names, 480251881Speter bret, max); 481251881Speter (void) fprintf(trace, "returning %d.\n", bret == NULL ? -1 : 482251881Speter bret - names); 483251881Speter if (bret == NULL) 484251881Speter return (-1); 485251881Speter else 486251881Speter return (bret - names); 487251881Speter#endif /* OLD */ 488251881Speter} 489251881Speter 490251881Speter/* 491251881Speter * return the value of the terminfo string 'infoname' 492251881Speter */ 493251881Speterchar * 494251881Spetergetinfostr(char *infoname) 495251881Speter{ 496251881Speter int i; 497251881Speter 498251881Speter if (verbose > 1) 499251881Speter (void) fprintf(trace, "looking for terminfo value of %s.\n", 500251881Speter infoname); 501251881Speter 502251881Speter i = search(strnames, strcount, infoname); 503251881Speter if (i != -1) { 504251881Speter if (verbose > 1) { 505251881Speter (void) fprintf(trace, "\tvalue is:"); 506251881Speter tpr(trace, strval[uselevel][i]); 507251881Speter (void) fprintf(trace, ".\n"); 508251881Speter } 509251881Speter return (strval[uselevel][i]); 510251881Speter } 511251881Speter 512251881Speter if (verbose > 1) 513251881Speter (void) fprintf(trace, "terminfo name '%s' not found.\n", 514251881Speter infoname); 515251881Speter 516251881Speter return ((char *)NULL); 517251881Speter} 518251881Speter 519251881Speter/* 520251881Speter * Replace the value stored for the terminfo boolean 521251881Speter * capability 'infoname' with the newvalue. 522251881Speter */ 523251881Spetervoid 524251881Speterputbool(char *infoname, int newvalue) 525251881Speter{ 526251881Speter int i; 527251881Speter 528251881Speter if (verbose > 1) 529251881Speter (void) fprintf(trace, "changing value for %s to %d.\n", 530251881Speter infoname, newvalue); 531251881Speter 532251881Speter i = search(boolnames, boolcount, infoname); 533251881Speter if (i != -1) { 534251881Speter if (verbose > 1) 535251881Speter (void) fprintf(trace, "value was: %d.\n", 536251881Speter boolval[uselevel][i]); 537251881Speter 538251881Speter boolval[uselevel][i] = newvalue; 539251881Speter return; 540251881Speter } 541251881Speter 542251881Speter (void) fprintf(stderr, "%s: TERM=%s: the boolean name '%s' was not " 543251881Speter "found!\n", progname, term_name, infoname); 544251881Speter} 545251881Speter 546251881Speter/* 547251881Speter * Replace the value stored for the terminfo number 548251881Speter * capability 'infoname' with the newvalue. 549251881Speter */ 550251881Spetervoid 551251881Speterputnum(char *infoname, int newvalue) 552251881Speter{ 553251881Speter int i; 554251881Speter 555251881Speter if (verbose > 1) 556251881Speter (void) fprintf(trace, "changing value for %s to %d.\n", 557251881Speter infoname, newvalue); 558251881Speter 559251881Speter i = search(numnames, numcount, infoname); 560251881Speter if (i != -1) { 561251881Speter if (verbose > 1) 562251881Speter (void) fprintf(trace, "value was: %d.\n", 563251881Speter numval[uselevel][i]); 564251881Speter 565251881Speter numval[uselevel][i] = newvalue; 566251881Speter return; 567251881Speter } 568251881Speter 569251881Speter (void) fprintf(stderr, "%s: TERM=%s: the numeric name '%s' was not " 570251881Speter "found!\n", 571251881Speter progname, term_name, infoname); 572251881Speter} 573251881Speter 574251881Speter/* 575251881Speter * replace the value stored for the terminfo string capability 'infoname' 576251881Speter * with the newvalue. 577251881Speter */ 578251881Spetervoid 579251881Speterputstr(char *infoname, char *newvalue) 580251881Speter{ 581251881Speter int i; 582251881Speter 583251881Speter if (verbose > 1) { 584251881Speter (void) fprintf(trace, "changing value for %s to ", infoname); 585251881Speter tpr(trace, newvalue); 586251881Speter (void) fprintf(trace, ".\n"); 587251881Speter } 588251881Speter 589251881Speter i = search(strnames, strcount, infoname); 590251881Speter if (i != -1) { 591251881Speter if (verbose > 1) { 592251881Speter (void) fprintf(trace, "value was:"); 593251881Speter tpr(trace, strval[uselevel][i]); 594251881Speter (void) fprintf(trace, ".\n"); 595251881Speter } 596251881Speter strval[uselevel][i] = nextstring; 597251881Speter while (*newvalue) 598251881Speter *nextstring++ = *newvalue++; 599251881Speter *nextstring++ = '\0'; 600251881Speter return; 601251881Speter } 602251881Speter 603251881Speter (void) fprintf(stderr, "%s: TERM=%s: the string name '%s' was not " 604251881Speter "found!\n", 605251881Speter progname, term_name, infoname); 606251881Speter} 607251881Speter 608251881Speter/* 609251881Speter * Add in extra delays if they are not recorded already. 610251881Speter * This is done before the padding information has been modified by 611251881Speter * changecalculations() below, so the padding information, if there 612251881Speter * already, is still at the beginning of the string in termcap format. 613251881Speter */ 614251881Spetervoid 615251881Speteraddpadding(int cappadding, char *infostr) 616251881Speter{ 617251881Speter char *cap; 618251881Speter char tempbuffer [100]; 619251881Speter 620251881Speter /* Is there padding to add? */ 621251881Speter if (cappadding > 0) 622251881Speter /* Is there a string to add it to? */ 623251881Speter if (cap = getinfostr(infostr)) 624251881Speter /* Is there any padding info already? */ 625251881Speter if (ispadchar(*cap)) { 626251881Speter /* EMPTY */; 627251881Speter /* Assume that the padding info that is there is correct. */ 628251881Speter } else { 629251881Speter /* Add the padding at the end of the present string. */ 630251881Speter (void) snprintf(tempbuffer, sizeof (tempbuffer), 631251881Speter "%s$<%d>", cap, cappadding); 632251881Speter putstr(infostr, tempbuffer); 633251881Speter } else { 634251881Speter /* Create a new string that only has the padding. */ 635251881Speter (void) sprintf(tempbuffer, "$<%d>", cappadding); 636251881Speter putstr(infostr, tempbuffer); 637251881Speter } 638251881Speter} 639251881Speter 640251881Speterstruct 641251881Speter { 642251881Speter char *capname; 643251881Speter char *keyedinfoname; 644251881Speter } ko_map[] = { 645251881Speter "al", "kil1", 646251881Speter "bs", "kbs", /* special addition */ 647251881Speter "bt", "kcbt", 648251881Speter "cd", "ked", 649251881Speter "ce", "kel", 650251881Speter "cl", "kclr", 651251881Speter "ct", "ktbc", 652251881Speter "dc", "kdch1", 653251881Speter "dl", "kdl1", 654251881Speter "do", "kcud1", 655251881Speter "ei", "krmir", 656251881Speter "ho", "khome", 657251881Speter "ic", "kich1", 658251881Speter "im", "kich1", /* special addition */ 659251881Speter "le", "kcub1", 660251881Speter "ll", "kll", 661251881Speter "nd", "kcuf1", 662251881Speter "sf", "kind", 663251881Speter "sr", "kri", 664251881Speter "st", "khts", 665251881Speter "up", "kcuu1", 666251881Speter/* "", "kctab", */ 667251881Speter/* "", "knp", */ 668251881Speter/* "", "kpp", */ 669251881Speter 0, 0 670251881Speter }; 671251881Speter 672251881Speter/* 673251881Speter * Work with the ko string. It is a comma separated list of keys for which 674251881Speter * the keyboard has a key by the same name that emits the same sequence. 675251881Speter * For example, ko = dc, im, ei means that there are keys called 676251881Speter * delete-character, enter-insert-mode and exit-insert-mode on the keyboard, 677251881Speter * and they emit the same sequences as specified in the dc, im and ei 678251881Speter * capabilities. 679251881Speter */ 680251881Speterstatic void 681251881Speterhandleko(void) 682251881Speter{ 683251881Speter char capname[3]; 684 char *capstr; 685 int i, j, found; 686 char *infostr; 687 688 if (verbose > 1) 689 (void) fprintf(trace, "working on termcap ko string.\n"); 690 691 if (ostrval[uselevel][cap_ko] == NULL) 692 return; 693 694 capname[2] = '\0'; 695 for (i = 0; ostrval[uselevel][cap_ko][i] != '\0'; ) { 696 /* isolate the termcap name */ 697 capname[0] = ostrval[uselevel][cap_ko][i++]; 698 if (ostrval[uselevel][cap_ko][i] == '\0') 699 break; 700 capname[1] = ostrval[uselevel][cap_ko][i++]; 701 if (ostrval[uselevel][cap_ko][i] == ',') 702 i++; 703 704 if (verbose > 1) { 705 (void) fprintf(trace, "key termcap name is '"); 706 tpr(trace, capname); 707 (void) fprintf(trace, "'.\n"); 708 } 709 710 /* match it up into our list */ 711 found = 0; 712 for (j = 0; !found && ko_map[j].keyedinfoname != NULL; j++) { 713 if (verbose > 1) 714 (void) fprintf(trace, "looking at termcap name %s.\n", 715 ko_map[j].capname); 716 if (capname[0] == ko_map[j].capname[0] && 717 capname[1] == ko_map[j].capname[1]) { 718 /* add the value to our database */ 719 if ((capstr = getcapstr(capname)) != NULL) { 720 infostr = getinfostr 721 (ko_map[j].keyedinfoname); 722 if (infostr == NULL) { 723 /* skip any possible padding */ 724 /* information */ 725 while (ispadchar(*capstr)) 726 capstr++; 727 putstr(ko_map[j].keyedinfoname, capstr); 728 } else 729 if (strcmp(capstr, infostr) != 0) { 730 (void) fprintf(stderr, 731 "%s: TERM=%s: a function " 732 "key for '%s' was " 733 "specified with the " 734 "value ", progname, 735 term_name, capname); 736 tpr(stderr, capstr); 737 (void) fprintf(stderr, 738 ", but it already has the " 739 "value '"); 740 tpr(stderr, infostr); 741 (void) fprintf(stderr, "'.\n"); 742 } 743 } 744 found = 1; 745 } 746 } 747 748 if (!found) { 749 (void) fprintf(stderr, "%s: TERM=%s: the unknown " 750 "termcap name '%s' was\n", progname, term_name, 751 capname); 752 (void) fprintf(stderr, "specified in the 'ko' " 753 "termcap capability.\n"); 754 } 755 } 756} 757 758#define CONTROL(x) ((x) & 037) 759struct 760 { 761 char vichar; 762 char *keyedinfoname; 763 } ma_map[] = { 764 CONTROL('J'), "kcud1", /* down */ 765 CONTROL('N'), "kcud1", 766 'j', "kcud1", 767 CONTROL('P'), "kcuu1", /* up */ 768 'k', "kcuu1", 769 'h', "kcub1", /* left */ 770 CONTROL('H'), "kcub1", 771 ' ', "kcuf1", /* right */ 772 'l', "kcuf1", 773 'H', "khome", /* home */ 774 CONTROL('L'), "kclr", /* clear */ 775 0, 0 776 }; 777 778/* 779 * Work with the ma string. This is a list of pairs of characters. 780 * The first character is the what a function key sends. The second 781 * character is the equivalent vi function that should be done when 782 * it receives that character. Note that only function keys that send 783 * a single character could be defined by this list. 784 */ 785 786void 787prchar(FILE *stream, int c) 788{ 789 char xbuf[2]; 790 xbuf[0] = c; 791 xbuf[1] = '\0'; 792 (void) fprintf(stream, "%s", iexpand(xbuf)); 793} 794 795static void 796handlema(void) 797{ 798 char vichar; 799 char cap[2]; 800 int i, j, found; 801 char *infostr; 802 803 if (verbose > 1) 804 (void) fprintf(trace, "working on termcap ma string.\n"); 805 806 if (ostrval[uselevel][cap_ma] == NULL) 807 return; 808 809 cap[1] = '\0'; 810 for (i = 0; ostrval[uselevel][cap_ma][i] != '\0'; ) { 811 /* isolate the key's value */ 812 cap[0] = ostrval[uselevel][cap_ma][i++]; 813 if (verbose > 1) { 814 (void) fprintf(trace, "key value is '"); 815 tpr(trace, cap); 816 (void) fprintf(trace, "'.\n"); 817 } 818 819 if (ostrval[uselevel][cap_ma][i] == '\0') 820 break; 821 822 /* isolate the vi key name */ 823 vichar = ostrval[uselevel][cap_ma][i++]; 824 if (verbose > 1) { 825 (void) fprintf(trace, "the vi key is '"); 826 prchar(trace, vichar); 827 (void) fprintf(trace, "'.\n"); 828 } 829 830 /* match up the vi name in our list */ 831 found = 0; 832 for (j = 0; !found && ma_map[j].keyedinfoname != NULL; j++) { 833 if (verbose > 1) { 834 (void) fprintf(trace, "looking at vi " 835 "character '"); 836 prchar(trace, ma_map[j].vichar); 837 (void) fprintf(trace, "'\n"); 838 } 839 if (vichar == ma_map[j].vichar) { 840 infostr = getinfostr(ma_map[j].keyedinfoname); 841 if (infostr == NULL) 842 putstr(ma_map[j].keyedinfoname, cap); 843 else if (strcmp(cap, infostr) != 0) { 844 (void) fprintf(stderr, "%s: TERM=%s: " 845 "the vi character '", progname, 846 term_name); 847 prchar(stderr, vichar); 848 (void) fprintf(stderr, 849 "' (info '%s') has the value '", 850 ma_map[j].keyedinfoname); 851 tpr(stderr, infostr); 852 (void) fprintf(stderr, "', but 'ma' " 853 "gives '"); 854 prchar(stderr, cap[0]); 855 (void) fprintf(stderr, "'.\n"); 856 } 857 found = 1; 858 } 859 } 860 861 if (!found) { 862 (void) fprintf(stderr, "%s: the unknown vi key '", 863 progname); 864 prchar(stderr, vichar); 865 (void) fprintf(stderr, "' was\n"); 866 (void) fprintf(stderr, "specified in the 'ma' termcap " 867 "capability.\n"); 868 } 869 } 870} 871 872/* 873 * Many capabilities were defaulted in termcap which must now be explicitly 874 * given. We'll assume that the defaults are in effect for this terminal. 875 */ 876void 877adddefaults(void) 878{ 879 char *cap; 880 int sg; 881 882 if (verbose > 1) 883 (void) fprintf(trace, "assigning defaults.\n"); 884 885 /* cr was assumed to be ^M, unless nc was given, */ 886 /* which meant it could not be done. */ 887 /* Also, xr meant that ^M acted strangely. */ 888 if ((getinfostr("cr") == NULL) && !oboolval[uselevel][cap_nc] && 889 !oboolval[uselevel][cap_xr]) 890 if ((cap = getcapstr("cr")) == NULL) 891 putstr("cr", "\r"); 892 else 893 putstr("cr", cap); 894 895 /* cursor down was assumed to be ^J if not specified by nl */ 896 if (getinfostr("cud1") == NULL) 897 if (ostrval[uselevel][cap_nl] != NULL) 898 putstr("cud1", ostrval[uselevel][cap_nl]); 899 else 900 putstr("cud1", "\n"); 901 902 /* ind was assumed to be ^J, unless ns was given, */ 903 /* which meant it could not be done. */ 904 if ((getinfostr("ind") == NULL) && !oboolval[uselevel][cap_ns]) 905 if (ostrval[uselevel][cap_nl] == NULL) 906 putstr("ind", "\n"); 907 else 908 putstr("ind", ostrval[uselevel][cap_nl]); 909 910 /* bel was assumed to be ^G */ 911 if (getinfostr("bel") == NULL) 912 putstr("bel", "\07"); 913 914 /* if bs, then could do backspacing, */ 915 /* with value of bc, default of ^H */ 916 if ((getinfostr("cub1") == NULL) && oboolval[uselevel][cap_bs]) 917 if (ostrval[uselevel][cap_bc] != NULL) 918 putstr("cub1", ostrval[uselevel][cap_bc]); 919 else 920 putstr("cub1", "\b"); 921 922 /* default xon to true */ 923 if (!otgetflag("xo")) 924 putbool("xon", 1); 925 926 /* if pt, then hardware tabs are allowed, */ 927 /* with value of ta, default of ^I */ 928 if ((getinfostr("ht") == NULL) && oboolval[uselevel][cap_pt]) 929 if ((cap = getcapstr("ta")) == NULL) 930 putstr("ht", "\t"); 931 else 932 putstr("ht", cap); 933 934 /* The dX numbers are now stored as padding */ 935 /* in the appropriate terminfo string. */ 936 addpadding(onumval[uselevel][cap_dB], "cub1"); 937 addpadding(onumval[uselevel][cap_dC], "cr"); 938 addpadding(onumval[uselevel][cap_dF], "ff"); 939 addpadding(onumval[uselevel][cap_dN], "cud1"); 940 addpadding(onumval[uselevel][cap_dT], "ht"); 941 942 /* The ug and sg caps were essentially identical, */ 943 /* so ug almost never got used. We set sg from ug */ 944 /* if it hasn't already been set. */ 945 if (onumval[uselevel][cap_ug] >= 0 && (sg = otgetnum("sg")) < 0) 946 putnum("xmc", onumval[uselevel][cap_ug]); 947 else if ((onumval[uselevel][cap_ug] >= 0) && 948 (sg >= 0) && (onumval[uselevel][cap_ug] != sg)) 949 (void) fprintf(stderr, 950 "%s: TERM=%s: Warning: termcap sg and ug had different " 951 "values (%d<->%d).\n", progname, term_name, sg, 952 onumval[uselevel][cap_ug]); 953 954 /* The MT boolean was never really part of termcap, */ 955 /* but we can check for it anyways. */ 956 if (oboolval[uselevel][cap_MT] && !otgetflag("km")) 957 putbool("km", 1); 958 959 /* the rs string was renamed r2 (info rs2) */ 960 if ((ostrval[uselevel][cap_rs] != NULL) && 961 (ostrval[uselevel][cap_rs][0] != NULL)) 962 putstr("rs2", ostrval[uselevel][cap_rs]); 963 964 handleko(); 965 handlema(); 966} 967 968#define caddch(x) *to++ = (x) 969 970/* 971 * add the string to the string table 972 */ 973char * 974caddstr(char *to, char *str) 975{ 976 while (*str) 977 *to++ = *str++; 978 return (to); 979} 980 981/* If there is no padding info or parmed strings, */ 982/* then we do not need to copy the string. */ 983int 984needscopying(char *string) 985{ 986 /* any string at all? */ 987 if (string == NULL) 988 return (0); 989 990 /* any padding info? */ 991 if (ispadchar(*string)) 992 return (1); 993 994 /* any parmed info? */ 995 while (*string) 996 if (*string++ == '%') 997 return (1); 998 999 return (0); 1000} 1001 1002/* 1003 * Certain manipulations of the stack require strange manipulations of the 1004 * values that are on the stack. To handle these, we save the values of the 1005 * parameters in registers at the very beginning and make the changes in 1006 * the registers. We don't want to do this in the general case because of the 1007 * potential performance loss. 1008 */ 1009int 1010fancycap(char *string) 1011{ 1012 int parmset = 0; 1013 1014 while (*string) 1015 if (*string++ == '%') { 1016 switch (*string) { 1017 /* These manipulate just the top value on */ 1018 /* the stack, so we only have to do */ 1019 /* something strange if a %r follows. */ 1020 case '>': case 'B': case 'D': 1021 parmset = 1; 1022 break; 1023 /* If the parm has already been been */ 1024 /* pushed onto the stack by %>, then we */ 1025 /* can not reverse the parms and must get */ 1026 /* them from the registers. */ 1027 case 'r': 1028 if (parmset) 1029 return (1); 1030 break; 1031 /* This manipulates both parameters, so we */ 1032 /* cannot just do one and leave the value */ 1033 /* on the stack like we can with %>, */ 1034 /* %B or %D. */ 1035 case 'n': 1036 return (1); 1037 } 1038 string++; 1039 } 1040 return (0); 1041} 1042 1043/* 1044 * Change old style of doing calculations to the new stack style. 1045 * Note that this will not necessarily produce the most efficient string, 1046 * but it will work. 1047 */ 1048void 1049changecalculations() 1050{ 1051 int i, currentparm; 1052 char *from, *to = nextstring; 1053 int ch; 1054 int parmset, parmsaved; 1055 char padding[100], *saveto; 1056 1057 for (i = 0; strnames[i]; i++) 1058 if (needscopying(strval[uselevel][i])) { 1059 if (verbose) { 1060 (void) fprintf(trace, "%s needs copying, " 1061 "was:", strnames [i]); 1062 tpr(trace, strval[uselevel][i]); 1063 (void) fprintf(trace, ".\n"); 1064 } 1065 1066 from = strval[uselevel][i]; 1067 strval[uselevel][i] = to; 1068 currentparm = 1; 1069 parmset = 0; 1070 1071 /* Handle padding information. Save it so that it can be */ 1072 /* placed at the end of the string where it should */ 1073 /* have been in the first place. */ 1074 if (ispadchar(*from)) { 1075 saveto = to; 1076 to = padding; 1077 to = caddstr(to, "$<"); 1078 while (isdigit(*from) || *from == '.') 1079 caddch(*from++); 1080 if (*from == '*') 1081 caddch(*from++); 1082 caddch('>'); 1083 caddch('\0'); 1084 to = saveto; 1085 } else 1086 padding[0] = '\0'; 1087 1088 if (fancycap(from)) { 1089 to = caddstr(to, "%p1%Pa%p2%Pb"); 1090 parmsaved = 1; 1091 (void) fprintf(stderr, 1092 "%s: TERM=%s: Warning: the string " 1093 "produced for '%s' may be inefficient.\n", 1094 progname, term_name, strnames[i]); 1095 (void) fprintf(stderr, "It should be " 1096 "looked at by hand.\n"); 1097 } else 1098 parmsaved = 0; 1099 1100 while ((ch = *from++) != '\0') 1101 if (ch != '%') 1102 caddch(ch); 1103 else 1104 switch (ch = *from++) { 1105 case '.': /* %. -> %p1%c */ 1106 case 'd': /* %d -> %p1%d */ 1107 case '2': /* %2 -> %p1%2.2d */ 1108 case '3': /* %3 -> %p1%3.3d */ 1109 case '+': 1110 /* %+x -> %p1%'x'%+%c */ 1111 1112 case '>': 1113 /* %>xy -> %p1%Pc%?%'x'%> */ 1114 /* %t%gc%'y'%+ */ 1115 /* if current value > x, then add y. */ 1116 /* No output. */ 1117 1118 case 'B': 1119 /* %B: BCD */ 1120 /* (16*(x/10))+(x%10) */ 1121 /* No output. */ 1122 /* (Adds Regent 100) */ 1123 1124 case 'D': 1125 /* %D: Reverse coding */ 1126 /* (x-2*(x%16)) */ 1127 /* No output. */ 1128 /* (Delta Data) */ 1129 1130 if (!parmset) 1131 if (parmsaved) { 1132 to = caddstr(to, "%g"); 1133 if (currentparm == 1) 1134 caddch('a'); 1135 else 1136 caddch('b'); 1137 } else { 1138 to = caddstr(to, "%p"); 1139 if (currentparm == 1) 1140 caddch('1'); 1141 else 1142 caddch('2'); 1143 } 1144 currentparm = 3 - currentparm; 1145 parmset = 0; 1146 switch (ch) { 1147 case '.': 1148 to = caddstr(to, "%c"); 1149 break; 1150 case 'd': 1151 to = caddstr(to, "%d"); 1152 break; 1153 case '2': case '3': 1154#ifdef USG /* Vr2==USG, Vr3==SYSV. Use %02d for Vr2, %2.2d for Vr3 */ 1155 caddch('%'); 1156 caddch('0'); 1157#else 1158 caddch('%'); 1159 caddch(ch); 1160 caddch('.'); 1161#endif /* USG vs. SYSV */ 1162 caddch(ch); 1163 caddch('d'); 1164 break; 1165 case '+': 1166 to = caddstr(to, "%'"); 1167 caddch(*from++); 1168 to = caddstr(to, 1169 "'%+%c"); 1170 break; 1171 case '>': 1172 to = caddstr(to, 1173 "%Pc%?%'"); 1174 caddch(*from++); 1175 to = caddstr(to, 1176 "'%>%t%gc%'"); 1177 caddch(*from++); 1178 to = caddstr(to, 1179 "'%+"); 1180 parmset = 1; 1181 break; 1182 case 'B': 1183 to = caddstr(to, 1184"%Pc%gc%{10}%/%{16}%*%gc%{10}%m%+"); 1185 parmset = 1; 1186 break; 1187 1188 case 'D': 1189 to = caddstr(to, 1190"%Pc%gc%gc%{16}%m%{2}%*%-"); 1191 parmset = 1; 1192 break; 1193 } 1194 break; 1195 1196 /* %r reverses current parameter */ 1197 case 'r': 1198 currentparm = 3 - currentparm; 1199 break; 1200 1201 /* %n: exclusive-or row AND column */ 1202 /* with 0140, 96 decimal, no output */ 1203 /* (Datamedia 2500, Exidy Sorceror) */ 1204 case 'n': 1205 to = caddstr(to, 1206 "%ga%'`'%^%Pa"); 1207 to = caddstr(to, 1208 "%gb%'`'%^%Pb"); 1209 break; 1210 1211 /* assume %x means %x */ 1212 /* this includes %i and %% */ 1213 default: 1214 caddch('%'); 1215 caddch(ch); 1216 } 1217 to = caddstr(to, padding); 1218 caddch('\0'); 1219 1220 if (verbose) { 1221 (void) fprintf(trace, "and has become:"); 1222 tpr(trace, strval[uselevel][i]); 1223 (void) fprintf(trace, ".\n"); 1224 } 1225 } 1226 nextstring = to; 1227} 1228 1229static void 1230print_no_use_entry(void) 1231{ 1232 int i; 1233 1234 pr_heading("", buflongname); 1235 pr_bheading(); 1236 1237 for (i = 0; boolcodes[i]; i++) 1238 if (boolval[0][i]) 1239 pr_boolean(boolnames[i], (char *)0, (char *)0, 1); 1240 1241 pr_bfooting(); 1242 pr_sheading(); 1243 1244 for (i = 0; numcodes[i]; i++) 1245 if (numval[0][i] > -1) 1246 pr_number(numnames[i], (char *)0, (char *)0, 1247 numval[0][i]); 1248 1249 pr_nfooting(); 1250 pr_sheading(); 1251 1252 for (i = 0; strcodes[i]; i++) 1253 if (strval[0][i]) 1254 pr_string(strnames[i], (char *)0, (char *)0, 1255 strval[0][i]); 1256 1257 pr_sfooting(); 1258} 1259 1260static void 1261print_use_entry(char *usename) 1262{ 1263 int i; 1264 1265 pr_heading("", buflongname); 1266 pr_bheading(); 1267 1268 for (i = 0; boolcodes[i]; i++) 1269 if (boolval[0][i] && !boolval[1][i]) 1270 pr_boolean(boolnames[i], (char *)0, (char *)0, 1); 1271 else if (!boolval[0][i] && boolval[1][i]) 1272 pr_boolean(boolnames[i], (char *)0, (char *)0, -1); 1273 1274 pr_bfooting(); 1275 pr_nheading(); 1276 1277 for (i = 0; numcodes[i]; i++) 1278 if ((numval[0][i] > -1) && (numval[0][i] != numval[1][i])) 1279 pr_number(numnames[i], (char *)0, (char *)0, 1280 numval[0][i]); 1281 else if ((numval [0] [i] == -1) && (numval [1] [i] > -1)) 1282 pr_number(numnames[i], (char *)0, (char *)0, -1); 1283 1284 pr_nfooting(); 1285 pr_sheading(); 1286 1287 for (i = 0; strcodes[i]; i++) 1288 /* print out str[0] if: */ 1289 /* str[0] != NULL and str[1] == NULL, or str[0] != str[1] */ 1290 if (strval[0][i] && ((strval[1][i] == NULL) || 1291 (strcmp(strval[0][i], strval[1][i]) != 0))) 1292 pr_string(strnames[i], (char *)0, (char *)0, 1293 strval[0][i]); 1294 /* print out @ if str[0] == NULL and str[1] != NULL */ 1295 else if (strval[0][i] == NULL && strval[1][i] != NULL) 1296 pr_string(strnames[i], (char *)0, (char *)0, 1297 (char *)0); 1298 1299 pr_sfooting(); 1300 1301 (void) printf("\tuse=%s,\n", usename); 1302} 1303 1304static void 1305captoinfo(void) 1306{ 1307 char usename[512]; 1308 char *sterm_name; 1309 1310 if (term_name == NULL) { 1311 (void) fprintf(stderr, "%s: Null term_name given.\n", 1312 progname); 1313 return; 1314 } 1315 1316 if (verbose) 1317 (void) fprintf(trace, "changing cap to info, TERM=%s.\n", 1318 term_name); 1319 1320 uselevel = 0; 1321 if (filltables() == 0) 1322 return; 1323 getlongname(); 1324 adddefaults(); 1325 changecalculations(); 1326 if (TLHtcfound != 0) { 1327 uselevel = 1; 1328 if (verbose) 1329 (void) fprintf(trace, "use= found, %s uses %s.\n", 1330 term_name, TLHtcname); 1331 (void) strcpy(usename, TLHtcname); 1332 sterm_name = term_name; 1333 term_name = usename; 1334 if (filltables() == 0) 1335 return; 1336 adddefaults(); 1337 changecalculations(); 1338 term_name = sterm_name; 1339 print_use_entry(usename); 1340 } else 1341 print_no_use_entry(); 1342} 1343 1344 1345#include <signal.h> /* use this file to determine if this is SVR4.0 system */ 1346 1347static void 1348use_etc_termcap(void) 1349{ 1350 if (verbose) 1351#ifdef SIGSTOP 1352 (void) fprintf(trace, "reading from /usr/share/lib/termcap\n"); 1353#else /* SIGSTOP */ 1354 (void) fprintf(trace, "reading from /etc/termcap\n"); 1355#endif /* SIGSTOP */ 1356 term_name = getenv("TERM"); 1357 captoinfo(); 1358} 1359 1360static void 1361initdirname(void) 1362{ 1363#if defined(SYSV) || defined(USG) /* handle both Sys Vr2 and Vr3 curses */ 1364 (void) getcwd(dirname, BUFSIZ-2); 1365#else 1366 (void) getwd(dirname); 1367#endif /* SYSV || USG */ 1368 if (verbose) 1369 (void) fprintf(trace, "current directory name=%s.\n", dirname); 1370 environ = newenviron; 1371} 1372 1373static void 1374setfilename(char *capfile) 1375{ 1376 if (capfile [0] == '/') 1377 (void) snprintf(TERMCAP, sizeof (TERMCAP), 1378 "TERMCAP=%s", capfile); 1379 else 1380 (void) snprintf(TERMCAP, sizeof (TERMCAP), 1381 "TERMCAP=%s/%s", dirname, capfile); 1382 if (verbose) 1383 (void) fprintf(trace, "setting the environment for %s.\n", 1384 TERMCAP); 1385} 1386 1387static void 1388setterm_name(void) 1389{ 1390 if (verbose) 1391 (void) fprintf(trace, "setting the environment " 1392 "for TERM=%s.\n", term_name); 1393 (void) snprintf(TERM, sizeof (TERM), "TERM=%s", term_name); 1394} 1395 1396/* Look at the current line to see if it is a list of names. */ 1397/* If it is, return the first name in the list, else NULL. */ 1398/* As a side-effect, comment lines and blank lines */ 1399/* are copied to standard output. */ 1400 1401char * 1402getterm_name(char *line) 1403{ 1404 char *lineptr = line; 1405 1406 if (verbose) 1407 (void) fprintf(trace, "extracting name from '%s'.\n", line); 1408 1409 /* Copy comment lines out. */ 1410 if (*line == '#') { 1411 if (copycomments) 1412 (void) printf("%s", line); 1413 } 1414 /* Blank lines get copied too. */ 1415 else if (isspace (*line)) { 1416 if (copycomments) { 1417 for (; *lineptr; lineptr++) 1418 if (!isspace(*lineptr)) 1419 break; 1420 if (*lineptr == '\0') 1421 (void) printf("\n"); 1422 } 1423 } 1424 else 1425 for (; *lineptr; lineptr++) 1426 if (*lineptr == '|' || *lineptr == ':') { 1427 *lineptr = '\0'; 1428 if (verbose) 1429 (void) fprintf(trace, 1430 "returning %s.\n", line); 1431 return (line); 1432 } 1433 if (verbose) 1434 (void) fprintf(trace, "returning NULL.\n"); 1435 return (NULL); 1436} 1437 1438static void 1439use_file(char *filename) 1440{ 1441 FILE *termfile; 1442 char buffer[BUFSIZ]; 1443 1444 if (verbose) 1445 (void) fprintf(trace, "reading from %s.\n", filename); 1446 1447 if ((termfile = fopen(filename, "r")) == NULL) { 1448 (void) fprintf(stderr, "%s: cannot open %s for reading.\n", 1449 progname, filename); 1450 return; 1451 } 1452 1453 copycomments++; 1454 setfilename(filename); 1455 1456 while (fgets(buffer, BUFSIZ, termfile) != NULL) { 1457 if ((term_name = getterm_name(buffer)) != NULL) { 1458 setterm_name(); 1459 captoinfo(); 1460 } 1461 } 1462} 1463 1464/* 1465 * Sort a name and code table pair according to the name table. 1466 * Use a simple bubble sort for now. Too bad I can't call qsort(3). 1467 * At least I only have to do it once for each table. 1468 */ 1469static void 1470sorttable(char *nametable[], char *codetable[]) 1471{ 1472 int i, j; 1473 char *c; 1474 1475 for (i = 0; nametable[i]; i++) 1476 for (j = 0; j < i; j++) 1477 if (strcmp(nametable[i], nametable[j]) < 0) { 1478 c = nametable[i]; 1479 nametable[i] = nametable[j]; 1480 nametable[j] = c; 1481 c = codetable[i]; 1482 codetable[i] = codetable[j]; 1483 codetable[j] = c; 1484 } 1485} 1486 1487/* 1488 * Initialize and sort the name and code tables. Allocate space for the 1489 * value tables. 1490 */ 1491static void 1492inittables(void) 1493{ 1494 unsigned int i; 1495 1496 for (i = 0; boolnames [i]; i++) 1497 ; 1498 boolval[0] = (char *)malloc(i * sizeof (char)); 1499 boolval[1] = (char *)malloc(i * sizeof (char)); 1500 boolcount = i; 1501 sorttable(boolnames, boolcodes); 1502 1503 for (i = 0; numcodes [i]; i++) 1504 ; 1505 numval[0] = (short *)malloc(i * sizeof (short)); 1506 numval[1] = (short *)malloc(i * sizeof (short)); 1507 numcount = i; 1508 sorttable(numnames, numcodes); 1509 1510 for (i = 0; strcodes [i]; i++) 1511 ; 1512 strval[0] = (char **)malloc(i * sizeof (char *)); 1513 strval[1] = (char **)malloc(i * sizeof (char *)); 1514 strcount = i; 1515 sorttable(strnames, strcodes); 1516} 1517 1518int 1519main(int argc, char **argv) 1520{ 1521 int c; 1522 char _capbuffer [8192]; 1523 char _bp [TBUFSIZE]; 1524 char _buflongname [128]; 1525 1526 capbuffer = &_capbuffer[0]; 1527 bp = &_bp[0]; 1528 buflongname = &_buflongname[0]; 1529 progname = argv[0]; 1530 1531 while ((c = getopt(argc, argv, "1vVw:")) != EOF) 1532 switch (c) { 1533 case '1': 1534 pr_onecolumn(1); 1535 break; 1536 case 'w': 1537 pr_width(atoi(optarg)); 1538 break; 1539 case 'v': 1540 verbose++; 1541 break; 1542 case 'V': 1543 (void) printf("%s: version %s\n", progname, 1544 "@(#)curses:screen/captoinfo.c 1.12"); 1545 (void) fflush(stdout); 1546 exit(0); 1547 /* FALLTHROUGH (not really) */ 1548 case '?': 1549 (void) fprintf(stderr, 1550 "usage: %s [-1Vv] [-w width] " 1551 "[filename ...]\n", progname); 1552 (void) fprintf(stderr, "\t-1\tsingle column " 1553 "output\n"); 1554 (void) fprintf(stderr, 1555 "\t-v\tverbose debugging output\n"); 1556 (void) fprintf(stderr, 1557 "\t-V\tprint program version\n"); 1558 exit(-1); 1559 } 1560 1561 /* initialize */ 1562 pr_init(pr_terminfo); 1563 inittables(); 1564 1565 if (optind >= argc) 1566 use_etc_termcap(); 1567 else { 1568 initdirname(); 1569 for (; optind < argc; optind++) 1570 use_file(argv [optind]); 1571 } 1572 1573 return (0); 1574} 1575 1576/* fake out the modules in print.c so we don't have to load in */ 1577/* cexpand.c and infotocap.c */ 1578/* ARGSUSED */ 1579int 1580cpr(FILE *stream, char *string) 1581{ 1582 return (0); 1583} 1584