Lose intermediate handling (unused). Change argument parsing to work properly over multiple buffers by saving a copy of the argument (we can't just save off/len since the buffer may vanish at any point).

pull/1/head
Nicholas Marriott 2007-09-29 14:25:49 +00:00
parent 653ee721df
commit 1e316cfc7c
5 changed files with 84 additions and 68 deletions

111
input.c
View File

@ -1,4 +1,4 @@
/* $Id: input.c,v 1.10 2007-09-29 10:57:39 nicm Exp $ */
/* $Id: input.c,v 1.11 2007-09-29 14:25:49 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -45,6 +45,8 @@ struct {
enum input_class input_lookup_class(u_char);
int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t);
int input_new_argument(struct input_ctx *);
int input_add_argument(struct input_ctx *, u_char ch);
void *input_state_first(u_char, enum input_class, struct input_ctx *);
void *input_state_escape(u_char, enum input_class, struct input_ctx *);
@ -101,11 +103,39 @@ input_lookup_class(u_char ch)
return (iclass);
}
int
input_new_argument(struct input_ctx *ictx)
{
struct input_arg *arg;
ARRAY_EXPAND(&ictx->args, 1);
arg = &ARRAY_LAST(&ictx->args);
arg->used = 0;
return (0);
}
int
input_add_argument(struct input_ctx *ictx, u_char ch)
{
struct input_arg *arg;
if (ARRAY_LENGTH(&ictx->args) == 0)
return (0);
arg = &ARRAY_LAST(&ictx->args);
if (arg->used > (sizeof arg->data) - 1)
return (-1);
arg->data[arg->used++] = ch;
return (0);
}
int
input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d)
{
struct input_arg *arg;
char tmp[64];
const char *errstr;
*n = d;
@ -113,15 +143,10 @@ input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d)
return (0);
arg = &ARRAY_ITEM(&ictx->args, i);
if (arg->len == 0)
if (*arg->data == '\0')
return (0);
if (arg->len > sizeof tmp - 1)
return (-1);
memcpy(tmp, ictx->buf + arg->off, arg->len);
tmp[arg->len] = '\0';
*n = strtonum(tmp, 0, UINT16_MAX, &errstr);
*n = strtonum(arg->data, 0, UINT16_MAX, &errstr);
if (errstr != NULL)
return (-1);
return (0);
@ -132,9 +157,6 @@ input_init(struct input_ctx *ictx, struct screen *s)
{
ictx->s = s;
ictx->intoff = 0;
ictx->intlen = 0;
ARRAY_INIT(&ictx->args);
ictx->state = input_state_first;
@ -225,8 +247,6 @@ input_state_escape(u_char ch, enum input_class iclass, struct input_ctx *ictx)
return (input_state_escape);
case INPUT_SPACE:
case INPUT_INTERMEDIATE:
ictx->intoff = ictx->off;
ictx->intlen = 1;
return (input_state_intermediate);
case INPUT_PARAMETER:
input_handle_private_two(ch, ictx);
@ -255,7 +275,6 @@ input_state_intermediate(
switch (iclass) {
case INPUT_SPACE:
case INPUT_INTERMEDIATE:
ictx->intlen++;
return (input_state_intermediate);
case INPUT_PARAMETER:
input_handle_private_two(ch, ictx);
@ -279,31 +298,30 @@ input_state_sequence_first(
u_char ch, enum input_class iclass, struct input_ctx *ictx)
{
ictx->private = '\0';
ARRAY_CLEAR(&ictx->args);
switch (iclass) {
case INPUT_PARAMETER:
if (ch >= 0x3c && ch <= 0x3f) {
/* Private control sequence. */
ictx->private = ch;
ictx->saved = ictx->off;
return (input_state_sequence_next);
}
input_new_argument(ictx);
break;
case INPUT_C0CONTROL:
case INPUT_C1CONTROL:
case INPUT_SPACE:
case INPUT_INTERMEDIATE:
case INPUT_UPPERCASE:
case INPUT_LOWERCASE:
case INPUT_C0CONTROL:
case INPUT_C1CONTROL:
case INPUT_DELETE:
case INPUT_G1DISPLAYABLE:
case INPUT_SPECIAL:
break;
}
/* Pass this character to next state directly. */
ictx->saved = ictx->off - 1;
/* Pass character on directly. */
return (input_state_sequence_next(ch, iclass, ictx));
}
@ -311,39 +329,26 @@ void *
input_state_sequence_next(
u_char ch, enum input_class iclass, struct input_ctx *ictx)
{
struct input_arg *iarg;
switch (iclass) {
case INPUT_SPACE:
case INPUT_INTERMEDIATE:
if (ictx->saved != ictx->off) {
ARRAY_EXPAND(&ictx->args, 1);
iarg = &ARRAY_LAST(&ictx->args);
iarg->off = ictx->saved;
iarg->len = ictx->off - ictx->saved - 1;
}
ictx->intoff = ictx->off;
ictx->intlen = 1;
if (input_add_argument(ictx, '\0') != 0)
break;
return (input_state_sequence_intermediate);
case INPUT_PARAMETER:
if (ch == ';') {
ARRAY_EXPAND(&ictx->args, 1);
iarg = &ARRAY_LAST(&ictx->args);
iarg->off = ictx->saved;
iarg->len = ictx->off - ictx->saved - 1;
ictx->saved = ictx->off;
if (input_add_argument(ictx, '\0') != 0)
break;
input_new_argument(ictx);
return (input_state_sequence_next);
}
if (input_add_argument(ictx, ch) != 0)
break;
return (input_state_sequence_next);
case INPUT_UPPERCASE:
case INPUT_LOWERCASE:
if (ictx->saved != ictx->off) {
ARRAY_EXPAND(&ictx->args, 1);
iarg = &ARRAY_LAST(&ictx->args);
iarg->off = ictx->saved;
iarg->len = ictx->off - ictx->saved - 1;
}
if (input_add_argument(ictx, '\0') != 0)
break;
input_handle_sequence(ch, ictx);
break;
case INPUT_C0CONTROL:
@ -363,7 +368,6 @@ input_state_sequence_intermediate(
switch (iclass) {
case INPUT_SPACE:
case INPUT_INTERMEDIATE:
ictx->intlen++;
return (input_state_sequence_intermediate);
case INPUT_UPPERCASE:
case INPUT_LOWERCASE:
@ -437,8 +441,7 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx)
void
input_handle_private_two(u_char ch, struct input_ctx *ictx)
{
log_debug2("-- p2 %zu: %hhu (%c) (%zu, %zu)",
ictx->off, ch, ch, ictx->intoff, ictx->intlen);
log_debug2("-- p2 %zu: %hhu (%c)", ictx->off, ch, ch);
switch (ch) {
case '=': /* DECKPAM */
@ -456,8 +459,7 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx)
void
input_handle_standard_two(u_char ch, struct input_ctx *ictx)
{
log_debug2("-- s2 %zu: %hhu (%c) (%zu,%zu)",
ictx->off, ch, ch, ictx->intoff, ictx->intlen);
log_debug2("-- s2 %zu: %hhu (%c)", ictx->off, ch, ch);
log_debug("unknown s2: %hhu", ch);
}
@ -491,26 +493,21 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx)
u_int i;
struct input_arg *iarg;
log_debug2("-- sq %zu: %hhu (%c) (%zu,%zu): %u",
ictx->off, ch, ch, ictx->intoff, ictx->intlen,
ARRAY_LENGTH(&ictx->args));
log_debug2("-- sq "
"%zu: %hhu (%c): %u", ictx->off, ch, ch, ARRAY_LENGTH(&ictx->args));
for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) {
iarg = &ARRAY_ITEM(&ictx->args, i);
if (iarg->len > 0) {
log_debug2(" ++ %u: (%zu) %.*s", i,
iarg->len, (int) iarg->len, ictx->buf + iarg->off);
}
if (*iarg->data != '\0')
log_debug2(" ++ %u: %s", i, iarg->data);
}
/* XXX bsearch? */
for (i = 0; i < (sizeof table / sizeof table[0]); i++) {
if (table[i].ch == ch) {
table[i].fn(ictx);
ARRAY_CLEAR(&ictx->args);
return;
}
}
ARRAY_CLEAR(&ictx->args);
log_debug("unknown sq: %c (%hhu %hhu)", ch, ch, ictx->private);
}

View File

@ -1,4 +1,4 @@
/* $Id: local.c,v 1.10 2007-09-29 10:57:39 nicm Exp $ */
/* $Id: local.c,v 1.11 2007-09-29 14:25:49 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -310,11 +310,13 @@ local_putc(int c)
if (c < 0 || c > (int) UCHAR_MAX)
fatalx("invalid character");
/* XXX
if (debug_level > 2) {
f = fopen("tmux-out.log", "a+");
fprintf(f, "%c", ch);
fclose(f);
}
*/
buffer_write(local_out, &ch, 1);
return (c);

13
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.25 2007-09-29 13:22:15 nicm Exp $ */
/* $Id: tmux.h,v 1.26 2007-09-29 14:25:49 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -396,11 +396,11 @@ struct screen {
#define SCREEN_DEFDATA ' '
#define SCREEN_DEFATTR 0
#define SCREEN_DEFCOLR 0x88
/* Input parser sequence argument. */
struct input_arg {
size_t off;
size_t len;
u_char data[64];
size_t used;
};
/* Input character classes. */
@ -431,10 +431,6 @@ struct input_ctx {
void *(*state)(u_char, enum input_class, struct input_ctx *);
size_t intoff;
size_t intlen;
size_t saved;
u_char private;
ARRAY_DECL(, struct input_arg) args;
};
@ -663,6 +659,7 @@ __dead void log_fatalx(const char *, ...);
/* xmalloc.c */
void *ensure_size(void *, size_t *, size_t, size_t);
void *ensure_for(void *, size_t *, size_t, size_t);
char *xmemstrdup(const char *, size_t);
char *xstrdup(const char *);
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);

