Blame gnulib-local/lib/tparm.c

Packit Bot 06c835
/* Substitution of parameters in strings from terminal descriptions.
Packit Bot 06c835
   Copyright (C) 2006, 2012, 2015 Free Software Foundation, Inc.
Packit Bot 06c835
Packit Bot 06c835
   This program is free software: you can redistribute it and/or modify
Packit Bot 06c835
   it under the terms of the GNU Lesser General Public License as published by
Packit Bot 06c835
   the Free Software Foundation; either version 2.1 of the License, or
Packit Bot 06c835
   (at your option) any later version.
Packit Bot 06c835
Packit Bot 06c835
   This program is distributed in the hope that it will be useful,
Packit Bot 06c835
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Bot 06c835
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Bot 06c835
   GNU Lesser General Public License for more details.
Packit Bot 06c835
Packit Bot 06c835
   You should have received a copy of the GNU Lesser General Public License
Packit Bot 06c835
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Bot 06c835
Packit Bot 06c835
/* Originally by Ross Ridge, Public Domain, 92/02/01 07:30:36 */
Packit Bot 06c835
Packit Bot 06c835
#include <config.h>
Packit Bot 06c835
Packit Bot 06c835
#include <stdarg.h>
Packit Bot 06c835
#include <stdio.h>
Packit Bot 06c835
#include <string.h>
Packit Bot 06c835
Packit Bot 06c835
#include "c-ctype.h"
Packit Bot 06c835
Packit Bot 06c835
#ifdef USE_SCCS_IDS
Packit Bot 06c835
static const char SCCSid[] = "@(#) mytinfo tparm.c 3.2 92/02/01 public domain, By Ross Ridge";
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
#ifndef MAX_PUSHED
Packit Bot 06c835
#define MAX_PUSHED      32
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
#define ARG     1
Packit Bot 06c835
#define NUM     2
Packit Bot 06c835
Packit Bot 06c835
#define INTEGER 1
Packit Bot 06c835
#define STRING  2
Packit Bot 06c835
Packit Bot 06c835
#define MAX_LINE 640
Packit Bot 06c835
Packit Bot 06c835
typedef struct stack_str
Packit Bot 06c835
{
Packit Bot 06c835
  int type;
Packit Bot 06c835
  int argnum;
Packit Bot 06c835
  int value;
Packit Bot 06c835
} stack;
Packit Bot 06c835
Packit Bot 06c835
static stack S[MAX_PUSHED];
Packit Bot 06c835
static stack vars['z'-'a'+1];
Packit Bot 06c835
static int pos = 0;
Packit Bot 06c835
Packit Bot 06c835
static
Packit Bot 06c835
struct arg_str
Packit Bot 06c835
{
Packit Bot 06c835
  int type;
Packit Bot 06c835
  int integer;
Packit Bot 06c835
  char *string;
Packit Bot 06c835
} arg_list[10];
Packit Bot 06c835
Packit Bot 06c835
static int argcnt;
Packit Bot 06c835
Packit Bot 06c835
static va_list tparm_args;
Packit Bot 06c835
Packit Bot 06c835
static int
Packit Bot 06c835
pusharg (int arg)
Packit Bot 06c835
{
Packit Bot 06c835
  if (pos == MAX_PUSHED)
Packit Bot 06c835
    return 1;
Packit Bot 06c835
  S[pos].type = ARG;
Packit Bot 06c835
  S[pos++].argnum = arg;
Packit Bot 06c835
  return 0;
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
static int
Packit Bot 06c835
pushnum (int num)
Packit Bot 06c835
{
Packit Bot 06c835
  if (pos == MAX_PUSHED)
Packit Bot 06c835
    return 1;
Packit Bot 06c835
  S[pos].type = NUM;
Packit Bot 06c835
  S[pos++].value = num;
Packit Bot 06c835
  return 0;
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
static int
Packit Bot 06c835
getarg (int argnum, int type, void *p)
Packit Bot 06c835
{
Packit Bot 06c835
  while (argcnt < argnum)
Packit Bot 06c835
    {
Packit Bot 06c835
      arg_list[argcnt].type = INTEGER;
Packit Bot 06c835
      arg_list[argcnt++].integer = (int) va_arg (tparm_args, int);
Packit Bot 06c835
    }
Packit Bot 06c835
  if (argcnt > argnum)
Packit Bot 06c835
    {
Packit Bot 06c835
      if (arg_list[argnum].type != type)
Packit Bot 06c835
        return 1;
Packit Bot 06c835
      else if (type == STRING)
Packit Bot 06c835
        *(char **)p = arg_list[argnum].string;
Packit Bot 06c835
      else
Packit Bot 06c835
        *(int *)p = arg_list[argnum].integer;
Packit Bot 06c835
    }
Packit Bot 06c835
  else
Packit Bot 06c835
    {
Packit Bot 06c835
      arg_list[argcnt].type = type;
Packit Bot 06c835
      if (type == STRING)
Packit Bot 06c835
        *(char **)p = arg_list[argcnt++].string = (char *) va_arg (tparm_args, char *);
Packit Bot 06c835
      else
Packit Bot 06c835
        *(int *)p = arg_list[argcnt++].integer = (int) va_arg (tparm_args, int);
Packit Bot 06c835
    }
Packit Bot 06c835
  return 0;
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
static int
Packit Bot 06c835
popstring (char **str)
Packit Bot 06c835
{
Packit Bot 06c835
  if (pos-- == 0)
Packit Bot 06c835
    return 1;
Packit Bot 06c835
  if (S[pos].type != ARG)
Packit Bot 06c835
    return 1;
Packit Bot 06c835
  return getarg (S[pos].argnum, STRING, str);
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
static int
Packit Bot 06c835
popnum (int *num)
Packit Bot 06c835
{
Packit Bot 06c835
  if (pos-- == 0)
Packit Bot 06c835
    return 1;
Packit Bot 06c835
  switch (S[pos].type)
Packit Bot 06c835
    {
Packit Bot 06c835
    case ARG:
Packit Bot 06c835
      return  getarg (S[pos].argnum, INTEGER, num);
Packit Bot 06c835
    case NUM:
Packit Bot 06c835
      *num = S[pos].value;
Packit Bot 06c835
      return 0;
Packit Bot 06c835
    }
Packit Bot 06c835
  return 1;
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
static int
Packit Bot 06c835
cvtchar (const char *sp, char *c)
Packit Bot 06c835
{
Packit Bot 06c835
  switch (*sp)
Packit Bot 06c835
    {
Packit Bot 06c835
    case '\\':
Packit Bot 06c835
      switch (*++sp)
Packit Bot 06c835
        {
Packit Bot 06c835
        case '\'':
Packit Bot 06c835
        case '$':
Packit Bot 06c835
        case '\\':
Packit Bot 06c835
        case '%':
Packit Bot 06c835
          *c = *sp;
Packit Bot 06c835
          return 2;
Packit Bot 06c835
        case '\0':
Packit Bot 06c835
          *c = '\\';
Packit Bot 06c835
          return 1;
Packit Bot 06c835
        case '0':
Packit Bot 06c835
          if (sp[1] == '0' && sp[2] == '0')
Packit Bot 06c835
            {
Packit Bot 06c835
              *c = '\0';
Packit Bot 06c835
              return 4;
Packit Bot 06c835
            }
Packit Bot 06c835
          *c = '\200'; /* '\0' ???? */
Packit Bot 06c835
          return 2;
Packit Bot 06c835
        default:
Packit Bot 06c835
          *c = *sp;
Packit Bot 06c835
          return 2;
Packit Bot 06c835
        }
Packit Bot 06c835
    default:
Packit Bot 06c835
      *c = *sp;
Packit Bot 06c835
      return 1;
Packit Bot 06c835
    }
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
/* sigh... this has got to be the ugliest code I've ever written.
Packit Bot 06c835
   Trying to handle everything has its cost, I guess.
Packit Bot 06c835
Packit Bot 06c835
   It actually isn't to hard to figure out if a given % code is supposed
Packit Bot 06c835
   to be interpeted with its termcap or terminfo meaning since almost
Packit Bot 06c835
   all terminfo codes are invalid unless something has been pushed on
Packit Bot 06c835
   the stack and termcap strings will never push things on the stack
Packit Bot 06c835
   (%p isn't used by termcap). So where we have a choice we make the
Packit Bot 06c835
   decision by wether or not somthing has been pushed on the stack.
Packit Bot 06c835
   The static variable termcap keeps track of this; it starts out set
Packit Bot 06c835
   to 1 and is incremented as each argument processed by a termcap % code,
Packit Bot 06c835
   however if something is pushed on the stack it's set to 0 and the
Packit Bot 06c835
   rest of the % codes are interpeted as terminfo % codes. Another way
Packit Bot 06c835
   of putting it is that if termcap equals one we haven't decided either
Packit Bot 06c835
   way yet, if it equals zero we're looking for terminfo codes, and if
Packit Bot 06c835
   its greater than 1 we're looking for termcap codes.
Packit Bot 06c835
Packit Bot 06c835
   Terminfo % codes:
Packit Bot 06c835
Packit Bot 06c835
        %%      output a '%'
Packit Bot 06c835
        %[[:][-+# ][width][.precision]][doxXs]
Packit Bot 06c835
                output pop according to the printf format
Packit Bot 06c835
        %c      output pop as a char
Packit Bot 06c835
        %'c'    push character constant c.
Packit Bot 06c835
        %{n}    push decimal constant n.
Packit Bot 06c835
        %p[1-9] push paramter [1-9]
Packit Bot 06c835
        %g[a-z] push variable [a-z]
Packit Bot 06c835
        %P[a-z] put pop in variable [a-z]
Packit Bot 06c835
        %l      push the length of pop (a string)
Packit Bot 06c835
        %+      add pop to pop and push the result
Packit Bot 06c835
        %-      subtract pop from pop and push the result
Packit Bot 06c835
        %*      multiply pop and pop and push the result
Packit Bot 06c835
        %&      bitwise and pop and pop and push the result
Packit Bot 06c835
        %|      bitwise or pop and pop and push the result
Packit Bot 06c835
        %^      bitwise xor pop and pop and push the result
Packit Bot 06c835
        %~      push the bitwise not of pop
Packit Bot 06c835
        %=      compare if pop and pop are equal and push the result
Packit Bot 06c835
        %>      compare if pop is less than pop and push the result
Packit Bot 06c835
        %<      compare if pop is greater than pop and push the result
Packit Bot 06c835
        %A      logical and pop and pop and push the result
Packit Bot 06c835
        %O      logical or pop and pop and push the result
Packit Bot 06c835
        %!      push the logical not of pop
Packit Bot 06c835
        %? condition %t if_true [%e if_false] %;
Packit Bot 06c835
                if condtion evaulates as true then evaluate if_true,
Packit Bot 06c835
                else evaluate if_false. elseif's can be done:
Packit Bot 06c835
        %? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
Packit Bot 06c835
        %i      add one to parameters 1 and 2. (ANSI)
Packit Bot 06c835
Packit Bot 06c835
  Termcap Codes:
Packit Bot 06c835
Packit Bot 06c835
        %%      output a %
Packit Bot 06c835
        %.      output parameter as a character
Packit Bot 06c835
        %d      output parameter as a decimal number
Packit Bot 06c835
        %2      output parameter in printf format %02d
Packit Bot 06c835
        %3      output parameter in printf format %03d
Packit Bot 06c835
        %+x     add the character x to parameter and output it as a character
Packit Bot 06c835
(UW)    %-x     subtract parameter FROM the character x and output it as a char
Packit Bot 06c835
(UW)    %ax     add the character x to parameter
Packit Bot 06c835
(GNU)   %a[+*-/=][cp]x
Packit Bot 06c835
                GNU arithmetic.
Packit Bot 06c835
(UW)    %sx     subtract parameter FROM the character x
Packit Bot 06c835
        %>xy    if parameter > character x then add character y to parameter
Packit Bot 06c835
        %B      convert to BCD (parameter = (parameter/10)*16 + parameter%16)
Packit Bot 06c835
        %D      Delta Data encode (parameter = parameter - 2*(paramter%16))
Packit Bot 06c835
        %i      increment the first two parameters by one
Packit Bot 06c835
        %n      xor the first two parameters by 0140
Packit Bot 06c835
(GNU)   %m      xor the first two parameters by 0177
Packit Bot 06c835
        %r      swap the first two parameters
Packit Bot 06c835
(GNU)   %b      backup to previous parameter
Packit Bot 06c835
(GNU)   %f      skip this parameter
Packit Bot 06c835
Packit Bot 06c835
  Note the two definitions of %a, the GNU definition is used if the characters
Packit Bot 06c835
  after the 'a' are valid, otherwise the UW definition is used.
Packit Bot 06c835
Packit Bot 06c835
  (GNU) used by GNU Emacs termcap libraries
Packit Bot 06c835
  (UW) used by the University of Waterloo (MFCF) termcap libraries
Packit Bot 06c835
Packit Bot 06c835
*/
Packit Bot 06c835
Packit Bot 06c835
char *
Packit Bot 06c835
tparm (const char *str, ...)
Packit Bot 06c835
{
Packit Bot 06c835
  static int termcap;
Packit Bot 06c835
  static char OOPS[] = "OOPS";
Packit Bot 06c835
  static char buf[MAX_LINE];
Packit Bot 06c835
  const char *sp;
Packit Bot 06c835
  char *dp;
Packit Bot 06c835
  char *fmt;
Packit Bot 06c835
  char scan_for;
Packit Bot 06c835
  int scan_depth;
Packit Bot 06c835
  int if_depth;
Packit Bot 06c835
  char fmt_buf[MAX_LINE];
Packit Bot 06c835
  char sbuf[MAX_LINE];
Packit Bot 06c835
Packit Bot 06c835
  va_start (tparm_args, str);
Packit Bot 06c835
Packit Bot 06c835
  sp = str;
Packit Bot 06c835
  dp = buf;
Packit Bot 06c835
  scan_for = 0;
Packit Bot 06c835
  scan_depth = 0;
Packit Bot 06c835
  if_depth = 0;
Packit Bot 06c835
  argcnt = 0;
Packit Bot 06c835
  pos = 0;
Packit Bot 06c835
  termcap = 1;
Packit Bot 06c835
  while (*sp != '\0')
Packit Bot 06c835
    {
Packit Bot 06c835
      switch (*sp)
Packit Bot 06c835
        {
Packit Bot 06c835
        case '\\':
Packit Bot 06c835
          if (scan_for)
Packit Bot 06c835
            {
Packit Bot 06c835
              if (*++sp != '\0')
Packit Bot 06c835
                sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            }
Packit Bot 06c835
          *dp++ = *sp++;
Packit Bot 06c835
          if (*sp != '\0')
Packit Bot 06c835
            *dp++ = *sp++;
Packit Bot 06c835
          break;
Packit Bot 06c835
        case '%':
Packit Bot 06c835
          sp++;
Packit Bot 06c835
          if (scan_for)
Packit Bot 06c835
            {
Packit Bot 06c835
              if (*sp == scan_for && if_depth == scan_depth)
Packit Bot 06c835
                {
Packit Bot 06c835
                  if (scan_for == ';')
Packit Bot 06c835
                    if_depth--;
Packit Bot 06c835
                  scan_for = 0;
Packit Bot 06c835
                }
Packit Bot 06c835
              else if (*sp == '?')
Packit Bot 06c835
                if_depth++;
Packit Bot 06c835
              else if (*sp == ';')
Packit Bot 06c835
                {
Packit Bot 06c835
                  if (if_depth == 0)
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  else
Packit Bot 06c835
                    if_depth--;
Packit Bot 06c835
                }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            }
Packit Bot 06c835
          fmt = NULL;
Packit Bot 06c835
          switch (*sp)
Packit Bot 06c835
            {
Packit Bot 06c835
            case '%':
Packit Bot 06c835
              *dp++ = *sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '+':
Packit Bot 06c835
              if (!termcap)
Packit Bot 06c835
                {
Packit Bot 06c835
                  int i, j;
Packit Bot 06c835
                  if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  i += j;
Packit Bot 06c835
                  if (pushnum (i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  sp++;
Packit Bot 06c835
                  break;
Packit Bot 06c835
                }
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case 'C':
Packit Bot 06c835
              if (*sp == 'C')
Packit Bot 06c835
                {
Packit Bot 06c835
                  int i;
Packit Bot 06c835
                  if (getarg (termcap - 1, INTEGER, &i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  if (i >= 96)
Packit Bot 06c835
                    {
Packit Bot 06c835
                      i /= 96;
Packit Bot 06c835
                      if (i == '$')
Packit Bot 06c835
                        *dp++ = '\\';
Packit Bot 06c835
                      *dp++ = i;
Packit Bot 06c835
                    }
Packit Bot 06c835
                }
Packit Bot 06c835
              fmt = "%c";
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case 'a':
Packit Bot 06c835
              if (!termcap)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (getarg (termcap - 1, INTEGER, &i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                if (*++sp == '\0')
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                if ((sp[1] == 'p' || sp[1] == 'c')
Packit Bot 06c835
                    && sp[2] != '\0' && fmt == NULL)
Packit Bot 06c835
                  {
Packit Bot 06c835
                    /* GNU arithmetic parameter, what they really need is
Packit Bot 06c835
                       terminfo.  */
Packit Bot 06c835
                    int val;
Packit Bot 06c835
                    int lc;
Packit Bot 06c835
                    if (sp[1] == 'p'
Packit Bot 06c835
                        && getarg (termcap - 1 + sp[2] - '@', INTEGER, &val))
Packit Bot 06c835
                      return OOPS;
Packit Bot 06c835
                    if (sp[1] == 'c')
Packit Bot 06c835
                      {
Packit Bot 06c835
                        char c;
Packit Bot 06c835
                        lc = cvtchar (sp + 2, &c) + 2;
Packit Bot 06c835
                        /* Mask out 8th bit so \200 can be used for \0 as per
Packit Bot 06c835
                           GNU docs.  */
Packit Bot 06c835
                        val = c & 0177;
Packit Bot 06c835
                      }
Packit Bot 06c835
                    else
Packit Bot 06c835
                      lc = 2;
Packit Bot 06c835
                    switch (sp[0])
Packit Bot 06c835
                      {
Packit Bot 06c835
                      case '=':
Packit Bot 06c835
                        break;
Packit Bot 06c835
                      case '+':
Packit Bot 06c835
                        val = i + val;
Packit Bot 06c835
                        break;
Packit Bot 06c835
                      case '-':
Packit Bot 06c835
                        val = i - val;
Packit Bot 06c835
                        break;
Packit Bot 06c835
                      case '*':
Packit Bot 06c835
                        val = i * val;
Packit Bot 06c835
                        break;
Packit Bot 06c835
                      case '/':
Packit Bot 06c835
                        val = i / val;
Packit Bot 06c835
                        break;
Packit Bot 06c835
                      default:
Packit Bot 06c835
                        /* Not really GNU's %a after all... */
Packit Bot 06c835
                        {
Packit Bot 06c835
                          char c;
Packit Bot 06c835
                          lc = cvtchar (sp, &c);
Packit Bot 06c835
                          val = c + i;
Packit Bot 06c835
                        }
Packit Bot 06c835
                        break;
Packit Bot 06c835
                      }
Packit Bot 06c835
                    arg_list[termcap - 1].integer = val;
Packit Bot 06c835
                    sp += lc;
Packit Bot 06c835
                    break;
Packit Bot 06c835
                  }
Packit Bot 06c835
                {
Packit Bot 06c835
                  char c;
Packit Bot 06c835
                  sp += cvtchar (sp, &c);
Packit Bot 06c835
                  arg_list[termcap - 1].integer = c + i;
Packit Bot 06c835
                }
Packit Bot 06c835
              }
Packit Bot 06c835
              if (fmt == NULL)
Packit Bot 06c835
                break;
Packit Bot 06c835
              sp--;
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case '-':
Packit Bot 06c835
              if (!termcap)
Packit Bot 06c835
                {
Packit Bot 06c835
                  int i, j;
Packit Bot 06c835
                  if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  i -= j;
Packit Bot 06c835
                  if (pushnum (i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  sp++;
Packit Bot 06c835
                  break;
Packit Bot 06c835
                }
Packit Bot 06c835
              fmt = "%c";
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case 's':
Packit Bot 06c835
              if (termcap && (fmt == NULL || *sp == '-'))
Packit Bot 06c835
                {
Packit Bot 06c835
                  int i;
Packit Bot 06c835
                  if (getarg (termcap - 1, INTEGER, &i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  if (*++sp == '\0')
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  {
Packit Bot 06c835
                    char c;
Packit Bot 06c835
                    sp += cvtchar (sp, &c);
Packit Bot 06c835
                    arg_list[termcap - 1].integer = c - i;
Packit Bot 06c835
                  }
Packit Bot 06c835
                  if (fmt == NULL)
Packit Bot 06c835
                    break;
Packit Bot 06c835
                  sp--;
Packit Bot 06c835
                }
Packit Bot 06c835
              if (!termcap)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case '.':
Packit Bot 06c835
              if (termcap && fmt == NULL)
Packit Bot 06c835
                fmt = "%c";
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case 'd':
Packit Bot 06c835
              if (termcap && fmt == NULL)
Packit Bot 06c835
                fmt = "%d";
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case '2':
Packit Bot 06c835
              if (termcap && fmt == NULL)
Packit Bot 06c835
                fmt = "%02d";
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case '3':
Packit Bot 06c835
              if (termcap && fmt == NULL)
Packit Bot 06c835
                fmt = "%03d";
Packit Bot 06c835
              /* FALLTHROUGH */
Packit Bot 06c835
            case ':': case ' ': case '#': case 'u':
Packit Bot 06c835
            case 'x': case 'X': case 'o': case 'c':
Packit Bot 06c835
            case '0': case '1': case '4': case '5':
Packit Bot 06c835
            case '6': case '7': case '8': case '9':
Packit Bot 06c835
              if (fmt == NULL)
Packit Bot 06c835
                {
Packit Bot 06c835
                  if (termcap)
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  if (*sp == ':')
Packit Bot 06c835
                    sp++;
Packit Bot 06c835
                  fmt = fmt_buf;
Packit Bot 06c835
                  *fmt++ = '%';
Packit Bot 06c835
                  while (*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd'
Packit Bot 06c835
                         && *sp != 'o' && *sp != 'c' && *sp != 'u')
Packit Bot 06c835
                    {
Packit Bot 06c835
                      if (*sp == '\0')
Packit Bot 06c835
                        return OOPS;
Packit Bot 06c835
                      *fmt++ = *sp++;
Packit Bot 06c835
                    }
Packit Bot 06c835
                  *fmt++ = *sp;
Packit Bot 06c835
                  *fmt = '\0';
Packit Bot 06c835
                  fmt = fmt_buf;
Packit Bot 06c835
                }
Packit Bot 06c835
              {
Packit Bot 06c835
                char conv_char = fmt[strlen (fmt) - 1];
Packit Bot 06c835
                if (conv_char == 's')
Packit Bot 06c835
                  {
Packit Bot 06c835
                    char *s;
Packit Bot 06c835
                    if (popstring (&s))
Packit Bot 06c835
                      return OOPS;
Packit Bot 06c835
                    sprintf (sbuf, fmt, s);
Packit Bot 06c835
                  }
Packit Bot 06c835
                else
Packit Bot 06c835
                  {
Packit Bot 06c835
                    int i;
Packit Bot 06c835
                    if (termcap)
Packit Bot 06c835
                      {
Packit Bot 06c835
                        if (getarg (termcap++ - 1, INTEGER, &i))
Packit Bot 06c835
                          return OOPS;
Packit Bot 06c835
                      }
Packit Bot 06c835
                    else
Packit Bot 06c835
                      if (popnum (&i))
Packit Bot 06c835
                        return OOPS;
Packit Bot 06c835
                    if (i == 0 && conv_char == 'c')
Packit Bot 06c835
                      strcpy (sbuf, "\000");
Packit Bot 06c835
                    else
Packit Bot 06c835
                      sprintf (sbuf, fmt, i);
Packit Bot 06c835
                  }
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              fmt = sbuf;
Packit Bot 06c835
              while (*fmt != '\0')
Packit Bot 06c835
                {
Packit Bot 06c835
                  if (*fmt == '$')
Packit Bot 06c835
                    *dp++ = '\\';
Packit Bot 06c835
                  *dp++ = *fmt++;
Packit Bot 06c835
                }
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'r':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (!termcap || getarg (1, INTEGER, &i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                arg_list[1].integer = arg_list[0].integer;
Packit Bot 06c835
                arg_list[0].integer = i;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'i':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (getarg (1, INTEGER, &i) || arg_list[0].type != INTEGER)
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              arg_list[1].integer++;
Packit Bot 06c835
              arg_list[0].integer++;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'n':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (!termcap || getarg (1, INTEGER, &i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              arg_list[0].integer ^= 0140;
Packit Bot 06c835
              arg_list[1].integer ^= 0140;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '>':
Packit Bot 06c835
              if (!termcap)
Packit Bot 06c835
                {
Packit Bot 06c835
                  int i, j;
Packit Bot 06c835
                  if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  i = (i > j);
Packit Bot 06c835
                  if (pushnum (i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  sp++;
Packit Bot 06c835
                  break;
Packit Bot 06c835
                }
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (getarg (termcap-1, INTEGER, &i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                {
Packit Bot 06c835
                  char c;
Packit Bot 06c835
                  sp += cvtchar (sp, &c);
Packit Bot 06c835
                  if (i > c)
Packit Bot 06c835
                    {
Packit Bot 06c835
                      sp += cvtchar (sp, &c);
Packit Bot 06c835
                      arg_list[termcap-1].integer += c;
Packit Bot 06c835
                    }
Packit Bot 06c835
                  else
Packit Bot 06c835
                    sp += cvtchar (sp, &c);
Packit Bot 06c835
                }
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'B':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (!termcap || getarg (termcap-1, INTEGER, &i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                arg_list[termcap-1].integer = 16 * (i / 10) + i % 10;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'D':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (!termcap || getarg (termcap-1, INTEGER, &i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                arg_list[termcap-1].integer = i - 2 * (i % 16);
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'p':
Packit Bot 06c835
              if (termcap > 1)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              if (*++sp == '\0')
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              {
Packit Bot 06c835
                int i = (*sp == '0' ? 9 : *sp - '1');
Packit Bot 06c835
                if (i < 0 || i > 9)
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                if (pusharg (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              termcap = 0;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'P':
Packit Bot 06c835
              if (termcap || *++sp == '\0')
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              {
Packit Bot 06c835
                int i = *sp++ - 'a';
Packit Bot 06c835
                if (i < 0 || i > 25)
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                if (pos-- == 0)
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                switch (vars[i].type = S[pos].type)
Packit Bot 06c835
                  {
Packit Bot 06c835
                  case ARG:
Packit Bot 06c835
                    vars[i].argnum = S[pos].argnum;
Packit Bot 06c835
                    break;
Packit Bot 06c835
                  case NUM:
Packit Bot 06c835
                    vars[i].value = S[pos].value;
Packit Bot 06c835
                    break;
Packit Bot 06c835
                  }
Packit Bot 06c835
              }
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'g':
Packit Bot 06c835
              if (termcap || *++sp == '\0')
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              {
Packit Bot 06c835
                int i = *sp++ - 'a';
Packit Bot 06c835
                if (i < 0 || i > 25)
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                switch (vars[i].type)
Packit Bot 06c835
                  {
Packit Bot 06c835
                  case ARG:
Packit Bot 06c835
                    if (pusharg (vars[i].argnum))
Packit Bot 06c835
                      return OOPS;
Packit Bot 06c835
                    break;
Packit Bot 06c835
                  case NUM:
Packit Bot 06c835
                    if (pushnum (vars[i].value))
Packit Bot 06c835
                      return OOPS;
Packit Bot 06c835
                    break;
Packit Bot 06c835
                  }
Packit Bot 06c835
              }
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '\'':
Packit Bot 06c835
              if (termcap > 1)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              if (*++sp == '\0')
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              {
Packit Bot 06c835
                char c;
Packit Bot 06c835
                sp += cvtchar (sp, &c);
Packit Bot 06c835
                if (pushnum (c) || *sp++ != '\'')
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              termcap = 0;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '{':
Packit Bot 06c835
              if (termcap > 1)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                i = 0;
Packit Bot 06c835
                sp++;
Packit Bot 06c835
                while (c_isdigit (*sp))
Packit Bot 06c835
                  i = 10 * i + *sp++ - '0';
Packit Bot 06c835
                if (*sp++ != '}' || pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              termcap = 0;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'l':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                char *s;
Packit Bot 06c835
                if (termcap || popstring (&s))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = strlen (s);
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '*':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (termcap || popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i *= j;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '/':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (termcap || popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i /= j;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'm':
Packit Bot 06c835
              if (termcap)
Packit Bot 06c835
                {
Packit Bot 06c835
                  int i;
Packit Bot 06c835
                  if (getarg (1, INTEGER, &i))
Packit Bot 06c835
                    return OOPS;
Packit Bot 06c835
                  arg_list[0].integer ^= 0177;
Packit Bot 06c835
                  arg_list[1].integer ^= 0177;
Packit Bot 06c835
                  sp++;
Packit Bot 06c835
                  break;
Packit Bot 06c835
                }
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i %= j;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '&':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i &= j;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '|':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i |= j;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '^':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i ^= j;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '=':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = (i == j);
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '<':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = (i < j);
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'A':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = (i && j);
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'O':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i, j;
Packit Bot 06c835
                if (popnum (&j) || popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = (i || j);
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '!':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = !i;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '~':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (popnum (&i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                i = ~i;
Packit Bot 06c835
                if (pushnum (i))
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case '?':
Packit Bot 06c835
              if (termcap > 1)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              termcap = 0;
Packit Bot 06c835
              if_depth++;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 't':
Packit Bot 06c835
              {
Packit Bot 06c835
                int i;
Packit Bot 06c835
                if (popnum (&i) || if_depth == 0)
Packit Bot 06c835
                  return OOPS;
Packit Bot 06c835
                if (!i)
Packit Bot 06c835
                  {
Packit Bot 06c835
                    scan_for = 'e';
Packit Bot 06c835
                    scan_depth = if_depth;
Packit Bot 06c835
                  }
Packit Bot 06c835
              }
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'e':
Packit Bot 06c835
              if (if_depth == 0)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              scan_for = ';';
Packit Bot 06c835
              scan_depth = if_depth;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case ';':
Packit Bot 06c835
              if (if_depth-- == 0)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'b':
Packit Bot 06c835
              if (--termcap < 1)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            case 'f':
Packit Bot 06c835
              if (!termcap++)
Packit Bot 06c835
                return OOPS;
Packit Bot 06c835
              sp++;
Packit Bot 06c835
              break;
Packit Bot 06c835
            }
Packit Bot 06c835
          break;
Packit Bot 06c835
        default:
Packit Bot 06c835
          if (scan_for)
Packit Bot 06c835
            sp++;
Packit Bot 06c835
          else
Packit Bot 06c835
            *dp++ = *sp++;
Packit Bot 06c835
          break;
Packit Bot 06c835
        }
Packit Bot 06c835
    }
Packit Bot 06c835
  va_end (tparm_args);
Packit Bot 06c835
  *dp = '\0';
Packit Bot 06c835
  return buf;
Packit Bot 06c835
}