Back to index

tetex-bin  3.0
Classes | Defines | Functions
lib_tparm.c File Reference
#include <curses.priv.h>
#include <ctype.h>
#include <term.h>
#include <tic.h>

Go to the source code of this file.

Classes

struct  stack_frame
union  stack_frame.data

Defines

#define STACKSIZE   20
#define isUPPER(c)   ((c) >= 'A' && (c) <= 'Z')
#define isLOWER(c)   ((c) >= 'a' && (c) <= 'z')
#define NUM_VARS   26

Functions

 NCURSES_EXPORT_VAR (int)
static void save_text (const char *fmt, const char *s, int len)
static void save_number (const char *fmt, int number, int len)
static void save_char (int c)
static void npush (int x)
static int npop (void)
static void spush (char *x)
static char * spop (void)
static const char * parse_format (const char *s, char *format, int *len)
 _nc_tparm_analyze (const char *string, char *p_is_s[NUM_PARM], int *popcount)
static char * tparam_internal (const char *string, va_list ap)
 tparm (NCURSES_CONST char *string,...)

Class Documentation

struct stack_frame

Definition at line 110 of file lib_tparm.c.

Class Members
union stack_frame data
bool num_type
union stack_frame.data

Definition at line 111 of file lib_tparm.c.

Class Members
int num
char * str

Define Documentation

#define isLOWER (   c)    ((c) >= 'a' && (c) <= 'z')

Definition at line 345 of file lib_tparm.c.

#define isUPPER (   c)    ((c) >= 'A' && (c) <= 'Z')

Definition at line 344 of file lib_tparm.c.

#define NUM_VARS   26
#define STACKSIZE   20

Definition at line 108 of file lib_tparm.c.


Function Documentation

_nc_tparm_analyze ( const char *  string,
char *  p_is_s[NUM_PARM],
int popcount 
)

Definition at line 359 of file lib_tparm.c.

{
    size_t len2;
    int i;
    int lastpop = -1;
    int len;
    int number = 0;
    const char *cp = string;
    static char dummy[] = "";

    if (cp == 0)
       return 0;

    if ((len2 = strlen(cp)) > fmt_size) {
       fmt_size = len2 + fmt_size + 2;
       if ((fmt_buff = typeRealloc(char, fmt_size, fmt_buff)) == 0)
             return 0;
    }

    memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);
    *popcount = 0;

    while ((cp - string) < (int) len2) {
       if (*cp == '%') {
           cp++;
           cp = parse_format(cp, fmt_buff, &len);
           switch (*cp) {
           default:
              break;

           case 'd':        /* FALLTHRU */
           case 'o':        /* FALLTHRU */
           case 'x':        /* FALLTHRU */
           case 'X':        /* FALLTHRU */
           case 'c':        /* FALLTHRU */
              if (lastpop <= 0)
                  number++;
              lastpop = -1;
              break;

           case 'l':
           case 's':
              if (lastpop > 0)
                  p_is_s[lastpop - 1] = dummy;
              ++number;
              break;

           case 'p':
              cp++;
              i = (UChar(*cp) - '0');
              if (i >= 0 && i <= NUM_PARM) {
                  lastpop = i;
                  if (lastpop > *popcount)
                     *popcount = lastpop;
              }
              break;

           case 'P':
              ++number;
              ++cp;
              break;

           case 'g':
              cp++;
              break;

           case S_QUOTE:
              cp += 2;
              lastpop = -1;
              break;

           case L_BRACE:
              cp++;
              while (isdigit(UChar(*cp))) {
                  cp++;
              }
              break;

           case '+':
           case '-':
           case '*':
           case '/':
           case 'm':
           case 'A':
           case 'O':
           case '&':
           case '|':
           case '^':
           case '=':
           case '<':
           case '>':
              lastpop = -1;
              number += 2;
              break;

           case '!':
           case '~':
              lastpop = -1;
              ++number;
              break;

           case 'i':
              /* will add 1 to first (usually two) parameters */
              break;
           }
       }
       if (*cp != '\0')
           cp++;
    }

    if (number > NUM_PARM)
       number = NUM_PARM;
    return number;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 118 of file lib_tparm.c.

