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