1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt * Copyright 2018-2019,2020 Thomas E. Dickey *
3*32bb5217SDaniel Fojt * Copyright 1998-2016,2017 Free Software Foundation, Inc. *
4fdd4e1e0SJan Lentfer * *
5fdd4e1e0SJan Lentfer * Permission is hereby granted, free of charge, to any person obtaining a *
6fdd4e1e0SJan Lentfer * copy of this software and associated documentation files (the *
7fdd4e1e0SJan Lentfer * "Software"), to deal in the Software without restriction, including *
8fdd4e1e0SJan Lentfer * without limitation the rights to use, copy, modify, merge, publish, *
9fdd4e1e0SJan Lentfer * distribute, distribute with modifications, sublicense, and/or sell *
10fdd4e1e0SJan Lentfer * copies of the Software, and to permit persons to whom the Software is *
11fdd4e1e0SJan Lentfer * furnished to do so, subject to the following conditions: *
12fdd4e1e0SJan Lentfer * *
13fdd4e1e0SJan Lentfer * The above copyright notice and this permission notice shall be included *
14fdd4e1e0SJan Lentfer * in all copies or substantial portions of the Software. *
15fdd4e1e0SJan Lentfer * *
16fdd4e1e0SJan Lentfer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17fdd4e1e0SJan Lentfer * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18fdd4e1e0SJan Lentfer * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19fdd4e1e0SJan Lentfer * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20fdd4e1e0SJan Lentfer * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21fdd4e1e0SJan Lentfer * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22fdd4e1e0SJan Lentfer * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23fdd4e1e0SJan Lentfer * *
24fdd4e1e0SJan Lentfer * Except as contained in this notice, the name(s) of the above copyright *
25fdd4e1e0SJan Lentfer * holders shall not be used in advertising or otherwise to promote the *
26fdd4e1e0SJan Lentfer * sale, use or other dealings in this Software without prior written *
27fdd4e1e0SJan Lentfer * authorization. *
28fdd4e1e0SJan Lentfer ****************************************************************************/
29fdd4e1e0SJan Lentfer
30fdd4e1e0SJan Lentfer /****************************************************************************
31fdd4e1e0SJan Lentfer * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
32fdd4e1e0SJan Lentfer * and: Eric S. Raymond <esr@snark.thyrsus.com> *
331d102085SJan Lentfer * and: Thomas E. Dickey 1996-on *
34fdd4e1e0SJan Lentfer ****************************************************************************/
35fdd4e1e0SJan Lentfer
36fdd4e1e0SJan Lentfer /*
37*32bb5217SDaniel Fojt * captoinfo.c
38*32bb5217SDaniel Fojt *
39*32bb5217SDaniel Fojt * Provide conversion in both directions between termcap and terminfo.
40*32bb5217SDaniel Fojt *
41*32bb5217SDaniel Fojt * cap-to-info --- conversion between termcap and terminfo formats
42fdd4e1e0SJan Lentfer *
43fdd4e1e0SJan Lentfer * The captoinfo() code was swiped from Ross Ridge's mytinfo package,
44fdd4e1e0SJan Lentfer * adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>.
45fdd4e1e0SJan Lentfer *
46*32bb5217SDaniel Fojt * It has just one entry point:
47fdd4e1e0SJan Lentfer *
48fdd4e1e0SJan Lentfer * char *_nc_captoinfo(n, s, parameterized)
49fdd4e1e0SJan Lentfer *
50fdd4e1e0SJan Lentfer * Convert value s for termcap string capability named n into terminfo
51fdd4e1e0SJan Lentfer * format.
52fdd4e1e0SJan Lentfer *
53fdd4e1e0SJan Lentfer * This code recognizes all the standard 4.4BSD %-escapes:
54fdd4e1e0SJan Lentfer *
55fdd4e1e0SJan Lentfer * %% output `%'
56fdd4e1e0SJan Lentfer * %d output value as in printf %d
57fdd4e1e0SJan Lentfer * %2 output value as in printf %2d
58fdd4e1e0SJan Lentfer * %3 output value as in printf %3d
59fdd4e1e0SJan Lentfer * %. output value as in printf %c
60fdd4e1e0SJan Lentfer * %+x add x to value, then do %.
61fdd4e1e0SJan Lentfer * %>xy if value > x then add y, no output
62fdd4e1e0SJan Lentfer * %r reverse order of two parameters, no output
63fdd4e1e0SJan Lentfer * %i increment by one, no output
64fdd4e1e0SJan Lentfer * %n exclusive-or all parameters with 0140 (Datamedia 2500)
65fdd4e1e0SJan Lentfer * %B BCD (16*(value/10)) + (value%10), no output
66fdd4e1e0SJan Lentfer * %D Reverse coding (value - 2*(value%16)), no output (Delta Data).
67fdd4e1e0SJan Lentfer *
68fdd4e1e0SJan Lentfer * Also, %02 and %03 are accepted as synonyms for %2 and %3.
69fdd4e1e0SJan Lentfer *
70fdd4e1e0SJan Lentfer * Besides all the standard termcap escapes, this translator understands
71fdd4e1e0SJan Lentfer * the following extended escapes:
72fdd4e1e0SJan Lentfer *
73fdd4e1e0SJan Lentfer * used by GNU Emacs termcap libraries
74fdd4e1e0SJan Lentfer * %a[+*-/=][cp]x GNU arithmetic.
75fdd4e1e0SJan Lentfer * %m xor the first two parameters by 0177
76fdd4e1e0SJan Lentfer * %b backup to previous parameter
77fdd4e1e0SJan Lentfer * %f skip this parameter
78fdd4e1e0SJan Lentfer *
79fdd4e1e0SJan Lentfer * used by the University of Waterloo (MFCF) termcap libraries
80fdd4e1e0SJan Lentfer * %-x subtract parameter FROM char x and output it as a char
81fdd4e1e0SJan Lentfer * %ax add the character x to parameter
82fdd4e1e0SJan Lentfer *
83fdd4e1e0SJan Lentfer * If #define WATERLOO is on, also enable these translations:
84fdd4e1e0SJan Lentfer *
85fdd4e1e0SJan Lentfer * %sx subtract parameter FROM the character x
86fdd4e1e0SJan Lentfer *
87fdd4e1e0SJan Lentfer * By default, this Waterloo translations are not compiled in, because
88fdd4e1e0SJan Lentfer * the Waterloo %s conflicts with the way terminfo uses %s in strings for
89fdd4e1e0SJan Lentfer * function programming.
90fdd4e1e0SJan Lentfer *
91fdd4e1e0SJan Lentfer * Note the two definitions of %a: the GNU definition is translated if the
92fdd4e1e0SJan Lentfer * characters after the 'a' are valid for it, otherwise the UW definition
93fdd4e1e0SJan Lentfer * is translated.
94fdd4e1e0SJan Lentfer */
95fdd4e1e0SJan Lentfer
96fdd4e1e0SJan Lentfer #include <curses.priv.h>
97fdd4e1e0SJan Lentfer
98fdd4e1e0SJan Lentfer #include <ctype.h>
99fdd4e1e0SJan Lentfer #include <tic.h>
100fdd4e1e0SJan Lentfer
101*32bb5217SDaniel Fojt MODULE_ID("$Id: captoinfo.c,v 1.98 2020/02/02 23:34:34 tom Exp $")
102*32bb5217SDaniel Fojt
103*32bb5217SDaniel Fojt #if 0
104*32bb5217SDaniel Fojt #define DEBUG_THIS(p) DEBUG(9, p)
105*32bb5217SDaniel Fojt #else
106*32bb5217SDaniel Fojt #define DEBUG_THIS(p) /* nothing */
107*32bb5217SDaniel Fojt #endif
108fdd4e1e0SJan Lentfer
109fdd4e1e0SJan Lentfer #define MAX_PUSHED 16 /* max # args we can push onto the stack */
110fdd4e1e0SJan Lentfer
111fdd4e1e0SJan Lentfer static int stack[MAX_PUSHED]; /* the stack */
112fdd4e1e0SJan Lentfer static int stackptr; /* the next empty place on the stack */
113fdd4e1e0SJan Lentfer static int onstack; /* the top of stack */
114fdd4e1e0SJan Lentfer static int seenm; /* seen a %m */
115fdd4e1e0SJan Lentfer static int seenn; /* seen a %n */
116fdd4e1e0SJan Lentfer static int seenr; /* seen a %r */
117fdd4e1e0SJan Lentfer static int param; /* current parameter */
118fdd4e1e0SJan Lentfer static char *dp; /* pointer to end of the converted string */
119fdd4e1e0SJan Lentfer
120fdd4e1e0SJan Lentfer static char *my_string;
121fdd4e1e0SJan Lentfer static size_t my_length;
122fdd4e1e0SJan Lentfer
123fdd4e1e0SJan Lentfer static char *
init_string(void)124fdd4e1e0SJan Lentfer init_string(void)
125fdd4e1e0SJan Lentfer /* initialize 'my_string', 'my_length' */
126fdd4e1e0SJan Lentfer {
127fdd4e1e0SJan Lentfer if (my_string == 0)
1283468e90cSJohn Marino TYPE_MALLOC(char, my_length = 256, my_string);
129fdd4e1e0SJan Lentfer
130fdd4e1e0SJan Lentfer *my_string = '\0';
131fdd4e1e0SJan Lentfer return my_string;
132fdd4e1e0SJan Lentfer }
133fdd4e1e0SJan Lentfer
134fdd4e1e0SJan Lentfer static char *
save_string(char * d,const char * const s)135fdd4e1e0SJan Lentfer save_string(char *d, const char *const s)
136fdd4e1e0SJan Lentfer {
13700d8f3c4SJohn Marino size_t have = (size_t) (d - my_string);
138fdd4e1e0SJan Lentfer size_t need = have + strlen(s) + 2;
139fdd4e1e0SJan Lentfer if (need > my_length) {
14000d8f3c4SJohn Marino my_string = (char *) _nc_doalloc(my_string, my_length = (need + need));
141fdd4e1e0SJan Lentfer if (my_string == 0)
142fdd4e1e0SJan Lentfer _nc_err_abort(MSG_NO_MEMORY);
143fdd4e1e0SJan Lentfer d = my_string + have;
144fdd4e1e0SJan Lentfer }
1453468e90cSJohn Marino _nc_STRCPY(d, s, my_length - have);
146fdd4e1e0SJan Lentfer return d + strlen(d);
147fdd4e1e0SJan Lentfer }
148fdd4e1e0SJan Lentfer
1491d102085SJan Lentfer static NCURSES_INLINE char *
save_char(char * s,int c)150fdd4e1e0SJan Lentfer save_char(char *s, int c)
151fdd4e1e0SJan Lentfer {
152fdd4e1e0SJan Lentfer static char temp[2];
153fdd4e1e0SJan Lentfer temp[0] = (char) c;
154fdd4e1e0SJan Lentfer return save_string(s, temp);
155fdd4e1e0SJan Lentfer }
156fdd4e1e0SJan Lentfer
157fdd4e1e0SJan Lentfer static void
push(void)158fdd4e1e0SJan Lentfer push(void)
159fdd4e1e0SJan Lentfer /* push onstack on to the stack */
160fdd4e1e0SJan Lentfer {
1611d102085SJan Lentfer if (stackptr >= MAX_PUSHED)
162fdd4e1e0SJan Lentfer _nc_warning("string too complex to convert");
163fdd4e1e0SJan Lentfer else
164fdd4e1e0SJan Lentfer stack[stackptr++] = onstack;
165fdd4e1e0SJan Lentfer }
166fdd4e1e0SJan Lentfer
167fdd4e1e0SJan Lentfer static void
pop(void)168fdd4e1e0SJan Lentfer pop(void)
169fdd4e1e0SJan Lentfer /* pop the top of the stack into onstack */
170fdd4e1e0SJan Lentfer {
171fdd4e1e0SJan Lentfer if (stackptr == 0) {
172fdd4e1e0SJan Lentfer if (onstack == 0)
173fdd4e1e0SJan Lentfer _nc_warning("I'm confused");
174fdd4e1e0SJan Lentfer else
175fdd4e1e0SJan Lentfer onstack = 0;
176fdd4e1e0SJan Lentfer } else
177fdd4e1e0SJan Lentfer onstack = stack[--stackptr];
178fdd4e1e0SJan Lentfer param++;
179fdd4e1e0SJan Lentfer }
180fdd4e1e0SJan Lentfer
181fdd4e1e0SJan Lentfer static int
cvtchar(register const char * sp)182fdd4e1e0SJan Lentfer cvtchar(register const char *sp)
183fdd4e1e0SJan Lentfer /* convert a character to a terminfo push */
184fdd4e1e0SJan Lentfer {
185fdd4e1e0SJan Lentfer unsigned char c = 0;
186fdd4e1e0SJan Lentfer int len;
187fdd4e1e0SJan Lentfer
188fdd4e1e0SJan Lentfer switch (*sp) {
189fdd4e1e0SJan Lentfer case '\\':
190fdd4e1e0SJan Lentfer switch (*++sp) {
191fdd4e1e0SJan Lentfer case '\'':
192fdd4e1e0SJan Lentfer case '$':
193fdd4e1e0SJan Lentfer case '\\':
194fdd4e1e0SJan Lentfer case '%':
195*32bb5217SDaniel Fojt c = UChar(*sp);
196fdd4e1e0SJan Lentfer len = 2;
197fdd4e1e0SJan Lentfer break;
198fdd4e1e0SJan Lentfer case '\0':
199fdd4e1e0SJan Lentfer c = '\\';
200fdd4e1e0SJan Lentfer len = 1;
201fdd4e1e0SJan Lentfer break;
202fdd4e1e0SJan Lentfer case '0':
203fdd4e1e0SJan Lentfer case '1':
204fdd4e1e0SJan Lentfer case '2':
205fdd4e1e0SJan Lentfer case '3':
206fdd4e1e0SJan Lentfer len = 1;
207fdd4e1e0SJan Lentfer while (isdigit(UChar(*sp))) {
208*32bb5217SDaniel Fojt c = UChar(8 * c + (*sp++ - '0'));
209fdd4e1e0SJan Lentfer len++;
210fdd4e1e0SJan Lentfer }
211fdd4e1e0SJan Lentfer break;
212fdd4e1e0SJan Lentfer default:
213*32bb5217SDaniel Fojt c = UChar(*sp);
214*32bb5217SDaniel Fojt len = (c != '\0') ? 2 : 1;
215fdd4e1e0SJan Lentfer break;
216fdd4e1e0SJan Lentfer }
217fdd4e1e0SJan Lentfer break;
218fdd4e1e0SJan Lentfer case '^':
219*32bb5217SDaniel Fojt c = UChar(*++sp);
220*32bb5217SDaniel Fojt if (c == '?')
221*32bb5217SDaniel Fojt c = 127;
222*32bb5217SDaniel Fojt else
223*32bb5217SDaniel Fojt c &= 0x1f;
224fdd4e1e0SJan Lentfer len = 2;
225fdd4e1e0SJan Lentfer break;
226fdd4e1e0SJan Lentfer default:
227*32bb5217SDaniel Fojt c = UChar(*sp);
228*32bb5217SDaniel Fojt len = (c != '\0') ? 1 : 0;
229fdd4e1e0SJan Lentfer }
230fdd4e1e0SJan Lentfer if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') {
231fdd4e1e0SJan Lentfer dp = save_string(dp, "%\'");
232fdd4e1e0SJan Lentfer dp = save_char(dp, c);
233fdd4e1e0SJan Lentfer dp = save_char(dp, '\'');
234*32bb5217SDaniel Fojt } else if (c != '\0') {
235fdd4e1e0SJan Lentfer dp = save_string(dp, "%{");
236fdd4e1e0SJan Lentfer if (c > 99)
237fdd4e1e0SJan Lentfer dp = save_char(dp, c / 100 + '0');
238fdd4e1e0SJan Lentfer if (c > 9)
239fdd4e1e0SJan Lentfer dp = save_char(dp, ((int) (c / 10)) % 10 + '0');
240fdd4e1e0SJan Lentfer dp = save_char(dp, c % 10 + '0');
241fdd4e1e0SJan Lentfer dp = save_char(dp, '}');
242fdd4e1e0SJan Lentfer }
243fdd4e1e0SJan Lentfer return len;
244fdd4e1e0SJan Lentfer }
245fdd4e1e0SJan Lentfer
246fdd4e1e0SJan Lentfer static void
getparm(int parm,int n)247fdd4e1e0SJan Lentfer getparm(int parm, int n)
248fdd4e1e0SJan Lentfer /* push n copies of param on the terminfo stack if not already there */
249fdd4e1e0SJan Lentfer {
250*32bb5217SDaniel Fojt int nn;
251*32bb5217SDaniel Fojt
252fdd4e1e0SJan Lentfer if (seenr) {
253fdd4e1e0SJan Lentfer if (parm == 1)
254fdd4e1e0SJan Lentfer parm = 2;
255fdd4e1e0SJan Lentfer else if (parm == 2)
256fdd4e1e0SJan Lentfer parm = 1;
257fdd4e1e0SJan Lentfer }
2583468e90cSJohn Marino
259*32bb5217SDaniel Fojt for (nn = 0; nn < n; ++nn) {
2603468e90cSJohn Marino dp = save_string(dp, "%p");
2613468e90cSJohn Marino dp = save_char(dp, '0' + parm);
2623468e90cSJohn Marino }
2633468e90cSJohn Marino
264fdd4e1e0SJan Lentfer if (onstack == parm) {
265fdd4e1e0SJan Lentfer if (n > 1) {
266fdd4e1e0SJan Lentfer _nc_warning("string may not be optimal");
267fdd4e1e0SJan Lentfer dp = save_string(dp, "%Pa");
268*32bb5217SDaniel Fojt while (n-- > 0) {
269fdd4e1e0SJan Lentfer dp = save_string(dp, "%ga");
270fdd4e1e0SJan Lentfer }
271fdd4e1e0SJan Lentfer }
272fdd4e1e0SJan Lentfer return;
273fdd4e1e0SJan Lentfer }
274fdd4e1e0SJan Lentfer if (onstack != 0)
275fdd4e1e0SJan Lentfer push();
276fdd4e1e0SJan Lentfer
277fdd4e1e0SJan Lentfer onstack = parm;
278fdd4e1e0SJan Lentfer
279fdd4e1e0SJan Lentfer if (seenn && parm < 3) {
280fdd4e1e0SJan Lentfer dp = save_string(dp, "%{96}%^");
281fdd4e1e0SJan Lentfer }
282fdd4e1e0SJan Lentfer
283fdd4e1e0SJan Lentfer if (seenm && parm < 3) {
284fdd4e1e0SJan Lentfer dp = save_string(dp, "%{127}%^");
285fdd4e1e0SJan Lentfer }
286fdd4e1e0SJan Lentfer }
287fdd4e1e0SJan Lentfer
288fdd4e1e0SJan Lentfer /*
289fdd4e1e0SJan Lentfer * Convert a termcap string to terminfo format.
290fdd4e1e0SJan Lentfer * 'cap' is the relevant terminfo capability index.
291fdd4e1e0SJan Lentfer * 's' is the string value of the capability.
292fdd4e1e0SJan Lentfer * 'parameterized' tells what type of translations to do:
293fdd4e1e0SJan Lentfer * % translations if 1
294fdd4e1e0SJan Lentfer * pad translations if >=0
295fdd4e1e0SJan Lentfer */
2961d102085SJan Lentfer NCURSES_EXPORT(char *)
_nc_captoinfo(const char * cap,const char * s,int const parameterized)297fdd4e1e0SJan Lentfer _nc_captoinfo(const char *cap, const char *s, int const parameterized)
298fdd4e1e0SJan Lentfer {
299fdd4e1e0SJan Lentfer const char *capstart;
300fdd4e1e0SJan Lentfer
301fdd4e1e0SJan Lentfer stackptr = 0;
302fdd4e1e0SJan Lentfer onstack = 0;
303fdd4e1e0SJan Lentfer seenm = 0;
304fdd4e1e0SJan Lentfer seenn = 0;
305fdd4e1e0SJan Lentfer seenr = 0;
306fdd4e1e0SJan Lentfer param = 1;
307fdd4e1e0SJan Lentfer
308*32bb5217SDaniel Fojt DEBUG_THIS(("_nc_captoinfo params %d, %s", parameterized, s));
309*32bb5217SDaniel Fojt
310fdd4e1e0SJan Lentfer dp = init_string();
311fdd4e1e0SJan Lentfer
312fdd4e1e0SJan Lentfer /* skip the initial padding (if we haven't been told not to) */
313fdd4e1e0SJan Lentfer capstart = 0;
314fdd4e1e0SJan Lentfer if (s == 0)
315fdd4e1e0SJan Lentfer s = "";
316fdd4e1e0SJan Lentfer if (parameterized >= 0 && isdigit(UChar(*s)))
317*32bb5217SDaniel Fojt for (capstart = s; *s != '\0'; s++)
318fdd4e1e0SJan Lentfer if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.'))
319fdd4e1e0SJan Lentfer break;
320fdd4e1e0SJan Lentfer
321fdd4e1e0SJan Lentfer while (*s != '\0') {
322fdd4e1e0SJan Lentfer switch (*s) {
323fdd4e1e0SJan Lentfer case '%':
324fdd4e1e0SJan Lentfer s++;
325fdd4e1e0SJan Lentfer if (parameterized < 1) {
326fdd4e1e0SJan Lentfer dp = save_char(dp, '%');
327fdd4e1e0SJan Lentfer break;
328fdd4e1e0SJan Lentfer }
329fdd4e1e0SJan Lentfer switch (*s++) {
330fdd4e1e0SJan Lentfer case '%':
331*32bb5217SDaniel Fojt dp = save_string(dp, "%%");
332fdd4e1e0SJan Lentfer break;
333fdd4e1e0SJan Lentfer case 'r':
334fdd4e1e0SJan Lentfer if (seenr++ == 1) {
335fdd4e1e0SJan Lentfer _nc_warning("saw %%r twice in %s", cap);
336fdd4e1e0SJan Lentfer }
337fdd4e1e0SJan Lentfer break;
338fdd4e1e0SJan Lentfer case 'm':
339fdd4e1e0SJan Lentfer if (seenm++ == 1) {
340fdd4e1e0SJan Lentfer _nc_warning("saw %%m twice in %s", cap);
341fdd4e1e0SJan Lentfer }
342fdd4e1e0SJan Lentfer break;
343fdd4e1e0SJan Lentfer case 'n':
344fdd4e1e0SJan Lentfer if (seenn++ == 1) {
345fdd4e1e0SJan Lentfer _nc_warning("saw %%n twice in %s", cap);
346fdd4e1e0SJan Lentfer }
347fdd4e1e0SJan Lentfer break;
348fdd4e1e0SJan Lentfer case 'i':
349fdd4e1e0SJan Lentfer dp = save_string(dp, "%i");
350fdd4e1e0SJan Lentfer break;
351fdd4e1e0SJan Lentfer case '6':
352fdd4e1e0SJan Lentfer case 'B':
353fdd4e1e0SJan Lentfer getparm(param, 1);
354fdd4e1e0SJan Lentfer dp = save_string(dp, "%{10}%/%{16}%*");
355fdd4e1e0SJan Lentfer getparm(param, 1);
356fdd4e1e0SJan Lentfer dp = save_string(dp, "%{10}%m%+");
357fdd4e1e0SJan Lentfer break;
358fdd4e1e0SJan Lentfer case '8':
359fdd4e1e0SJan Lentfer case 'D':
360fdd4e1e0SJan Lentfer getparm(param, 2);
361fdd4e1e0SJan Lentfer dp = save_string(dp, "%{2}%*%-");
362fdd4e1e0SJan Lentfer break;
363fdd4e1e0SJan Lentfer case '>':
364fdd4e1e0SJan Lentfer /* %?%{x}%>%t%{y}%+%; */
365*32bb5217SDaniel Fojt if (s[0] && s[1]) {
366*32bb5217SDaniel Fojt getparm(param, 2);
367fdd4e1e0SJan Lentfer dp = save_string(dp, "%?");
368fdd4e1e0SJan Lentfer s += cvtchar(s);
369fdd4e1e0SJan Lentfer dp = save_string(dp, "%>%t");
370fdd4e1e0SJan Lentfer s += cvtchar(s);
371fdd4e1e0SJan Lentfer dp = save_string(dp, "%+%;");
372*32bb5217SDaniel Fojt } else {
373*32bb5217SDaniel Fojt _nc_warning("expected two characters after %%>");
374*32bb5217SDaniel Fojt dp = save_string(dp, "%>");
375*32bb5217SDaniel Fojt }
376fdd4e1e0SJan Lentfer break;
377fdd4e1e0SJan Lentfer case 'a':
378fdd4e1e0SJan Lentfer if ((*s == '=' || *s == '+' || *s == '-'
379fdd4e1e0SJan Lentfer || *s == '*' || *s == '/')
380fdd4e1e0SJan Lentfer && (s[1] == 'p' || s[1] == 'c')
381fdd4e1e0SJan Lentfer && s[2] != '\0') {
382fdd4e1e0SJan Lentfer int l;
383fdd4e1e0SJan Lentfer l = 2;
384fdd4e1e0SJan Lentfer if (*s != '=')
385fdd4e1e0SJan Lentfer getparm(param, 1);
386fdd4e1e0SJan Lentfer if (s[1] == 'p') {
387fdd4e1e0SJan Lentfer getparm(param + s[2] - '@', 1);
388fdd4e1e0SJan Lentfer if (param != onstack) {
389fdd4e1e0SJan Lentfer pop();
390fdd4e1e0SJan Lentfer param--;
391fdd4e1e0SJan Lentfer }
392fdd4e1e0SJan Lentfer l++;
393fdd4e1e0SJan Lentfer } else
394fdd4e1e0SJan Lentfer l += cvtchar(s + 2);
395fdd4e1e0SJan Lentfer switch (*s) {
396fdd4e1e0SJan Lentfer case '+':
397fdd4e1e0SJan Lentfer dp = save_string(dp, "%+");
398fdd4e1e0SJan Lentfer break;
399fdd4e1e0SJan Lentfer case '-':
400fdd4e1e0SJan Lentfer dp = save_string(dp, "%-");
401fdd4e1e0SJan Lentfer break;
402fdd4e1e0SJan Lentfer case '*':
403fdd4e1e0SJan Lentfer dp = save_string(dp, "%*");
404fdd4e1e0SJan Lentfer break;
405fdd4e1e0SJan Lentfer case '/':
406fdd4e1e0SJan Lentfer dp = save_string(dp, "%/");
407fdd4e1e0SJan Lentfer break;
408fdd4e1e0SJan Lentfer case '=':
409fdd4e1e0SJan Lentfer if (seenr) {
410fdd4e1e0SJan Lentfer if (param == 1)
411fdd4e1e0SJan Lentfer onstack = 2;
412fdd4e1e0SJan Lentfer else if (param == 2)
413fdd4e1e0SJan Lentfer onstack = 1;
414fdd4e1e0SJan Lentfer else
415fdd4e1e0SJan Lentfer onstack = param;
416fdd4e1e0SJan Lentfer } else
417fdd4e1e0SJan Lentfer onstack = param;
418fdd4e1e0SJan Lentfer break;
419fdd4e1e0SJan Lentfer }
420fdd4e1e0SJan Lentfer s += l;
421fdd4e1e0SJan Lentfer break;
422fdd4e1e0SJan Lentfer }
423fdd4e1e0SJan Lentfer getparm(param, 1);
424fdd4e1e0SJan Lentfer s += cvtchar(s);
425fdd4e1e0SJan Lentfer dp = save_string(dp, "%+");
426fdd4e1e0SJan Lentfer break;
427fdd4e1e0SJan Lentfer case '+':
428fdd4e1e0SJan Lentfer getparm(param, 1);
429fdd4e1e0SJan Lentfer s += cvtchar(s);
430fdd4e1e0SJan Lentfer dp = save_string(dp, "%+%c");
431fdd4e1e0SJan Lentfer pop();
432fdd4e1e0SJan Lentfer break;
433fdd4e1e0SJan Lentfer case 's':
434fdd4e1e0SJan Lentfer #ifdef WATERLOO
435fdd4e1e0SJan Lentfer s += cvtchar(s);
436fdd4e1e0SJan Lentfer getparm(param, 1);
437fdd4e1e0SJan Lentfer dp = save_string(dp, "%-");
438fdd4e1e0SJan Lentfer #else
439fdd4e1e0SJan Lentfer getparm(param, 1);
440fdd4e1e0SJan Lentfer dp = save_string(dp, "%s");
441fdd4e1e0SJan Lentfer pop();
442fdd4e1e0SJan Lentfer #endif /* WATERLOO */
443fdd4e1e0SJan Lentfer break;
444fdd4e1e0SJan Lentfer case '-':
445fdd4e1e0SJan Lentfer s += cvtchar(s);
446fdd4e1e0SJan Lentfer getparm(param, 1);
447fdd4e1e0SJan Lentfer dp = save_string(dp, "%-%c");
448fdd4e1e0SJan Lentfer pop();
449fdd4e1e0SJan Lentfer break;
450fdd4e1e0SJan Lentfer case '.':
451fdd4e1e0SJan Lentfer getparm(param, 1);
452fdd4e1e0SJan Lentfer dp = save_string(dp, "%c");
453fdd4e1e0SJan Lentfer pop();
454fdd4e1e0SJan Lentfer break;
455fdd4e1e0SJan Lentfer case '0': /* not clear any of the historical termcaps did this */
456*32bb5217SDaniel Fojt if (*s == '3') {
457*32bb5217SDaniel Fojt ++s;
458fdd4e1e0SJan Lentfer goto see03;
459*32bb5217SDaniel Fojt }
460*32bb5217SDaniel Fojt if (*s == '2') {
461*32bb5217SDaniel Fojt ++s;
462*32bb5217SDaniel Fojt goto see02;
463*32bb5217SDaniel Fojt }
464fdd4e1e0SJan Lentfer goto invalid;
465fdd4e1e0SJan Lentfer case '2':
466*32bb5217SDaniel Fojt see02:
467fdd4e1e0SJan Lentfer getparm(param, 1);
468fdd4e1e0SJan Lentfer dp = save_string(dp, "%2d");
469fdd4e1e0SJan Lentfer pop();
470fdd4e1e0SJan Lentfer break;
471fdd4e1e0SJan Lentfer case '3':
472fdd4e1e0SJan Lentfer see03:
473fdd4e1e0SJan Lentfer getparm(param, 1);
474fdd4e1e0SJan Lentfer dp = save_string(dp, "%3d");
475fdd4e1e0SJan Lentfer pop();
476fdd4e1e0SJan Lentfer break;
477fdd4e1e0SJan Lentfer case 'd':
478fdd4e1e0SJan Lentfer getparm(param, 1);
479fdd4e1e0SJan Lentfer dp = save_string(dp, "%d");
480fdd4e1e0SJan Lentfer pop();
481fdd4e1e0SJan Lentfer break;
482fdd4e1e0SJan Lentfer case 'f':
483fdd4e1e0SJan Lentfer param++;
484fdd4e1e0SJan Lentfer break;
485fdd4e1e0SJan Lentfer case 'b':
486fdd4e1e0SJan Lentfer param--;
487fdd4e1e0SJan Lentfer break;
488fdd4e1e0SJan Lentfer case '\\':
489fdd4e1e0SJan Lentfer dp = save_string(dp, "%\\");
490fdd4e1e0SJan Lentfer break;
491fdd4e1e0SJan Lentfer default:
492fdd4e1e0SJan Lentfer invalid:
493fdd4e1e0SJan Lentfer dp = save_char(dp, '%');
494fdd4e1e0SJan Lentfer s--;
495fdd4e1e0SJan Lentfer _nc_warning("unknown %% code %s (%#x) in %s",
496fdd4e1e0SJan Lentfer unctrl((chtype) *s), UChar(*s), cap);
497fdd4e1e0SJan Lentfer break;
498fdd4e1e0SJan Lentfer }
499fdd4e1e0SJan Lentfer break;
500fdd4e1e0SJan Lentfer default:
501*32bb5217SDaniel Fojt if (*s != '\0')
502fdd4e1e0SJan Lentfer dp = save_char(dp, *s++);
503fdd4e1e0SJan Lentfer break;
504fdd4e1e0SJan Lentfer }
505fdd4e1e0SJan Lentfer }
506fdd4e1e0SJan Lentfer
507fdd4e1e0SJan Lentfer /*
508fdd4e1e0SJan Lentfer * Now, if we stripped off some leading padding, add it at the end
509fdd4e1e0SJan Lentfer * of the string as mandatory padding.
510fdd4e1e0SJan Lentfer */
511fdd4e1e0SJan Lentfer if (capstart) {
512fdd4e1e0SJan Lentfer dp = save_string(dp, "$<");
513*32bb5217SDaniel Fojt for (s = capstart; *s != '\0'; s++)
514fdd4e1e0SJan Lentfer if (isdigit(UChar(*s)) || *s == '*' || *s == '.')
515fdd4e1e0SJan Lentfer dp = save_char(dp, *s);
516fdd4e1e0SJan Lentfer else
517fdd4e1e0SJan Lentfer break;
518fdd4e1e0SJan Lentfer dp = save_string(dp, "/>");
519fdd4e1e0SJan Lentfer }
520fdd4e1e0SJan Lentfer
521fdd4e1e0SJan Lentfer (void) save_char(dp, '\0');
522*32bb5217SDaniel Fojt
523*32bb5217SDaniel Fojt DEBUG_THIS(("... _nc_captoinfo %s", NonNull(my_string)));
524*32bb5217SDaniel Fojt
525fdd4e1e0SJan Lentfer return (my_string);
526fdd4e1e0SJan Lentfer }
527fdd4e1e0SJan Lentfer
528fdd4e1e0SJan Lentfer /*
529fdd4e1e0SJan Lentfer * Check for an expression that corresponds to "%B" (BCD):
530fdd4e1e0SJan Lentfer * (parameter / 10) * 16 + (parameter % 10)
531fdd4e1e0SJan Lentfer */
532fdd4e1e0SJan Lentfer static int
bcd_expression(const char * str)533fdd4e1e0SJan Lentfer bcd_expression(const char *str)
534fdd4e1e0SJan Lentfer {
535fdd4e1e0SJan Lentfer /* leave this non-const for HPUX */
536fdd4e1e0SJan Lentfer static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+";
537fdd4e1e0SJan Lentfer int len = 0;
538fdd4e1e0SJan Lentfer char ch1, ch2;
539fdd4e1e0SJan Lentfer
540fdd4e1e0SJan Lentfer if (sscanf(str, fmt, &ch1, &ch2) == 2
541fdd4e1e0SJan Lentfer && isdigit(UChar(ch1))
542fdd4e1e0SJan Lentfer && isdigit(UChar(ch2))
543fdd4e1e0SJan Lentfer && (ch1 == ch2)) {
544fdd4e1e0SJan Lentfer len = 28;
545fdd4e1e0SJan Lentfer #ifndef NDEBUG
546fdd4e1e0SJan Lentfer {
547fdd4e1e0SJan Lentfer char buffer[80];
548fdd4e1e0SJan Lentfer int tst;
5493468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) fmt, ch1, ch2);
550fdd4e1e0SJan Lentfer tst = strlen(buffer) - 1;
551fdd4e1e0SJan Lentfer assert(len == tst);
552fdd4e1e0SJan Lentfer }
553fdd4e1e0SJan Lentfer #endif
554fdd4e1e0SJan Lentfer }
555fdd4e1e0SJan Lentfer return len;
556fdd4e1e0SJan Lentfer }
557fdd4e1e0SJan Lentfer
558fdd4e1e0SJan Lentfer static char *
save_tc_char(char * bufptr,int c1)559fdd4e1e0SJan Lentfer save_tc_char(char *bufptr, int c1)
560fdd4e1e0SJan Lentfer {
561fdd4e1e0SJan Lentfer if (is7bits(c1) && isprint(c1)) {
562fdd4e1e0SJan Lentfer if (c1 == ':' || c1 == '\\')
563fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, '\\');
564fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, c1);
565fdd4e1e0SJan Lentfer } else {
566*32bb5217SDaniel Fojt char temp[80];
567*32bb5217SDaniel Fojt
5683468e90cSJohn Marino if (c1 == (c1 & 0x1f)) { /* iscntrl() returns T on 255 */
5693468e90cSJohn Marino _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
5703468e90cSJohn Marino "%.20s", unctrl((chtype) c1));
5713468e90cSJohn Marino } else {
5723468e90cSJohn Marino _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
5733468e90cSJohn Marino "\\%03o", c1);
5743468e90cSJohn Marino }
575fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, temp);
576fdd4e1e0SJan Lentfer }
577fdd4e1e0SJan Lentfer return bufptr;
578fdd4e1e0SJan Lentfer }
579fdd4e1e0SJan Lentfer
580fdd4e1e0SJan Lentfer static char *
save_tc_inequality(char * bufptr,int c1,int c2)581fdd4e1e0SJan Lentfer save_tc_inequality(char *bufptr, int c1, int c2)
582fdd4e1e0SJan Lentfer {
583fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%>");
584fdd4e1e0SJan Lentfer bufptr = save_tc_char(bufptr, c1);
585fdd4e1e0SJan Lentfer bufptr = save_tc_char(bufptr, c2);
586fdd4e1e0SJan Lentfer return bufptr;
587fdd4e1e0SJan Lentfer }
588fdd4e1e0SJan Lentfer
589fdd4e1e0SJan Lentfer /*
590*32bb5217SDaniel Fojt * info-to-cap --- conversion between terminfo and termcap formats
591*32bb5217SDaniel Fojt *
592fdd4e1e0SJan Lentfer * Here are the capabilities infotocap assumes it can translate to:
593fdd4e1e0SJan Lentfer *
594fdd4e1e0SJan Lentfer * %% output `%'
595fdd4e1e0SJan Lentfer * %d output value as in printf %d
596fdd4e1e0SJan Lentfer * %2 output value as in printf %2d
597fdd4e1e0SJan Lentfer * %3 output value as in printf %3d
598fdd4e1e0SJan Lentfer * %. output value as in printf %c
599fdd4e1e0SJan Lentfer * %+c add character c to value, then do %.
600fdd4e1e0SJan Lentfer * %>xy if value > x then add y, no output
601fdd4e1e0SJan Lentfer * %r reverse order of two parameters, no output
602fdd4e1e0SJan Lentfer * %i increment by one, no output
603fdd4e1e0SJan Lentfer * %n exclusive-or all parameters with 0140 (Datamedia 2500)
604fdd4e1e0SJan Lentfer * %B BCD (16*(value/10)) + (value%10), no output
605fdd4e1e0SJan Lentfer * %D Reverse coding (value - 2*(value%16)), no output (Delta Data).
606fdd4e1e0SJan Lentfer * %m exclusive-or all parameters with 0177 (not in 4.4BSD)
607fdd4e1e0SJan Lentfer */
608fdd4e1e0SJan Lentfer
609*32bb5217SDaniel Fojt #define octal_fixup(n, c) fixups[n].ch = ((fixups[n].ch << 3) | ((c) - '0'))
610*32bb5217SDaniel Fojt
611fdd4e1e0SJan Lentfer /*
612fdd4e1e0SJan Lentfer * Convert a terminfo string to termcap format. Parameters are as in
613fdd4e1e0SJan Lentfer * _nc_captoinfo().
614fdd4e1e0SJan Lentfer */
6151d102085SJan Lentfer NCURSES_EXPORT(char *)
_nc_infotocap(const char * cap GCC_UNUSED,const char * str,int const parameterized)616fdd4e1e0SJan Lentfer _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized)
617fdd4e1e0SJan Lentfer {
618fdd4e1e0SJan Lentfer int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0;
619fdd4e1e0SJan Lentfer const char *padding;
620fdd4e1e0SJan Lentfer const char *trimmed = 0;
62100d8f3c4SJohn Marino int in0, in1, in2;
622fdd4e1e0SJan Lentfer char ch1 = 0, ch2 = 0;
623fdd4e1e0SJan Lentfer char *bufptr = init_string();
6243468e90cSJohn Marino char octal[4];
625fdd4e1e0SJan Lentfer int len;
626*32bb5217SDaniel Fojt int digits;
627fdd4e1e0SJan Lentfer bool syntax_error = FALSE;
628*32bb5217SDaniel Fojt int myfix = 0;
629*32bb5217SDaniel Fojt struct {
630*32bb5217SDaniel Fojt int ch;
631*32bb5217SDaniel Fojt int offset;
632*32bb5217SDaniel Fojt } fixups[MAX_TC_FIXUPS];
633*32bb5217SDaniel Fojt
634*32bb5217SDaniel Fojt DEBUG_THIS(("_nc_infotocap params %d, %s", parameterized, str));
635fdd4e1e0SJan Lentfer
636fdd4e1e0SJan Lentfer /* we may have to move some trailing mandatory padding up front */
637fdd4e1e0SJan Lentfer padding = str + strlen(str) - 1;
6383468e90cSJohn Marino if (padding > str && *padding == '>') {
6393468e90cSJohn Marino if (*--padding == '/')
640fdd4e1e0SJan Lentfer --padding;
641fdd4e1e0SJan Lentfer while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
642fdd4e1e0SJan Lentfer padding--;
643fdd4e1e0SJan Lentfer if (padding > str && *padding == '<' && *--padding == '$')
644fdd4e1e0SJan Lentfer trimmed = padding;
645fdd4e1e0SJan Lentfer padding += 2;
646fdd4e1e0SJan Lentfer
647fdd4e1e0SJan Lentfer while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
648fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, *padding++);
649fdd4e1e0SJan Lentfer }
650fdd4e1e0SJan Lentfer
651*32bb5217SDaniel Fojt for (; !syntax_error &&
652*32bb5217SDaniel Fojt *str &&
653*32bb5217SDaniel Fojt ((trimmed == 0) || (str < trimmed)); str++) {
654fdd4e1e0SJan Lentfer int c1, c2;
655fdd4e1e0SJan Lentfer char *cp = 0;
656fdd4e1e0SJan Lentfer
65700d8f3c4SJohn Marino if (str[0] == '^') {
65800d8f3c4SJohn Marino if (str[1] == '\0' || (str + 1) == trimmed) {
65900d8f3c4SJohn Marino bufptr = save_string(bufptr, "\\136");
66000d8f3c4SJohn Marino ++str;
661*32bb5217SDaniel Fojt } else if (str[1] == '?') {
662*32bb5217SDaniel Fojt /*
663*32bb5217SDaniel Fojt * Although the 4.3BSD termcap file has an instance of "kb=^?",
664*32bb5217SDaniel Fojt * that appears to be just cut/paste since neither 4.3BSD nor
665*32bb5217SDaniel Fojt * 4.4BSD termcap interprets "^?" as DEL.
666*32bb5217SDaniel Fojt */
667*32bb5217SDaniel Fojt bufptr = save_string(bufptr, "\\177");
668*32bb5217SDaniel Fojt ++str;
66900d8f3c4SJohn Marino } else {
67000d8f3c4SJohn Marino bufptr = save_char(bufptr, *str++);
67100d8f3c4SJohn Marino bufptr = save_char(bufptr, *str);
67200d8f3c4SJohn Marino }
67300d8f3c4SJohn Marino } else if (str[0] == '\\') {
67400d8f3c4SJohn Marino if (str[1] == '\0' || (str + 1) == trimmed) {
67500d8f3c4SJohn Marino bufptr = save_string(bufptr, "\\134");
67600d8f3c4SJohn Marino ++str;
67700d8f3c4SJohn Marino } else if (str[1] == '^') {
67800d8f3c4SJohn Marino bufptr = save_string(bufptr, "\\136");
67900d8f3c4SJohn Marino ++str;
68000d8f3c4SJohn Marino } else if (str[1] == ',') {
681fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, *++str);
68200d8f3c4SJohn Marino } else {
683*32bb5217SDaniel Fojt int xx1;
6843468e90cSJohn Marino
68500d8f3c4SJohn Marino bufptr = save_char(bufptr, *str++);
6863468e90cSJohn Marino xx1 = *str;
6873468e90cSJohn Marino if (_nc_strict_bsd) {
6883468e90cSJohn Marino
689*32bb5217SDaniel Fojt if (isoctal(UChar(xx1))) {
690*32bb5217SDaniel Fojt int pad = 0;
691*32bb5217SDaniel Fojt int xx2;
692*32bb5217SDaniel Fojt int fix = 0;
693*32bb5217SDaniel Fojt
694*32bb5217SDaniel Fojt if (!isoctal(UChar(str[1])))
6953468e90cSJohn Marino pad = 2;
696*32bb5217SDaniel Fojt else if (str[1] && !isoctal(UChar(str[2])))
6973468e90cSJohn Marino pad = 1;
6983468e90cSJohn Marino
6993468e90cSJohn Marino /*
7003468e90cSJohn Marino * Test for "\0", "\00" or "\000" and transform those
7013468e90cSJohn Marino * into "\200".
7023468e90cSJohn Marino */
7033468e90cSJohn Marino if (xx1 == '0'
7043468e90cSJohn Marino && ((pad == 2) || (str[1] == '0'))
7053468e90cSJohn Marino && ((pad >= 1) || (str[2] == '0'))) {
7063468e90cSJohn Marino xx2 = '2';
7073468e90cSJohn Marino } else {
7083468e90cSJohn Marino xx2 = '0';
7093468e90cSJohn Marino pad = 0; /* FIXME - optionally pad to 3 digits */
7103468e90cSJohn Marino }
711*32bb5217SDaniel Fojt if (myfix < MAX_TC_FIXUPS) {
712*32bb5217SDaniel Fojt fix = 3 - pad;
713*32bb5217SDaniel Fojt fixups[myfix].ch = 0;
714*32bb5217SDaniel Fojt fixups[myfix].offset = (int) (bufptr
715*32bb5217SDaniel Fojt - my_string
716*32bb5217SDaniel Fojt - 1);
717*32bb5217SDaniel Fojt }
7183468e90cSJohn Marino while (pad-- > 0) {
7193468e90cSJohn Marino bufptr = save_char(bufptr, xx2);
720*32bb5217SDaniel Fojt if (myfix < MAX_TC_FIXUPS) {
721*32bb5217SDaniel Fojt fixups[myfix].ch <<= 3;
722*32bb5217SDaniel Fojt fixups[myfix].ch |= (xx2 - '0');
723*32bb5217SDaniel Fojt }
7243468e90cSJohn Marino xx2 = '0';
7253468e90cSJohn Marino }
726*32bb5217SDaniel Fojt if (myfix < MAX_TC_FIXUPS) {
727*32bb5217SDaniel Fojt int n;
728*32bb5217SDaniel Fojt for (n = 0; n < fix; ++n) {
729*32bb5217SDaniel Fojt fixups[myfix].ch <<= 3;
730*32bb5217SDaniel Fojt fixups[myfix].ch |= (str[n] - '0');
731*32bb5217SDaniel Fojt }
732*32bb5217SDaniel Fojt if (fixups[myfix].ch < 32) {
733*32bb5217SDaniel Fojt ++myfix;
734*32bb5217SDaniel Fojt }
735*32bb5217SDaniel Fojt }
7363468e90cSJohn Marino } else if (strchr("E\\nrtbf", xx1) == 0) {
7373468e90cSJohn Marino switch (xx1) {
7383468e90cSJohn Marino case 'e':
7393468e90cSJohn Marino xx1 = 'E';
7403468e90cSJohn Marino break;
7413468e90cSJohn Marino case 'l':
7423468e90cSJohn Marino xx1 = 'n';
7433468e90cSJohn Marino break;
7443468e90cSJohn Marino case 's':
7453468e90cSJohn Marino bufptr = save_char(bufptr, '0');
7463468e90cSJohn Marino bufptr = save_char(bufptr, '4');
7473468e90cSJohn Marino xx1 = '0';
7483468e90cSJohn Marino break;
7493468e90cSJohn Marino case ':':
7503468e90cSJohn Marino /*
7513468e90cSJohn Marino * Note: termcap documentation claims that ":"
7523468e90cSJohn Marino * must be escaped as "\072", however the
7533468e90cSJohn Marino * documentation is incorrect - read the code.
7543468e90cSJohn Marino * The replacement does not work reliably,
7553468e90cSJohn Marino * so the advice is not helpful.
7563468e90cSJohn Marino */
7573468e90cSJohn Marino bufptr = save_char(bufptr, '0');
7583468e90cSJohn Marino bufptr = save_char(bufptr, '7');
7593468e90cSJohn Marino xx1 = '2';
7603468e90cSJohn Marino break;
7613468e90cSJohn Marino default:
7623468e90cSJohn Marino /* should not happen, but handle this anyway */
7633468e90cSJohn Marino _nc_SPRINTF(octal, _nc_SLIMIT(sizeof(octal))
7643468e90cSJohn Marino "%03o", UChar(xx1));
7653468e90cSJohn Marino bufptr = save_char(bufptr, octal[0]);
7663468e90cSJohn Marino bufptr = save_char(bufptr, octal[1]);
7673468e90cSJohn Marino xx1 = octal[2];
7683468e90cSJohn Marino break;
7693468e90cSJohn Marino }
7703468e90cSJohn Marino }
771*32bb5217SDaniel Fojt } else {
772*32bb5217SDaniel Fojt if (myfix < MAX_TC_FIXUPS && isoctal(UChar(xx1))) {
773*32bb5217SDaniel Fojt bool will_fix = TRUE;
774*32bb5217SDaniel Fojt int n;
775*32bb5217SDaniel Fojt
776*32bb5217SDaniel Fojt fixups[myfix].ch = 0;
777*32bb5217SDaniel Fojt fixups[myfix].offset = (int) (bufptr - my_string - 1);
778*32bb5217SDaniel Fojt for (n = 0; n < 3; ++n) {
779*32bb5217SDaniel Fojt if (isoctal(str[n])) {
780*32bb5217SDaniel Fojt octal_fixup(myfix, str[n]);
781*32bb5217SDaniel Fojt } else {
782*32bb5217SDaniel Fojt will_fix = FALSE;
783*32bb5217SDaniel Fojt break;
784*32bb5217SDaniel Fojt }
785*32bb5217SDaniel Fojt }
786*32bb5217SDaniel Fojt if (will_fix && (fixups[myfix].ch < 32))
787*32bb5217SDaniel Fojt ++myfix;
788*32bb5217SDaniel Fojt }
7893468e90cSJohn Marino }
7903468e90cSJohn Marino bufptr = save_char(bufptr, xx1);
79100d8f3c4SJohn Marino }
792fdd4e1e0SJan Lentfer } else if (str[0] == '$' && str[1] == '<') { /* discard padding */
793fdd4e1e0SJan Lentfer str += 2;
794fdd4e1e0SJan Lentfer while (isdigit(UChar(*str))
795fdd4e1e0SJan Lentfer || *str == '.'
796fdd4e1e0SJan Lentfer || *str == '*'
797fdd4e1e0SJan Lentfer || *str == '/'
798fdd4e1e0SJan Lentfer || *str == '>')
799fdd4e1e0SJan Lentfer str++;
800fdd4e1e0SJan Lentfer --str;
80100d8f3c4SJohn Marino } else if (sscanf(str,
80200d8f3c4SJohn Marino "[%%?%%p1%%{8}%%<%%t%d%%p1%%d%%e%%p1%%{16}%%<%%t%d%%p1%%{8}%%-%%d%%e%d;5;%%p1%%d%%;m",
80300d8f3c4SJohn Marino &in0, &in1, &in2) == 3
80400d8f3c4SJohn Marino && ((in0 == 4 && in1 == 10 && in2 == 48)
80500d8f3c4SJohn Marino || (in0 == 3 && in1 == 9 && in2 == 38))) {
80600d8f3c4SJohn Marino /* dumb-down an optimized case from xterm-256color for termcap */
8073468e90cSJohn Marino if ((str = strstr(str, ";m")) == 0)
8083468e90cSJohn Marino break; /* cannot happen */
80900d8f3c4SJohn Marino ++str;
81000d8f3c4SJohn Marino if (in2 == 48) {
81100d8f3c4SJohn Marino bufptr = save_string(bufptr, "[48;5;%dm");
81200d8f3c4SJohn Marino } else {
81300d8f3c4SJohn Marino bufptr = save_string(bufptr, "[38;5;%dm");
81400d8f3c4SJohn Marino }
815fdd4e1e0SJan Lentfer } else if (str[0] == '%' && str[1] == '%') { /* escaped '%' */
816fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%%");
8171d102085SJan Lentfer ++str;
818fdd4e1e0SJan Lentfer } else if (*str != '%' || (parameterized < 1)) {
819fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, *str);
820fdd4e1e0SJan Lentfer } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) {
821fdd4e1e0SJan Lentfer str = strchr(str, ';');
822fdd4e1e0SJan Lentfer bufptr = save_tc_inequality(bufptr, c1, c2);
823fdd4e1e0SJan Lentfer } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) {
824fdd4e1e0SJan Lentfer str = strchr(str, ';');
8253468e90cSJohn Marino bufptr = save_tc_inequality(bufptr, c1, ch2);
826fdd4e1e0SJan Lentfer } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) {
827fdd4e1e0SJan Lentfer str = strchr(str, ';');
8283468e90cSJohn Marino bufptr = save_tc_inequality(bufptr, ch1, c2);
829fdd4e1e0SJan Lentfer } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) {
830fdd4e1e0SJan Lentfer str = strchr(str, ';');
8313468e90cSJohn Marino bufptr = save_tc_inequality(bufptr, ch1, ch2);
832fdd4e1e0SJan Lentfer } else if ((len = bcd_expression(str)) != 0) {
833fdd4e1e0SJan Lentfer str += len;
834fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%B");
835*32bb5217SDaniel Fojt } else if ((sscanf(str, "%%{%d}%%+%%%c", &c1, &ch2) == 2
836*32bb5217SDaniel Fojt || sscanf(str, "%%'%c'%%+%%%c", &ch1, &ch2) == 2)
837*32bb5217SDaniel Fojt && ch2 == 'c'
838fdd4e1e0SJan Lentfer && (cp = strchr(str, '+'))) {
839fdd4e1e0SJan Lentfer str = cp + 2;
840fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%+");
841fdd4e1e0SJan Lentfer
842fdd4e1e0SJan Lentfer if (ch1)
843fdd4e1e0SJan Lentfer c1 = ch1;
844fdd4e1e0SJan Lentfer bufptr = save_tc_char(bufptr, c1);
845fdd4e1e0SJan Lentfer }
846fdd4e1e0SJan Lentfer /* FIXME: this "works" for 'delta' */
8473468e90cSJohn Marino else if (strncmp(str, "%{2}%*%-", (size_t) 8) == 0) {
848fdd4e1e0SJan Lentfer str += 7;
849fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%D");
8503468e90cSJohn Marino } else if (strncmp(str, "%{96}%^", (size_t) 7) == 0) {
851fdd4e1e0SJan Lentfer str += 6;
852fdd4e1e0SJan Lentfer if (saw_m++ == 0) {
853fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%n");
854fdd4e1e0SJan Lentfer }
8553468e90cSJohn Marino } else if (strncmp(str, "%{127}%^", (size_t) 8) == 0) {
856fdd4e1e0SJan Lentfer str += 7;
857fdd4e1e0SJan Lentfer if (saw_n++ == 0) {
858fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%m");
859fdd4e1e0SJan Lentfer }
860fdd4e1e0SJan Lentfer } else { /* cm-style format element */
861fdd4e1e0SJan Lentfer str++;
862fdd4e1e0SJan Lentfer switch (*str) {
863fdd4e1e0SJan Lentfer case '%':
864fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, '%');
865fdd4e1e0SJan Lentfer break;
866fdd4e1e0SJan Lentfer
867fdd4e1e0SJan Lentfer case '0':
868fdd4e1e0SJan Lentfer case '1':
869fdd4e1e0SJan Lentfer case '2':
870fdd4e1e0SJan Lentfer case '3':
871fdd4e1e0SJan Lentfer case '4':
872fdd4e1e0SJan Lentfer case '5':
873fdd4e1e0SJan Lentfer case '6':
874fdd4e1e0SJan Lentfer case '7':
875fdd4e1e0SJan Lentfer case '8':
876fdd4e1e0SJan Lentfer case '9':
877fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, '%');
8783468e90cSJohn Marino ch1 = 0;
8793468e90cSJohn Marino ch2 = 0;
880*32bb5217SDaniel Fojt digits = 0;
8813468e90cSJohn Marino while (isdigit(UChar(*str))) {
882*32bb5217SDaniel Fojt if (++digits > 2) {
883*32bb5217SDaniel Fojt syntax_error = TRUE;
884*32bb5217SDaniel Fojt break;
885*32bb5217SDaniel Fojt }
8863468e90cSJohn Marino ch2 = ch1;
8873468e90cSJohn Marino ch1 = *str++;
888*32bb5217SDaniel Fojt if (digits == 2 && ch2 != '0') {
889*32bb5217SDaniel Fojt syntax_error = TRUE;
890*32bb5217SDaniel Fojt break;
891*32bb5217SDaniel Fojt } else if (_nc_strict_bsd) {
892*32bb5217SDaniel Fojt if (ch1 > '3') {
893*32bb5217SDaniel Fojt syntax_error = TRUE;
894*32bb5217SDaniel Fojt break;
895*32bb5217SDaniel Fojt }
8963468e90cSJohn Marino } else {
8973468e90cSJohn Marino bufptr = save_char(bufptr, ch1);
8983468e90cSJohn Marino }
8993468e90cSJohn Marino }
900*32bb5217SDaniel Fojt if (syntax_error)
901*32bb5217SDaniel Fojt break;
902*32bb5217SDaniel Fojt /*
903*32bb5217SDaniel Fojt * Convert %02 to %2 and %03 to %3
904*32bb5217SDaniel Fojt */
905*32bb5217SDaniel Fojt if (ch2 == '0' && !_nc_strict_bsd) {
906*32bb5217SDaniel Fojt ch2 = 0;
907*32bb5217SDaniel Fojt bufptr[-2] = bufptr[-1];
908*32bb5217SDaniel Fojt *--bufptr = 0;
909*32bb5217SDaniel Fojt }
9103468e90cSJohn Marino if (_nc_strict_bsd) {
911*32bb5217SDaniel Fojt if (ch2 != 0 && ch2 != '0') {
912*32bb5217SDaniel Fojt syntax_error = TRUE;
913*32bb5217SDaniel Fojt } else if (ch1 < '2') {
9143468e90cSJohn Marino ch1 = 'd';
915*32bb5217SDaniel Fojt }
9163468e90cSJohn Marino bufptr = save_char(bufptr, ch1);
9173468e90cSJohn Marino }
918*32bb5217SDaniel Fojt if (strchr("oxX.", *str)) {
919*32bb5217SDaniel Fojt syntax_error = TRUE; /* termcap doesn't have octal, hex */
920fdd4e1e0SJan Lentfer }
921fdd4e1e0SJan Lentfer break;
922fdd4e1e0SJan Lentfer
923fdd4e1e0SJan Lentfer case 'd':
924fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%d");
925fdd4e1e0SJan Lentfer break;
926fdd4e1e0SJan Lentfer
927fdd4e1e0SJan Lentfer case 'c':
928fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%.");
929fdd4e1e0SJan Lentfer break;
930fdd4e1e0SJan Lentfer
931fdd4e1e0SJan Lentfer /*
932fdd4e1e0SJan Lentfer * %s isn't in termcap, but it's convenient to pass it through
933fdd4e1e0SJan Lentfer * so we can represent things like terminfo pfkey strings in
934fdd4e1e0SJan Lentfer * termcap notation.
935fdd4e1e0SJan Lentfer */
936fdd4e1e0SJan Lentfer case 's':
937*32bb5217SDaniel Fojt if (_nc_strict_bsd) {
938*32bb5217SDaniel Fojt syntax_error = TRUE;
939*32bb5217SDaniel Fojt } else {
940fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%s");
941*32bb5217SDaniel Fojt }
942fdd4e1e0SJan Lentfer break;
943fdd4e1e0SJan Lentfer
944fdd4e1e0SJan Lentfer case 'p':
945fdd4e1e0SJan Lentfer str++;
946fdd4e1e0SJan Lentfer if (*str == '1')
947fdd4e1e0SJan Lentfer seenone = 1;
948fdd4e1e0SJan Lentfer else if (*str == '2') {
949fdd4e1e0SJan Lentfer if (!seenone && !seentwo) {
950fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%r");
951fdd4e1e0SJan Lentfer seentwo++;
952fdd4e1e0SJan Lentfer }
953*32bb5217SDaniel Fojt } else if (*str >= '3') {
954*32bb5217SDaniel Fojt syntax_error = TRUE;
955*32bb5217SDaniel Fojt }
956fdd4e1e0SJan Lentfer break;
957fdd4e1e0SJan Lentfer
958fdd4e1e0SJan Lentfer case 'i':
959fdd4e1e0SJan Lentfer bufptr = save_string(bufptr, "%i");
960fdd4e1e0SJan Lentfer break;
961fdd4e1e0SJan Lentfer
962fdd4e1e0SJan Lentfer default:
963fdd4e1e0SJan Lentfer bufptr = save_char(bufptr, *str);
964fdd4e1e0SJan Lentfer syntax_error = TRUE;
965fdd4e1e0SJan Lentfer break;
966fdd4e1e0SJan Lentfer } /* endswitch (*str) */
967fdd4e1e0SJan Lentfer } /* endelse (*str == '%') */
968fdd4e1e0SJan Lentfer
9691d102085SJan Lentfer /*
9701d102085SJan Lentfer * 'str' always points to the end of what was scanned in this step,
9711d102085SJan Lentfer * but that may not be the end of the string.
9721d102085SJan Lentfer */
9731d102085SJan Lentfer assert(str != 0);
9743468e90cSJohn Marino if (str == 0 || *str == '\0')
975fdd4e1e0SJan Lentfer break;
976fdd4e1e0SJan Lentfer
977fdd4e1e0SJan Lentfer } /* endwhile (*str) */
978fdd4e1e0SJan Lentfer
979*32bb5217SDaniel Fojt if (!syntax_error &&
980*32bb5217SDaniel Fojt myfix > 0 &&
981*32bb5217SDaniel Fojt ((int) strlen(my_string) - (4 * myfix)) < MIN_TC_FIXUPS) {
982*32bb5217SDaniel Fojt while (--myfix >= 0) {
983*32bb5217SDaniel Fojt char *p = fixups[myfix].offset + my_string;
984*32bb5217SDaniel Fojt *p++ = '^';
985*32bb5217SDaniel Fojt *p++ = (char) (fixups[myfix].ch | '@');
986*32bb5217SDaniel Fojt while ((p[0] = p[2]) != '\0') {
987*32bb5217SDaniel Fojt ++p;
988*32bb5217SDaniel Fojt }
989*32bb5217SDaniel Fojt }
990*32bb5217SDaniel Fojt }
991*32bb5217SDaniel Fojt
992*32bb5217SDaniel Fojt DEBUG_THIS(("... _nc_infotocap %s",
993*32bb5217SDaniel Fojt syntax_error
994*32bb5217SDaniel Fojt ? "<ERR>"
995*32bb5217SDaniel Fojt : _nc_visbuf(my_string)));
996*32bb5217SDaniel Fojt
997fdd4e1e0SJan Lentfer return (syntax_error ? NULL : my_string);
998fdd4e1e0SJan Lentfer }
999fdd4e1e0SJan Lentfer
1000fdd4e1e0SJan Lentfer #ifdef MAIN
1001fdd4e1e0SJan Lentfer
1002fdd4e1e0SJan Lentfer int curr_line;
1003fdd4e1e0SJan Lentfer
1004fdd4e1e0SJan Lentfer int
main(int argc,char * argv[])1005fdd4e1e0SJan Lentfer main(int argc, char *argv[])
1006fdd4e1e0SJan Lentfer {
1007fdd4e1e0SJan Lentfer int c, tc = FALSE;
1008fdd4e1e0SJan Lentfer
1009fdd4e1e0SJan Lentfer while ((c = getopt(argc, argv, "c")) != EOF)
1010fdd4e1e0SJan Lentfer switch (c) {
1011fdd4e1e0SJan Lentfer case 'c':
1012fdd4e1e0SJan Lentfer tc = TRUE;
1013fdd4e1e0SJan Lentfer break;
1014fdd4e1e0SJan Lentfer }
1015fdd4e1e0SJan Lentfer
1016fdd4e1e0SJan Lentfer curr_line = 0;
1017fdd4e1e0SJan Lentfer for (;;) {
1018fdd4e1e0SJan Lentfer char buf[BUFSIZ];
1019fdd4e1e0SJan Lentfer
1020fdd4e1e0SJan Lentfer ++curr_line;
1021fdd4e1e0SJan Lentfer if (fgets(buf, sizeof(buf), stdin) == 0)
1022fdd4e1e0SJan Lentfer break;
1023fdd4e1e0SJan Lentfer buf[strlen(buf) - 1] = '\0';
1024fdd4e1e0SJan Lentfer _nc_set_source(buf);
1025fdd4e1e0SJan Lentfer
1026fdd4e1e0SJan Lentfer if (tc) {
1027fdd4e1e0SJan Lentfer char *cp = _nc_infotocap("to termcap", buf, 1);
1028fdd4e1e0SJan Lentfer
1029fdd4e1e0SJan Lentfer if (cp)
1030fdd4e1e0SJan Lentfer (void) fputs(cp, stdout);
1031fdd4e1e0SJan Lentfer } else
1032fdd4e1e0SJan Lentfer (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout);
1033fdd4e1e0SJan Lentfer (void) putchar('\n');
1034fdd4e1e0SJan Lentfer }
1035fdd4e1e0SJan Lentfer return (0);
1036fdd4e1e0SJan Lentfer }
1037fdd4e1e0SJan Lentfer #endif /* MAIN */
1038fdd4e1e0SJan Lentfer
10391d102085SJan Lentfer #if NO_LEAKS
10401d102085SJan Lentfer NCURSES_EXPORT(void)
_nc_captoinfo_leaks(void)10411d102085SJan Lentfer _nc_captoinfo_leaks(void)
10421d102085SJan Lentfer {
10431d102085SJan Lentfer if (my_string != 0) {
10441d102085SJan Lentfer FreeAndNull(my_string);
10451d102085SJan Lentfer }
10461d102085SJan Lentfer my_length = 0;
10471d102085SJan Lentfer }
10481d102085SJan Lentfer #endif
1049