Back to index

tetex-bin  3.0
captoinfo.c
Go to the documentation of this file.
00001 /****************************************************************************
00002  * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc.              *
00003  *                                                                          *
00004  * Permission is hereby granted, free of charge, to any person obtaining a  *
00005  * copy of this software and associated documentation files (the            *
00006  * "Software"), to deal in the Software without restriction, including      *
00007  * without limitation the rights to use, copy, modify, merge, publish,      *
00008  * distribute, distribute with modifications, sublicense, and/or sell       *
00009  * copies of the Software, and to permit persons to whom the Software is    *
00010  * furnished to do so, subject to the following conditions:                 *
00011  *                                                                          *
00012  * The above copyright notice and this permission notice shall be included  *
00013  * in all copies or substantial portions of the Software.                   *
00014  *                                                                          *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00018  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00021  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00022  *                                                                          *
00023  * Except as contained in this notice, the name(s) of the above copyright   *
00024  * holders shall not be used in advertising or otherwise to promote the     *
00025  * sale, use or other dealings in this Software without prior written       *
00026  * authorization.                                                           *
00027  ****************************************************************************/
00028 
00029 /****************************************************************************
00030  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
00031  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
00032  *     and: Thomas E. Dickey                        1996-on                 *
00033  ****************************************************************************/
00034 
00035 /*
00036  *     captoinfo.c --- conversion between termcap and terminfo formats
00037  *
00038  *     The captoinfo() code was swiped from Ross Ridge's mytinfo package,
00039  *     adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>.
00040  *
00041  *     There is just one entry point:
00042  *
00043  *     char *_nc_captoinfo(n, s, parameterized)
00044  *
00045  *     Convert value s for termcap string capability named n into terminfo
00046  *     format.
00047  *
00048  *     This code recognizes all the standard 4.4BSD %-escapes:
00049  *
00050  *     %%       output `%'
00051  *     %d       output value as in printf %d
00052  *     %2       output value as in printf %2d
00053  *     %3       output value as in printf %3d
00054  *     %.       output value as in printf %c
00055  *     %+x      add x to value, then do %.
00056  *     %>xy     if value > x then add y, no output
00057  *     %r       reverse order of two parameters, no output
00058  *     %i       increment by one, no output
00059  *     %n       exclusive-or all parameters with 0140 (Datamedia 2500)
00060  *     %B       BCD (16*(value/10)) + (value%10), no output
00061  *     %D       Reverse coding (value - 2*(value%16)), no output (Delta Data).
00062  *
00063  *     Also, %02 and %03 are accepted as synonyms for %2 and %3.
00064  *
00065  *     Besides all the standard termcap escapes, this translator understands
00066  *     the following extended escapes:
00067  *
00068  *     used by GNU Emacs termcap libraries
00069  *            %a[+*-/=][cp]x       GNU arithmetic.
00070  *            %m            xor the first two parameters by 0177
00071  *            %b            backup to previous parameter
00072  *            %f            skip this parameter
00073  *
00074  *     used by the University of Waterloo (MFCF) termcap libraries
00075  *            %-x     subtract parameter FROM char x and output it as a char
00076  *            %ax     add the character x to parameter
00077  *
00078  *     If #define WATERLOO is on, also enable these translations:
00079  *
00080  *            %sx     subtract parameter FROM the character x
00081  *
00082  *     By default, this Waterloo translations are not compiled in, because
00083  *     the Waterloo %s conflicts with the way terminfo uses %s in strings for
00084  *     function programming.
00085  *
00086  *     Note the two definitions of %a: the GNU definition is translated if the
00087  *     characters after the 'a' are valid for it, otherwise the UW definition
00088  *     is translated.
00089  */
00090 
00091 #include <curses.priv.h>
00092 
00093 #include <ctype.h>
00094 #include <tic.h>
00095 
00096 MODULE_ID("$Id: captoinfo.c,v 1.46 2004/08/28 18:08:50 tom Exp $")
00097 
00098 #define MAX_PUSHED   16     /* max # args we can push onto the stack */
00099 
00100 static int stack[MAX_PUSHED];      /* the stack */
00101 static int stackptr;        /* the next empty place on the stack */
00102 static int onstack;         /* the top of stack */
00103 static int seenm;           /* seen a %m */
00104 static int seenn;           /* seen a %n */
00105 static int seenr;           /* seen a %r */
00106 static int param;           /* current parameter */
00107 static char *dp;            /* pointer to end of the converted string */
00108 
00109 static char *my_string;
00110 static size_t my_length;
00111 
00112 static char *
00113 init_string(void)
00114 /* initialize 'my_string', 'my_length' */
00115 {
00116     if (my_string == 0)
00117        my_string = typeMalloc(char, my_length = 256);
00118     if (my_string == 0)
00119        _nc_err_abort(MSG_NO_MEMORY);
00120 
00121     *my_string = '\0';
00122     return my_string;
00123 }
00124 
00125 static char *
00126 save_string(char *d, const char *const s)
00127 {
00128     size_t have = (d - my_string);
00129     size_t need = have + strlen(s) + 2;
00130     if (need > my_length) {
00131        my_string = (char *) realloc(my_string, my_length = (need + need));
00132        if (my_string == 0)
00133            _nc_err_abort(MSG_NO_MEMORY);
00134        d = my_string + have;
00135     }
00136     (void) strcpy(d, s);
00137     return d + strlen(d);
00138 }
00139 
00140 static inline char *
00141 save_char(char *s, int c)
00142 {
00143     static char temp[2];
00144     temp[0] = (char) c;
00145     return save_string(s, temp);
00146 }
00147 
00148 static void
00149 push(void)
00150 /* push onstack on to the stack */
00151 {
00152     if (stackptr > MAX_PUSHED)
00153        _nc_warning("string too complex to convert");
00154     else
00155        stack[stackptr++] = onstack;
00156 }
00157 
00158 static void
00159 pop(void)
00160 /* pop the top of the stack into onstack */
00161 {
00162     if (stackptr == 0) {
00163        if (onstack == 0)
00164            _nc_warning("I'm confused");
00165        else
00166            onstack = 0;
00167     } else
00168        onstack = stack[--stackptr];
00169     param++;
00170 }
00171 
00172 static int
00173 cvtchar(register const char *sp)
00174 /* convert a character to a terminfo push */
00175 {
00176     unsigned char c = 0;
00177     int len;
00178 
00179     switch (*sp) {
00180     case '\\':
00181        switch (*++sp) {
00182        case '\'':
00183        case '$':
00184        case '\\':
00185        case '%':
00186            c = *sp;
00187            len = 2;
00188            break;
00189        case '\0':
00190            c = '\\';
00191            len = 1;
00192            break;
00193        case '0':
00194        case '1':
00195        case '2':
00196        case '3':
00197            len = 1;
00198            while (isdigit(UChar(*sp))) {
00199               c = 8 * c + (*sp++ - '0');
00200               len++;
00201            }
00202            break;
00203        default:
00204            c = *sp;
00205            len = 2;
00206            break;
00207        }
00208        break;
00209     case '^':
00210        c = (*++sp & 0x1f);
00211        len = 2;
00212        break;
00213     default:
00214        c = *sp;
00215        len = 1;
00216     }
00217     if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') {
00218        dp = save_string(dp, "%\'");
00219        dp = save_char(dp, c);
00220        dp = save_char(dp, '\'');
00221     } else {
00222        dp = save_string(dp, "%{");
00223        if (c > 99)
00224            dp = save_char(dp, c / 100 + '0');
00225        if (c > 9)
00226            dp = save_char(dp, ((int) (c / 10)) % 10 + '0');
00227        dp = save_char(dp, c % 10 + '0');
00228        dp = save_char(dp, '}');
00229     }
00230     return len;
00231 }
00232 
00233 static void
00234 getparm(int parm, int n)
00235 /* push n copies of param on the terminfo stack if not already there */
00236 {
00237     if (seenr) {
00238        if (parm == 1)
00239            parm = 2;
00240        else if (parm == 2)
00241            parm = 1;
00242     }
00243     if (onstack == parm) {
00244        if (n > 1) {
00245            _nc_warning("string may not be optimal");
00246            dp = save_string(dp, "%Pa");
00247            while (n--) {
00248               dp = save_string(dp, "%ga");
00249            }
00250        }
00251        return;
00252     }
00253     if (onstack != 0)
00254        push();
00255 
00256     onstack = parm;
00257 
00258     while (n--) {
00259        dp = save_string(dp, "%p");
00260        dp = save_char(dp, '0' + parm);
00261     }
00262 
00263     if (seenn && parm < 3) {
00264        dp = save_string(dp, "%{96}%^");
00265     }
00266 
00267     if (seenm && parm < 3) {
00268        dp = save_string(dp, "%{127}%^");
00269     }
00270 }
00271 
00272 /*
00273  * Convert a termcap string to terminfo format.
00274  * 'cap' is the relevant terminfo capability index.
00275  * 's' is the string value of the capability.
00276  * 'parameterized' tells what type of translations to do:
00277  *     % translations if 1
00278  *     pad translations if >=0
00279  */
00280 NCURSES_EXPORT(char *)
00281 _nc_captoinfo(const char *cap, const char *s, int const parameterized)
00282 {
00283     const char *capstart;
00284 
00285     stackptr = 0;
00286     onstack = 0;
00287     seenm = 0;
00288     seenn = 0;
00289     seenr = 0;
00290     param = 1;
00291 
00292     dp = init_string();
00293 
00294     /* skip the initial padding (if we haven't been told not to) */
00295     capstart = 0;
00296     if (s == 0)
00297        s = "";
00298     if (parameterized >= 0 && isdigit(UChar(*s)))
00299        for (capstart = s;; s++)
00300            if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.'))
00301               break;
00302 
00303     while (*s != '\0') {
00304        switch (*s) {
00305        case '%':
00306            s++;
00307            if (parameterized < 1) {
00308               dp = save_char(dp, '%');
00309               break;
00310            }
00311            switch (*s++) {
00312            case '%':
00313               dp = save_char(dp, '%');
00314               break;
00315            case 'r':
00316               if (seenr++ == 1) {
00317                   _nc_warning("saw %%r twice in %s", cap);
00318               }
00319               break;
00320            case 'm':
00321               if (seenm++ == 1) {
00322                   _nc_warning("saw %%m twice in %s", cap);
00323               }
00324               break;
00325            case 'n':
00326               if (seenn++ == 1) {
00327                   _nc_warning("saw %%n twice in %s", cap);
00328               }
00329               break;
00330            case 'i':
00331               dp = save_string(dp, "%i");
00332               break;
00333            case '6':
00334            case 'B':
00335               getparm(param, 1);
00336               dp = save_string(dp, "%{10}%/%{16}%*");
00337               getparm(param, 1);
00338               dp = save_string(dp, "%{10}%m%+");
00339               break;
00340            case '8':
00341            case 'D':
00342               getparm(param, 2);
00343               dp = save_string(dp, "%{2}%*%-");
00344               break;
00345            case '>':
00346               getparm(param, 2);
00347               /* %?%{x}%>%t%{y}%+%; */
00348               dp = save_string(dp, "%?");
00349               s += cvtchar(s);
00350               dp = save_string(dp, "%>%t");
00351               s += cvtchar(s);
00352               dp = save_string(dp, "%+%;");
00353               break;
00354            case 'a':
00355               if ((*s == '=' || *s == '+' || *s == '-'
00356                    || *s == '*' || *s == '/')
00357                   && (s[1] == 'p' || s[1] == 'c')
00358                   && s[2] != '\0') {
00359                   int l;
00360                   l = 2;
00361                   if (*s != '=')
00362                      getparm(param, 1);
00363                   if (s[1] == 'p') {
00364                      getparm(param + s[2] - '@', 1);
00365                      if (param != onstack) {
00366                          pop();
00367                          param--;
00368                      }
00369                      l++;
00370                   } else
00371                      l += cvtchar(s + 2);
00372                   switch (*s) {
00373                   case '+':
00374                      dp = save_string(dp, "%+");
00375                      break;
00376                   case '-':
00377                      dp = save_string(dp, "%-");
00378                      break;
00379                   case '*':
00380                      dp = save_string(dp, "%*");
00381                      break;
00382                   case '/':
00383                      dp = save_string(dp, "%/");
00384                      break;
00385                   case '=':
00386                      if (seenr) {
00387                          if (param == 1)
00388                             onstack = 2;
00389                          else if (param == 2)
00390                             onstack = 1;
00391                          else
00392                             onstack = param;
00393                      } else
00394                          onstack = param;
00395                      break;
00396                   }
00397                   s += l;
00398                   break;
00399               }
00400               getparm(param, 1);
00401               s += cvtchar(s);
00402               dp = save_string(dp, "%+");
00403               break;
00404            case '+':
00405               getparm(param, 1);
00406               s += cvtchar(s);
00407               dp = save_string(dp, "%+%c");
00408               pop();
00409               break;
00410            case 's':
00411 #ifdef WATERLOO
00412               s += cvtchar(s);
00413               getparm(param, 1);
00414               dp = save_string(dp, "%-");
00415 #else
00416               getparm(param, 1);
00417               dp = save_string(dp, "%s");
00418               pop();
00419 #endif /* WATERLOO */
00420               break;
00421            case '-':
00422               s += cvtchar(s);
00423               getparm(param, 1);
00424               dp = save_string(dp, "%-%c");
00425               pop();
00426               break;
00427            case '.':
00428               getparm(param, 1);
00429               dp = save_string(dp, "%c");
00430               pop();
00431               break;
00432            case '0':        /* not clear any of the historical termcaps did this */
00433               if (*s == '3')
00434                   goto see03;
00435               else if (*s != '2')
00436                   goto invalid;
00437               /* FALLTHRU */
00438            case '2':
00439               getparm(param, 1);
00440               dp = save_string(dp, "%2d");
00441               pop();
00442               break;
00443            case '3':
00444              see03:
00445               getparm(param, 1);
00446               dp = save_string(dp, "%3d");
00447               pop();
00448               break;
00449            case 'd':
00450               getparm(param, 1);
00451               dp = save_string(dp, "%d");
00452               pop();
00453               break;
00454            case 'f':
00455               param++;
00456               break;
00457            case 'b':
00458               param--;
00459               break;
00460            case '\\':
00461               dp = save_string(dp, "%\\");
00462               break;
00463            default:
00464              invalid:
00465               dp = save_char(dp, '%');
00466               s--;
00467               _nc_warning("unknown %% code %s (%#x) in %s",
00468                          unctrl((chtype) *s), UChar(*s), cap);
00469               break;
00470            }
00471            break;
00472 #ifdef REVISIBILIZE
00473        case '\\':
00474            dp = save_char(dp, *s++);
00475            dp = save_char(dp, *s++);
00476            break;
00477        case '\n':
00478            dp = save_string(dp, "\\n");
00479            s++;
00480            break;
00481        case '\t':
00482            dp = save_string(dp, "\\t");
00483            s++;
00484            break;
00485        case '\r':
00486            dp = save_string(dp, "\\r");
00487            s++;
00488            break;
00489        case '\200':
00490            dp = save_string(dp, "\\0");
00491            s++;
00492            break;
00493        case '\f':
00494            dp = save_string(dp, "\\f");
00495            s++;
00496            break;
00497        case '\b':
00498            dp = save_string(dp, "\\b");
00499            s++;
00500            break;
00501        case ' ':
00502            dp = save_string(dp, "\\s");
00503            s++;
00504            break;
00505        case '^':
00506            dp = save_string(dp, "\\^");
00507            s++;
00508            break;
00509        case ':':
00510            dp = save_string(dp, "\\:");
00511            s++;
00512            break;
00513        case ',':
00514            dp = save_string(dp, "\\,");
00515            s++;
00516            break;
00517        default:
00518            if (*s == '\033') {
00519               dp = save_string(dp, "\\E");
00520               s++;
00521            } else if (*s > 0 && *s < 32) {
00522               dp = save_char(dp, '^');
00523               dp = save_char(dp, *s + '@');
00524               s++;
00525            } else if (*s <= 0 || *s >= 127) {
00526               dp = save_char(dp, '\\');
00527               dp = save_char(dp, ((*s & 0300) >> 6) + '0');
00528               dp = save_char(dp, ((*s & 0070) >> 3) + '0');
00529               dp = save_char(dp, (*s & 0007) + '0');
00530               s++;
00531            } else
00532               dp = save_char(dp, *s++);
00533            break;
00534 #else
00535        default:
00536            dp = save_char(dp, *s++);
00537            break;
00538 #endif
00539        }
00540     }
00541 
00542     /*
00543      * Now, if we stripped off some leading padding, add it at the end
00544      * of the string as mandatory padding.
00545      */
00546     if (capstart) {
00547        dp = save_string(dp, "$<");
00548        for (s = capstart;; s++)
00549            if (isdigit(UChar(*s)) || *s == '*' || *s == '.')
00550               dp = save_char(dp, *s);
00551            else
00552               break;
00553        dp = save_string(dp, "/>");
00554     }
00555 
00556     (void) save_char(dp, '\0');
00557     return (my_string);
00558 }
00559 
00560 /*
00561  * Check for an expression that corresponds to "%B" (BCD):
00562  *     (parameter / 10) * 16 + (parameter % 10)
00563  */
00564 static int
00565 bcd_expression(const char *str)
00566 {
00567     /* leave this non-const for HPUX */
00568     static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+";
00569     int len = 0;
00570     char ch1, ch2;
00571 
00572     if (sscanf(str, fmt, &ch1, &ch2) == 2
00573        && isdigit(UChar(ch1))
00574        && isdigit(UChar(ch2))
00575        && (ch1 == ch2)) {
00576        len = 28;
00577 #ifndef NDEBUG
00578        {
00579            char buffer[80];
00580            int tst;
00581            sprintf(buffer, fmt, ch1, ch2);
00582            tst = strlen(buffer) - 1;
00583            assert(len == tst);
00584        }
00585 #endif
00586     }
00587     return len;
00588 }
00589 
00590 static char *
00591 save_tc_char(char *bufptr, int c1)
00592 {
00593     char temp[80];
00594 
00595     if (is7bits(c1) && isprint(c1)) {
00596        if (c1 == ':' || c1 == '\\')
00597            bufptr = save_char(bufptr, '\\');
00598        bufptr = save_char(bufptr, c1);
00599     } else {
00600        if (c1 == (c1 & 0x1f))      /* iscntrl() returns T on 255 */
00601            (void) strcpy(temp, unctrl((chtype) c1));
00602        else
00603            (void) sprintf(temp, "\\%03o", c1);
00604        bufptr = save_string(bufptr, temp);
00605     }
00606     return bufptr;
00607 }
00608 
00609 static char *
00610 save_tc_inequality(char *bufptr, int c1, int c2)
00611 {
00612     bufptr = save_string(bufptr, "%>");
00613     bufptr = save_tc_char(bufptr, c1);
00614     bufptr = save_tc_char(bufptr, c2);
00615     return bufptr;
00616 }
00617 
00618 /*
00619  * Here are the capabilities infotocap assumes it can translate to:
00620  *
00621  *     %%       output `%'
00622  *     %d       output value as in printf %d
00623  *     %2       output value as in printf %2d
00624  *     %3       output value as in printf %3d
00625  *     %.       output value as in printf %c
00626  *     %+c      add character c to value, then do %.
00627  *     %>xy     if value > x then add y, no output
00628  *     %r       reverse order of two parameters, no output
00629  *     %i       increment by one, no output
00630  *     %n       exclusive-or all parameters with 0140 (Datamedia 2500)
00631  *     %B       BCD (16*(value/10)) + (value%10), no output
00632  *     %D       Reverse coding (value - 2*(value%16)), no output (Delta Data).
00633  *     %m       exclusive-or all parameters with 0177 (not in 4.4BSD)
00634  */
00635 
00636 /*
00637  * Convert a terminfo string to termcap format.  Parameters are as in
00638  * _nc_captoinfo().
00639  */
00640 NCURSES_EXPORT(char *)
00641 _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized)
00642 {
00643     int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0;
00644     const char *padding;
00645     const char *trimmed = 0;
00646     char ch1 = 0, ch2 = 0;
00647     char *bufptr = init_string();
00648     int len;
00649     bool syntax_error = FALSE;
00650 
00651     /* we may have to move some trailing mandatory padding up front */
00652     padding = str + strlen(str) - 1;
00653     if (padding > str && *padding == '>' && *--padding == '/') {
00654        --padding;
00655        while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
00656            padding--;
00657        if (padding > str && *padding == '<' && *--padding == '$')
00658            trimmed = padding;
00659        padding += 2;
00660 
00661        while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
00662            bufptr = save_char(bufptr, *padding++);
00663     }
00664 
00665     for (; *str && str != trimmed; str++) {
00666        int c1, c2;
00667        char *cp = 0;
00668 
00669        if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) {
00670            bufptr = save_char(bufptr, *++str);
00671        } else if (str[0] == '$' && str[1] == '<') {     /* discard padding */
00672            str += 2;
00673            while (isdigit(UChar(*str))
00674                  || *str == '.'
00675                  || *str == '*'
00676                  || *str == '/'
00677                  || *str == '>')
00678               str++;
00679            --str;
00680        } else if (str[0] == '%' && str[1] == '%') {     /* escaped '%' */
00681            bufptr = save_string(bufptr, "%%");
00682            ++str;
00683        } else if (*str != '%' || (parameterized < 1)) {
00684            bufptr = save_char(bufptr, *str);
00685        } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) {
00686            str = strchr(str, ';');
00687            bufptr = save_tc_inequality(bufptr, c1, c2);
00688        } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) {
00689            str = strchr(str, ';');
00690            bufptr = save_tc_inequality(bufptr, c1, c2);
00691        } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) {
00692            str = strchr(str, ';');
00693            bufptr = save_tc_inequality(bufptr, c1, c2);
00694        } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) {
00695            str = strchr(str, ';');
00696            bufptr = save_tc_inequality(bufptr, c1, c2);
00697        } else if ((len = bcd_expression(str)) != 0) {
00698            str += len;
00699            bufptr = save_string(bufptr, "%B");
00700        } else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1
00701                   || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1)
00702                  && (cp = strchr(str, '+'))) {
00703            str = cp + 2;
00704            bufptr = save_string(bufptr, "%+");
00705 
00706            if (ch1)
00707               c1 = ch1;
00708            bufptr = save_tc_char(bufptr, c1);
00709        }
00710        /* FIXME: this "works" for 'delta' */
00711        else if (strncmp(str, "%{2}%*%-", 8) == 0) {
00712            str += 7;
00713            bufptr = save_string(bufptr, "%D");
00714        } else if (strncmp(str, "%{96}%^", 7) == 0) {
00715            str += 6;
00716            if (saw_m++ == 0) {
00717               bufptr = save_string(bufptr, "%n");
00718            }
00719        } else if (strncmp(str, "%{127}%^", 8) == 0) {
00720            str += 7;
00721            if (saw_n++ == 0) {
00722               bufptr = save_string(bufptr, "%m");
00723            }
00724        } else {             /* cm-style format element */
00725            str++;
00726            switch (*str) {
00727            case '%':
00728               bufptr = save_char(bufptr, '%');
00729               break;
00730 
00731            case '0':
00732            case '1':
00733            case '2':
00734            case '3':
00735            case '4':
00736            case '5':
00737            case '6':
00738            case '7':
00739            case '8':
00740            case '9':
00741               bufptr = save_char(bufptr, '%');
00742               while (isdigit(UChar(*str)))
00743                   bufptr = save_char(bufptr, *str++);
00744               if (strchr("doxX.", *str)) {
00745                   if (*str != 'd') /* termcap doesn't have octal, hex */
00746                      return 0;
00747               }
00748               break;
00749 
00750            case 'd':
00751               bufptr = save_string(bufptr, "%d");
00752               break;
00753 
00754            case 'c':
00755               bufptr = save_string(bufptr, "%.");
00756               break;
00757 
00758               /*
00759                * %s isn't in termcap, but it's convenient to pass it through
00760                * so we can represent things like terminfo pfkey strings in
00761                * termcap notation.
00762                */
00763            case 's':
00764               bufptr = save_string(bufptr, "%s");
00765               break;
00766 
00767            case 'p':
00768               str++;
00769               if (*str == '1')
00770                   seenone = 1;
00771               else if (*str == '2') {
00772                   if (!seenone && !seentwo) {
00773                      bufptr = save_string(bufptr, "%r");
00774                      seentwo++;
00775                   }
00776               } else if (*str >= '3')
00777                   return (0);
00778               break;
00779 
00780            case 'i':
00781               bufptr = save_string(bufptr, "%i");
00782               break;
00783 
00784            default:
00785               bufptr = save_char(bufptr, *str);
00786               syntax_error = TRUE;
00787               break;
00788            }                /* endswitch (*str) */
00789        }                    /* endelse (*str == '%') */
00790 
00791        if (*str == '\0')
00792            break;
00793 
00794     }                       /* endwhile (*str) */
00795 
00796     return (syntax_error ? NULL : my_string);
00797 }
00798 
00799 #ifdef MAIN
00800 
00801 int curr_line;
00802 
00803 int
00804 main(int argc, char *argv[])
00805 {
00806     int c, tc = FALSE;
00807 
00808     while ((c = getopt(argc, argv, "c")) != EOF)
00809        switch (c) {
00810        case 'c':
00811            tc = TRUE;
00812            break;
00813        }
00814 
00815     curr_line = 0;
00816     for (;;) {
00817        char buf[BUFSIZ];
00818 
00819        ++curr_line;
00820        if (fgets(buf, sizeof(buf), stdin) == 0)
00821            break;
00822        buf[strlen(buf) - 1] = '\0';
00823        _nc_set_source(buf);
00824 
00825        if (tc) {
00826            char *cp = _nc_infotocap("to termcap", buf, 1);
00827 
00828            if (cp)
00829               (void) fputs(cp, stdout);
00830        } else
00831            (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout);
00832        (void) putchar('\n');
00833     }
00834     return (0);
00835 }
00836 #endif /* MAIN */
00837 
00838 /* captoinfo.c ends here */