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