{
    if (out_buff != 0) {
       FreeAndNull(out_buff);
       out_size = 0;
       out_used = 0;
       FreeAndNull(fmt_buff);
       fmt_size = 0;
    }
}
#endif

static inline void
get_space(size_t need)
{
    need += out_used;
    if (need > out_size) {
       out_size = need * 2;
       out_buff = typeRealloc(char, out_size, out_buff);
       if (out_buff == 0)
           _nc_err_abort(MSG_NO_MEMORY);
    }
}
static int npop ( void  ) [inline, static]

Definition at line 209 of file lib_tparm.c.

{
    int result = 0;
    if (stack_ptr > 0) {
       stack_ptr--;
       if (stack[stack_ptr].num_type)
           result = stack[stack_ptr].data.num;
    } else {
       DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(tparam_base)));
       _nc_tparm_err++;
    }
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void npush ( int  x) [inline, static]

Definition at line 196 of file lib_tparm.c.

{
    if (stack_ptr < STACKSIZE) {
       stack[stack_ptr].num_type = TRUE;
       stack[stack_ptr].data.num = x;
       stack_ptr++;
    } else {
       DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(tparam_base)));
       _nc_tparm_err++;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* parse_format ( const char *  s,
char *  format,
int len 
) [inline, static]

Definition at line 253 of file lib_tparm.c.

{
    *len = 0;
    if (format != 0) {
       bool done = FALSE;
       bool allowminus = FALSE;
       bool dot = FALSE;
       bool err = FALSE;
       char *fmt = format;
       int my_width = 0;
       int my_prec = 0;
       int value = 0;

       *len = 0;
       *format++ = '%';
       while (*s != '\0' && !done) {
           switch (*s) {
           case 'c':        /* FALLTHRU */
           case 'd':        /* FALLTHRU */
           case 'o':        /* FALLTHRU */
           case 'x':        /* FALLTHRU */
           case 'X':        /* FALLTHRU */
           case 's':
              *format++ = *s;
              done = TRUE;
              break;
           case '.':
              *format++ = *s++;
              if (dot) {
                  err = TRUE;
              } else {      /* value before '.' is the width */
                  dot = TRUE;
                  my_width = value;
              }
              value = 0;
              break;
           case '#':
              *format++ = *s++;
              break;
           case ' ':
              *format++ = *s++;
              break;
           case ':':
              s++;
              allowminus = TRUE;
              break;
           case '-':
              if (allowminus) {
                  *format++ = *s++;
              } else {
                  done = TRUE;
              }
              break;
           default:
              if (isdigit(UChar(*s))) {
                  value = (value * 10) + (*s - '0');
                  if (value > 10000)
                     err = TRUE;
                  *format++ = *s++;
              } else {
                  done = TRUE;
              }
           }
       }

       /*
        * If we found an error, ignore (and remove) the flags.
        */
       if (err) {
           my_width = my_prec = value = 0;
           format = fmt;
           *format++ = '%';
           *format++ = *s;
       }

       /*
        * Any value after '.' is the precision.  If we did not see '.', then
        * the value is the width.
        */
       if (dot)
           my_prec = value;
       else
           my_width = value;

       *format = '\0';
       /* return maximum string length in print */
       *len = (my_width > my_prec) ? my_width : my_prec;
    }
    return s;
}

Here is the caller graph for this function:

static void save_char ( int  c) [inline, static]

Definition at line 187 of file lib_tparm.c.

{
    if (c == 0)
       c = 0200;
    get_space(1);
    out_buff[out_used++] = c;
}

Here is the caller graph for this function:

static void save_number ( const char *  fmt,
int  number,
int  len 
) [inline, static]

Definition at line 175 of file lib_tparm.c.