View File

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.13 2007-09-29 09:15:49 nicm Exp $ */
/* $Id: window.c,v 1.14 2007-09-29 14:25:49 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -314,9 +314,17 @@ window_input(struct window *w, struct buffer *b, size_t size)
void
window_output(struct window *w, struct buffer *b)
{
FILE *f;
if (BUFFER_USED(w->in) == 0)
return;
if (debug_level > 2) {
f = fopen("tmux-in.log", "a+");
fwrite(BUFFER_OUT(w->in), BUFFER_USED(w->in), 1, f);
fclose(f);
}
input_parse(&w->ictx, BUFFER_OUT(w->in), BUFFER_USED(w->in), b);
buffer_remove(w->in, BUFFER_USED(w->in));

View File

@ -1,4 +1,4 @@
/* $Id: xmalloc.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */
/* $Id: xmalloc.c,v 1.3 2007-09-29 14:25:49 nicm Exp $ */
/*
* Copyright (c) 2004 Nicholas Marriott <nicm@users.sourceforge.net>
@ -69,6 +69,18 @@ ensure_size(void *buf, size_t *len, size_t nmemb, size_t size)
return (buf);
}
char *
xmemstrdup(const char *buf, size_t len)
{
char *s;
s = xmalloc(len + 1);
memcpy(s, buf, len);
s[len] = '\0';
return (s);
}
char *
xstrdup(const char *s)
{