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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
34 * captoinfo - convert a termcap description to a terminfo description
37 * captoinfo [-1vV] [-w width] [ filename ... ]
40 * Tony Hansen, January 22, 1984.
51 #define trace stderr /* send trace messages to stderr */
53 /* extra termcap variables no longer in terminfo */
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) */
64 int cap_bs
= 0, cap_nc
= 1, cap_ns
= 2, cap_pt
= 3, cap_MT
= 4, cap_xr
= 5;
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 */
77 int cap_dB
= 0, cap_dC
= 1, cap_dF
= 2, cap_dN
= 3, cap_dT
= 4, cap_ug
= 5;
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). */
91 int cap_bc
= 0, cap_ko
= 1, cap_ma
= 2, cap_nl
= 3, cap_rs
= 4;
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
)];
98 /* externs from libcurses.a */
99 extern char *boolnames
[], *boolcodes
[];
100 extern char *numnames
[], *numcodes
[];
101 extern char *strnames
[], *strcodes
[];
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 */
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
];
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 };
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 */
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 */
135 static int verbose
= 0; /* debugging printing level */
136 static int copycomments
= 0; /* copy comments from tercap source */
138 #define ispadchar(c) (isdigit(c) || (c) == '.' || (c) == '*')
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);
155 * Verify that the names given in the termcap entry are all valid.
159 capsearch(char *codes
[], char *ocodes
[], char *cap
)
161 for (; *codes
; codes
++)
162 if (((*codes
)[0] == cap
[0]) && ((*codes
)[1] == cap
[1]))
165 for (; *ocodes
; ocodes
++)
166 if (((*ocodes
)[0] == cap
[0]) && ((*ocodes
)[1] == cap
[1]))
176 enum { tbool
, tnum
, tstr
, tcancel
, tunknown
} type
;
180 while (*tbuf
== '\t' || *tbuf
== ' ' || *tbuf
== ':')
186 /* commented out entry? */
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
,
202 (void) fprintf(trace
, "looking at termcap string "
206 case ':': case '\0': type
= tbool
; break;
207 case '#': type
= tnum
; break;
208 case '=': type
= tstr
; break;
209 case '@': type
= tcancel
; break;
211 (void) fprintf(stderr
,
212 "%s: TERM=%s: unknown type given for the "
213 "termcap code '%.2s'.\n", progname
,
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");
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
,
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
,
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
,
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
);
266 * Fill up the termcap tables.
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");
284 (void) fprintf(trace
, "bp=");
285 (void) cpr(trace
, bp
);
286 (void) fprintf(trace
, ".\n");
292 /* Retrieve the values that are in terminfo. */
295 for (i
= 0; boolcodes
[i
]; i
++) {
296 boolval
[uselevel
][i
] = otgetflag(boolcodes
[i
]);
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
]);
306 for (i
= 0; numcodes
[i
]; i
++) {
307 numval
[uselevel
][i
] = otgetnum(numcodes
[i
]);
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
]);
316 nextstring
= capbuffer
;
319 for (i
= 0; strcodes
[i
]; i
++) {
320 strval
[uselevel
][i
] = otgetstr(strcodes
[i
], &nextstring
);
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");
330 (void) fprintf(trace
, "str=NULL.\n");
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
;
341 /* Retrieve the values not found in terminfo anymore. */
344 for (i
= 0; oboolcodes
[i
]; i
++) {
345 oboolval
[uselevel
][i
] = otgetflag(oboolcodes
[i
]);
347 (void) fprintf(trace
, "oboolcodes=%s, ",
349 (void) fprintf(trace
, "flag=%d.\n",
350 oboolval
[uselevel
][i
]);
355 for (i
= 0; onumcodes
[i
]; i
++) {
356 onumval
[uselevel
][i
] = otgetnum(onumcodes
[i
]);
358 (void) fprintf(trace
, "onumcodes=%s, ", onumcodes
[i
]);
359 (void) fprintf(trace
, "num=%d.\n",
360 onumval
[uselevel
][i
]);
365 for (i
= 0; ostrcodes
[i
]; i
++) {
366 ostrval
[uselevel
][i
] = otgetstr(ostrcodes
[i
], &nextstring
);
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");
375 (void) fprintf(trace
, "ostr=NULL.\n");
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
;
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
396 char *b
= &bp
[0], *l
= buflongname
;
398 /* Skip the two character name */
402 /* Copy the rest of the names */
403 while (*b
&& *b
!= ':')
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
);
415 * Return the value of the termcap string 'capname' as stored in our list.
418 getcapstr(char *capname
)
423 (void) fprintf(trace
, "looking for termcap value of %s.\n",
426 /* Check the old termcap list. */
427 for (i
= 0; ostrcodes
[i
]; i
++)
428 if (strcmp(ostrcodes
[i
], capname
) == 0) {
430 (void) fprintf(trace
, "\tvalue is:");
431 tpr(trace
, ostrval
[uselevel
][i
]);
432 (void) fprintf(trace
, ".\n");
434 return (ostrval
[uselevel
][i
]);
438 (void) fprintf(trace
, "termcap name '%s' not found in "
439 "ostrcodes.\n", capname
);
441 /* Check the terminfo list. */
442 for (i
= 0; strcodes
[i
]; i
++)
443 if (strcmp(strcodes
[i
], capname
) == 0) {
445 (void) fprintf(trace
, "\tvalue is:");
446 tpr(trace
, strval
[uselevel
][i
]);
447 (void) fprintf(trace
, ".\n");
449 return (strval
[uselevel
][i
]);
452 (void) fprintf(stderr
, "%s: TERM=%s: termcap name '%s' not found.\n",
453 progname
, term_name
, capname
);
455 return ((char *)NULL
);
459 * Search for a name in the given table and
461 * Someday I'll redo this to use bsearch().
465 search(char *names
[], int max
, char *infoname
)
469 for (i
= 0; names
[i
] != NULL
; i
++)
470 if (strcmp(names
[i
], infoname
) == 0)
473 #else /* this doesn't work for some reason */
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
,
481 (void) fprintf(trace
, "returning %d.\n", bret
== NULL
? -1 :
486 return (bret
- names
);
491 * return the value of the terminfo string 'infoname'
494 getinfostr(char *infoname
)
499 (void) fprintf(trace
, "looking for terminfo value of %s.\n",
502 i
= search(strnames
, strcount
, infoname
);
505 (void) fprintf(trace
, "\tvalue is:");
506 tpr(trace
, strval
[uselevel
][i
]);
507 (void) fprintf(trace
, ".\n");
509 return (strval
[uselevel
][i
]);
513 (void) fprintf(trace
, "terminfo name '%s' not found.\n",
516 return ((char *)NULL
);
520 * Replace the value stored for the terminfo boolean
521 * capability 'infoname' with the newvalue.
524 putbool(char *infoname
, int newvalue
)
529 (void) fprintf(trace
, "changing value for %s to %d.\n",
532 i
= search(boolnames
, boolcount
, infoname
);
535 (void) fprintf(trace
, "value was: %d.\n",
536 boolval
[uselevel
][i
]);
538 boolval
[uselevel
][i
] = newvalue
;
542 (void) fprintf(stderr
, "%s: TERM=%s: the boolean name '%s' was not "
543 "found!\n", progname
, term_name
, infoname
);
547 * Replace the value stored for the terminfo number
548 * capability 'infoname' with the newvalue.
551 putnum(char *infoname
, int newvalue
)
556 (void) fprintf(trace
, "changing value for %s to %d.\n",
559 i
= search(numnames
, numcount
, infoname
);
562 (void) fprintf(trace
, "value was: %d.\n",
563 numval
[uselevel
][i
]);
565 numval
[uselevel
][i
] = newvalue
;
569 (void) fprintf(stderr
, "%s: TERM=%s: the numeric name '%s' was not "
571 progname
, term_name
, infoname
);
575 * replace the value stored for the terminfo string capability 'infoname'
579 putstr(char *infoname
, char *newvalue
)
584 (void) fprintf(trace
, "changing value for %s to ", infoname
);
585 tpr(trace
, newvalue
);
586 (void) fprintf(trace
, ".\n");
589 i
= search(strnames
, strcount
, infoname
);
592 (void) fprintf(trace
, "value was:");
593 tpr(trace
, strval
[uselevel
][i
]);
594 (void) fprintf(trace
, ".\n");
596 strval
[uselevel
][i
] = nextstring
;
598 *nextstring
++ = *newvalue
++;
599 *nextstring
++ = '\0';
603 (void) fprintf(stderr
, "%s: TERM=%s: the string name '%s' was not "
605 progname
, term_name
, infoname
);
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.
615 addpadding(int cappadding
, char *infostr
)
618 char tempbuffer
[100];
620 /* Is there padding to add? */
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
)) {
627 /* Assume that the padding info that is there is correct. */
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
);
634 /* Create a new string that only has the padding. */
635 (void) sprintf(tempbuffer
, "$<%d>", cappadding
);
636 putstr(infostr
, tempbuffer
);
646 "bs", "kbs", /* special addition */
658 "im", "kich1", /* special addition */
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
689 (void) fprintf(trace
, "working on termcap ko string.\n");
691 if (ostrval
[uselevel
][cap_ko
] == NULL
)
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')
700 capname
[1] = ostrval
[uselevel
][cap_ko
][i
++];
701 if (ostrval
[uselevel
][cap_ko
][i
] == ',')
705 (void) fprintf(trace
, "key termcap name is '");
707 (void) fprintf(trace
, "'.\n");
710 /* match it up into our list */
712 for (j
= 0; !found
&& ko_map
[j
].keyedinfoname
!= NULL
; j
++) {
714 (void) fprintf(trace
, "looking at termcap name %s.\n",
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
) {
721 (ko_map
[j
].keyedinfoname
);
722 if (infostr
== NULL
) {
723 /* skip any possible padding */
725 while (ispadchar(*capstr
))
727 putstr(ko_map
[j
].keyedinfoname
, capstr
);
729 if (strcmp(capstr
, infostr
) != 0) {
730 (void) fprintf(stderr
,
731 "%s: TERM=%s: a function "
733 "specified with the "
737 (void) fprintf(stderr
,
738 ", but it already has the "
740 tpr(stderr
, infostr
);
741 (void) fprintf(stderr
, "'.\n");
749 (void) fprintf(stderr
, "%s: TERM=%s: the unknown "
750 "termcap name '%s' was\n", progname
, term_name
,
752 (void) fprintf(stderr
, "specified in the 'ko' "
753 "termcap capability.\n");
758 #define CONTROL(x) ((x) & 037)
764 CONTROL('J'), "kcud1", /* down */
765 CONTROL('N'), "kcud1",
767 CONTROL('P'), "kcuu1", /* up */
769 'h', "kcub1", /* left */
770 CONTROL('H'), "kcub1",
771 ' ', "kcuf1", /* right */
773 'H', "khome", /* home */
774 CONTROL('L'), "kclr", /* clear */
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.
787 prchar(FILE *stream
, int c
)
792 (void) fprintf(stream
, "%s", iexpand(xbuf
));
804 (void) fprintf(trace
, "working on termcap ma string.\n");
806 if (ostrval
[uselevel
][cap_ma
] == NULL
)
810 for (i
= 0; ostrval
[uselevel
][cap_ma
][i
] != '\0'; ) {
811 /* isolate the key's value */
812 cap
[0] = ostrval
[uselevel
][cap_ma
][i
++];
814 (void) fprintf(trace
, "key value is '");
816 (void) fprintf(trace
, "'.\n");
819 if (ostrval
[uselevel
][cap_ma
][i
] == '\0')
822 /* isolate the vi key name */
823 vichar
= ostrval
[uselevel
][cap_ma
][i
++];
825 (void) fprintf(trace
, "the vi key is '");
826 prchar(trace
, vichar
);
827 (void) fprintf(trace
, "'.\n");
830 /* match up the vi name in our list */
832 for (j
= 0; !found
&& ma_map
[j
].keyedinfoname
!= NULL
; j
++) {
834 (void) fprintf(trace
, "looking at vi "
836 prchar(trace
, ma_map
[j
].vichar
);
837 (void) fprintf(trace
, "'\n");
839 if (vichar
== ma_map
[j
].vichar
) {
840 infostr
= getinfostr(ma_map
[j
].keyedinfoname
);
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
,
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' "
854 prchar(stderr
, cap
[0]);
855 (void) fprintf(stderr
, "'.\n");
862 (void) fprintf(stderr
, "%s: the unknown vi key '",
864 prchar(stderr
, vichar
);
865 (void) fprintf(stderr
, "' was\n");
866 (void) fprintf(stderr
, "specified in the 'ma' termcap "
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.
883 (void) fprintf(trace
, "assigning defaults.\n");
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
)
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
]);
900 putstr("cud1", "\n");
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
)
908 putstr("ind", ostrval
[uselevel
][cap_nl
]);
910 /* bel was assumed to be ^G */
911 if (getinfostr("bel") == NULL
)
912 putstr("bel", "\07");
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
]);
920 putstr("cub1", "\b");
922 /* default xon to true */
923 if (!otgetflag("xo"))
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
)
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");
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
]);
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"))
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
]);
968 #define caddch(x) *to++ = (x)
971 * add the string to the string table
974 caddstr(char *to
, char *str
)
981 /* If there is no padding info or parmed strings, */
982 /* then we do not need to copy the string. */
984 needscopying(char *string
)
986 /* any string at all? */
990 /* any padding info? */
991 if (ispadchar(*string
))
994 /* any parmed info? */
996 if (*string
++ == '%')
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.
1010 fancycap(char *string
)
1015 if (*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':
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. */
1031 /* This manipulates both parameters, so we */
1032 /* cannot just do one and leave the value */
1033 /* on the stack like we can with %>, */
1044 * Change old style of doing calculations to the new stack style.
1045 * Note that this will not necessarily produce the most efficient string,
1049 changecalculations()
1052 char *from
, *to
= nextstring
;
1054 int parmset
, parmsaved
;
1055 char padding
[100], *saveto
;
1057 for (i
= 0; strnames
[i
]; i
++)
1058 if (needscopying(strval
[uselevel
][i
])) {
1060 (void) fprintf(trace
, "%s needs copying, "
1061 "was:", strnames
[i
]);
1062 tpr(trace
, strval
[uselevel
][i
]);
1063 (void) fprintf(trace
, ".\n");
1066 from
= strval
[uselevel
][i
];
1067 strval
[uselevel
][i
] = to
;
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
)) {
1077 to
= caddstr(to
, "$<");
1078 while (isdigit(*from
) || *from
== '.')
1088 if (fancycap(from
)) {
1089 to
= caddstr(to
, "%p1%Pa%p2%Pb");
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");
1100 while ((ch
= *from
++) != '\0')
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 */
1110 /* %+x -> %p1%'x'%+%c */
1113 /* %>xy -> %p1%Pc%?%'x'%> */
1115 /* if current value > x, then add y. */
1120 /* (16*(x/10))+(x%10) */
1122 /* (Adds Regent 100) */
1125 /* %D: Reverse coding */
1132 to
= caddstr(to
, "%g");
1133 if (currentparm
== 1)
1138 to
= caddstr(to
, "%p");
1139 if (currentparm
== 1)
1144 currentparm
= 3 - currentparm
;
1148 to
= caddstr(to
, "%c");
1151 to
= caddstr(to
, "%d");
1154 #ifdef USG /* Vr2==USG, Vr3==SYSV. Use %02d for Vr2, %2.2d for Vr3 */
1161 #endif /* USG vs. SYSV */
1166 to
= caddstr(to
, "%'");
1184 "%Pc%gc%{10}%/%{16}%*%gc%{10}%m%+");
1190 "%Pc%gc%gc%{16}%m%{2}%*%-");
1196 /* %r reverses current parameter */
1198 currentparm
= 3 - currentparm
;
1201 /* %n: exclusive-or row AND column */
1202 /* with 0140, 96 decimal, no output */
1203 /* (Datamedia 2500, Exidy Sorceror) */
1211 /* assume %x means %x */
1212 /* this includes %i and %% */
1217 to
= caddstr(to
, padding
);
1221 (void) fprintf(trace
, "and has become:");
1222 tpr(trace
, strval
[uselevel
][i
]);
1223 (void) fprintf(trace
, ".\n");
1230 print_no_use_entry(void)
1234 pr_heading("", buflongname
);
1237 for (i
= 0; boolcodes
[i
]; i
++)
1239 pr_boolean(boolnames
[i
], (char *)0, (char *)0, 1);
1244 for (i
= 0; numcodes
[i
]; i
++)
1245 if (numval
[0][i
] > -1)
1246 pr_number(numnames
[i
], (char *)0, (char *)0,
1252 for (i
= 0; strcodes
[i
]; i
++)
1254 pr_string(strnames
[i
], (char *)0, (char *)0,
1261 print_use_entry(char *usename
)
1265 pr_heading("", buflongname
);
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);
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,
1281 else if ((numval
[0] [i
] == -1) && (numval
[1] [i
] > -1))
1282 pr_number(numnames
[i
], (char *)0, (char *)0, -1);
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,
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,
1301 (void) printf("\tuse=%s,\n", usename
);
1310 if (term_name
== NULL
) {
1311 (void) fprintf(stderr
, "%s: Null term_name given.\n",
1317 (void) fprintf(trace
, "changing cap to info, TERM=%s.\n",
1321 if (filltables() == 0)
1325 changecalculations();
1326 if (TLHtcfound
!= 0) {
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)
1337 changecalculations();
1338 term_name
= sterm_name
;
1339 print_use_entry(usename
);
1341 print_no_use_entry();
1345 #include <signal.h> /* use this file to determine if this is SVR4.0 system */
1348 use_etc_termcap(void)
1352 (void) fprintf(trace
, "reading from /usr/share/lib/termcap\n");
1354 (void) fprintf(trace
, "reading from /etc/termcap\n");
1355 #endif /* SIGSTOP */
1356 term_name
= getenv("TERM");
1363 #if defined(SYSV) || defined(USG) /* handle both Sys Vr2 and Vr3 curses */
1364 (void) getcwd(dirname
, BUFSIZ
-2);
1366 (void) getwd(dirname
);
1367 #endif /* SYSV || USG */
1369 (void) fprintf(trace
, "current directory name=%s.\n", dirname
);
1370 environ
= newenviron
;
1374 setfilename(char *capfile
)
1376 if (capfile
[0] == '/')
1377 (void) snprintf(TERMCAP
, sizeof (TERMCAP
),
1378 "TERMCAP=%s", capfile
);
1380 (void) snprintf(TERMCAP
, sizeof (TERMCAP
),
1381 "TERMCAP=%s/%s", dirname
, capfile
);
1383 (void) fprintf(trace
, "setting the environment for %s.\n",
1391 (void) fprintf(trace
, "setting the environment "
1392 "for TERM=%s.\n", term_name
);
1393 (void) snprintf(TERM
, sizeof (TERM
), "TERM=%s", term_name
);
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. */
1402 getterm_name(char *line
)
1404 char *lineptr
= line
;
1407 (void) fprintf(trace
, "extracting name from '%s'.\n", line
);
1409 /* Copy comment lines out. */
1412 (void) printf("%s", line
);
1414 /* Blank lines get copied too. */
1415 else if (isspace (*line
)) {
1417 for (; *lineptr
; lineptr
++)
1418 if (!isspace(*lineptr
))
1420 if (*lineptr
== '\0')
1421 (void) printf("\n");
1425 for (; *lineptr
; lineptr
++)
1426 if (*lineptr
== '|' || *lineptr
== ':') {
1429 (void) fprintf(trace
,
1430 "returning %s.\n", line
);
1434 (void) fprintf(trace
, "returning NULL.\n");
1439 use_file(char *filename
)
1442 char buffer
[BUFSIZ
];
1445 (void) fprintf(trace
, "reading from %s.\n", filename
);
1447 if ((termfile
= fopen(filename
, "r")) == NULL
) {
1448 (void) fprintf(stderr
, "%s: cannot open %s for reading.\n",
1449 progname
, filename
);
1454 setfilename(filename
);
1456 while (fgets(buffer
, BUFSIZ
, termfile
) != NULL
) {
1457 if ((term_name
= getterm_name(buffer
)) != NULL
) {
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.
1470 sorttable(char *nametable
[], char *codetable
[])
1475 for (i
= 0; nametable
[i
]; i
++)
1476 for (j
= 0; j
< i
; j
++)
1477 if (strcmp(nametable
[i
], nametable
[j
]) < 0) {
1479 nametable
[i
] = nametable
[j
];
1482 codetable
[i
] = codetable
[j
];
1488 * Initialize and sort the name and code tables. Allocate space for the
1496 for (i
= 0; boolnames
[i
]; i
++)
1498 boolval
[0] = (char *)malloc(i
* sizeof (char));
1499 boolval
[1] = (char *)malloc(i
* sizeof (char));
1501 sorttable(boolnames
, boolcodes
);
1503 for (i
= 0; numcodes
[i
]; i
++)
1505 numval
[0] = (short *)malloc(i
* sizeof (short));
1506 numval
[1] = (short *)malloc(i
* sizeof (short));
1508 sorttable(numnames
, numcodes
);
1510 for (i
= 0; strcodes
[i
]; i
++)
1512 strval
[0] = (char **)malloc(i
* sizeof (char *));
1513 strval
[1] = (char **)malloc(i
* sizeof (char *));
1515 sorttable(strnames
, strcodes
);
1519 main(int argc
, char **argv
)
1522 char _capbuffer
[8192];
1523 char _bp
[TBUFSIZE
];
1524 char _buflongname
[128];
1526 capbuffer
= &_capbuffer
[0];
1528 buflongname
= &_buflongname
[0];
1531 while ((c
= getopt(argc
, argv
, "1vVw:")) != EOF
)
1537 pr_width(atoi(optarg
));
1543 (void) printf("%s: version %s\n", progname
,
1544 "@(#)curses:screen/captoinfo.c 1.12");
1545 (void) fflush(stdout
);
1547 /* FALLTHROUGH (not really) */
1549 (void) fprintf(stderr
,
1550 "usage: %s [-1Vv] [-w width] "
1551 "[filename ...]\n", progname
);
1552 (void) fprintf(stderr
, "\t-1\tsingle column "
1554 (void) fprintf(stderr
,
1555 "\t-v\tverbose debugging output\n");
1556 (void) fprintf(stderr
,
1557 "\t-V\tprint program version\n");
1562 pr_init(pr_terminfo
);
1569 for (; optind
< argc
; optind
++)
1570 use_file(argv
[optind
]);
1576 /* fake out the modules in print.c so we don't have to load in */
1577 /* cexpand.c and infotocap.c */
1580 cpr(FILE *stream
, char *string
)