1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 /*
33 * NAME
34 * captoinfo - convert a termcap description to a terminfo description
35 *
36 * SYNOPSIS
37 * captoinfo [-1vV] [-w width] [ filename ... ]
38 *
39 * AUTHOR
40 * Tony Hansen, January 22, 1984.
41 */
42
43 #include "curses.h"
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include "otermcap.h"
49 #include "print.h"
50
51 #define trace stderr /* send trace messages to stderr */
52
53 /* extra termcap variables no longer in terminfo */
54 char *oboolcodes[] =
55 {
56 "bs", /* Terminal can backspace with "^H" */
57 "nc", /* No correctly working carriage return (DM2500,H2000) */
58 "ns", /* Terminal is a CRT but does not scroll. */
59 "pt", /* Has hardware tabs (may need to be set with "is") */
60 "MT", /* Has meta key, alternate code. */
61 "xr", /* Return acts like ce \r \n (Delta Data) */
62 0
63 };
64 int cap_bs = 0, cap_nc = 1, cap_ns = 2, cap_pt = 3, cap_MT = 4, cap_xr = 5;
65 char *onumcodes[] =
66 {
67 "dB", /* Number of millisec of bs delay needed */
68 "dC", /* Number of millisec of cr delay needed */
69 "dF", /* Number of millisec of ff delay needed */
70 "dN", /* Number of millisec of nl delay needed */
71 "dT", /* Number of millisec of tab delay needed */
72 "ug", /* Number of blank chars left by us or ue */
73 /* Ignore the 'kn' number. It was ill-defined and never used. */
74 "kn", /* Number of "other" keys */
75 0
76 };
77 int cap_dB = 0, cap_dC = 1, cap_dF = 2, cap_dN = 3, cap_dT = 4, cap_ug = 5;
78
79 char *ostrcodes[] =
80 {
81 "bc", /* Backspace if not "^H" */
82 "ko", /* Termcap entries for other non-function keys */
83 "ma", /* Arrow key map, used by vi version 2 only */
84 "nl", /* Newline character (default "\n") */
85 "rs", /* undocumented reset string, like is (info is2) */
86 /* Ignore the 'ml' and 'mu' strings. */
87 "ml", /* Memory lock on above cursor. */
88 "mu", /* Memory unlock (turn off memory lock). */
89 0
90 };
91 int cap_bc = 0, cap_ko = 1, cap_ma = 2, cap_nl = 3, cap_rs = 4;
92
93 #define numelements(x) (sizeof (x)/sizeof (x[0]))
94 char oboolval[2][numelements(oboolcodes)];
95 short onumval[2][numelements(onumcodes)];
96 char *ostrval[2][numelements(ostrcodes)];
97
98 /* externs from libcurses.a */
99 extern char *boolnames[], *boolcodes[];
100 extern char *numnames[], *numcodes[];
101 extern char *strnames[], *strcodes[];
102
103 /* globals for this file */
104 char *progname; /* argv [0], the name of the program */
105 static char *term_name; /* the name of the terminal being worked on */
106 static int uselevel; /* whether we're dealing with use= info */
107 static int boolcount, /* the maximum numbers of each name array */
108 numcount,
109 strcount;
110
111 /* globals dealing with the environment */
112 extern char **environ;
113 static char TERM[100];
114 #if defined(SYSV) || defined(USG) /* handle both Sys Vr2 and Vr3 curses */
115 static char dirname[BUFSIZ];
116 #else
117 #include <sys/param.h>
118 static char dirname[MAXPATHLEN];
119 #endif /* SYSV || USG */
120 static char TERMCAP[BUFSIZ+15];
121 static char *newenviron[] = { &TERM[0], &TERMCAP[0], 0 };
122
123 /* dynamic arrays */
124 static char *boolval[2]; /* dynamic array of boolean values */
125 static short *numval[2]; /* dynamic array of numeric values */
126 static char **strval[2]; /* dynamic array of string pointers */
127
128 /* data buffers */
129 static char *capbuffer; /* string table, pointed at by strval */
130 static char *nextstring; /* pointer into string table */
131 static char *bp; /* termcap raw string table */
132 static char *buflongname; /* place to copy the long names */
133
134 /* flags */
135 static int verbose = 0; /* debugging printing level */
136 static int copycomments = 0; /* copy comments from tercap source */
137
138 #define ispadchar(c) (isdigit(c) || (c) == '.' || (c) == '*')
139
140 static void getlongname(void);
141 static void handleko(void);
142 static void handlema(void);
143 static void print_no_use_entry(void);
144 static void print_use_entry(char *);
145 static void captoinfo(void);
146 static void use_etc_termcap(void);
147 static void initdirname(void);
148 static void setfilename(char *);
149 static void setterm_name(void);
150 static void use_file(char *);
151 static void sorttable(char *[], char *[]);
152 static void inittables(void);
153
154 /*
155 * Verify that the names given in the termcap entry are all valid.
156 */
157
158 int
capsearch(char * codes[],char * ocodes[],char * cap)159 capsearch(char *codes[], char *ocodes[], char *cap)
160 {
161 for (; *codes; codes++)
162 if (((*codes)[0] == cap[0]) && ((*codes)[1] == cap[1]))
163 return (1);
164
165 for (; *ocodes; ocodes++)
166 if (((*ocodes)[0] == cap[0]) && ((*ocodes)[1] == cap[1]))
167 return (1);
168
169 return (0);
170 }
171
172 void
checktermcap()173 checktermcap()
174 {
175 char *tbuf = bp;
176 enum { tbool, tnum, tstr, tcancel, tunknown } type;
177
178 for (;;) {
179 tbuf = tskip(tbuf);
180 while (*tbuf == '\t' || *tbuf == ' ' || *tbuf == ':')
181 tbuf++;
182
183 if (*tbuf == 0)
184 return;
185
186 /* commented out entry? */
187 if (*tbuf == '.') {
188 if (verbose)
189 (void) fprintf(trace, "termcap string '%c%c' "
190 "commented out.\n", tbuf[1], tbuf[2]);
191 if (!capsearch(boolcodes, oboolcodes, tbuf + 1) &&
192 !capsearch(numcodes, onumcodes, tbuf + 1) &&
193 !capsearch(strcodes, ostrcodes, tbuf + 1))
194 (void) fprintf(stderr,
195 "%s: TERM=%s: commented out code '%.2s' "
196 "is unknown.\n", progname, term_name,
197 tbuf+1);
198 continue;
199 }
200
201 if (verbose)
202 (void) fprintf(trace, "looking at termcap string "
203 "'%.2s'.\n", tbuf);
204
205 switch (tbuf[2]) {
206 case ':': case '\0': type = tbool; break;
207 case '#': type = tnum; break;
208 case '=': type = tstr; break;
209 case '@': type = tcancel; break;
210 default:
211 (void) fprintf(stderr,
212 "%s: TERM=%s: unknown type given for the "
213 "termcap code '%.2s'.\n", progname,
214 term_name, tbuf);
215 type = tunknown;
216 }
217
218 if (verbose > 1)
219 (void) fprintf(trace, "type of '%.2s' is %s.\n", tbuf,
220 (type == tbool) ? "boolean" :
221 (type == tnum) ? "numeric" :
222 (type = tstr) ? "string" :
223 (type = tcancel) ? "canceled" : "unknown");
224
225 /* look for the name in bools */
226 if (capsearch(boolcodes, oboolcodes, tbuf)) {
227 if (type != tbool && type != tcancel)
228 (void) fprintf(stderr,
229 "%s: TERM=%s: wrong type given for the "
230 "boolean termcap code '%.2s'.\n", progname,
231 term_name, tbuf);
232 continue;
233 }
234
235 /* look for the name in nums */
236 if (capsearch(numcodes, onumcodes, tbuf)) {
237 if (type != tnum && type != tcancel)
238 (void) fprintf(stderr,
239 "%s: TERM=%s: wrong type given for the "
240 "numeric termcap code '%.2s'.\n", progname,
241 term_name, tbuf);
242 continue;
243 }
244
245 /* look for the name in strs */
246 if (capsearch(strcodes, ostrcodes, tbuf)) {
247 if (type != tstr && type != tcancel)
248 (void) fprintf(stderr,
249 "%s: TERM=%s: wrong type given for the "
250 "string termcap code '%.2s'.\n", progname,
251 term_name, tbuf);
252 continue;
253 }
254
255 (void) fprintf(stderr,
256 "%s: TERM=%s: the %s termcap code '%.2s' is not a valid "
257 "name.\n", progname, term_name,
258 (type == tbool) ? "boolean" :
259 (type == tnum) ? "numeric" :
260 (type = tstr) ? "string" :
261 (type = tcancel) ? "canceled" : "(unknown type)", tbuf);
262 }
263 }
264
265 /*
266 * Fill up the termcap tables.
267 */
268 int
filltables(void)269 filltables(void)
270 {
271 int i, tret;
272
273 /* Retrieve the termcap entry. */
274 if ((tret = otgetent(bp, term_name)) != 1) {
275 (void) fprintf(stderr,
276 "%s: TERM=%s: tgetent failed with return code %d (%s).\n",
277 progname, term_name, tret,
278 (tret == 0) ? "non-existent or invalid entry" :
279 (tret == -1) ? "cannot open $TERMCAP" : "unknown reason");
280 return (0);
281 }
282
283 if (verbose) {
284 (void) fprintf(trace, "bp=");
285 (void) cpr(trace, bp);
286 (void) fprintf(trace, ".\n");
287 }
288
289 if (uselevel == 0)
290 checktermcap();
291
292 /* Retrieve the values that are in terminfo. */
293
294 /* booleans */
295 for (i = 0; boolcodes[i]; i++) {
296 boolval[uselevel][i] = otgetflag(boolcodes[i]);
297 if (verbose > 1) {
298 (void) fprintf(trace, "boolcodes=%s, ", boolcodes[i]);
299 (void) fprintf(trace, "boolnames=%s, ", boolnames[i]);
300 (void) fprintf(trace,
301 "flag=%d.\n", boolval[uselevel][i]);
302 }
303 }
304
305 /* numbers */
306 for (i = 0; numcodes[i]; i++) {
307 numval[uselevel][i] = otgetnum(numcodes[i]);
308 if (verbose > 1) {
309 (void) fprintf(trace, "numcodes=%s, ", numcodes[i]);
310 (void) fprintf(trace, "numnames=%s, ", numnames[i]);
311 (void) fprintf(trace, "num=%d.\n", numval[uselevel][i]);
312 }
313 }
314
315 if (uselevel == 0)
316 nextstring = capbuffer;
317
318 /* strings */
319 for (i = 0; strcodes[i]; i++) {
320 strval[uselevel][i] = otgetstr(strcodes[i], &nextstring);
321 if (verbose > 1) {
322 (void) fprintf(trace, "strcodes=%s, ", strcodes [i]);
323 (void) fprintf(trace, "strnames=%s, ", strnames [i]);
324 if (strval[uselevel][i]) {
325 (void) fprintf(trace, "str=");
326 tpr(trace, strval[uselevel][i]);
327 (void) fprintf(trace, ".\n");
328 }
329 else
330 (void) fprintf(trace, "str=NULL.\n");
331 }
332 /* remove zero length strings */
333 if (strval[uselevel][i] && (strval[uselevel][i][0] == '\0')) {
334 (void) fprintf(stderr,
335 "%s: TERM=%s: cap %s (info %s) is NULL: REMOVED\n",
336 progname, term_name, strcodes[i], strnames[i]);
337 strval[uselevel][i] = NULL;
338 }
339 }
340
341 /* Retrieve the values not found in terminfo anymore. */
342
343 /* booleans */
344 for (i = 0; oboolcodes[i]; i++) {
345 oboolval[uselevel][i] = otgetflag(oboolcodes[i]);
346 if (verbose > 1) {
347 (void) fprintf(trace, "oboolcodes=%s, ",
348 oboolcodes[i]);
349 (void) fprintf(trace, "flag=%d.\n",
350 oboolval[uselevel][i]);
351 }
352 }
353
354 /* numbers */
355 for (i = 0; onumcodes[i]; i++) {
356 onumval[uselevel][i] = otgetnum(onumcodes[i]);
357 if (verbose > 1) {
358 (void) fprintf(trace, "onumcodes=%s, ", onumcodes[i]);
359 (void) fprintf(trace, "num=%d.\n",
360 onumval[uselevel][i]);
361 }
362 }
363
364 /* strings */
365 for (i = 0; ostrcodes[i]; i++) {
366 ostrval[uselevel][i] = otgetstr(ostrcodes[i], &nextstring);
367 if (verbose > 1) {
368 (void) fprintf(trace, "ostrcodes=%s, ", ostrcodes[i]);
369 if (ostrval[uselevel][i]) {
370 (void) fprintf(trace, "ostr=");
371 tpr(trace, ostrval[uselevel][i]);
372 (void) fprintf(trace, ".\n");
373 }
374 else
375 (void) fprintf(trace, "ostr=NULL.\n");
376 }
377 /* remove zero length strings */
378 if (ostrval[uselevel][i] && (ostrval[uselevel][i][0] == '\0')) {
379 (void) fprintf(stderr,
380 "%s: TERM=%s: cap %s (no terminfo name) is NULL: "
381 "REMOVED\n", progname, term_name, ostrcodes[i]);
382 ostrval[uselevel][i] = NULL;
383 }
384 }
385 return (1);
386 }
387
388 /*
389 * This routine copies the set of names from the termcap entry into
390 * a separate buffer, getting rid of the old obsolete two character
391 * names.
392 */
393 static void
getlongname(void)394 getlongname(void)
395 {
396 char *b = &bp[0], *l = buflongname;
397
398 /* Skip the two character name */
399 if (bp[2] == '|')
400 b = &bp[3];
401
402 /* Copy the rest of the names */
403 while (*b && *b != ':')
404 *l++ = *b++;
405 *l = '\0';
406
407 if (b != &bp[0]) {
408 (void) fprintf(stderr, "%s: obsolete 2 character name "
409 "'%2.2s' removed.\n", progname, bp);
410 (void) fprintf(stderr, "\tsynonyms are: '%s'\n", buflongname);
411 }
412 }
413
414 /*
415 * Return the value of the termcap string 'capname' as stored in our list.
416 */
417 char *
getcapstr(char * capname)418 getcapstr(char *capname)
419 {
420 int i;
421
422 if (verbose > 1)
423 (void) fprintf(trace, "looking for termcap value of %s.\n",
424 capname);
425
426 /* Check the old termcap list. */
427 for (i = 0; ostrcodes[i]; i++)
428 if (strcmp(ostrcodes[i], capname) == 0) {
429 if (verbose > 1) {
430 (void) fprintf(trace, "\tvalue is:");
431 tpr(trace, ostrval[uselevel][i]);
432 (void) fprintf(trace, ".\n");
433 }
434 return (ostrval[uselevel][i]);
435 }
436
437 if (verbose > 1)
438 (void) fprintf(trace, "termcap name '%s' not found in "
439 "ostrcodes.\n", capname);
440
441 /* Check the terminfo list. */
442 for (i = 0; strcodes[i]; i++)
443 if (strcmp(strcodes[i], capname) == 0) {
444 if (verbose > 1) {
445 (void) fprintf(trace, "\tvalue is:");
446 tpr(trace, strval[uselevel][i]);
447 (void) fprintf(trace, ".\n");
448 }
449 return (strval[uselevel][i]);
450 }
451
452 (void) fprintf(stderr, "%s: TERM=%s: termcap name '%s' not found.\n",
453 progname, term_name, capname);
454
455 return ((char *)NULL);
456 }
457
458 /*
459 * Search for a name in the given table and
460 * return the index.
461 * Someday I'll redo this to use bsearch().
462 */
463 /* ARGSUSED */
464 int
search(char * names[],int max,char * infoname)465 search(char *names[], int max, char *infoname)
466 {
467 #ifndef BSEARCH
468 int i;
469 for (i = 0; names [i] != NULL; i++)
470 if (strcmp(names [i], infoname) == 0)
471 return (i);
472 return (-1);
473 #else /* this doesn't work for some reason */
474 char **bret;
475
476 bret = (char **)bsearch(infoname, (char *)names, max,
477 sizeof (char *), strcmp);
478 (void) fprintf(trace, "search looking for %s.\n", infoname);
479 (void) fprintf(trace, "base=%#x, bret=%#x, nel=%d.\n", names,
480 bret, max);
481 (void) fprintf(trace, "returning %d.\n", bret == NULL ? -1 :
482 bret - names);
483 if (bret == NULL)
484 return (-1);
485 else
486 return (bret - names);
487 #endif /* OLD */
488 }
489
490 /*
491 * return the value of the terminfo string 'infoname'
492 */
493 char *
getinfostr(char * infoname)494 getinfostr(char *infoname)
495 {
496 int i;
497
498 if (verbose > 1)
499 (void) fprintf(trace, "looking for terminfo value of %s.\n",
500 infoname);
501
502 i = search(strnames, strcount, infoname);
503 if (i != -1) {
504 if (verbose > 1) {
505 (void) fprintf(trace, "\tvalue is:");
506 tpr(trace, strval[uselevel][i]);
507 (void) fprintf(trace, ".\n");
508 }
509 return (strval[uselevel][i]);
510 }
511
512 if (verbose > 1)
513 (void) fprintf(trace, "terminfo name '%s' not found.\n",
514 infoname);
515
516 return ((char *)NULL);
517 }
518
519 /*
520 * Replace the value stored for the terminfo boolean
521 * capability 'infoname' with the newvalue.
522 */
523 void
putbool(char * infoname,int newvalue)524 putbool(char *infoname, int newvalue)
525 {
526 int i;
527
528 if (verbose > 1)
529 (void) fprintf(trace, "changing value for %s to %d.\n",
530 infoname, newvalue);
531
532 i = search(boolnames, boolcount, infoname);
533 if (i != -1) {
534 if (verbose > 1)
535 (void) fprintf(trace, "value was: %d.\n",
536 boolval[uselevel][i]);
537
538 boolval[uselevel][i] = newvalue;
539 return;
540 }
541
542 (void) fprintf(stderr, "%s: TERM=%s: the boolean name '%s' was not "
543 "found!\n", progname, term_name, infoname);
544 }
545
546 /*
547 * Replace the value stored for the terminfo number
548 * capability 'infoname' with the newvalue.
549 */
550 void
putnum(char * infoname,int newvalue)551 putnum(char *infoname, int newvalue)
552 {
553 int i;
554
555 if (verbose > 1)
556 (void) fprintf(trace, "changing value for %s to %d.\n",
557 infoname, newvalue);
558
559 i = search(numnames, numcount, infoname);
560 if (i != -1) {
561 if (verbose > 1)
562 (void) fprintf(trace, "value was: %d.\n",
563 numval[uselevel][i]);
564
565 numval[uselevel][i] = newvalue;
566 return;
567 }
568
569 (void) fprintf(stderr, "%s: TERM=%s: the numeric name '%s' was not "
570 "found!\n",
571 progname, term_name, infoname);
572 }
573
574 /*
575 * replace the value stored for the terminfo string capability 'infoname'
576 * with the newvalue.
577 */
578 void
putstr(char * infoname,char * newvalue)579 putstr(char *infoname, char *newvalue)
580 {
581 int i;
582
583 if (verbose > 1) {
584 (void) fprintf(trace, "changing value for %s to ", infoname);
585 tpr(trace, newvalue);
586 (void) fprintf(trace, ".\n");
587 }
588
589 i = search(strnames, strcount, infoname);
590 if (i != -1) {
591 if (verbose > 1) {
592 (void) fprintf(trace, "value was:");
593 tpr(trace, strval[uselevel][i]);
594 (void) fprintf(trace, ".\n");
595 }
596 strval[uselevel][i] = nextstring;
597 while (*newvalue)
598 *nextstring++ = *newvalue++;
599 *nextstring++ = '\0';
600 return;
601 }
602
603 (void) fprintf(stderr, "%s: TERM=%s: the string name '%s' was not "
604 "found!\n",
605 progname, term_name, infoname);
606 }
607
608 /*
609 * Add in extra delays if they are not recorded already.
610 * This is done before the padding information has been modified by
611 * changecalculations() below, so the padding information, if there
612 * already, is still at the beginning of the string in termcap format.
613 */
614 void
addpadding(int cappadding,char * infostr)615 addpadding(int cappadding, char *infostr)
616 {
617 char *cap;
618 char tempbuffer [100];
619
620 /* Is there padding to add? */
621 if (cappadding > 0)
622 /* Is there a string to add it to? */
623 if (cap = getinfostr(infostr))
624 /* Is there any padding info already? */
625 if (ispadchar(*cap)) {
626 /* EMPTY */;
627 /* Assume that the padding info that is there is correct. */
628 } else {
629 /* Add the padding at the end of the present string. */
630 (void) snprintf(tempbuffer, sizeof (tempbuffer),
631 "%s$<%d>", cap, cappadding);
632 putstr(infostr, tempbuffer);
633 } else {
634 /* Create a new string that only has the padding. */
635 (void) sprintf(tempbuffer, "$<%d>", cappadding);
636 putstr(infostr, tempbuffer);
637 }
638 }
639
640 struct
641 {
642 char *capname;
643 char *keyedinfoname;
644 } ko_map[] = {
645 "al", "kil1",
646 "bs", "kbs", /* special addition */
647 "bt", "kcbt",
648 "cd", "ked",
649 "ce", "kel",
650 "cl", "kclr",
651 "ct", "ktbc",
652 "dc", "kdch1",
653 "dl", "kdl1",
654 "do", "kcud1",
655 "ei", "krmir",
656 "ho", "khome",
657 "ic", "kich1",
658 "im", "kich1", /* special addition */
659 "le", "kcub1",
660 "ll", "kll",
661 "nd", "kcuf1",
662 "sf", "kind",
663 "sr", "kri",
664 "st", "khts",
665 "up", "kcuu1",
666 /* "", "kctab", */
667 /* "", "knp", */
668 /* "", "kpp", */
669 0, 0
670 };
671
672 /*
673 * Work with the ko string. It is a comma separated list of keys for which
674 * the keyboard has a key by the same name that emits the same sequence.
675 * For example, ko = dc, im, ei means that there are keys called
676 * delete-character, enter-insert-mode and exit-insert-mode on the keyboard,
677 * and they emit the same sequences as specified in the dc, im and ei
678 * capabilities.
679 */
680 static void
handleko(void)681 handleko(void)
682 {
683 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)
759 struct
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
786 void
prchar(FILE * stream,int c)787 prchar(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
795 static void
handlema(void)796 handlema(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 */
876 void
adddefaults(void)877 adddefaults(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 */
973 char *
caddstr(char * to,char * str)974 caddstr(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. */
983 int
needscopying(char * string)984 needscopying(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 */
1009 int
fancycap(char * string)1010 fancycap(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 */
1048 void
changecalculations()1049 changecalculations()
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
1229 static void
print_no_use_entry(void)1230 print_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
1260 static void
print_use_entry(char * usename)1261 print_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
1304 static void
captoinfo(void)1305 captoinfo(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
1347 static void
use_etc_termcap(void)1348 use_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
1360 static void
initdirname(void)1361 initdirname(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
1373 static void
setfilename(char * capfile)1374 setfilename(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
1387 static void
setterm_name(void)1388 setterm_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
1401 char *
getterm_name(char * line)1402 getterm_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
1438 static void
use_file(char * filename)1439 use_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 */
1469 static void
sorttable(char * nametable[],char * codetable[])1470 sorttable(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 */
1491 static void
inittables(void)1492 inittables(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
1518 int
main(int argc,char ** argv)1519 main(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 */
1579 int
cpr(FILE * stream,char * string)1580 cpr(FILE *stream, char *string)
1581 {
1582 return (0);
1583 }
1584