summaryrefslogtreecommitdiff
path: root/src/fe-text/tparm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-text/tparm.c')
-rw-r--r--src/fe-text/tparm.c740
1 files changed, 0 insertions, 740 deletions
diff --git a/src/fe-text/tparm.c b/src/fe-text/tparm.c
deleted file mode 100644
index 97c790da..00000000
--- a/src/fe-text/tparm.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * tparm.c
- *
- * By Ross Ridge
- * Public Domain
- * 92/02/01 07:30:36
- *
- */
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef MAX_PUSHED
-#define MAX_PUSHED 32
-#endif
-
-#define ARG 1
-#define NUM 2
-
-#define INTEGER 1
-#define STRING 2
-
-#define MAX_LINE 640
-
-typedef void* anyptr;
-
-typedef struct stack_str {
- int type;
- int argnum;
- int value;
-} stack;
-
-static stack S[MAX_PUSHED];
-static stack vars['z'-'a'+1];
-static int pos = 0;
-
-static struct arg_str {
- int type;
- int integer;
- char *string;
-} arg_list[10];
-
-static int argcnt;
-
-static va_list tparm_args;
-
-static int pusharg(int arg)
-{
- if (pos == MAX_PUSHED)
- return 1;
- S[pos].type = ARG;
- S[pos++].argnum = arg;
- return 0;
-}
-
-static int pushnum(int num)
-{
- if (pos == MAX_PUSHED)
- return 1;
- S[pos].type = NUM;
- S[pos++].value = num;
- return 0;
-}
-
-/* VARARGS2 */
-static int getarg(int argnum, int type, anyptr p)
-{
- while (argcnt < argnum) {
- arg_list[argcnt].type = INTEGER;
- arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
- }
- if (argcnt > argnum) {
- if (arg_list[argnum].type != type)
- return 1;
- else if (type == STRING)
- *(char **)p = arg_list[argnum].string;
- else
- *(int *)p = arg_list[argnum].integer;
- } else {
- arg_list[argcnt].type = type;
- if (type == STRING)
- *(char **)p = arg_list[argcnt++].string
- = (char *) va_arg(tparm_args, char *);
- else
- *(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
- }
- return 0;
-}
-
-
-static int popstring(char **str)
-{
- if (pos-- == 0)
- return 1;
- if (S[pos].type != ARG)
- return 1;
- return(getarg(S[pos].argnum, STRING, (anyptr) str));
-}
-
-static int popnum(int *num)
-{
- if (pos-- == 0)
- return 1;
- switch (S[pos].type) {
- case ARG:
- return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
- case NUM:
- *num = S[pos].value;
- return 0;
- }
- return 1;
-}
-
-static int cvtchar(const char *sp, char *c)
-{
- switch(*sp) {
- case '\\':
- switch(*++sp) {
- case '\'':
- case '$':
- case '\\':
- case '%':
- *c = *sp;
- return 2;
- case '\0':
- *c = '\\';
- return 1;
- case '0':
- if (sp[1] == '0' && sp[2] == '0') {
- *c = '\0';
- return 4;
- }
- *c = '\200'; /* '\0' ???? */
- return 2;
- default:
- *c = *sp;
- return 2;
- }
- default:
- *c = *sp;
- return 1;
- }
-}
-
-static int termcap;
-
-/* sigh... this has got to be the ugliest code I've ever written.
- Trying to handle everything has its cost, I guess.
-
- It actually isn't to hard to figure out if a given % code is supposed
- to be interpeted with its termcap or terminfo meaning since almost
- all terminfo codes are invalid unless something has been pushed on
- the stack and termcap strings will never push things on the stack
- (%p isn't used by termcap). So where we have a choice we make the
- decision by whether or not somthing has been pushed on the stack.
- The static variable termcap keeps track of this; it starts out set
- to 1 and is incremented as each argument processed by a termcap % code,
- however if something is pushed on the stack it's set to 0 and the
- rest of the % codes are interpeted as terminfo % codes. Another way
- of putting it is that if termcap equals one we haven't decided either
- way yet, if it equals zero we're looking for terminfo codes, and if
- its greater than 1 we're looking for termcap codes.
-
- Terminfo % codes:
-
- %% output a '%'
- %[[:][-+# ][width][.precision]][doxXs]
- output pop according to the printf format
- %c output pop as a char
- %'c' push character constant c.
- %{n} push decimal constant n.
- %p[1-9] push parameter [1-9]
- %g[a-z] push variable [a-z]
- %P[a-z] put pop in variable [a-z]
- %l push the length of pop (a string)
- %+ add pop to pop and push the result
- %- subtract pop from pop and push the result
- %* multiply pop and pop and push the result
- %& bitwise and pop and pop and push the result
- %| bitwise or pop and pop and push the result
- %^ bitwise xor pop and pop and push the result
- %~ push the bitwise not of pop
- %= compare if pop and pop are equal and push the result
- %> compare if pop is less than pop and push the result
- %< compare if pop is greater than pop and push the result
- %A logical and pop and pop and push the result
- %O logical or pop and pop and push the result
- %! push the logical not of pop
- %? condition %t if_true [%e if_false] %;
- if condition evaulates as true then evaluate if_true,
- else evaluate if_false. elseif's can be done:
-%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
- %i add one to parameters 1 and 2. (ANSI)
-
- Termcap Codes:
-
- %% output a %
- %. output parameter as a character
- %d output parameter as a decimal number
- %2 output parameter in printf format %02d
- %3 output parameter in printf format %03d
- %+x add the character x to parameter and output it as a character
-(UW) %-x subtract parameter FROM the character x and output it as a char
-(UW) %ax add the character x to parameter
-(GNU) %a[+*-/=][cp]x
- GNU arithmetic.
-(UW) %sx subtract parameter FROM the character x
- %>xy if parameter > character x then add character y to parameter
- %B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
- %D Delta Data encode (parameter = parameter - 2*(parameter%16))
- %i increment the first two parameters by one
- %n xor the first two parameters by 0140
-(GNU) %m xor the first two parameters by 0177
- %r swap the first two parameters
-(GNU) %b backup to previous parameter
-(GNU) %f skip this parameter
-
- Note the two definitions of %a, the GNU definition is used if the characters
- after the 'a' are valid, otherwise the UW definition is used.
-
- (GNU) used by GNU Emacs termcap libraries
- (UW) used by the University of Waterloo (MFCF) termcap libraries
-
-*/
-
-char *tparm(const char *str, ...) {
- static char OOPS[] = "OOPS";
- static char buf[MAX_LINE];
- register const char *sp;
- register char *dp;
- register char *fmt;
- char conv_char;
- char scan_for;
- int scan_depth = 0, if_depth;
- static int i, j;
- static char *s, c;
- char fmt_buf[MAX_LINE];
- char sbuf[MAX_LINE];
-
- va_start(tparm_args, str);
-
- sp = str;
- dp = buf;
- scan_for = 0;
- if_depth = 0;
- argcnt = 0;
- pos = 0;
- termcap = 1;
- while (*sp != '\0') {
- switch(*sp) {
- case '\\':
- if (scan_for) {
- if (*++sp != '\0')
- sp++;
- break;
- }
- *dp++ = *sp++;
- if (*sp != '\0')
- *dp++ = *sp++;
- break;
- case '%':
- sp++;
- if (scan_for) {
- if (*sp == scan_for && if_depth == scan_depth) {
- if (scan_for == ';')
- if_depth--;
- scan_for = 0;
- } else if (*sp == '?')
- if_depth++;
- else if (*sp == ';') {
- if (if_depth == 0)
- return OOPS;
- else
- if_depth--;
- }
- sp++;
- break;
- }
- fmt = NULL;
- switch(*sp) {
- case '%':
- *dp++ = *sp++;
- break;
- case '+':
- if (!termcap) {
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i += j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- }
- ;/* FALLTHROUGH */
- case 'C':
- if (*sp == 'C') {
- if (getarg(termcap - 1, INTEGER, &i))
- return OOPS;
- if (i >= 96) {
- i /= 96;
- if (i == '$')
- *dp++ = '\\';
- *dp++ = i;
- }
- }
- fmt = "%c";
- /* FALLTHROUGH */
- case 'a':
- if (!termcap)
- return OOPS;
- if (getarg(termcap - 1, INTEGER, (anyptr) &i))
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- if ((sp[1] == 'p' || sp[1] == 'c')
- && sp[2] != '\0' && fmt == NULL) {
- /* GNU aritmitic parameter, what they
- really need is terminfo. */
- int val, lc;
- if (sp[1] == 'p'
- && getarg(termcap - 1 + sp[2] - '@',
- INTEGER, (anyptr) &val))
- return OOPS;
- if (sp[1] == 'c') {
- lc = cvtchar(sp + 2, &c) + 2;
- /* Mask out 8th bit so \200 can be
- used for \0 as per GNU doc's */
- val = c & 0177;
- } else
- lc = 2;
- switch(sp[0]) {
- case '=':
- break;
- case '+':
- val = i + val;
- break;
- case '-':
- val = i - val;
- break;
- case '*':
- val = i * val;
- break;
- case '/':
- val = i / val;
- break;
- default:
- /* Not really GNU's %a after all... */
- lc = cvtchar(sp, &c);
- val = c + i;
- break;
- }
- arg_list[termcap - 1].integer = val;
- sp += lc;
- break;
- }
- sp += cvtchar(sp, &c);
- arg_list[termcap - 1].integer = c + i;
- if (fmt == NULL)
- break;
- sp--;
- /* FALLTHROUGH */
- case '-':
- if (!termcap) {
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i -= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- }
- fmt = "%c";
- /* FALLTHROUGH */
- case 's':
- if (termcap && (fmt == NULL || *sp == '-')) {
- if (getarg(termcap - 1, INTEGER, &i))
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- sp += cvtchar(sp, &c);
- arg_list[termcap - 1].integer = c - i;
- if (fmt == NULL)
- break;
- sp--;
- }
- if (!termcap)
- return OOPS;
- ;/* FALLTHROUGH */
- case '.':
- if (termcap && fmt == NULL)
- fmt = "%c";
- ;/* FALLTHROUGH */
- case 'd':
- if (termcap && fmt == NULL)
- fmt = "%d";
- ;/* FALLTHROUGH */
- case '2':
- if (termcap && fmt == NULL)
- fmt = "%02d";
- ;/* FALLTHROUGH */
- case '3':
- if (termcap && fmt == NULL)
- fmt = "%03d";
- ;/* FALLTHROUGH */
- case ':': case ' ': case '#': case 'u':
- case 'x': case 'X': case 'o': case 'c':
- case '0': case '1': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (fmt == NULL) {
- if (termcap)
- return OOPS;
- if (*sp == ':')
- sp++;
- fmt = fmt_buf;
- *fmt++ = '%';
- while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
- if (*sp == '\0')
- return OOPS;
- *fmt++ = *sp++;
- }
- *fmt++ = *sp;
- *fmt = '\0';
- fmt = fmt_buf;
- }
- conv_char = fmt[strlen(fmt) - 1];
- if (conv_char == 's') {
- if (popstring(&s))
- return OOPS;
- sprintf(sbuf, fmt, s);
- } else {
- if (termcap) {
- if (getarg(termcap++ - 1,
- INTEGER, &i))
- return OOPS;
- } else
- if (popnum(&i))
- return OOPS;
- if (i == 0 && conv_char == 'c')
- *sbuf = 0;
- else
- sprintf(sbuf, fmt, i);
- }
- sp++;
- fmt = sbuf;
- while(*fmt != '\0') {
- if (*fmt == '$')
- *dp++ = '\\';
- *dp++ = *fmt++;
- }
- break;
- case 'r':
- if (!termcap || getarg(1, INTEGER, &i))
- return OOPS;
- arg_list[1].integer = arg_list[0].integer;
- arg_list[0].integer = i;
- sp++;
- break;
- case 'i':
- if (getarg(1, INTEGER, &i)
- || arg_list[0].type != INTEGER)
- return OOPS;
- arg_list[1].integer++;
- arg_list[0].integer++;
- sp++;
- break;
- case 'n':
- if (!termcap || getarg(1, INTEGER, &i))
- return OOPS;
- arg_list[0].integer ^= 0140;
- arg_list[1].integer ^= 0140;
- sp++;
- break;
- case '>':
- if (!termcap) {
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i > j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- }
- if (getarg(termcap-1, INTEGER, &i))
- return OOPS;
- sp += cvtchar(sp, &c);
- if (i > c) {
- sp += cvtchar(sp, &c);
- arg_list[termcap-1].integer += c;
- } else
- sp += cvtchar(sp, &c);
- sp++;
- break;
- case 'B':
- if (!termcap || getarg(termcap-1, INTEGER, &i))
- return OOPS;
- arg_list[termcap-1].integer = 16*(i/10)+i%10;
- sp++;
- break;
- case 'D':
- if (!termcap || getarg(termcap-1, INTEGER, &i))
- return OOPS;
- arg_list[termcap-1].integer = i - 2 * (i % 16);
- sp++;
- break;
- case 'p':
- if (termcap > 1)
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- if (*sp == '0')
- i = 9;
- else
- i = *sp - '1';
- if (i < 0 || i > 9)
- return OOPS;
- if (pusharg(i))
- return OOPS;
- termcap = 0;
- sp++;
- break;
- case 'P':
- if (termcap || *++sp == '\0')
- return OOPS;
- i = *sp++ - 'a';
- if (i < 0 || i > 25)
- return OOPS;
- if (pos-- == 0)
- return OOPS;
- switch(vars[i].type = S[pos].type) {
- case ARG:
- vars[i].argnum = S[pos].argnum;
- break;
- case NUM:
- vars[i].value = S[pos].value;
- break;
- }
- break;
- case 'g':
- if (termcap || *++sp == '\0')
- return OOPS;
- i = *sp++ - 'a';
- if (i < 0 || i > 25)
- return OOPS;
- switch(vars[i].type) {
- case ARG:
- if (pusharg(vars[i].argnum))
- return OOPS;
- break;
- case NUM:
- if (pushnum(vars[i].value))
- return OOPS;
- break;
- }
- break;
- case '\'':
- if (termcap > 1)
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- sp += cvtchar(sp, &c);
- if (pushnum(c) || *sp++ != '\'')
- return OOPS;
- termcap = 0;
- break;
- case '{':
- if (termcap > 1)
- return OOPS;
- i = 0;
- sp++;
- while(isdigit((int) (unsigned char) *sp))
- i = 10 * i + *sp++ - '0';
- if (*sp++ != '}' || pushnum(i))
- return OOPS;
- termcap = 0;
- break;
- case 'l':
- if (termcap || popstring(&s))
- return OOPS;
- i = strlen(s);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '*':
- if (termcap || popnum(&j) || popnum(&i))
- return OOPS;
- i *= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '/':
- if (termcap || popnum(&j) || popnum(&i))
- return OOPS;
- i /= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case 'm':
- if (termcap) {
- if (getarg(1, INTEGER, &i))
- return OOPS;
- arg_list[0].integer ^= 0177;
- arg_list[1].integer ^= 0177;
- sp++;
- break;
- }
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i %= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '&':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i &= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '|':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i |= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '^':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i ^= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '=':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i == j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '<':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i < j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case 'A':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i && j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case 'O':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i || j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '!':
- if (popnum(&i))
- return OOPS;
- i = !i;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '~':
- if (popnum(&i))
- return OOPS;
- i = ~i;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '?':
- if (termcap > 1)
- return OOPS;
- termcap = 0;
- if_depth++;
- sp++;
- break;
- case 't':
- if (popnum(&i) || if_depth == 0)
- return OOPS;
- if (!i) {
- scan_for = 'e';
- scan_depth = if_depth;
- }
- sp++;
- break;
- case 'e':
- if (if_depth == 0)
- return OOPS;
- scan_for = ';';
- scan_depth = if_depth;
- sp++;
- break;
- case ';':
- if (if_depth-- == 0)
- return OOPS;
- sp++;
- break;
- case 'b':
- if (--termcap < 1)
- return OOPS;
- sp++;
- break;
- case 'f':
- if (!termcap++)
- return OOPS;
- sp++;
- break;
- }
- break;
- default:
- if (scan_for)
- sp++;
- else
- *dp++ = *sp++;
- break;
- }
- }
- va_end(tparm_args);
- *dp = '\0';
- return buf;
-}