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 /*
31 * NAME
32 * captoinfo - convert a termcap description to a terminfo description
33 *
34 * SYNOPSIS
35 * captoinfo [-1vV] [-w width] [ filename ... ]
36 *
37 * AUTHOR
38 * Tony Hansen, January 22, 1984.
39 */
40
41 #include "curses.h"
42 #include <ctype.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include "otermcap.h"
47 #include "print.h"
48
49 #define trace stderr /* send trace messages to stderr */
50
51 /* extra termcap variables no longer in terminfo */
52 char *oboolcodes[] =
53 {
54 "bs", /* Terminal can backspace with "^H" */
55 "nc", /* No correctly working carriage return (DM2500,H2000) */
56 "ns", /* Terminal is a CRT but does not scroll. */
57 "pt", /* Has hardware tabs (may need to be set with "is") */
58 "MT", /* Has meta key, alternate code. */
59 "xr", /* Return acts like ce \r \n (Delta Data) */
60 0
61 };
62 int cap_bs = 0, cap_nc = 1, cap_ns = 2, cap_pt = 3, cap_MT = 4, cap_xr = 5;
63 char *onumcodes[] =
64 {
65 "dB", /* Number of millisec of bs delay needed */
66 "dC", /* Number of millisec of cr delay needed */
67 "dF", /* Number of millisec of ff delay needed */
68 "dN", /* Number of millisec of nl delay needed */
69 "dT", /* Number of millisec of tab delay needed */
70 "ug", /* Number of blank chars left by us or ue */
71 /* Ignore the 'kn' number. It was ill-defined and never used. */
72 "kn", /* Number of "other" keys */
73 0
74 };
75 int cap_dB = 0, cap_dC = 1, cap_dF = 2, cap_dN = 3, cap_dT = 4, cap_ug = 5;
76
77 char *ostrcodes[] =
78 {
79 "bc", /* Backspace if not "^H" */
80 "ko", /* Termcap entries for other non-function keys */
81 "ma", /* Arrow key map, used by vi version 2 only */
82 "nl", /* Newline character (default "\n") */
83 "rs", /* undocumented reset string, like is (info is2) */
84 /* Ignore the 'ml' and 'mu' strings. */
85 "ml", /* Memory lock on above cursor. */
86 "mu", /* Memory unlock (turn off memory lock). */
87 0
88 };
89 int cap_bc = 0, cap_ko = 1, cap_ma = 2, cap_nl = 3, cap_rs = 4;
90
91 #define numelements(x) (sizeof (x)/sizeof (x[0]))
92 char oboolval[2][numelements(oboolcodes)];
93 short onumval[2][numelements(onumcodes)];
94 char *ostrval[2][numelements(ostrcodes)];
95
96 /* externs from libcurses.a */
97 extern char *boolnames[], *boolcodes[];
98 extern char *numnames[], *numcodes[];
99 extern char *strnames[], *strcodes[];
100
101 /* globals for this file */
102 char *progname; /* argv [0], the name of the program */
103 static char *term_name; /* the name of the terminal being worked on */
104 static int uselevel; /* whether we're dealing with use= info */
105 static int boolcount, /* the maximum numbers of each name array */
106 numcount,
107 strcount;
108
109 /* globals dealing with the environment */
110 extern char **environ;
111 static char TERM[100];
112 #if defined(SYSV) || defined(USG) /* handle both Sys Vr2 and Vr3 curses */
113 static char dirname[BUFSIZ];
114 #else
115 #include <sys/param.h>
116 static char dirname[MAXPATHLEN];
117 #endif /* SYSV || USG */
118 static char TERMCAP[BUFSIZ+15];
119 static char *newenviron[] = { &TERM[0], &TERMCAP[0], 0 };
120
121 /* dynamic arrays */
122 static char *boolval[2]; /* dynamic array of boolean values */
123 static short *numval[2]; /* dynamic array of numeric values */
124 static char **strval[2]; /* dynamic array of string pointers */
125
126 /* data buffers */
127 static char *capbuffer; /* string table, pointed at by strval */
128 static char *nextstring; /* pointer into string table */
129 static char *bp; /* termcap raw string table */
130 static char *buflongname; /* place to copy the long names */
131
132 /* flags */
133 static int verbose = 0; /* debugging printing level */
134 static int copycomments = 0; /* copy comments from tercap source */
135
136 #define ispadchar(c) (isdigit(c) || (c) == '.' || (c) == '*')
137
138 static void getlongname(void);
139 static void handleko(void);
140 static void handlema(void);
141 static void print_no_use_entry(void);
142 static void print_use_entry(char *);
143 static void captoinfo(void);
144 static void use_etc_termcap(void);
145 static void initdirname(void);
146 static void setfilename(char *);
147 static void setterm_name(void);
148 static void use_file(char *);
149 static void sorttable(char *[], char *[]);
150 static void inittables(void);
151
152 /*
153 * Verify that the names given in the termcap entry are all valid.
154 */
155
156 int
capsearch(char * codes[],char * ocodes[],char * cap)157 capsearch(char *codes[], char *ocodes[], char *cap)
158 {
159 for (; *codes; codes++)
160 if (((*codes)[0] == cap[0]) && ((*codes)[1] == cap[1]))
161 return (1);
162
163 for (; *ocodes; ocodes++)
164 if (((*ocodes)[0] == cap[0]) && ((*ocodes)[1] == cap[1]))
165 return (1);
166
167 return (0);
168 }
169
170 void
checktermcap()171 checktermcap()
172 {
173 char *tbuf = bp;
174 enum { tbool, tnum, tstr, tcancel, tunknown } type;
175
176 for (;;) {
177 tbuf = tskip(tbuf);
178 while (*tbuf == '\t' || *tbuf == ' ' || *tbuf == ':')
179 tbuf++;
180
181 if (*tbuf == 0)
182 return;
183
184 /* commented out entry? */
185 if (*tbuf == '.') {
186 if (verbose)
187 (void) fprintf(trace, "termcap string '%c%c' "
188 "commented out.\n", tbuf[1], tbuf[2]);
189 if (!capsearch(boolcodes, oboolcodes, tbuf + 1) &&
190 !capsearch(numcodes, onumcodes, tbuf + 1) &&
191 !capsearch(strcodes, ostrcodes, tbuf + 1))
192 (void) fprintf(stderr,
193 "%s: TERM=%s: commented out code '%.2s' "
194 "is unknown.\n", progname, term_name,
195 tbuf+1);
196 continue;
197 }
198
199 if (verbose)
200 (void) fprintf(trace, "looking at termcap string "
201 "'%.2s'.\n", tbuf);
202
203 switch (tbuf[2]) {
204 case ':': case '\0': type = tbool; break;
205 case '#': type = tnum; break;
206 case '=': type = tstr; break;
207 case '@': type = tcancel; break;
208 default:
209 (void) fprintf(stderr,
210 "%s: TERM=%s: unknown type given for the "
211 "termcap code '%.2s'.\n", progname,
212 term_name, tbuf);
213 type = tunknown;
214 }
215
216 if (verbose > 1)
217 (void) fprintf(trace, "type of '%.2s' is %s.\n", tbuf,
218 (type == tbool) ? "boolean" :
219 (type == tnum) ? "numeric" :
220 (type = tstr) ? "string" :
221 (type = tcancel) ? "canceled" : "unknown");
222
223 /* look for the name in bools */
224 if (capsearch(boolcodes, oboolcodes, tbuf)) {
225 if (type != tbool && type != tcancel)
226 (void) fprintf(stderr,
227 "%s: TERM=%s: wrong type given for the "
228 "boolean termcap code '%.2s'.\n", progname,
229 term_name, tbuf);
230 continue;
231 }
232
233 /* look for the name in nums */
234 if (capsearch(numcodes, onumcodes, tbuf)) {
235 if (type != tnum && type != tcancel)
236 (void) fprintf(stderr,
237 "%s: TERM=%s: wrong type given for the "
238 "numeric termcap code '%.2s'.\n", progname,
239 term_name, tbuf);
240 continue;
241 }
242
243 /* look for the name in strs */
244 if (capsearch(strcodes, ostrcodes, tbuf)) {
245 if (type != tstr && type != tcancel)
246 (void) fprintf(stderr,
247 "%s: TERM=%s: wrong type given for the "
248 "string termcap code '%.2s'.\n", progname,
249 term_name, tbuf);
250 continue;
251 }
252
253 (void) fprintf(stderr,
254 "%s: TERM=%s: the %s termcap code '%.2s' is not a valid "
255 "name.\n", progname, term_name,
256 (type == tbool) ? "boolean" :
257 (type == tnum) ? "numeric" :
258 (type = tstr) ? "string" :
259 (type = tcancel) ? "canceled" : "(unknown type)", tbuf);
260 }
261 }
262
263 /*
264 * Fill up the termcap tables.
265 */
266 int
filltables(void)267 filltables(void)
268 {
269 int i, tret;
270
271 /* Retrieve the termcap entry. */
272 if ((tret = otgetent(bp, term_name)) != 1) {
273 (void) fprintf(stderr,
274 "%s: TERM=%s: tgetent failed with return code %d (%s).\n",
275 progname, term_name, tret,
276 (tret == 0) ? "non-existent or invalid entry" :
277 (tret == -1) ? "cannot open $TERMCAP" : "unknown reason");
278 return (0);
279 }
280
281 if (verbose) {
282 (void) fprintf(trace, "bp=");
283 (void) cpr(trace, bp);
284 (void) fprintf(trace, ".\n");
285 }
286
287 if (uselevel == 0)
288 checktermcap();
289
290 /* Retrieve the values that are in terminfo. */
291
292 /* booleans */
293 for (i = 0; boolcodes[i]; i++) {
294 boolval[uselevel][i] = otgetflag(boolcodes[i]);
295 if (verbose > 1) {
296 (void) fprintf(trace, "boolcodes=%s, ", boolcodes[i]);
297 (void) fprintf(trace, "boolnames=%s, ", boolnames[i]);
298 (void) fprintf(trace,
299 "flag=%d.\n", boolval[uselevel][i]);
300 }
301 }
302
303 /* numbers */
304 for (i = 0; numcodes[i]; i++) {
305 numval[uselevel][i] = otgetnum(numcodes[i]);
306 if (verbose > 1) {
307 (void) fprintf(trace, "numcodes=%s, ", numcodes[i]);
308 (void) fprintf(trace, "numnames=%s, ", numnames[i]);
309 (void) fprintf(trace, "num=%d.\n", numval[uselevel][i]);
310 }
311 }
312
313 if (uselevel == 0)
314 nextstring = capbuffer;
315
316 /* strings */
317 for (i = 0; strcodes[i]; i++) {
318 strval[uselevel][i] = otgetstr(strcodes[i], &nextstring);
319 if (verbose > 1) {
320 (void) fprintf(trace, "strcodes=%s, ", strcodes [i]);
321 (void) fprintf(trace, "strnames=%s, ", strnames [i]);
322 if (strval[uselevel][i]) {
323 (void) fprintf(trace, "str=");
324 tpr(trace, strval[uselevel][i]);
325 (void) fprintf(trace, ".\n");
326 }
327 else
328 (void) fprintf(trace, "str=NULL.\n");
329 }
330 /* remove zero length strings */
331 if (strval[uselevel][i] && (strval[uselevel][i][0] == '\0')) {
332 (void) fprintf(stderr,
333 "%s: TERM=%s: cap %s (info %s) is NULL: REMOVED\n",
334 progname, term_name, strcodes[i], strnames[i]);
335 strval[uselevel][i] = NULL;
336 }
337 }
338
339 /* Retrieve the values not found in terminfo anymore. */
340
341 /* booleans */
342 for (i = 0; oboolcodes[i]; i++) {
343 oboolval[uselevel][i] = otgetflag(oboolcodes[i]);
344 if (verbose > 1) {
345 (void) fprintf(trace, "oboolcodes=%s, ",
346 oboolcodes[i]);
347 (void) fprintf(trace, "flag=%d.\n",
348 oboolval[uselevel][i]);
349 }
350 }
351
352 /* numbers */
353 for (i = 0; onumcodes[i]; i++) {
354 onumval[uselevel][i] = otgetnum(onumcodes[i]);
355 if (verbose > 1) {
356 (void) fprintf(trace, "onumcodes=%s, ", onumcodes[i]);
357 (void) fprintf(trace, "num=%d.\n",
358 onumval[uselevel][i]);
359 }
360 }
361
362 /* strings */
363 for (i = 0; ostrcodes[i]; i++) {
364 ostrval[uselevel][i] = otgetstr(ostrcodes[i], &nextstring);
365 if (verbose > 1) {
366 (void) fprintf(trace, "ostrcodes=%s, ", ostrcodes[i]);
367 if (ostrval[uselevel][i]) {
368 (void) fprintf(trace, "ostr=");
369 tpr(trace, ostrval[uselevel][i]);
370 (void) fprintf(trace, ".\n");
371 }
372 else
373 (void) fprintf(trace, "ostr=NULL.\n");
374 }
375 /* remove zero length strings */
376 if (ostrval[uselevel][i] && (ostrval[uselevel][i][0] == '\0')) {
377 (void) fprintf(stderr,
378 "%s: TERM=%s: cap %s (no terminfo name) is NULL: "
379 "REMOVED\n", progname, term_name, ostrcodes[i]);
380 ostrval[uselevel][i] = NULL;
381 }
382 }
383 return (1);
384 }
385
386 /*
387 * This routine copies the set of names from the termcap entry into
388 * a separate buffer, getting rid of the old obsolete two character
389 * names.
390 */
391 static void
getlongname(void)392 getlongname(void)
393 {
394 char *b = &bp[0], *l = buflongname;
395
396 /* Skip the two character name */
397 if (bp[2] == '|')
398 b = &bp[3];
399
400 /* Copy the rest of the names */
401 while (*b && *b != ':')
402 *l++ = *b++;
403 *l = '\0';
404
405 if (b != &bp[0]) {
406 (void) fprintf(stderr, "%s: obsolete 2 character name "
407 "'%2.2s' removed.\n", progname, bp);
408 (void) fprintf(stderr, "\tsynonyms are: '%s'\n", buflongname);
409 }
410 }
411
412 /*
413 * Return the value of the termcap string 'capname' as stored in our list.
414 */
415 char *
getcapstr(char * capname)416 getcapstr(char *capname)
417 {
418 int i;
419
420 if (verbose > 1)
421 (void) fprintf(trace, "looking for termcap value of %s.\n",
422 capname);
423
424 /* Check the old termcap list. */
425 for (i = 0; ostrcodes[i]; i++)
426 if (strcmp(ostrcodes[i], capname) == 0) {
427 if (verbose > 1) {
428 (void) fprintf(trace, "\tvalue is:");
429 tpr(trace, ostrval[uselevel][i]);
430 (void) fprintf(trace, ".\n");
431 }
432 return (ostrval[uselevel][i]);
433 }
434
435 if (verbose > 1)
436 (void) fprintf(trace, "termcap name '%s' not found in "
437 "ostrcodes.\n", capname);
438
439 /* Check the terminfo list. */
440 for (i = 0; strcodes[i]; i++)
441 if (strcmp(strcodes[i], capname) == 0) {
442 if (verbose > 1) {
443 (void) fprintf(trace, "\tvalue is:");
444 tpr(trace, strval[uselevel][i]);
445 (void) fprintf(trace, ".\n");
446 }
447 return (strval[uselevel][i]);
448 }
449
450 (void) fprintf(stderr, "%s: TERM=%s: termcap name '%s' not found.\n",
451 progname, term_name, capname);
452
453 return ((char *)NULL);
454 }
455
456 /*
457 * Search for a name in the given table and
458 * return the index.
459 * Someday I'll redo this to use bsearch().
460 */
461 /* ARGSUSED */
462 int
search(char * names[],int max,char * infoname)463 search(char *names[], int max, char *infoname)
464 {
465 #ifndef BSEARCH
466 int i;
467 for (i = 0; names [i] != NULL; i++)
468 if (strcmp(names [i], infoname) == 0)
469 return (i);
470 return (-1);
471 #else /* this doesn't work for some reason */
472 char **bret;
473
474 bret = (char **)bsearch(infoname, (char *)names, max,
475 sizeof (char *), strcmp);
476 (void) fprintf(trace, "search looking for %s.\n", infoname);
477 (void) fprintf(trace, "base=%#x, bret=%#x, nel=%d.\n", names,
478 bret, max);
479 (void) fprintf(trace, "returning %d.\n", bret == NULL ? -1 :
480 bret - names);
481 if (bret == NULL)
482 return (-1);
483 else
484 return (bret - names);
485 #endif /* OLD */
486 }
487
488 /*
489 * return the value of the terminfo string 'infoname'
490 */
491 char *
getinfostr(char * infoname)492 getinfostr(char *infoname)
493 {
494 int i;
495
496 if (verbose > 1)
497 (void) fprintf(trace, "looking for terminfo value of %s.\n",
498 infoname);
499
500 i = search(strnames, strcount, infoname);
501 if (i != -1) {
502 if (verbose > 1) {
503 (void) fprintf(trace, "\tvalue is:");
504 tpr(trace, strval[uselevel][i]);
505 (void) fprintf(trace, ".\n");
506 }
507 return (strval[uselevel][i]);
508 }
509
510 if (verbose > 1)
511 (void) fprintf(trace, "terminfo name '%s' not found.\n",
512 infoname);
513
514 return ((char *)NULL);
515 }
516
517 /*
518 * Replace the value stored for the terminfo boolean
519 * capability 'infoname' with the newvalue.
520 */
521 void
putbool(char * infoname,int newvalue)522 putbool(char *infoname, int newvalue)
523 {
524 int i;
525
526 if (verbose > 1)
527 (void) fprintf(trace, "changing value for %s to %d.\n",
528 infoname, newvalue);
529
530 i = search(boolnames, boolcount, infoname);
531 if (i != -1) {
532 if (verbose > 1)
533 (void) fprintf(trace, "value was: %d.\n",
534 boolval[uselevel][i]);
535
536 boolval[uselevel][i] = newvalue;
537 return;
538 }
539
540 (void) fprintf(stderr, "%s: TERM=%s: the boolean name '%s' was not "
541 "found!\n", progname, term_name, infoname);
542 }
543
544 /*
545 * Replace the value stored for the terminfo number
546 * capability 'infoname' with the newvalue.
547 */
548 void
putnum(char * infoname,int newvalue)549 putnum(char *infoname, int newvalue)
550 {
551 int i;
552
553 if (verbose > 1)
554 (void) fprintf(trace, "changing value for %s to %d.\n",
555 infoname, newvalue);
556
557 i = search(numnames, numcount, infoname);
558 if (i != -1) {
559 if (verbose > 1)
560 (void) fprintf(trace, "value was: %d.\n",
561 numval[uselevel][i]);
562
563 numval[uselevel][i] = newvalue;
564 return;
565 }
566
567 (void) fprintf(stderr, "%s: TERM=%s: the numeric name '%s' was not "
568 "found!\n",
569 progname, term_name, infoname);
570 }
571
572 /*
573 * replace the value stored for the terminfo string capability 'infoname'
574 * with the newvalue.
575 */
576 void
putstr(char * infoname,char * newvalue)577 putstr(char *infoname, char *newvalue)
578 {
579 int i;
580
581 if (verbose > 1) {
582 (void) fprintf(trace, "changing value for %s to ", infoname);
583 tpr(trace, newvalue);
584 (void) fprintf(trace, ".\n");
585 }
586
587 i = search(strnames, strcount, infoname);
588 if (i != -1) {
589 if (verbose > 1) {
590 (void) fprintf(trace, "value was:");
591 tpr(trace, strval[uselevel][i]);
592 (void) fprintf(trace, ".\n");
593 }
594 strval[uselevel][i] = nextstring;
595 while (*newvalue)
596 *nextstring++ = *newvalue++;
597 *nextstring++ = '\0';
598 return;
599 }
600
601 (void) fprintf(stderr, "%s: TERM=%s: the string name '%s' was not "
602 "found!\n",
603 progname, term_name, infoname);
604 }
605
606 /*
607 * Add in extra delays if they are not recorded already.
608 * This is done before the padding information has been modified by
609 * changecalculations() below, so the padding information, if there
610 * already, is still at the beginning of the string in termcap format.
611 */
612 void
addpadding(int cappadding,char * infostr)613 addpadding(int cappadding, char *infostr)
614 {
615 char *cap;
616 char tempbuffer [100];
617
618 /* Is there padding to add? */
619 if (cappadding > 0)
620 /* Is there a string to add it to? */
621 if (cap = getinfostr(infostr))
622 /* Is there any padding info already? */
623 if (ispadchar(*cap)) {
624 /* EMPTY */;
625 /* Assume that the padding info that is there is correct. */
626 } else {
627 /* Add the padding at the end of the present string. */
628 (void) snprintf(tempbuffer, sizeof (tempbuffer),
629 "%s$<%d>", cap, cappadding);
630 putstr(infostr, tempbuffer);
631 } else {
632 /* Create a new string that only has the padding. */
633 (void) sprintf(tempbuffer, "$<%d>", cappadding);
634 putstr(infostr, tempbuffer);
635 }
636 }
637
638 struct
639 {
640 char *capname;
641 char *keyedinfoname;
642 } ko_map[] = {
643 "al", "kil1",
644 "bs", "kbs", /* special addition */
645 "bt", "kcbt",
646 "cd", "ked",
647 "ce", "kel",
648 "cl", "kclr",
649 "ct", "ktbc",
650 "dc", "kdch1",
651 "dl", "kdl1",
652 "do", "kcud1",
653 "ei", "krmir",
654 "ho", "khome",
655 "ic", "kich1",
656 "im", "kich1", /* special addition */
657 "le", "kcub1",
658 "ll", "kll",
659 "nd", "kcuf1",
660 "sf", "kind",
661 "sr", "kri",
662 "st", "khts",
663 "up", "kcuu1",
664 /* "", "kctab", */
665 /* "", "knp", */
666 /* "", "kpp", */
667 0, 0
668 };
669
670 /*
671 * Work with the ko string. It is a comma separated list of keys for which
672 * the keyboard has a key by the same name that emits the same sequence.
673 * For example, ko = dc, im, ei means that there are keys called
674 * delete-character, enter-insert-mode and exit-insert-mode on the keyboard,
675 * and they emit the same sequences as specified in the dc, im and ei
676 * capabilities.
677 */
678 static void
handleko(void)679 handleko(void)
680 {
681 char capname[3];
682 char *capstr;
683 int i, j, found;
684 char *infostr;
685
686 if (verbose > 1)
687 (void) fprintf(trace, "working on termcap ko string.\n");
688
689 if (ostrval[uselevel][cap_ko] == NULL)
690 return;
691
692 capname[2] = '\0';
693 for (i = 0; ostrval[uselevel][cap_ko][i] != '\0'; ) {
694 /* isolate the termcap name */
695 capname[0] = ostrval[uselevel][cap_ko][i++];
696 if (ostrval[uselevel][cap_ko][i] == '\0')
697 break;
698 capname[1] = ostrval[uselevel][cap_ko][i++];
699 if (ostrval[uselevel][cap_ko][i] == ',')
700 i++;
701
702 if (verbose > 1) {
703 (void) fprintf(trace, "key termcap name is '");
704 tpr(trace, capname);
705 (void) fprintf(trace, "'.\n");
706 }
707
708 /* match it up into our list */
709 found = 0;
710 for (j = 0; !found && ko_map[j].keyedinfoname != NULL; j++) {
711 if (verbose > 1)
712 (void) fprintf(trace, "looking at termcap name %s.\n",
713 ko_map[j].capname);
714 if (capname[0] == ko_map[j].capname[0] &&
715 capname[1] == ko_map[j].capname[1]) {
716 /* add the value to our database */
717 if ((capstr = getcapstr(capname)) != NULL) {
718 infostr = getinfostr
719 (ko_map[j].keyedinfoname);
720 if (infostr == NULL) {
721 /* skip any possible padding */
722 /* information */
723 while (ispadchar(*capstr))
724 capstr++;
725 putstr(ko_map[j].keyedinfoname, capstr);
726 } else
727 if (strcmp(capstr, infostr) != 0) {
728 (void) fprintf(stderr,
729 "%s: TERM=%s: a function "
730 "key for '%s' was "
731 "specified with the "
732 "value ", progname,
733 term_name, capname);
734 tpr(stderr, capstr);
735 (void) fprintf(stderr,
736 ", but it already has the "
737 "value '");
738 tpr(stderr, infostr);
739 (void) fprintf(stderr, "'.\n");
740 }
741 }
742 found = 1;
743 }
744 }
745
746 if (!found) {
747 (void) fprintf(stderr, "%s: TERM=%s: the unknown "
748 "termcap name '%s' was\n", progname, term_name,
749 capname);
750 (void) fprintf(stderr, "specified in the 'ko' "
751 "termcap capability.\n");
752 }
753 }
754 }
755
756 #define CONTROL(x) ((x) & 037)
757 struct
758 {
759 char vichar;
760 char *keyedinfoname;
761 } ma_map[] = {
762 CONTROL('J'), "kcud1", /* down */
763 CONTROL('N'), "kcud1",
764 'j', "kcud1",
765 CONTROL('P'), "kcuu1", /* up */
766 'k', "kcuu1",
767 'h', "kcub1", /* left */
768 CONTROL('H'), "kcub1",
769 ' ', "kcuf1", /* right */
770 'l', "kcuf1",
771 'H', "khome", /* home */
772 CONTROL('L'), "kclr", /* clear */
773 0, 0
774 };
775
776 /*
777 * Work with the ma string. This is a list of pairs of characters.
778 * The first character is the what a function key sends. The second
779 * character is the equivalent vi function that should be done when
780 * it receives that character. Note that only function keys that send
781 * a single character could be defined by this list.
782 */
783
784 void
prchar(FILE * stream,int c)785 prchar(FILE *stream, int c)
786 {
787 char xbuf[2];
788 xbuf[0] = c;
789 xbuf[1] = '\0';
790 (void) fprintf(stream, "%s", iexpand(xbuf));
791 }
792
793 static void
handlema(void)794 handlema(void)
795 {
796 char vichar;
797 char cap[2];
798 int i, j, found;
799 char *infostr;
800
801 if (verbose > 1)
802 (void) fprintf(trace, "working on termcap ma string.\n");
803
804 if (ostrval[uselevel][cap_ma] == NULL)
805 return;
806
807 cap[1] = '\0';
808 for (i = 0; ostrval[uselevel][cap_ma][i] != '\0'; ) {
809 /* isolate the key's value */
810 cap[0] = ostrval[uselevel][cap_ma][i++];
811 if (verbose > 1) {
812 (void) fprintf(trace, "key value is '");
813 tpr(trace, cap);
814 (void) fprintf(trace, "'.\n");
815 }
816
817 if (ostrval[uselevel][cap_ma][i] == '\0')
818 break;
819
820 /* isolate the vi key name */
821 vichar = ostrval[uselevel][cap_ma][i++];
822 if (verbose > 1) {
823 (void) fprintf(trace, "the vi key is '");
824 prchar(trace, vichar);
825 (void) fprintf(trace, "'.\n");
826 }
827
828 /* match up the vi name in our list */
829 found = 0;
830 for (j = 0; !found && ma_map[j].keyedinfoname != NULL; j++) {
831 if (verbose > 1) {
832 (void) fprintf(trace, "looking at vi "
833 "character '");
834 prchar(trace, ma_map[j].vichar);
835 (void) fprintf(trace, "'\n");
836 }
837 if (vichar == ma_map[j].vichar) {
838 infostr = getinfostr(ma_map[j].keyedinfoname);
839 if (infostr == NULL)
840 putstr(ma_map[j].keyedinfoname, cap);
841 else if (strcmp(cap, infostr) != 0) {
842 (void) fprintf(stderr, "%s: TERM=%s: "
843 "the vi character '", progname,
844 term_name);
845 prchar(stderr, vichar);
846 (void) fprintf(stderr,
847 "' (info '%s') has the value '",
848 ma_map[j].keyedinfoname);
849 tpr(stderr, infostr);
850 (void) fprintf(stderr, "', but 'ma' "
851 "gives '");
852 prchar(stderr, cap[0]);
853 (void) fprintf(stderr, "'.\n");
854 }
855 found = 1;
856 }
857 }
858
859 if (!found) {
860 (void) fprintf(stderr, "%s: the unknown vi key '",
861 progname);
862 prchar(stderr, vichar);
863 (void) fprintf(stderr, "' was\n");
864 (void) fprintf(stderr, "specified in the 'ma' termcap "
865 "capability.\n");
866 }
867 }
868 }
869
870 /*
871 * Many capabilities were defaulted in termcap which must now be explicitly
872 * given. We'll assume that the defaults are in effect for this terminal.
873 */
874 void
adddefaults(void)875 adddefaults(void)
876 {
877 char *cap;
878 int sg;
879
880 if (verbose > 1)
881 (void) fprintf(trace, "assigning defaults.\n");
882
883 /* cr was assumed to be ^M, unless nc was given, */
884 /* which meant it could not be done. */
885 /* Also, xr meant that ^M acted strangely. */
886 if ((getinfostr("cr") == NULL) && !oboolval[uselevel][cap_nc] &&
887 !oboolval[uselevel][cap_xr])
888 if ((cap = getcapstr("cr")) == NULL)
889 putstr("cr", "\r");
890 else
891 putstr("cr", cap);
892
893 /* cursor down was assumed to be ^J if not specified by nl */
894 if (getinfostr("cud1") == NULL)
895 if (ostrval[uselevel][cap_nl] != NULL)
896 putstr("cud1", ostrval[uselevel][cap_nl]);
897 else
898 putstr("cud1", "\n");
899
900 /* ind was assumed to be ^J, unless ns was given, */
901 /* which meant it could not be done. */
902 if ((getinfostr("ind") == NULL) && !oboolval[uselevel][cap_ns])
903 if (ostrval[uselevel][cap_nl] == NULL)
904 putstr("ind", "\n");
905 else
906 putstr("ind", ostrval[uselevel][cap_nl]);
907
908 /* bel was assumed to be ^G */
909 if (getinfostr("bel") == NULL)
910 putstr("bel", "\07");
911
912 /* if bs, then could do backspacing, */
913 /* with value of bc, default of ^H */
914 if ((getinfostr("cub1") == NULL) && oboolval[uselevel][cap_bs])
915 if (ostrval[uselevel][cap_bc] != NULL)
916 putstr("cub1", ostrval[uselevel][cap_bc]);
917 else
918 putstr("cub1", "\b");
919
920 /* default xon to true */
921 if (!otgetflag("xo"))
922 putbool("xon", 1);
923
924 /* if pt, then hardware tabs are allowed, */
925 /* with value of ta, default of ^I */
926 if ((getinfostr("ht") == NULL) && oboolval[uselevel][cap_pt])
927 if ((cap = getcapstr("ta")) == NULL)
928 putstr("ht", "\t");
929 else
930 putstr("ht", cap);
931
932 /* The dX numbers are now stored as padding */
933 /* in the appropriate terminfo string. */
934 addpadding(onumval[uselevel][cap_dB], "cub1");
935 addpadding(onumval[uselevel][cap_dC], "cr");
936 addpadding(onumval[uselevel][cap_dF], "ff");
937 addpadding(onumval[uselevel][cap_dN], "cud1");
938 addpadding(onumval[uselevel][cap_dT], "ht");
939
940 /* The ug and sg caps were essentially identical, */
941 /* so ug almost never got used. We set sg from ug */
942 /* if it hasn't already been set. */
943 if (onumval[uselevel][cap_ug] >= 0 && (sg = otgetnum("sg")) < 0)
944 putnum("xmc", onumval[uselevel][cap_ug]);
945 else if ((onumval[uselevel][cap_ug] >= 0) &&
946 (sg >= 0) && (onumval[uselevel][cap_ug] != sg))
947 (void) fprintf(stderr,
948 "%s: TERM=%s: Warning: termcap sg and ug had different "
949 "values (%d<->%d).\n", progname, term_name, sg,
950 onumval[uselevel][cap_ug]);
951
952 /* The MT boolean was never really part of termcap, */
953 /* but we can check for it anyways. */
954 if (oboolval[uselevel][cap_MT] && !otgetflag("km"))
955 putbool("km", 1);
956
957 /* the rs string was renamed r2 (info rs2) */
958 if ((ostrval[uselevel][cap_rs] != NULL) &&
959 (ostrval[uselevel][cap_rs][0] != '\0'))
960 putstr("rs2", ostrval[uselevel][cap_rs]);
961
962 handleko();
963 handlema();
964 }
965
966 #define caddch(x) *to++ = (x)
967
968 /*
969 * add the string to the string table
970 */
971 char *
caddstr(char * to,char * str)972 caddstr(char *to, char *str)
973 {
974 while (*str)
975 *to++ = *str++;
976 return (to);
977 }
978
979 /* If there is no padding info or parmed strings, */
980 /* then we do not need to copy the string. */
981 int
needscopying(char * string)982 needscopying(char *string)
983 {
984 /* any string at all? */
985 if (string == NULL)
986 return (0);
987
988 /* any padding info? */
989 if (ispadchar(*string))
990 return (1);
991
992 /* any parmed info? */
993 while (*string)
994 if (*string++ == '%')
995 return (1);
996
997 return (0);
998 }
999
1000 /*
1001 * Certain manipulations of the stack require strange manipulations of the
1002 * values that are on the stack. To handle these, we save the values of the
1003 * parameters in registers at the very beginning and make the changes in
1004 * the registers. We don't want to do this in the general case because of the
1005 * potential performance loss.
1006 */
1007 int
fancycap(char * string)1008 fancycap(char *string)
1009 {
1010 int parmset = 0;
1011
1012 while (*string)
1013 if (*string++ == '%') {
1014 switch (*string) {
1015 /* These manipulate just the top value on */
1016 /* the stack, so we only have to do */
1017 /* something strange if a %r follows. */
1018 case '>': case 'B': case 'D':
1019 parmset = 1;
1020 break;
1021 /* If the parm has already been been */
1022 /* pushed onto the stack by %>, then we */
1023 /* can not reverse the parms and must get */
1024 /* them from the registers. */
1025 case 'r':
1026 if (parmset)
1027 return (1);
1028 break;
1029 /* This manipulates both parameters, so we */
1030 /* cannot just do one and leave the value */
1031 /* on the stack like we can with %>, */
1032 /* %B or %D. */
1033 case 'n':
1034 return (1);
1035 }
1036 string++;
1037 }
1038 return (0);
1039 }
1040
1041 /*
1042 * Change old style of doing calculations to the new stack style.
1043 * Note that this will not necessarily produce the most efficient string,
1044 * but it will work.
1045 */
1046 void
changecalculations()1047 changecalculations()
1048 {
1049 int i, currentparm;
1050 char *from, *to = nextstring;
1051 int ch;
1052 int parmset, parmsaved;
1053 char padding[100], *saveto;
1054
1055 for (i = 0; strnames[i]; i++)
1056 if (needscopying(strval[uselevel][i])) {
1057 if (verbose) {
1058 (void) fprintf(trace, "%s needs copying, "
1059 "was:", strnames [i]);
1060 tpr(trace, strval[uselevel][i]);
1061 (void) fprintf(trace, ".\n");
1062 }
1063
1064 from = strval[uselevel][i];
1065 strval[uselevel][i] = to;
1066 currentparm = 1;
1067 parmset = 0;
1068
1069 /* Handle padding information. Save it so that it can be */
1070 /* placed at the end of the string where it should */
1071 /* have been in the first place. */
1072 if (ispadchar(*from)) {
1073 saveto = to;
1074 to = padding;
1075 to = caddstr(to, "$<");
1076 while (isdigit(*from) || *from == '.')
1077 caddch(*from++);
1078 if (*from == '*')
1079 caddch(*from++);
1080 caddch('>');
1081 caddch('\0');
1082 to = saveto;
1083 } else
1084 padding[0] = '\0';
1085
1086 if (fancycap(from)) {
1087 to = caddstr(to, "%p1%Pa%p2%Pb");
1088 parmsaved = 1;
1089 (void) fprintf(stderr,
1090 "%s: TERM=%s: Warning: the string "
1091 "produced for '%s' may be inefficient.\n",
1092 progname, term_name, strnames[i]);
1093 (void) fprintf(stderr, "It should be "
1094 "looked at by hand.\n");
1095 } else
1096 parmsaved = 0;
1097
1098 while ((ch = *from++) != '\0')
1099 if (ch != '%')
1100 caddch(ch);
1101 else
1102 switch (ch = *from++) {
1103 case '.': /* %. -> %p1%c */
1104 case 'd': /* %d -> %p1%d */
1105 case '2': /* %2 -> %p1%2.2d */
1106 case '3': /* %3 -> %p1%3.3d */
1107 case '+':
1108 /* %+x -> %p1%'x'%+%c */
1109
1110 case '>':
1111 /* %>xy -> %p1%Pc%?%'x'%> */
1112 /* %t%gc%'y'%+ */
1113 /* if current value > x, then add y. */
1114 /* No output. */
1115
1116 case 'B':
1117 /* %B: BCD */
1118 /* (16*(x/10))+(x%10) */
1119 /* No output. */
1120 /* (Adds Regent 100) */
1121
1122 case 'D':
1123 /* %D: Reverse coding */
1124 /* (x-2*(x%16)) */
1125 /* No output. */
1126 /* (Delta Data) */
1127
1128 if (!parmset)
1129 if (parmsaved) {
1130 to = caddstr(to, "%g");
1131 if (currentparm == 1)
1132 caddch('a');
1133 else
1134 caddch('b');
1135 } else {
1136 to = caddstr(to, "%p");
1137 if (currentparm == 1)
1138 caddch('1');
1139 else
1140 caddch('2');
1141 }
1142 currentparm = 3 - currentparm;
1143 parmset = 0;
1144 switch (ch) {
1145 case '.':
1146 to = caddstr(to, "%c");
1147 break;
1148 case 'd':
1149 to = caddstr(to, "%d");
1150 break;
1151 case '2': case '3':
1152 #ifdef USG /* Vr2==USG, Vr3==SYSV. Use %02d for Vr2, %2.2d for Vr3 */
1153 caddch('%');
1154 caddch('0');
1155 #else
1156 caddch('%');
1157 caddch(ch);
1158 caddch('.');
1159 #endif /* USG vs. SYSV */
1160 caddch(ch);
1161 caddch('d');
1162 break;
1163 case '+':
1164 to = caddstr(to, "%'");
1165 caddch(*from++);
1166 to = caddstr(to,
1167 "'%+%c");
1168 break;
1169 case '>':
1170 to = caddstr(to,
1171 "%Pc%?%'");
1172 caddch(*from++);
1173 to = caddstr(to,
1174 "'%>%t%gc%'");
1175 caddch(*from++);
1176 to = caddstr(to,
1177 "'%+");
1178 parmset = 1;
1179 break;
1180 case 'B':
1181 to = caddstr(to,
1182 "%Pc%gc%{10}%/%{16}%*%gc%{10}%m%+");
1183 parmset = 1;
1184 break;
1185
1186 case 'D':
1187 to = caddstr(to,
1188 "%Pc%gc%gc%{16}%m%{2}%*%-");
1189 parmset = 1;
1190 break;
1191 }
1192 break;
1193
1194 /* %r reverses current parameter */
1195 case 'r':
1196 currentparm = 3 - currentparm;
1197 break;
1198
1199 /* %n: exclusive-or row AND column */
1200 /* with 0140, 96 decimal, no output */
1201 /* (Datamedia 2500, Exidy Sorceror) */
1202 case 'n':
1203 to = caddstr(to,
1204 "%ga%'`'%^%Pa");
1205 to = caddstr(to,
1206 "%gb%'`'%^%Pb");
1207 break;
1208
1209 /* assume %x means %x */
1210 /* this includes %i and %% */
1211 default:
1212 caddch('%');
1213 caddch(ch);
1214 }
1215 to = caddstr(to, padding);
1216 caddch('\0');
1217
1218 if (verbose) {
1219 (void) fprintf(trace, "and has become:");
1220 tpr(trace, strval[uselevel][i]);
1221 (void) fprintf(trace, ".\n");
1222 }
1223 }
1224 nextstring = to;
1225 }
1226
1227 static void
print_no_use_entry(void)1228 print_no_use_entry(void)
1229 {
1230 int i;
1231
1232 pr_heading("", buflongname);
1233 pr_bheading();
1234
1235 for (i = 0; boolcodes[i]; i++)
1236 if (boolval[0][i])
1237 pr_boolean(boolnames[i], (char *)0, (char *)0, 1);
1238
1239 pr_bfooting();
1240 pr_sheading();
1241
1242 for (i = 0; numcodes[i]; i++)
1243 if (numval[0][i] > -1)
1244 pr_number(numnames[i], (char *)0, (char *)0,
1245 numval[0][i]);
1246
1247 pr_nfooting();
1248 pr_sheading();
1249
1250 for (i = 0; strcodes[i]; i++)
1251 if (strval[0][i])
1252 pr_string(strnames[i], (char *)0, (char *)0,
1253 strval[0][i]);
1254
1255 pr_sfooting();
1256 }
1257
1258 static void
print_use_entry(char * usename)1259 print_use_entry(char *usename)
1260 {
1261 int i;
1262
1263 pr_heading("", buflongname);
1264 pr_bheading();
1265
1266 for (i = 0; boolcodes[i]; i++)
1267 if (boolval[0][i] && !boolval[1][i])
1268 pr_boolean(boolnames[i], (char *)0, (char *)0, 1);
1269 else if (!boolval[0][i] && boolval[1][i])
1270 pr_boolean(boolnames[i], (char *)0, (char *)0, -1);
1271
1272 pr_bfooting();
1273 pr_nheading();
1274
1275 for (i = 0; numcodes[i]; i++)
1276 if ((numval[0][i] > -1) && (numval[0][i] != numval[1][i]))
1277 pr_number(numnames[i], (char *)0, (char *)0,
1278 numval[0][i]);
1279 else if ((numval [0] [i] == -1) && (numval [1] [i] > -1))
1280 pr_number(numnames[i], (char *)0, (char *)0, -1);
1281
1282 pr_nfooting();
1283 pr_sheading();
1284
1285 for (i = 0; strcodes[i]; i++)
1286 /* print out str[0] if: */
1287 /* str[0] != NULL and str[1] == NULL, or str[0] != str[1] */
1288 if (strval[0][i] && ((strval[1][i] == NULL) ||
1289 (strcmp(strval[0][i], strval[1][i]) != 0)))
1290 pr_string(strnames[i], (char *)0, (char *)0,
1291 strval[0][i]);
1292 /* print out @ if str[0] == NULL and str[1] != NULL */
1293 else if (strval[0][i] == NULL && strval[1][i] != NULL)
1294 pr_string(strnames[i], (char *)0, (char *)0,
1295 (char *)0);
1296
1297 pr_sfooting();
1298
1299 (void) printf("\tuse=%s,\n", usename);
1300 }
1301
1302 static void
captoinfo(void)1303 captoinfo(void)
1304 {
1305 char usename[512];
1306 char *sterm_name;
1307
1308 if (term_name == NULL) {
1309 (void) fprintf(stderr, "%s: Null term_name given.\n",
1310 progname);
1311 return;
1312 }
1313
1314 if (verbose)
1315 (void) fprintf(trace, "changing cap to info, TERM=%s.\n",
1316 term_name);
1317
1318 uselevel = 0;
1319 if (filltables() == 0)
1320 return;
1321 getlongname();
1322 adddefaults();
1323 changecalculations();
1324 if (TLHtcfound != 0) {
1325 uselevel = 1;
1326 if (verbose)
1327 (void) fprintf(trace, "use= found, %s uses %s.\n",
1328 term_name, TLHtcname);
1329 (void) strcpy(usename, TLHtcname);
1330 sterm_name = term_name;
1331 term_name = usename;
1332 if (filltables() == 0)
1333 return;
1334 adddefaults();
1335 changecalculations();
1336 term_name = sterm_name;
1337 print_use_entry(usename);
1338 } else
1339 print_no_use_entry();
1340 }
1341
1342
1343 #include <signal.h> /* use this file to determine if this is SVR4.0 system */
1344
1345 static void
use_etc_termcap(void)1346 use_etc_termcap(void)
1347 {
1348 if (verbose)
1349 #ifdef SIGSTOP
1350 (void) fprintf(trace, "reading from /usr/share/lib/termcap\n");
1351 #else /* SIGSTOP */
1352 (void) fprintf(trace, "reading from /etc/termcap\n");
1353 #endif /* SIGSTOP */
1354 term_name = getenv("TERM");
1355 captoinfo();
1356 }
1357
1358 static void
initdirname(void)1359 initdirname(void)
1360 {
1361 #if defined(SYSV) || defined(USG) /* handle both Sys Vr2 and Vr3 curses */
1362 (void) getcwd(dirname, BUFSIZ-2);
1363 #else
1364 (void) getwd(dirname);
1365 #endif /* SYSV || USG */
1366 if (verbose)
1367 (void) fprintf(trace, "current directory name=%s.\n", dirname);
1368 environ = newenviron;
1369 }
1370
1371 static void
setfilename(char * capfile)1372 setfilename(char *capfile)
1373 {
1374 if (capfile [0] == '/')
1375 (void) snprintf(TERMCAP, sizeof (TERMCAP),
1376 "TERMCAP=%s", capfile);
1377 else
1378 (void) snprintf(TERMCAP, sizeof (TERMCAP),
1379 "TERMCAP=%s/%s", dirname, capfile);
1380 if (verbose)
1381 (void) fprintf(trace, "setting the environment for %s.\n",
1382 TERMCAP);
1383 }
1384
1385 static void
setterm_name(void)1386 setterm_name(void)
1387 {
1388 if (verbose)
1389 (void) fprintf(trace, "setting the environment "
1390 "for TERM=%s.\n", term_name);
1391 (void) snprintf(TERM, sizeof (TERM), "TERM=%s", term_name);
1392 }
1393
1394 /* Look at the current line to see if it is a list of names. */
1395 /* If it is, return the first name in the list, else NULL. */
1396 /* As a side-effect, comment lines and blank lines */
1397 /* are copied to standard output. */
1398
1399 char *
getterm_name(char * line)1400 getterm_name(char *line)
1401 {
1402 char *lineptr = line;
1403
1404 if (verbose)
1405 (void) fprintf(trace, "extracting name from '%s'.\n", line);
1406
1407 /* Copy comment lines out. */
1408 if (*line == '#') {
1409 if (copycomments)
1410 (void) printf("%s", line);
1411 }
1412 /* Blank lines get copied too. */
1413 else if (isspace (*line)) {
1414 if (copycomments) {
1415 for (; *lineptr; lineptr++)
1416 if (!isspace(*lineptr))
1417 break;
1418 if (*lineptr == '\0')
1419 (void) printf("\n");
1420 }
1421 }
1422 else
1423 for (; *lineptr; lineptr++)
1424 if (*lineptr == '|' || *lineptr == ':') {
1425 *lineptr = '\0';
1426 if (verbose)
1427 (void) fprintf(trace,
1428 "returning %s.\n", line);
1429 return (line);
1430 }
1431 if (verbose)
1432 (void) fprintf(trace, "returning NULL.\n");
1433 return (NULL);
1434 }
1435
1436 static void
use_file(char * filename)1437 use_file(char *filename)
1438 {
1439 FILE *termfile;
1440 char buffer[BUFSIZ];
1441
1442 if (verbose)
1443 (void) fprintf(trace, "reading from %s.\n", filename);
1444
1445 if ((termfile = fopen(filename, "r")) == NULL) {
1446 (void) fprintf(stderr, "%s: cannot open %s for reading.\n",
1447 progname, filename);
1448 return;
1449 }
1450
1451 copycomments++;
1452 setfilename(filename);
1453
1454 while (fgets(buffer, BUFSIZ, termfile) != NULL) {
1455 if ((term_name = getterm_name(buffer)) != NULL) {
1456 setterm_name();
1457 captoinfo();
1458 }
1459 }
1460 }
1461
1462 /*
1463 * Sort a name and code table pair according to the name table.
1464 * Use a simple bubble sort for now. Too bad I can't call qsort(3).
1465 * At least I only have to do it once for each table.
1466 */
1467 static void
sorttable(char * nametable[],char * codetable[])1468 sorttable(char *nametable[], char *codetable[])
1469 {
1470 int i, j;
1471 char *c;
1472
1473 for (i = 0; nametable[i]; i++)
1474 for (j = 0; j < i; j++)
1475 if (strcmp(nametable[i], nametable[j]) < 0) {
1476 c = nametable[i];
1477 nametable[i] = nametable[j];
1478 nametable[j] = c;
1479 c = codetable[i];
1480 codetable[i] = codetable[j];
1481 codetable[j] = c;
1482 }
1483 }
1484
1485 /*
1486 * Initialize and sort the name and code tables. Allocate space for the
1487 * value tables.
1488 */
1489 static void
inittables(void)1490 inittables(void)
1491 {
1492 unsigned int i;
1493
1494 for (i = 0; boolnames [i]; i++)
1495 ;
1496 boolval[0] = (char *)malloc(i * sizeof (char));
1497 boolval[1] = (char *)malloc(i * sizeof (char));
1498 boolcount = i;
1499 sorttable(boolnames, boolcodes);
1500
1501 for (i = 0; numcodes [i]; i++)
1502 ;
1503 numval[0] = (short *)malloc(i * sizeof (short));
1504 numval[1] = (short *)malloc(i * sizeof (short));
1505 numcount = i;
1506 sorttable(numnames, numcodes);
1507
1508 for (i = 0; strcodes [i]; i++)
1509 ;
1510 strval[0] = (char **)malloc(i * sizeof (char *));
1511 strval[1] = (char **)malloc(i * sizeof (char *));
1512 strcount = i;
1513 sorttable(strnames, strcodes);
1514 }
1515
1516 int
main(int argc,char ** argv)1517 main(int argc, char **argv)
1518 {
1519 int c;
1520 char _capbuffer [8192];
1521 char _bp [TBUFSIZE];
1522 char _buflongname [128];
1523
1524 capbuffer = &_capbuffer[0];
1525 bp = &_bp[0];
1526 buflongname = &_buflongname[0];
1527 progname = argv[0];
1528
1529 while ((c = getopt(argc, argv, "1vVw:")) != EOF)
1530 switch (c) {
1531 case '1':
1532 pr_onecolumn(1);
1533 break;
1534 case 'w':
1535 pr_width(atoi(optarg));
1536 break;
1537 case 'v':
1538 verbose++;
1539 break;
1540 case 'V':
1541 (void) printf("%s: version %s\n", progname,
1542 "@(#)curses:screen/captoinfo.c 1.12");
1543 (void) fflush(stdout);
1544 exit(0);
1545 /* FALLTHROUGH (not really) */
1546 case '?':
1547 (void) fprintf(stderr,
1548 "usage: %s [-1Vv] [-w width] "
1549 "[filename ...]\n", progname);
1550 (void) fprintf(stderr, "\t-1\tsingle column "
1551 "output\n");
1552 (void) fprintf(stderr,
1553 "\t-v\tverbose debugging output\n");
1554 (void) fprintf(stderr,
1555 "\t-V\tprint program version\n");
1556 exit(-1);
1557 }
1558
1559 /* initialize */
1560 pr_init(pr_terminfo);
1561 inittables();
1562
1563 if (optind >= argc)
1564 use_etc_termcap();
1565 else {
1566 initdirname();
1567 for (; optind < argc; optind++)
1568 use_file(argv [optind]);
1569 }
1570
1571 return (0);
1572 }
1573
1574 /* fake out the modules in print.c so we don't have to load in */
1575 /* cexpand.c and infotocap.c */
1576 /* ARGSUSED */
1577 int
cpr(FILE * stream,char * string)1578 cpr(FILE *stream, char *string)
1579 {
1580 return (0);
1581 }
1582