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