{
    if (len < 30)
       len = 30;            /* actually log10(MAX_INT)+1 */

    get_space((unsigned) len + 1);

    (void) sprintf(out_buff + out_used, fmt, number);
    out_used += strlen(out_buff + out_used);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void save_text ( const char *  fmt,
const char *  s,
int  len 
) [inline, static]

Definition at line 162 of file lib_tparm.c.

{
    size_t s_len = strlen(s);
    if (len > (int) s_len)
       s_len = len;

    get_space(s_len + 1);

    (void) sprintf(out_buff + out_used, fmt, s);
    out_used += strlen(out_buff + out_used);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* spop ( void  ) [inline, static]

Definition at line 237 of file lib_tparm.c.

{
    static char dummy[] = "";      /* avoid const-cast */
    char *result = dummy;
    if (stack_ptr > 0) {
       stack_ptr--;
       if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0)
           result = stack[stack_ptr].data.str;
    } else {
       DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(tparam_base)));
       _nc_tparm_err++;
    }
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void spush ( char *  x) [inline, static]

Definition at line 224 of file lib_tparm.c.

{
    if (stack_ptr < STACKSIZE) {
       stack[stack_ptr].num_type = FALSE;
       stack[stack_ptr].data.str = x;
       stack_ptr++;
    } else {
       DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(tparam_base)));
       _nc_tparm_err++;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* tparam_internal ( const char *  string,
va_list  ap 
) [inline, static]

Definition at line 475 of file lib_tparm.c.

{
#define NUM_VARS 26
    char *p_is_s[NUM_PARM];
    long param[NUM_PARM];
    int popcount;
    int number;
    int len;
    int level;
    int x, y;
    int i;
    const char *cp = string;
    size_t len2;
    static int dynamic_var[NUM_VARS];
    static int static_vars[NUM_VARS];

    if (cp == NULL)
       return NULL;

    out_used = 0;
    len2 = strlen(cp);

    /*
     * Find the highest parameter-number referred to in the format string.
     * Use this value to limit the number of arguments copied from the
     * variable-length argument list.
     */
    number = _nc_tparm_analyze(cp, p_is_s, &popcount);
    if (fmt_buff == 0)
       return NULL;

    for (i = 0; i < max(popcount, number); i++) {
       /*
        * A few caps (such as plab_norm) have string-valued parms.
        * We'll have to assume that the caller knows the difference, since
        * a char* and an int may not be the same size on the stack.  The
        * normal prototype for this uses 9 long's, which is consistent with
        * our va_arg() usage.
        */
       if (p_is_s[i] != 0) {
           p_is_s[i] = va_arg(ap, char *);
       } else {
           param[i] = va_arg(ap, long int);
       }
    }

    /*
     * This is a termcap compatibility hack.  If there are no explicit pop
     * operations in the string, load the stack in such a way that
     * successive pops will grab successive parameters.  That will make
     * the expansion of (for example) \E[%d;%dH work correctly in termcap
     * style, which means tparam() will expand termcap strings OK.
     */
    stack_ptr = 0;
    if (popcount == 0) {
       popcount = number;
       for (i = number - 1; i >= 0; i--)
           npush(param[i]);
    }
#ifdef TRACE
    if (_nc_tracing & TRACE_CALLS) {
       for (i = 0; i < popcount; i++) {
           if (p_is_s[i] != 0)
              save_text(", %s", _nc_visbuf(p_is_s[i]), 0);
           else
              save_number(", %d", param[i], 0);
       }
       _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(cp), out_buff);
       out_used = 0;
    }
