remove curses terminal and ncurses macro

This commit is contained in:
ailin-nemui 2016-03-30 10:14:57 +02:00
commit 9ee4803770
10 changed files with 20 additions and 1576 deletions

View file

@ -4,8 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core/ \
-I$(top_srcdir)/src/fe-common/core/ \
$(GLIB_CFLAGS) \
$(CURSES_INCLUDEDIR)
$(GLIB_CFLAGS)
irssi_DEPENDENCIES = \
@COMMON_LIBS@ \
@ -22,25 +21,11 @@ irssi_LDADD = \
@PROG_LIBS@ \
@TEXTUI_LIBS@
tparm_sources = \
tparm.c
terminfo_sources = \
term-terminfo.c \
terminfo-core.c
curses_sources = \
term-curses.c
if NEED_TPARM
use_tparm_sources = $(tparm_sources)
endif
if USE_CURSES
use_term_sources = $(curses_sources)
else
use_term_sources = $(terminfo_sources)
endif
irssi_SOURCES = \
gui-entry.c \
@ -57,7 +42,6 @@ irssi_SOURCES = \
statusbar-items.c \
term.c \
term-dummy.c \
$(use_tparm_sources) \
$(use_term_sources) \
textbuffer.c \
textbuffer-commands.c \
@ -85,6 +69,4 @@ noinst_HEADERS = \
module-formats.h
EXTRA_DIST = \
$(tparm_sources) \
$(terminfo_sources) \
$(curses_sources)
$(terminfo_sources)

View file

@ -1,415 +0,0 @@
/*
term-curses.c : irssi
Copyright (C) 1999-2001 Timo Sirainen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "module.h"
#include "signals.h"
#include "settings.h"
#include "term.h"
#include "mainwindows.h"
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
# include <ncurses.h>
#else
# include <curses.h>
#endif
#include <termios.h>
#include <signal.h>
#ifndef COLOR_PAIRS
# define COLOR_PAIRS 64
#endif
#if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM)
# define USE_RESIZE_TERM
#endif
#ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE 0
#endif
struct _TERM_WINDOW {
int x, y;
int width, height;
WINDOW *win;
};
TERM_WINDOW *root_window;
static int curs_x, curs_y;
static int freeze_refresh;
static struct termios old_tio;
static int init_curses(void)
{
char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
int num;
struct termios tio;
if (!initscr())
return FALSE;
cbreak(); noecho(); idlok(stdscr, 1);
#ifdef HAVE_CURSES_IDCOK
/*idcok(stdscr, 1); - disabled currently, causes redrawing problems with NetBSD */
#endif
intrflush(stdscr, FALSE); nodelay(stdscr, TRUE);
/* Disable INTR, QUIT, VDSUSP and SUSP keys */
if (tcgetattr(0, &old_tio) == 0) {
memcpy(&tio, &old_tio, sizeof(tio));
tio.c_cc[VINTR] = _POSIX_VDISABLE;
tio.c_cc[VQUIT] = _POSIX_VDISABLE;
#ifdef VDSUSP
tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
#endif
#ifdef VSUSP
tio.c_cc[VSUSP] = _POSIX_VDISABLE;
#endif
tcsetattr(0, TCSADRAIN, &tio);
}
if (has_colors())
start_color();
else if (term_use_colors)
term_use_colors = FALSE;
#ifdef HAVE_NCURSES_USE_DEFAULT_COLORS
/* this lets us to use the "default" background color for colors <= 7 so
background pixmaps etc. show up right */
use_default_colors();
for (num = 1; num < COLOR_PAIRS; num++)
init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]);
init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more
people want dark grey than white on white.. */
#else
for (num = 1; num < COLOR_PAIRS; num++)
init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]);
init_pair(63, 0, 0);
#endif
clear();
return TRUE;
}
static int term_init_int(void)
{
int ret;
ret = init_curses();
if (!ret) return 0;
curs_x = curs_y = 0;
freeze_refresh = 0;
root_window = g_new0(TERM_WINDOW, 1);
root_window->win = stdscr;
term_width = COLS;
term_height = LINES;
return ret;
}
static void term_deinit_int(void)
{
tcsetattr(0, TCSADRAIN, &old_tio);
endwin();
g_free_and_null(root_window);
}
int term_init(void)
{
if (!term_init_int())
return FALSE;
settings_add_int("lookandfeel", "default_color", 7);
term_common_init();
return TRUE;
}
void term_deinit(void)
{
term_common_deinit();
term_deinit_int();
}
/* Resize terminal - if width or height is negative,
the new size is unknown and should be figured out somehow */
void term_resize(int width, int height)
{
#ifdef HAVE_CURSES_RESIZETERM
if (width < 0 || height < 0) {
#endif
term_deinit_int();
term_init_int();
#ifdef HAVE_CURSES_RESIZETERM
} else if (term_width != width || term_height != height) {
term_width = width;
term_height = height;
resizeterm(term_height, term_width);
}
#endif
}
void term_resize_final(int width, int height)
{
#ifdef HAVE_CURSES_RESIZETERM
if (width < 0 || height < 0)
mainwindows_recreate();
#else
mainwindows_recreate();
#endif
}
/* Returns TRUE if terminal has colors */
int term_has_colors(void)
{
return has_colors();
}
/* Force the colors on any way you can */
void term_force_colors(int set)
{
/* don't do anything with curses */
}
/* Clear screen */
void term_clear(void)
{
term_set_color(root_window, 0);
clear();
}
/* Beep */
void term_beep(void)
{
beep();
}
/* Create a new window in terminal */
TERM_WINDOW *term_window_create(int x, int y, int width, int height)
{
TERM_WINDOW *window;
window = g_new0(TERM_WINDOW, 1);
window->x = x; window->y = y;
window->width = width; window->height = height;
window->win = newwin(height, width, y, x);
if (window->win == NULL)
g_error("newwin() failed: %d,%d %d,%d", x, y, width, height);
idlok(window->win, 1);
return window;
}
/* Destroy a terminal window */
void term_window_destroy(TERM_WINDOW *window)
{
delwin(window->win);
g_free(window);
}
/* Move/resize a window */
void term_window_move(TERM_WINDOW *window, int x, int y,
int width, int height)
{
/* some checks to make sure the window is visible in screen,
otherwise curses could get nasty and not show our window anymore. */
if (width < 1) width = 1;
if (height < 1) height = 1;
if (x+width > term_width) x = term_width-width;
if (y+height > term_height) y = term_height-height;
#ifdef HAVE_CURSES_WRESIZE
if (window->width != width || window->height != height)
wresize(window->win, height, width);
if (window->x != x || window->y != y)
mvwin(window->win, y, x);
#else
if (window->width != width || window->height != height ||
window->x != x || window->y != y) {
delwin(window->win);
window->win = newwin(height, width, y, x);
idlok(window->win, 1);
}
#endif
window->x = x; window->y = y;
window->width = width; window->height = height;
}
/* Clear window */
void term_window_clear(TERM_WINDOW *window)
{
werase(window->win);
}
/* Scroll window up/down */
void term_window_scroll(TERM_WINDOW *window, int count)
{
scrollok(window->win, TRUE);
wscrl(window->win, count);
scrollok(window->win, FALSE);
}
static int get_attr(int color)
{
int attr;
if ((color & FG_MASK) >> 4)
color = (color & ~FG_MASK) | term_color256map[color & FG_MASK];
if ((color & BG_MASK) >> (BG_SHIFT + 4))
color = (color & ~BG_MASK) | (term_color256map[(color & BG_MASK) >> BG_SHIFT] << BG_SHIFT);
if (!term_use_colors)
attr = (color & (0x7 << BG_SHIFT)) ? A_REVERSE : 0;
else if ((color & ((0xf << BG_SHIFT) | 0xf)) == 8 || (color & (FG_MASK | BG_MASK | ATTR_RESETFG)) == 0)
attr = COLOR_PAIR(63);
else if ((color & ((0x7 << BG_SHIFT) | 0x7)) == 0)
attr = A_NORMAL;
else {
if (color & ATTR_RESETFG) {
color &= ~FG_MASK;
color |= settings_get_int("default_color");
}
attr = COLOR_PAIR((color&0x7) | ((color&(0x7<<BG_SHIFT))>>BG_SHIFT<<3));
}
if ((color & 0x8) || (color & ATTR_BOLD)) attr |= A_BOLD;
if (color & ATTR_BLINK) attr |= A_BLINK;
if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE;
if (color & ATTR_REVERSE) attr |= A_REVERSE;
#ifdef A_ITALIC
if (color & ATTR_ITALIC) attr |= A_ITALIC;
#endif
return attr;
}
/* Change active color */
void term_set_color(TERM_WINDOW *window, int col)
{
wattrset(window->win, get_attr(col));
wbkgdset(window->win, ' ' | get_attr(col));
}
void term_move(TERM_WINDOW *window, int x, int y)
{
wmove(window->win, y, x);
}
void term_addch(TERM_WINDOW *window, char chr)
{
waddch(window->win, chr);
}
void term_add_unichar(TERM_WINDOW *window, unichar chr)
{
#ifdef WIDEC_CURSES
cchar_t wch;
wchar_t temp[2];
temp[0] = chr;
temp[1] = 0;
if (setcchar(&wch, temp, A_NORMAL, 0, NULL) == OK)
wadd_wch(window->win, &wch);
else
#endif
waddch(window->win, chr);
}
void term_addstr(TERM_WINDOW *window, const char *str)
{
waddstr(window->win, (const char *) str);
}
void term_clrtoeol(TERM_WINDOW *window)
{
wclrtoeol(window->win);
}
void term_move_cursor(int x, int y)
{
curs_x = x;
curs_y = y;
}
void term_refresh_freeze(void)
{
freeze_refresh++;
}
void term_refresh_thaw(void)
{
if (freeze_refresh > 0) {
freeze_refresh--;
if (freeze_refresh == 0) term_refresh(NULL);
}
}
void term_refresh(TERM_WINDOW *window)
{
if (window != NULL)
wnoutrefresh(window->win);
if (freeze_refresh == 0) {
move(curs_y, curs_x);
wnoutrefresh(stdscr);
doupdate();
}
}
void term_stop(void)
{
term_deinit_int();
kill(getpid(), SIGTSTP);
term_init_int();
irssi_redraw();
}
void term_set_input_type(int type)
{
}
void term_gets(GArray *buffer, int *line_count)
{
#ifdef WIDEC_CURSES
wint_t key;
#else
int key;
#endif
for (;;) {
#ifdef WIDEC_CURSES
if (get_wch(&key) == ERR)
#else
if ((key = getch()) == ERR)
#endif
break;
#ifdef KEY_RESIZE
if (key == KEY_RESIZE)
continue;
#endif
g_array_append_val(buffer, key);
if (key == '\r' || key == '\n')
(*line_count)++;
}
}

View file

@ -17,7 +17,6 @@ inline static int term_putchar(int c)
char *tparm();
int tputs();
#ifdef HAVE_TERMINFO
int setupterm();
char *tigetstr();
int tigetnum();
@ -25,15 +24,6 @@ int tigetflag();
#define term_getstr(x, buffer) tigetstr(x.ti_name)
#define term_getnum(x) tigetnum(x.ti_name);
#define term_getflag(x) tigetflag(x.ti_name);
#else
int tgetent();
char *tgetstr();
int tgetnum();
int tgetflag();
#define term_getstr(x, buffer) tgetstr(x.tc_name, &buffer)
#define term_getnum(x) tgetnum(x.tc_name)
#define term_getflag(x) tgetflag(x.tc_name)
#endif
#define CAP_TYPE_FLAG 0
#define CAP_TYPE_INT 1
@ -415,9 +405,6 @@ static void term_fill_capabilities(TERM_REC *term)
char *sval;
void *ptr;
#ifndef HAVE_TERMINFO
char *tptr = term->buffer2;
#endif
for (i = 0; i < sizeof(tcaps)/sizeof(tcaps[0]); i++) {
ptr = G_STRUCT_MEMBER_P(term, tcaps[i].offset);
@ -583,9 +570,7 @@ void terminfo_stop(TERM_REC *term)
static int term_setup(TERM_REC *term)
{
GString *str;
#ifdef HAVE_TERMINFO
int err;
#endif
char *term_env;
term_env = getenv("TERM");
@ -594,18 +579,10 @@ static int term_setup(TERM_REC *term)
return 0;
}
#ifdef HAVE_TERMINFO
if (setupterm(term_env, 1, &err) != 0) {
fprintf(stderr, "setupterm() failed for TERM=%s: %d\n", term_env, err);
return 0;
}
#else
if (tgetent(term->buffer1, term_env) < 1)
{
fprintf(stderr, "Termcap not found for TERM=%s\n", term_env);
return 0;
}
#endif
term_fill_capabilities(term);

View file

@ -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;
}