1*fdd4e1e0SJan Lentfer /****************************************************************************
2*fdd4e1e0SJan Lentfer  * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc.              *
3*fdd4e1e0SJan Lentfer  *                                                                          *
4*fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
5*fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
6*fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
7*fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
8*fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
9*fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
10*fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
11*fdd4e1e0SJan Lentfer  *                                                                          *
12*fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
13*fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
14*fdd4e1e0SJan Lentfer  *                                                                          *
15*fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16*fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17*fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18*fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19*fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20*fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21*fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22*fdd4e1e0SJan Lentfer  *                                                                          *
23*fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
24*fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
25*fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
26*fdd4e1e0SJan Lentfer  * authorization.                                                           *
27*fdd4e1e0SJan Lentfer  ****************************************************************************/
28*fdd4e1e0SJan Lentfer 
29*fdd4e1e0SJan Lentfer /****************************************************************************
30*fdd4e1e0SJan Lentfer  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31*fdd4e1e0SJan Lentfer  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32*fdd4e1e0SJan Lentfer  ****************************************************************************/
33*fdd4e1e0SJan Lentfer 
34*fdd4e1e0SJan Lentfer /*
35*fdd4e1e0SJan Lentfer  *	captoinfo.c --- conversion between termcap and terminfo formats
36*fdd4e1e0SJan Lentfer  *
37*fdd4e1e0SJan Lentfer  *	The captoinfo() code was swiped from Ross Ridge's mytinfo package,
38*fdd4e1e0SJan Lentfer  *	adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>.
39*fdd4e1e0SJan Lentfer  *
40*fdd4e1e0SJan Lentfer  *	There is just one entry point:
41*fdd4e1e0SJan Lentfer  *
42*fdd4e1e0SJan Lentfer  *	char *_nc_captoinfo(n, s, parameterized)
43*fdd4e1e0SJan Lentfer  *
44*fdd4e1e0SJan Lentfer  *	Convert value s for termcap string capability named n into terminfo
45*fdd4e1e0SJan Lentfer  *	format.
46*fdd4e1e0SJan Lentfer  *
47*fdd4e1e0SJan Lentfer  *	This code recognizes all the standard 4.4BSD %-escapes:
48*fdd4e1e0SJan Lentfer  *
49*fdd4e1e0SJan Lentfer  *	%%       output `%'
50*fdd4e1e0SJan Lentfer  *	%d       output value as in printf %d
51*fdd4e1e0SJan Lentfer  *	%2       output value as in printf %2d
52*fdd4e1e0SJan Lentfer  *	%3       output value as in printf %3d
53*fdd4e1e0SJan Lentfer  *	%.       output value as in printf %c
54*fdd4e1e0SJan Lentfer  *	%+x      add x to value, then do %.
55*fdd4e1e0SJan Lentfer  *	%>xy     if value > x then add y, no output
56*fdd4e1e0SJan Lentfer  *	%r       reverse order of two parameters, no output
57*fdd4e1e0SJan Lentfer  *	%i       increment by one, no output
58*fdd4e1e0SJan Lentfer  *	%n       exclusive-or all parameters with 0140 (Datamedia 2500)
59*fdd4e1e0SJan Lentfer  *	%B       BCD (16*(value/10)) + (value%10), no output
60*fdd4e1e0SJan Lentfer  *	%D       Reverse coding (value - 2*(value%16)), no output (Delta Data).
61*fdd4e1e0SJan Lentfer  *
62*fdd4e1e0SJan Lentfer  *	Also, %02 and %03 are accepted as synonyms for %2 and %3.
63*fdd4e1e0SJan Lentfer  *
64*fdd4e1e0SJan Lentfer  *	Besides all the standard termcap escapes, this translator understands
65*fdd4e1e0SJan Lentfer  *	the following extended escapes:
66*fdd4e1e0SJan Lentfer  *
67*fdd4e1e0SJan Lentfer  *	used by GNU Emacs termcap libraries
68*fdd4e1e0SJan Lentfer  *		%a[+*-/=][cp]x	GNU arithmetic.
69*fdd4e1e0SJan Lentfer  *		%m		xor the first two parameters by 0177
70*fdd4e1e0SJan Lentfer  *		%b		backup to previous parameter
71*fdd4e1e0SJan Lentfer  *		%f		skip this parameter
72*fdd4e1e0SJan Lentfer  *
73*fdd4e1e0SJan Lentfer  *	used by the University of Waterloo (MFCF) termcap libraries
74*fdd4e1e0SJan Lentfer  *		%-x	 subtract parameter FROM char x and output it as a char
75*fdd4e1e0SJan Lentfer  *		%ax	 add the character x to parameter
76*fdd4e1e0SJan Lentfer  *
77*fdd4e1e0SJan Lentfer  *	If #define WATERLOO is on, also enable these translations:
78*fdd4e1e0SJan Lentfer  *
79*fdd4e1e0SJan Lentfer  *		%sx	 subtract parameter FROM the character x
80*fdd4e1e0SJan Lentfer  *
81*fdd4e1e0SJan Lentfer  *	By default, this Waterloo translations are not compiled in, because
82*fdd4e1e0SJan Lentfer  *	the Waterloo %s conflicts with the way terminfo uses %s in strings for
83*fdd4e1e0SJan Lentfer  *	function programming.
84*fdd4e1e0SJan Lentfer  *
85*fdd4e1e0SJan Lentfer  *	Note the two definitions of %a: the GNU definition is translated if the
86*fdd4e1e0SJan Lentfer  *	characters after the 'a' are valid for it, otherwise the UW definition
87*fdd4e1e0SJan Lentfer  *	is translated.
88*fdd4e1e0SJan Lentfer  */
89*fdd4e1e0SJan Lentfer 
90*fdd4e1e0SJan Lentfer #include <curses.priv.h>
91*fdd4e1e0SJan Lentfer 
92*fdd4e1e0SJan Lentfer #include <ctype.h>
93*fdd4e1e0SJan Lentfer #include <tic.h>
94*fdd4e1e0SJan Lentfer 
95*fdd4e1e0SJan Lentfer MODULE_ID("$Id: captoinfo.c,v 1.45 2003/11/08 21:28:04 tom Exp $")
96*fdd4e1e0SJan Lentfer 
97*fdd4e1e0SJan Lentfer #define MAX_PUSHED	16	/* max # args we can push onto the stack */
98*fdd4e1e0SJan Lentfer 
99*fdd4e1e0SJan Lentfer static int stack[MAX_PUSHED];	/* the stack */
100*fdd4e1e0SJan Lentfer static int stackptr;		/* the next empty place on the stack */
101*fdd4e1e0SJan Lentfer static int onstack;		/* the top of stack */
102*fdd4e1e0SJan Lentfer static int seenm;		/* seen a %m */
103*fdd4e1e0SJan Lentfer static int seenn;		/* seen a %n */
104*fdd4e1e0SJan Lentfer static int seenr;		/* seen a %r */
105*fdd4e1e0SJan Lentfer static int param;		/* current parameter */
106*fdd4e1e0SJan Lentfer static char *dp;		/* pointer to end of the converted string */
107*fdd4e1e0SJan Lentfer 
108*fdd4e1e0SJan Lentfer static char *my_string;
109*fdd4e1e0SJan Lentfer static size_t my_length;
110*fdd4e1e0SJan Lentfer 
111*fdd4e1e0SJan Lentfer static char *
112*fdd4e1e0SJan Lentfer init_string(void)
113*fdd4e1e0SJan Lentfer /* initialize 'my_string', 'my_length' */
114*fdd4e1e0SJan Lentfer {
115*fdd4e1e0SJan Lentfer     if (my_string == 0)
116*fdd4e1e0SJan Lentfer 	my_string = typeMalloc(char, my_length = 256);
117*fdd4e1e0SJan Lentfer     if (my_string == 0)
118*fdd4e1e0SJan Lentfer 	_nc_err_abort(MSG_NO_MEMORY);
119*fdd4e1e0SJan Lentfer 
120*fdd4e1e0SJan Lentfer     *my_string = '\0';
121*fdd4e1e0SJan Lentfer     return my_string;
122*fdd4e1e0SJan Lentfer }
123*fdd4e1e0SJan Lentfer 
124*fdd4e1e0SJan Lentfer static char *
125*fdd4e1e0SJan Lentfer save_string(char *d, const char *const s)
126*fdd4e1e0SJan Lentfer {
127*fdd4e1e0SJan Lentfer     size_t have = (d - my_string);
128*fdd4e1e0SJan Lentfer     size_t need = have + strlen(s) + 2;
129*fdd4e1e0SJan Lentfer     if (need > my_length) {
130*fdd4e1e0SJan Lentfer 	my_string = (char *) realloc(my_string, my_length = (need + need));
131*fdd4e1e0SJan Lentfer 	if (my_string == 0)
132*fdd4e1e0SJan Lentfer 	    _nc_err_abort(MSG_NO_MEMORY);
133*fdd4e1e0SJan Lentfer 	d = my_string + have;
134*fdd4e1e0SJan Lentfer     }
135*fdd4e1e0SJan Lentfer     (void) strcpy(d, s);
136*fdd4e1e0SJan Lentfer     return d + strlen(d);
137*fdd4e1e0SJan Lentfer }
138*fdd4e1e0SJan Lentfer 
139*fdd4e1e0SJan Lentfer static inline char *
140*fdd4e1e0SJan Lentfer save_char(char *s, int c)
141*fdd4e1e0SJan Lentfer {
142*fdd4e1e0SJan Lentfer     static char temp[2];
143*fdd4e1e0SJan Lentfer     temp[0] = (char) c;
144*fdd4e1e0SJan Lentfer     return save_string(s, temp);
145*fdd4e1e0SJan Lentfer }
146*fdd4e1e0SJan Lentfer 
147*fdd4e1e0SJan Lentfer static void
148*fdd4e1e0SJan Lentfer push(void)
149*fdd4e1e0SJan Lentfer /* push onstack on to the stack */
150*fdd4e1e0SJan Lentfer {
151*fdd4e1e0SJan Lentfer     if (stackptr > MAX_PUSHED)
152*fdd4e1e0SJan Lentfer 	_nc_warning("string too complex to convert");
153*fdd4e1e0SJan Lentfer     else
154*fdd4e1e0SJan Lentfer 	stack[stackptr++] = onstack;
155*fdd4e1e0SJan Lentfer }
156*fdd4e1e0SJan Lentfer 
157*fdd4e1e0SJan Lentfer static void
158*fdd4e1e0SJan Lentfer pop(void)
159*fdd4e1e0SJan Lentfer /* pop the top of the stack into onstack */
160*fdd4e1e0SJan Lentfer {
161*fdd4e1e0SJan Lentfer     if (stackptr == 0) {
162*fdd4e1e0SJan Lentfer 	if (onstack == 0)
163*fdd4e1e0SJan Lentfer 	    _nc_warning("I'm confused");
164*fdd4e1e0SJan Lentfer 	else
165*fdd4e1e0SJan Lentfer 	    onstack = 0;
166*fdd4e1e0SJan Lentfer     } else
167*fdd4e1e0SJan Lentfer 	onstack = stack[--stackptr];
168*fdd4e1e0SJan Lentfer     param++;
169*fdd4e1e0SJan Lentfer }
170*fdd4e1e0SJan Lentfer 
171*fdd4e1e0SJan Lentfer static int
172*fdd4e1e0SJan Lentfer cvtchar(register const char *sp)
173*fdd4e1e0SJan Lentfer /* convert a character to a terminfo push */
174*fdd4e1e0SJan Lentfer {
175*fdd4e1e0SJan Lentfer     unsigned char c = 0;
176*fdd4e1e0SJan Lentfer     int len;
177*fdd4e1e0SJan Lentfer 
178*fdd4e1e0SJan Lentfer     switch (*sp) {
179*fdd4e1e0SJan Lentfer     case '\\':
180*fdd4e1e0SJan Lentfer 	switch (*++sp) {
181*fdd4e1e0SJan Lentfer 	case '\'':
182*fdd4e1e0SJan Lentfer 	case '$':
183*fdd4e1e0SJan Lentfer 	case '\\':
184*fdd4e1e0SJan Lentfer 	case '%':
185*fdd4e1e0SJan Lentfer 	    c = *sp;
186*fdd4e1e0SJan Lentfer 	    len = 2;
187*fdd4e1e0SJan Lentfer 	    break;
188*fdd4e1e0SJan Lentfer 	case '\0':
189*fdd4e1e0SJan Lentfer 	    c = '\\';
190*fdd4e1e0SJan Lentfer 	    len = 1;
191*fdd4e1e0SJan Lentfer 	    break;
192*fdd4e1e0SJan Lentfer 	case '0':
193*fdd4e1e0SJan Lentfer 	case '1':
194*fdd4e1e0SJan Lentfer 	case '2':
195*fdd4e1e0SJan Lentfer 	case '3':
196*fdd4e1e0SJan Lentfer 	    len = 1;
197*fdd4e1e0SJan Lentfer 	    while (isdigit(UChar(*sp))) {
198*fdd4e1e0SJan Lentfer 		c = 8 * c + (*sp++ - '0');
199*fdd4e1e0SJan Lentfer 		len++;
200*fdd4e1e0SJan Lentfer 	    }
201*fdd4e1e0SJan Lentfer 	    break;
202*fdd4e1e0SJan Lentfer 	default:
203*fdd4e1e0SJan Lentfer 	    c = *sp;
204*fdd4e1e0SJan Lentfer 	    len = 2;
205*fdd4e1e0SJan Lentfer 	    break;
206*fdd4e1e0SJan Lentfer 	}
207*fdd4e1e0SJan Lentfer 	break;
208*fdd4e1e0SJan Lentfer     case '^':
209*fdd4e1e0SJan Lentfer 	c = (*++sp & 0x1f);
210*fdd4e1e0SJan Lentfer 	len = 2;
211*fdd4e1e0SJan Lentfer 	break;
212*fdd4e1e0SJan Lentfer     default:
213*fdd4e1e0SJan Lentfer 	c = *sp;
214*fdd4e1e0SJan Lentfer 	len = 1;
215*fdd4e1e0SJan Lentfer     }
216*fdd4e1e0SJan Lentfer     if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') {
217*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "%\'");
218*fdd4e1e0SJan Lentfer 	dp = save_char(dp, c);
219*fdd4e1e0SJan Lentfer 	dp = save_char(dp, '\'');
220*fdd4e1e0SJan Lentfer     } else {
221*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "%{");
222*fdd4e1e0SJan Lentfer 	if (c > 99)
223*fdd4e1e0SJan Lentfer 	    dp = save_char(dp, c / 100 + '0');
224*fdd4e1e0SJan Lentfer 	if (c > 9)
225*fdd4e1e0SJan Lentfer 	    dp = save_char(dp, ((int) (c / 10)) % 10 + '0');
226*fdd4e1e0SJan Lentfer 	dp = save_char(dp, c % 10 + '0');
227*fdd4e1e0SJan Lentfer 	dp = save_char(dp, '}');
228*fdd4e1e0SJan Lentfer     }
229*fdd4e1e0SJan Lentfer     return len;
230*fdd4e1e0SJan Lentfer }
231*fdd4e1e0SJan Lentfer 
232*fdd4e1e0SJan Lentfer static void
233*fdd4e1e0SJan Lentfer getparm(int parm, int n)
234*fdd4e1e0SJan Lentfer /* push n copies of param on the terminfo stack if not already there */
235*fdd4e1e0SJan Lentfer {
236*fdd4e1e0SJan Lentfer     if (seenr) {
237*fdd4e1e0SJan Lentfer 	if (parm == 1)
238*fdd4e1e0SJan Lentfer 	    parm = 2;
239*fdd4e1e0SJan Lentfer 	else if (parm == 2)
240*fdd4e1e0SJan Lentfer 	    parm = 1;
241*fdd4e1e0SJan Lentfer     }
242*fdd4e1e0SJan Lentfer     if (onstack == parm) {
243*fdd4e1e0SJan Lentfer 	if (n > 1) {
244*fdd4e1e0SJan Lentfer 	    _nc_warning("string may not be optimal");
245*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "%Pa");
246*fdd4e1e0SJan Lentfer 	    while (n--) {
247*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%ga");
248*fdd4e1e0SJan Lentfer 	    }
249*fdd4e1e0SJan Lentfer 	}
250*fdd4e1e0SJan Lentfer 	return;
251*fdd4e1e0SJan Lentfer     }
252*fdd4e1e0SJan Lentfer     if (onstack != 0)
253*fdd4e1e0SJan Lentfer 	push();
254*fdd4e1e0SJan Lentfer 
255*fdd4e1e0SJan Lentfer     onstack = parm;
256*fdd4e1e0SJan Lentfer 
257*fdd4e1e0SJan Lentfer     while (n--) {
258*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "%p");
259*fdd4e1e0SJan Lentfer 	dp = save_char(dp, '0' + parm);
260*fdd4e1e0SJan Lentfer     }
261*fdd4e1e0SJan Lentfer 
262*fdd4e1e0SJan Lentfer     if (seenn && parm < 3) {
263*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "%{96}%^");
264*fdd4e1e0SJan Lentfer     }
265*fdd4e1e0SJan Lentfer 
266*fdd4e1e0SJan Lentfer     if (seenm && parm < 3) {
267*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "%{127}%^");
268*fdd4e1e0SJan Lentfer     }
269*fdd4e1e0SJan Lentfer }
270*fdd4e1e0SJan Lentfer 
271*fdd4e1e0SJan Lentfer /*
272*fdd4e1e0SJan Lentfer  * Convert a termcap string to terminfo format.
273*fdd4e1e0SJan Lentfer  * 'cap' is the relevant terminfo capability index.
274*fdd4e1e0SJan Lentfer  * 's' is the string value of the capability.
275*fdd4e1e0SJan Lentfer  * 'parameterized' tells what type of translations to do:
276*fdd4e1e0SJan Lentfer  *	% translations if 1
277*fdd4e1e0SJan Lentfer  *	pad translations if >=0
278*fdd4e1e0SJan Lentfer  */
279*fdd4e1e0SJan Lentfer char *
280*fdd4e1e0SJan Lentfer _nc_captoinfo(const char *cap, const char *s, int const parameterized)
281*fdd4e1e0SJan Lentfer {
282*fdd4e1e0SJan Lentfer     const char *capstart;
283*fdd4e1e0SJan Lentfer 
284*fdd4e1e0SJan Lentfer     stackptr = 0;
285*fdd4e1e0SJan Lentfer     onstack = 0;
286*fdd4e1e0SJan Lentfer     seenm = 0;
287*fdd4e1e0SJan Lentfer     seenn = 0;
288*fdd4e1e0SJan Lentfer     seenr = 0;
289*fdd4e1e0SJan Lentfer     param = 1;
290*fdd4e1e0SJan Lentfer 
291*fdd4e1e0SJan Lentfer     dp = init_string();
292*fdd4e1e0SJan Lentfer 
293*fdd4e1e0SJan Lentfer     /* skip the initial padding (if we haven't been told not to) */
294*fdd4e1e0SJan Lentfer     capstart = 0;
295*fdd4e1e0SJan Lentfer     if (s == 0)
296*fdd4e1e0SJan Lentfer 	s = "";
297*fdd4e1e0SJan Lentfer     if (parameterized >= 0 && isdigit(UChar(*s)))
298*fdd4e1e0SJan Lentfer 	for (capstart = s;; s++)
299*fdd4e1e0SJan Lentfer 	    if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.'))
300*fdd4e1e0SJan Lentfer 		break;
301*fdd4e1e0SJan Lentfer 
302*fdd4e1e0SJan Lentfer     while (*s != '\0') {
303*fdd4e1e0SJan Lentfer 	switch (*s) {
304*fdd4e1e0SJan Lentfer 	case '%':
305*fdd4e1e0SJan Lentfer 	    s++;
306*fdd4e1e0SJan Lentfer 	    if (parameterized < 1) {
307*fdd4e1e0SJan Lentfer 		dp = save_char(dp, '%');
308*fdd4e1e0SJan Lentfer 		break;
309*fdd4e1e0SJan Lentfer 	    }
310*fdd4e1e0SJan Lentfer 	    switch (*s++) {
311*fdd4e1e0SJan Lentfer 	    case '%':
312*fdd4e1e0SJan Lentfer 		dp = save_char(dp, '%');
313*fdd4e1e0SJan Lentfer 		break;
314*fdd4e1e0SJan Lentfer 	    case 'r':
315*fdd4e1e0SJan Lentfer 		if (seenr++ == 1) {
316*fdd4e1e0SJan Lentfer 		    _nc_warning("saw %%r twice in %s", cap);
317*fdd4e1e0SJan Lentfer 		}
318*fdd4e1e0SJan Lentfer 		break;
319*fdd4e1e0SJan Lentfer 	    case 'm':
320*fdd4e1e0SJan Lentfer 		if (seenm++ == 1) {
321*fdd4e1e0SJan Lentfer 		    _nc_warning("saw %%m twice in %s", cap);
322*fdd4e1e0SJan Lentfer 		}
323*fdd4e1e0SJan Lentfer 		break;
324*fdd4e1e0SJan Lentfer 	    case 'n':
325*fdd4e1e0SJan Lentfer 		if (seenn++ == 1) {
326*fdd4e1e0SJan Lentfer 		    _nc_warning("saw %%n twice in %s", cap);
327*fdd4e1e0SJan Lentfer 		}
328*fdd4e1e0SJan Lentfer 		break;
329*fdd4e1e0SJan Lentfer 	    case 'i':
330*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%i");
331*fdd4e1e0SJan Lentfer 		break;
332*fdd4e1e0SJan Lentfer 	    case '6':
333*fdd4e1e0SJan Lentfer 	    case 'B':
334*fdd4e1e0SJan Lentfer 		getparm(param, 1);
335*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%{10}%/%{16}%*");
336*fdd4e1e0SJan Lentfer 		getparm(param, 1);
337*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%{10}%m%+");
338*fdd4e1e0SJan Lentfer 		break;
339*fdd4e1e0SJan Lentfer 	    case '8':
340*fdd4e1e0SJan Lentfer 	    case 'D':
341*fdd4e1e0SJan Lentfer 		getparm(param, 2);
342*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%{2}%*%-");
343*fdd4e1e0SJan Lentfer 		break;
344*fdd4e1e0SJan Lentfer 	    case '>':
345*fdd4e1e0SJan Lentfer 		getparm(param, 2);
346*fdd4e1e0SJan Lentfer 		/* %?%{x}%>%t%{y}%+%; */
347*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%?");
348*fdd4e1e0SJan Lentfer 		s += cvtchar(s);
349*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%>%t");
350*fdd4e1e0SJan Lentfer 		s += cvtchar(s);
351*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%+%;");
352*fdd4e1e0SJan Lentfer 		break;
353*fdd4e1e0SJan Lentfer 	    case 'a':
354*fdd4e1e0SJan Lentfer 		if ((*s == '=' || *s == '+' || *s == '-'
355*fdd4e1e0SJan Lentfer 		     || *s == '*' || *s == '/')
356*fdd4e1e0SJan Lentfer 		    && (s[1] == 'p' || s[1] == 'c')
357*fdd4e1e0SJan Lentfer 		    && s[2] != '\0') {
358*fdd4e1e0SJan Lentfer 		    int l;
359*fdd4e1e0SJan Lentfer 		    l = 2;
360*fdd4e1e0SJan Lentfer 		    if (*s != '=')
361*fdd4e1e0SJan Lentfer 			getparm(param, 1);
362*fdd4e1e0SJan Lentfer 		    if (s[1] == 'p') {
363*fdd4e1e0SJan Lentfer 			getparm(param + s[2] - '@', 1);
364*fdd4e1e0SJan Lentfer 			if (param != onstack) {
365*fdd4e1e0SJan Lentfer 			    pop();
366*fdd4e1e0SJan Lentfer 			    param--;
367*fdd4e1e0SJan Lentfer 			}
368*fdd4e1e0SJan Lentfer 			l++;
369*fdd4e1e0SJan Lentfer 		    } else
370*fdd4e1e0SJan Lentfer 			l += cvtchar(s + 2);
371*fdd4e1e0SJan Lentfer 		    switch (*s) {
372*fdd4e1e0SJan Lentfer 		    case '+':
373*fdd4e1e0SJan Lentfer 			dp = save_string(dp, "%+");
374*fdd4e1e0SJan Lentfer 			break;
375*fdd4e1e0SJan Lentfer 		    case '-':
376*fdd4e1e0SJan Lentfer 			dp = save_string(dp, "%-");
377*fdd4e1e0SJan Lentfer 			break;
378*fdd4e1e0SJan Lentfer 		    case '*':
379*fdd4e1e0SJan Lentfer 			dp = save_string(dp, "%*");
380*fdd4e1e0SJan Lentfer 			break;
381*fdd4e1e0SJan Lentfer 		    case '/':
382*fdd4e1e0SJan Lentfer 			dp = save_string(dp, "%/");
383*fdd4e1e0SJan Lentfer 			break;
384*fdd4e1e0SJan Lentfer 		    case '=':
385*fdd4e1e0SJan Lentfer 			if (seenr) {
386*fdd4e1e0SJan Lentfer 			    if (param == 1)
387*fdd4e1e0SJan Lentfer 				onstack = 2;
388*fdd4e1e0SJan Lentfer 			    else if (param == 2)
389*fdd4e1e0SJan Lentfer 				onstack = 1;
390*fdd4e1e0SJan Lentfer 			    else
391*fdd4e1e0SJan Lentfer 				onstack = param;
392*fdd4e1e0SJan Lentfer 			} else
393*fdd4e1e0SJan Lentfer 			    onstack = param;
394*fdd4e1e0SJan Lentfer 			break;
395*fdd4e1e0SJan Lentfer 		    }
396*fdd4e1e0SJan Lentfer 		    s += l;
397*fdd4e1e0SJan Lentfer 		    break;
398*fdd4e1e0SJan Lentfer 		}
399*fdd4e1e0SJan Lentfer 		getparm(param, 1);
400*fdd4e1e0SJan Lentfer 		s += cvtchar(s);
401*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%+");
402*fdd4e1e0SJan Lentfer 		break;
403*fdd4e1e0SJan Lentfer 	    case '+':
404*fdd4e1e0SJan Lentfer 		getparm(param, 1);
405*fdd4e1e0SJan Lentfer 		s += cvtchar(s);
406*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%+%c");
407*fdd4e1e0SJan Lentfer 		pop();
408*fdd4e1e0SJan Lentfer 		break;
409*fdd4e1e0SJan Lentfer 	    case 's':
410*fdd4e1e0SJan Lentfer #ifdef WATERLOO
411*fdd4e1e0SJan Lentfer 		s += cvtchar(s);
412*fdd4e1e0SJan Lentfer 		getparm(param, 1);
413*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%-");
414*fdd4e1e0SJan Lentfer #else
415*fdd4e1e0SJan Lentfer 		getparm(param, 1);
416*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%s");
417*fdd4e1e0SJan Lentfer 		pop();
418*fdd4e1e0SJan Lentfer #endif /* WATERLOO */
419*fdd4e1e0SJan Lentfer 		break;
420*fdd4e1e0SJan Lentfer 	    case '-':
421*fdd4e1e0SJan Lentfer 		s += cvtchar(s);
422*fdd4e1e0SJan Lentfer 		getparm(param, 1);
423*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%-%c");
424*fdd4e1e0SJan Lentfer 		pop();
425*fdd4e1e0SJan Lentfer 		break;
426*fdd4e1e0SJan Lentfer 	    case '.':
427*fdd4e1e0SJan Lentfer 		getparm(param, 1);
428*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%c");
429*fdd4e1e0SJan Lentfer 		pop();
430*fdd4e1e0SJan Lentfer 		break;
431*fdd4e1e0SJan Lentfer 	    case '0':		/* not clear any of the historical termcaps did this */
432*fdd4e1e0SJan Lentfer 		if (*s == '3')
433*fdd4e1e0SJan Lentfer 		    goto see03;
434*fdd4e1e0SJan Lentfer 		else if (*s != '2')
435*fdd4e1e0SJan Lentfer 		    goto invalid;
436*fdd4e1e0SJan Lentfer 		/* FALLTHRU */
437*fdd4e1e0SJan Lentfer 	    case '2':
438*fdd4e1e0SJan Lentfer 		getparm(param, 1);
439*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%2d");
440*fdd4e1e0SJan Lentfer 		pop();
441*fdd4e1e0SJan Lentfer 		break;
442*fdd4e1e0SJan Lentfer 	    case '3':
443*fdd4e1e0SJan Lentfer 	      see03:
444*fdd4e1e0SJan Lentfer 		getparm(param, 1);
445*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%3d");
446*fdd4e1e0SJan Lentfer 		pop();
447*fdd4e1e0SJan Lentfer 		break;
448*fdd4e1e0SJan Lentfer 	    case 'd':
449*fdd4e1e0SJan Lentfer 		getparm(param, 1);
450*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%d");
451*fdd4e1e0SJan Lentfer 		pop();
452*fdd4e1e0SJan Lentfer 		break;
453*fdd4e1e0SJan Lentfer 	    case 'f':
454*fdd4e1e0SJan Lentfer 		param++;
455*fdd4e1e0SJan Lentfer 		break;
456*fdd4e1e0SJan Lentfer 	    case 'b':
457*fdd4e1e0SJan Lentfer 		param--;
458*fdd4e1e0SJan Lentfer 		break;
459*fdd4e1e0SJan Lentfer 	    case '\\':
460*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "%\\");
461*fdd4e1e0SJan Lentfer 		break;
462*fdd4e1e0SJan Lentfer 	    default:
463*fdd4e1e0SJan Lentfer 	      invalid:
464*fdd4e1e0SJan Lentfer 		dp = save_char(dp, '%');
465*fdd4e1e0SJan Lentfer 		s--;
466*fdd4e1e0SJan Lentfer 		_nc_warning("unknown %% code %s (%#x) in %s",
467*fdd4e1e0SJan Lentfer 			    unctrl((chtype) *s), UChar(*s), cap);
468*fdd4e1e0SJan Lentfer 		break;
469*fdd4e1e0SJan Lentfer 	    }
470*fdd4e1e0SJan Lentfer 	    break;
471*fdd4e1e0SJan Lentfer #ifdef REVISIBILIZE
472*fdd4e1e0SJan Lentfer 	case '\\':
473*fdd4e1e0SJan Lentfer 	    dp = save_char(dp, *s++);
474*fdd4e1e0SJan Lentfer 	    dp = save_char(dp, *s++);
475*fdd4e1e0SJan Lentfer 	    break;
476*fdd4e1e0SJan Lentfer 	case '\n':
477*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\n");
478*fdd4e1e0SJan Lentfer 	    s++;
479*fdd4e1e0SJan Lentfer 	    break;
480*fdd4e1e0SJan Lentfer 	case '\t':
481*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\t");
482*fdd4e1e0SJan Lentfer 	    s++;
483*fdd4e1e0SJan Lentfer 	    break;
484*fdd4e1e0SJan Lentfer 	case '\r':
485*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\r");
486*fdd4e1e0SJan Lentfer 	    s++;
487*fdd4e1e0SJan Lentfer 	    break;
488*fdd4e1e0SJan Lentfer 	case '\200':
489*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\0");
490*fdd4e1e0SJan Lentfer 	    s++;
491*fdd4e1e0SJan Lentfer 	    break;
492*fdd4e1e0SJan Lentfer 	case '\f':
493*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\f");
494*fdd4e1e0SJan Lentfer 	    s++;
495*fdd4e1e0SJan Lentfer 	    break;
496*fdd4e1e0SJan Lentfer 	case '\b':
497*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\b");
498*fdd4e1e0SJan Lentfer 	    s++;
499*fdd4e1e0SJan Lentfer 	    break;
500*fdd4e1e0SJan Lentfer 	case ' ':
501*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\s");
502*fdd4e1e0SJan Lentfer 	    s++;
503*fdd4e1e0SJan Lentfer 	    break;
504*fdd4e1e0SJan Lentfer 	case '^':
505*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\^");
506*fdd4e1e0SJan Lentfer 	    s++;
507*fdd4e1e0SJan Lentfer 	    break;
508*fdd4e1e0SJan Lentfer 	case ':':
509*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\:");
510*fdd4e1e0SJan Lentfer 	    s++;
511*fdd4e1e0SJan Lentfer 	    break;
512*fdd4e1e0SJan Lentfer 	case ',':
513*fdd4e1e0SJan Lentfer 	    dp = save_string(dp, "\\,");
514*fdd4e1e0SJan Lentfer 	    s++;
515*fdd4e1e0SJan Lentfer 	    break;
516*fdd4e1e0SJan Lentfer 	default:
517*fdd4e1e0SJan Lentfer 	    if (*s == '\033') {
518*fdd4e1e0SJan Lentfer 		dp = save_string(dp, "\\E");
519*fdd4e1e0SJan Lentfer 		s++;
520*fdd4e1e0SJan Lentfer 	    } else if (*s > 0 && *s < 32) {
521*fdd4e1e0SJan Lentfer 		dp = save_char(dp, '^');
522*fdd4e1e0SJan Lentfer 		dp = save_char(dp, *s + '@');
523*fdd4e1e0SJan Lentfer 		s++;
524*fdd4e1e0SJan Lentfer 	    } else if (*s <= 0 || *s >= 127) {
525*fdd4e1e0SJan Lentfer 		dp = save_char(dp, '\\');
526*fdd4e1e0SJan Lentfer 		dp = save_char(dp, ((*s & 0300) >> 6) + '0');
527*fdd4e1e0SJan Lentfer 		dp = save_char(dp, ((*s & 0070) >> 3) + '0');
528*fdd4e1e0SJan Lentfer 		dp = save_char(dp, (*s & 0007) + '0');
529*fdd4e1e0SJan Lentfer 		s++;
530*fdd4e1e0SJan Lentfer 	    } else
531*fdd4e1e0SJan Lentfer 		dp = save_char(dp, *s++);
532*fdd4e1e0SJan Lentfer 	    break;
533*fdd4e1e0SJan Lentfer #else
534*fdd4e1e0SJan Lentfer 	default:
535*fdd4e1e0SJan Lentfer 	    dp = save_char(dp, *s++);
536*fdd4e1e0SJan Lentfer 	    break;
537*fdd4e1e0SJan Lentfer #endif
538*fdd4e1e0SJan Lentfer 	}
539*fdd4e1e0SJan Lentfer     }
540*fdd4e1e0SJan Lentfer 
541*fdd4e1e0SJan Lentfer     /*
542*fdd4e1e0SJan Lentfer      * Now, if we stripped off some leading padding, add it at the end
543*fdd4e1e0SJan Lentfer      * of the string as mandatory padding.
544*fdd4e1e0SJan Lentfer      */
545*fdd4e1e0SJan Lentfer     if (capstart) {
546*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "$<");
547*fdd4e1e0SJan Lentfer 	for (s = capstart;; s++)
548*fdd4e1e0SJan Lentfer 	    if (isdigit(UChar(*s)) || *s == '*' || *s == '.')
549*fdd4e1e0SJan Lentfer 		dp = save_char(dp, *s);
550*fdd4e1e0SJan Lentfer 	    else
551*fdd4e1e0SJan Lentfer 		break;
552*fdd4e1e0SJan Lentfer 	dp = save_string(dp, "/>");
553*fdd4e1e0SJan Lentfer     }
554*fdd4e1e0SJan Lentfer 
555*fdd4e1e0SJan Lentfer     (void) save_char(dp, '\0');
556*fdd4e1e0SJan Lentfer     return (my_string);
557*fdd4e1e0SJan Lentfer }
558*fdd4e1e0SJan Lentfer 
559*fdd4e1e0SJan Lentfer /*
560*fdd4e1e0SJan Lentfer  * Check for an expression that corresponds to "%B" (BCD):
561*fdd4e1e0SJan Lentfer  *	(parameter / 10) * 16 + (parameter % 10)
562*fdd4e1e0SJan Lentfer  */
563*fdd4e1e0SJan Lentfer static int
564*fdd4e1e0SJan Lentfer bcd_expression(const char *str)
565*fdd4e1e0SJan Lentfer {
566*fdd4e1e0SJan Lentfer     /* leave this non-const for HPUX */
567*fdd4e1e0SJan Lentfer     static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+";
568*fdd4e1e0SJan Lentfer     int len = 0;
569*fdd4e1e0SJan Lentfer     char ch1, ch2;
570*fdd4e1e0SJan Lentfer 
571*fdd4e1e0SJan Lentfer     if (sscanf(str, fmt, &ch1, &ch2) == 2
572*fdd4e1e0SJan Lentfer 	&& isdigit(UChar(ch1))
573*fdd4e1e0SJan Lentfer 	&& isdigit(UChar(ch2))
574*fdd4e1e0SJan Lentfer 	&& (ch1 == ch2)) {
575*fdd4e1e0SJan Lentfer 	len = 28;
576*fdd4e1e0SJan Lentfer #ifndef NDEBUG
577*fdd4e1e0SJan Lentfer 	{
578*fdd4e1e0SJan Lentfer 	    char buffer[80];
579*fdd4e1e0SJan Lentfer 	    int tst;
580*fdd4e1e0SJan Lentfer 	    sprintf(buffer, fmt, ch1, ch2);
581*fdd4e1e0SJan Lentfer 	    tst = strlen(buffer) - 1;
582*fdd4e1e0SJan Lentfer 	    assert(len == tst);
583*fdd4e1e0SJan Lentfer 	}
584*fdd4e1e0SJan Lentfer #endif
585*fdd4e1e0SJan Lentfer     }
586*fdd4e1e0SJan Lentfer     return len;
587*fdd4e1e0SJan Lentfer }
588*fdd4e1e0SJan Lentfer 
589*fdd4e1e0SJan Lentfer static char *
590*fdd4e1e0SJan Lentfer save_tc_char(char *bufptr, int c1)
591*fdd4e1e0SJan Lentfer {
592*fdd4e1e0SJan Lentfer     char temp[80];
593*fdd4e1e0SJan Lentfer 
594*fdd4e1e0SJan Lentfer     if (is7bits(c1) && isprint(c1)) {
595*fdd4e1e0SJan Lentfer 	if (c1 == ':' || c1 == '\\')
596*fdd4e1e0SJan Lentfer 	    bufptr = save_char(bufptr, '\\');
597*fdd4e1e0SJan Lentfer 	bufptr = save_char(bufptr, c1);
598*fdd4e1e0SJan Lentfer     } else {
599*fdd4e1e0SJan Lentfer 	if (c1 == (c1 & 0x1f))	/* iscntrl() returns T on 255 */
600*fdd4e1e0SJan Lentfer 	    (void) strcpy(temp, unctrl((chtype) c1));
601*fdd4e1e0SJan Lentfer 	else
602*fdd4e1e0SJan Lentfer 	    (void) sprintf(temp, "\\%03o", c1);
603*fdd4e1e0SJan Lentfer 	bufptr = save_string(bufptr, temp);
604*fdd4e1e0SJan Lentfer     }
605*fdd4e1e0SJan Lentfer     return bufptr;
606*fdd4e1e0SJan Lentfer }
607*fdd4e1e0SJan Lentfer 
608*fdd4e1e0SJan Lentfer static char *
609*fdd4e1e0SJan Lentfer save_tc_inequality(char *bufptr, int c1, int c2)
610*fdd4e1e0SJan Lentfer {
611*fdd4e1e0SJan Lentfer     bufptr = save_string(bufptr, "%>");
612*fdd4e1e0SJan Lentfer     bufptr = save_tc_char(bufptr, c1);
613*fdd4e1e0SJan Lentfer     bufptr = save_tc_char(bufptr, c2);
614*fdd4e1e0SJan Lentfer     return bufptr;
615*fdd4e1e0SJan Lentfer }
616*fdd4e1e0SJan Lentfer 
617*fdd4e1e0SJan Lentfer /*
618*fdd4e1e0SJan Lentfer  * Here are the capabilities infotocap assumes it can translate to:
619*fdd4e1e0SJan Lentfer  *
620*fdd4e1e0SJan Lentfer  *     %%       output `%'
621*fdd4e1e0SJan Lentfer  *     %d       output value as in printf %d
622*fdd4e1e0SJan Lentfer  *     %2       output value as in printf %2d
623*fdd4e1e0SJan Lentfer  *     %3       output value as in printf %3d
624*fdd4e1e0SJan Lentfer  *     %.       output value as in printf %c
625*fdd4e1e0SJan Lentfer  *     %+c      add character c to value, then do %.
626*fdd4e1e0SJan Lentfer  *     %>xy     if value > x then add y, no output
627*fdd4e1e0SJan Lentfer  *     %r       reverse order of two parameters, no output
628*fdd4e1e0SJan Lentfer  *     %i       increment by one, no output
629*fdd4e1e0SJan Lentfer  *     %n       exclusive-or all parameters with 0140 (Datamedia 2500)
630*fdd4e1e0SJan Lentfer  *     %B       BCD (16*(value/10)) + (value%10), no output
631*fdd4e1e0SJan Lentfer  *     %D       Reverse coding (value - 2*(value%16)), no output (Delta Data).
632*fdd4e1e0SJan Lentfer  *     %m       exclusive-or all parameters with 0177 (not in 4.4BSD)
633*fdd4e1e0SJan Lentfer  */
634*fdd4e1e0SJan Lentfer 
635*fdd4e1e0SJan Lentfer /*
636*fdd4e1e0SJan Lentfer  * Convert a terminfo string to termcap format.  Parameters are as in
637*fdd4e1e0SJan Lentfer  * _nc_captoinfo().
638*fdd4e1e0SJan Lentfer  */
639*fdd4e1e0SJan Lentfer char *
640*fdd4e1e0SJan Lentfer _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized)
641*fdd4e1e0SJan Lentfer {
642*fdd4e1e0SJan Lentfer     int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0;
643*fdd4e1e0SJan Lentfer     const char *padding;
644*fdd4e1e0SJan Lentfer     const char *trimmed = 0;
645*fdd4e1e0SJan Lentfer     char ch1 = 0, ch2 = 0;
646*fdd4e1e0SJan Lentfer     char *bufptr = init_string();
647*fdd4e1e0SJan Lentfer     int len;
648*fdd4e1e0SJan Lentfer     bool syntax_error = FALSE;
649*fdd4e1e0SJan Lentfer 
650*fdd4e1e0SJan Lentfer     /* we may have to move some trailing mandatory padding up front */
651*fdd4e1e0SJan Lentfer     padding = str + strlen(str) - 1;
652*fdd4e1e0SJan Lentfer     if (padding > str && *padding == '>' && *--padding == '/') {
653*fdd4e1e0SJan Lentfer 	--padding;
654*fdd4e1e0SJan Lentfer 	while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
655*fdd4e1e0SJan Lentfer 	    padding--;
656*fdd4e1e0SJan Lentfer 	if (padding > str && *padding == '<' && *--padding == '$')
657*fdd4e1e0SJan Lentfer 	    trimmed = padding;
658*fdd4e1e0SJan Lentfer 	padding += 2;
659*fdd4e1e0SJan Lentfer 
660*fdd4e1e0SJan Lentfer 	while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
661*fdd4e1e0SJan Lentfer 	    bufptr = save_char(bufptr, *padding++);
662*fdd4e1e0SJan Lentfer     }
663*fdd4e1e0SJan Lentfer 
664*fdd4e1e0SJan Lentfer     for (; *str && str != trimmed; str++) {
665*fdd4e1e0SJan Lentfer 	int c1, c2;
666*fdd4e1e0SJan Lentfer 	char *cp = 0;
667*fdd4e1e0SJan Lentfer 
668*fdd4e1e0SJan Lentfer 	if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) {
669*fdd4e1e0SJan Lentfer 	    bufptr = save_char(bufptr, *++str);
670*fdd4e1e0SJan Lentfer 	} else if (str[0] == '$' && str[1] == '<') {	/* discard padding */
671*fdd4e1e0SJan Lentfer 	    str += 2;
672*fdd4e1e0SJan Lentfer 	    while (isdigit(UChar(*str))
673*fdd4e1e0SJan Lentfer 		   || *str == '.'
674*fdd4e1e0SJan Lentfer 		   || *str == '*'
675*fdd4e1e0SJan Lentfer 		   || *str == '/'
676*fdd4e1e0SJan Lentfer 		   || *str == '>')
677*fdd4e1e0SJan Lentfer 		str++;
678*fdd4e1e0SJan Lentfer 	    --str;
679*fdd4e1e0SJan Lentfer 	} else if (str[0] == '%' && str[1] == '%') {	/* escaped '%' */
680*fdd4e1e0SJan Lentfer 	    bufptr = save_string(bufptr, "%%");
681*fdd4e1e0SJan Lentfer 	} else if (*str != '%' || (parameterized < 1)) {
682*fdd4e1e0SJan Lentfer 	    bufptr = save_char(bufptr, *str);
683*fdd4e1e0SJan Lentfer 	} else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) {
684*fdd4e1e0SJan Lentfer 	    str = strchr(str, ';');
685*fdd4e1e0SJan Lentfer 	    bufptr = save_tc_inequality(bufptr, c1, c2);
686*fdd4e1e0SJan Lentfer 	} else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) {
687*fdd4e1e0SJan Lentfer 	    str = strchr(str, ';');
688*fdd4e1e0SJan Lentfer 	    bufptr = save_tc_inequality(bufptr, c1, c2);
689*fdd4e1e0SJan Lentfer 	} else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) {
690*fdd4e1e0SJan Lentfer 	    str = strchr(str, ';');
691*fdd4e1e0SJan Lentfer 	    bufptr = save_tc_inequality(bufptr, c1, c2);
692*fdd4e1e0SJan Lentfer 	} else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) {
693*fdd4e1e0SJan Lentfer 	    str = strchr(str, ';');
694*fdd4e1e0SJan Lentfer 	    bufptr = save_tc_inequality(bufptr, c1, c2);
695*fdd4e1e0SJan Lentfer 	} else if ((len = bcd_expression(str)) != 0) {
696*fdd4e1e0SJan Lentfer 	    str += len;
697*fdd4e1e0SJan Lentfer 	    bufptr = save_string(bufptr, "%B");
698*fdd4e1e0SJan Lentfer 	} else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1
699*fdd4e1e0SJan Lentfer 		    || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1)
700*fdd4e1e0SJan Lentfer 		   && (cp = strchr(str, '+'))) {
701*fdd4e1e0SJan Lentfer 	    str = cp + 2;
702*fdd4e1e0SJan Lentfer 	    bufptr = save_string(bufptr, "%+");
703*fdd4e1e0SJan Lentfer 
704*fdd4e1e0SJan Lentfer 	    if (ch1)
705*fdd4e1e0SJan Lentfer 		c1 = ch1;
706*fdd4e1e0SJan Lentfer 	    bufptr = save_tc_char(bufptr, c1);
707*fdd4e1e0SJan Lentfer 	}
708*fdd4e1e0SJan Lentfer 	/* FIXME: this "works" for 'delta' */
709*fdd4e1e0SJan Lentfer 	else if (strncmp(str, "%{2}%*%-", 8) == 0) {
710*fdd4e1e0SJan Lentfer 	    str += 7;
711*fdd4e1e0SJan Lentfer 	    bufptr = save_string(bufptr, "%D");
712*fdd4e1e0SJan Lentfer 	} else if (strncmp(str, "%{96}%^", 7) == 0) {
713*fdd4e1e0SJan Lentfer 	    str += 6;
714*fdd4e1e0SJan Lentfer 	    if (saw_m++ == 0) {
715*fdd4e1e0SJan Lentfer 		bufptr = save_string(bufptr, "%n");
716*fdd4e1e0SJan Lentfer 	    }
717*fdd4e1e0SJan Lentfer 	} else if (strncmp(str, "%{127}%^", 8) == 0) {
718*fdd4e1e0SJan Lentfer 	    str += 7;
719*fdd4e1e0SJan Lentfer 	    if (saw_n++ == 0) {
720*fdd4e1e0SJan Lentfer 		bufptr = save_string(bufptr, "%m");
721*fdd4e1e0SJan Lentfer 	    }
722*fdd4e1e0SJan Lentfer 	} else {		/* cm-style format element */
723*fdd4e1e0SJan Lentfer 	    str++;
724*fdd4e1e0SJan Lentfer 	    switch (*str) {
725*fdd4e1e0SJan Lentfer 	    case '%':
726*fdd4e1e0SJan Lentfer 		bufptr = save_char(bufptr, '%');
727*fdd4e1e0SJan Lentfer 		break;
728*fdd4e1e0SJan Lentfer 
729*fdd4e1e0SJan Lentfer 	    case '0':
730*fdd4e1e0SJan Lentfer 	    case '1':
731*fdd4e1e0SJan Lentfer 	    case '2':
732*fdd4e1e0SJan Lentfer 	    case '3':
733*fdd4e1e0SJan Lentfer 	    case '4':
734*fdd4e1e0SJan Lentfer 	    case '5':
735*fdd4e1e0SJan Lentfer 	    case '6':
736*fdd4e1e0SJan Lentfer 	    case '7':
737*fdd4e1e0SJan Lentfer 	    case '8':
738*fdd4e1e0SJan Lentfer 	    case '9':
739*fdd4e1e0SJan Lentfer 		bufptr = save_char(bufptr, '%');
740*fdd4e1e0SJan Lentfer 		while (isdigit(UChar(*str)))
741*fdd4e1e0SJan Lentfer 		    bufptr = save_char(bufptr, *str++);
742*fdd4e1e0SJan Lentfer 		if (strchr("doxX.", *str)) {
743*fdd4e1e0SJan Lentfer 		    if (*str != 'd')	/* termcap doesn't have octal, hex */
744*fdd4e1e0SJan Lentfer 			return 0;
745*fdd4e1e0SJan Lentfer 		}
746*fdd4e1e0SJan Lentfer 		break;
747*fdd4e1e0SJan Lentfer 
748*fdd4e1e0SJan Lentfer 	    case 'd':
749*fdd4e1e0SJan Lentfer 		bufptr = save_string(bufptr, "%d");
750*fdd4e1e0SJan Lentfer 		break;
751*fdd4e1e0SJan Lentfer 
752*fdd4e1e0SJan Lentfer 	    case 'c':
753*fdd4e1e0SJan Lentfer 		bufptr = save_string(bufptr, "%.");
754*fdd4e1e0SJan Lentfer 		break;
755*fdd4e1e0SJan Lentfer 
756*fdd4e1e0SJan Lentfer 		/*
757*fdd4e1e0SJan Lentfer 		 * %s isn't in termcap, but it's convenient to pass it through
758*fdd4e1e0SJan Lentfer 		 * so we can represent things like terminfo pfkey strings in
759*fdd4e1e0SJan Lentfer 		 * termcap notation.
760*fdd4e1e0SJan Lentfer 		 */
761*fdd4e1e0SJan Lentfer 	    case 's':
762*fdd4e1e0SJan Lentfer 		bufptr = save_string(bufptr, "%s");
763*fdd4e1e0SJan Lentfer 		break;
764*fdd4e1e0SJan Lentfer 
765*fdd4e1e0SJan Lentfer 	    case 'p':
766*fdd4e1e0SJan Lentfer 		str++;
767*fdd4e1e0SJan Lentfer 		if (*str == '1')
768*fdd4e1e0SJan Lentfer 		    seenone = 1;
769*fdd4e1e0SJan Lentfer 		else if (*str == '2') {
770*fdd4e1e0SJan Lentfer 		    if (!seenone && !seentwo) {
771*fdd4e1e0SJan Lentfer 			bufptr = save_string(bufptr, "%r");
772*fdd4e1e0SJan Lentfer 			seentwo++;
773*fdd4e1e0SJan Lentfer 		    }
774*fdd4e1e0SJan Lentfer 		} else if (*str >= '3')
775*fdd4e1e0SJan Lentfer 		    return (0);
776*fdd4e1e0SJan Lentfer 		break;
777*fdd4e1e0SJan Lentfer 
778*fdd4e1e0SJan Lentfer 	    case 'i':
779*fdd4e1e0SJan Lentfer 		bufptr = save_string(bufptr, "%i");
780*fdd4e1e0SJan Lentfer 		break;
781*fdd4e1e0SJan Lentfer 
782*fdd4e1e0SJan Lentfer 	    default:
783*fdd4e1e0SJan Lentfer 		bufptr = save_char(bufptr, *str);
784*fdd4e1e0SJan Lentfer 		syntax_error = TRUE;
785*fdd4e1e0SJan Lentfer 		break;
786*fdd4e1e0SJan Lentfer 	    }			/* endswitch (*str) */
787*fdd4e1e0SJan Lentfer 	}			/* endelse (*str == '%') */
788*fdd4e1e0SJan Lentfer 
789*fdd4e1e0SJan Lentfer 	if (*str == '\0')
790*fdd4e1e0SJan Lentfer 	    break;
791*fdd4e1e0SJan Lentfer 
792*fdd4e1e0SJan Lentfer     }				/* endwhile (*str) */
793*fdd4e1e0SJan Lentfer 
794*fdd4e1e0SJan Lentfer     return (syntax_error ? NULL : my_string);
795*fdd4e1e0SJan Lentfer }
796*fdd4e1e0SJan Lentfer 
797*fdd4e1e0SJan Lentfer #ifdef MAIN
798*fdd4e1e0SJan Lentfer 
799*fdd4e1e0SJan Lentfer int curr_line;
800*fdd4e1e0SJan Lentfer 
801*fdd4e1e0SJan Lentfer int
802*fdd4e1e0SJan Lentfer main(int argc, char *argv[])
803*fdd4e1e0SJan Lentfer {
804*fdd4e1e0SJan Lentfer     int c, tc = FALSE;
805*fdd4e1e0SJan Lentfer 
806*fdd4e1e0SJan Lentfer     while ((c = getopt(argc, argv, "c")) != EOF)
807*fdd4e1e0SJan Lentfer 	switch (c) {
808*fdd4e1e0SJan Lentfer 	case 'c':
809*fdd4e1e0SJan Lentfer 	    tc = TRUE;
810*fdd4e1e0SJan Lentfer 	    break;
811*fdd4e1e0SJan Lentfer 	}
812*fdd4e1e0SJan Lentfer 
813*fdd4e1e0SJan Lentfer     curr_line = 0;
814*fdd4e1e0SJan Lentfer     for (;;) {
815*fdd4e1e0SJan Lentfer 	char buf[BUFSIZ];
816*fdd4e1e0SJan Lentfer 
817*fdd4e1e0SJan Lentfer 	++curr_line;
818*fdd4e1e0SJan Lentfer 	if (fgets(buf, sizeof(buf), stdin) == 0)
819*fdd4e1e0SJan Lentfer 	    break;
820*fdd4e1e0SJan Lentfer 	buf[strlen(buf) - 1] = '\0';
821*fdd4e1e0SJan Lentfer 	_nc_set_source(buf);
822*fdd4e1e0SJan Lentfer 
823*fdd4e1e0SJan Lentfer 	if (tc) {
824*fdd4e1e0SJan Lentfer 	    char *cp = _nc_infotocap("to termcap", buf, 1);
825*fdd4e1e0SJan Lentfer 
826*fdd4e1e0SJan Lentfer 	    if (cp)
827*fdd4e1e0SJan Lentfer 		(void) fputs(cp, stdout);
828*fdd4e1e0SJan Lentfer 	} else
829*fdd4e1e0SJan Lentfer 	    (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout);
830*fdd4e1e0SJan Lentfer 	(void) putchar('\n');
831*fdd4e1e0SJan Lentfer     }
832*fdd4e1e0SJan Lentfer     return (0);
833*fdd4e1e0SJan Lentfer }
834*fdd4e1e0SJan Lentfer #endif /* MAIN */
835*fdd4e1e0SJan Lentfer 
836*fdd4e1e0SJan Lentfer /* captoinfo.c ends here */
837