#endif /* TRACE */

    while ((cp - string) < (int) len2) {
       if (*cp != '%') {
           save_char(UChar(*cp));
       } else {
           tparam_base = cp++;
           cp = parse_format(cp, fmt_buff, &len);
           switch (*cp) {
           default:
              break;
           case '%':
              save_char('%');
              break;

           case 'd':        /* FALLTHRU */
           case 'o':        /* FALLTHRU */
           case 'x':        /* FALLTHRU */
           case 'X':        /* FALLTHRU */
              save_number(fmt_buff, npop(), len);
              break;

           case 'c':        /* FALLTHRU */
              save_char(npop());
              break;

           case 'l':
              save_number("%d", (int) strlen(spop()), 0);
              break;

           case 's':
              save_text(fmt_buff, spop(), len);
              break;

           case 'p':
              cp++;
              i = (UChar(*cp) - '1');
              if (i >= 0 && i < NUM_PARM) {
                  if (p_is_s[i])
                     spush(p_is_s[i]);
                  else
                     npush(param[i]);
              }
              break;

           case 'P':
              cp++;
              if (isUPPER(*cp)) {
                  i = (UChar(*cp) - 'A');
                  static_vars[i] = npop();
              } else if (isLOWER(*cp)) {
                  i = (UChar(*cp) - 'a');
                  dynamic_var[i] = npop();
              }
              break;

           case 'g':
              cp++;
              if (isUPPER(*cp)) {
                  i = (UChar(*cp) - 'A');
                  npush(static_vars[i]);
              } else if (isLOWER(*cp)) {
                  i = (UChar(*cp) - 'a');
                  npush(dynamic_var[i]);
              }
              break;

           case S_QUOTE:
              cp++;
              npush(UChar(*cp));
              cp++;
              break;

           case L_BRACE:
              number = 0;
              cp++;
              while (isdigit(UChar(*cp))) {
                  number = (number * 10) + (UChar(*cp) - '0');
                  cp++;
              }
              npush(number);
              break;

           case '+':
              npush(npop() + npop());
              break;

           case '-':
              y = npop();
              x = npop();
              npush(x - y);
              break;

           case '*':
              npush(npop() * npop());
              break;

           case '/':
              y = npop();
              x = npop();
              npush(y ? (x / y) : 0);
              break;

           case 'm':
              y = npop();
              x = npop();
              npush(y ? (x % y) : 0);
              break;

           case 'A':
              npush(npop() && npop());
              break;

           case 'O':
              npush(npop() || npop());
              break;

           case '&':
              npush(npop() & npop());
              break;

           case '|':
              npush(npop() | npop());
              break;

           case '^':
              npush(npop() ^ npop());
              break;

           case '=':
              y = npop();
              x = npop();
              npush(x == y);
              break;

           case '<':
              y = npop();
              x = npop();
              npush(x < y);
              break;

           case '>':
              y = npop();
              x = npop();
              npush(x > y);
              break;

           case '!':
              npush(!npop());
              break;

           case '~':
              npush(~npop());
              break;

           case 'i':
              if (p_is_s[0] == 0)
                  param[0]++;
              if (p_is_s[1] == 0)
                  param[1]++;
              break;

           case '?':
              break;

           case 't':
              x = npop();
              if (!x) {
                  /* scan forward for %e or %; at level zero */
                  cp++;
                  level = 0;
                  while (*cp) {
                     if (*cp == '%') {
                         cp++;
                         if (*cp == '?')
                            level++;
                         else if (*cp == ';') {
                            if (level > 0)
                                level--;
                            else
                                break;
                         } else if (*cp == 'e' && level == 0)
                            break;
                     }

                     if (*cp)
                         cp++;
                  }
              }
              break;

           case 'e':
              /* scan forward for a %; at level zero */
              cp++;
              level = 0;
              while (*cp) {
                  if (*cp == '%') {
                     cp++;
                     if (*cp == '?')
                         level++;
                     else if (*cp == ';') {
                         if (level > 0)
                            level--;
                         else
                            break;
                     }
                  }

                  if (*cp)
                     cp++;
              }
              break;

           case ';':
              break;

           }                /* endswitch (*cp) */
       }                    /* endelse (*cp == '%') */

       if (*cp == '\0')
           break;

       cp++;
    }                       /* endwhile (*cp) */

    get_space(1);
    out_buff[out_used] = '\0';

    T((T_RETURN("%s"), _nc_visbuf(out_buff)));
    return (out_buff);
}

Here is the call graph for this function:

Here is the caller graph for this function:

tparm ( NCURSES_CONST char *  string,
  ... 
)

Definition at line 778 of file lib_tparm.c.

{
    va_list ap;
    char *result;

    _nc_tparm_err = 0;
    va_start(ap, string);
#ifdef TRACE
    tname = "tparm";
#endif /* TRACE */
    result = tparam_internal(string, ap);
    va_end(ap);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function: