diff --git a/clang.c b/clang.c index 1ec289a..21298c1 100644 --- a/clang.c +++ b/clang.c @@ -1316,7 +1316,7 @@ static CmdDef c_commands[] = { CMD2( '{', '}', "c-electric-key", do_c_electric, ESi, "*ki") CMD2( KEY_RET, KEY_NONE, - "c-newline", do_c_newline, ES, "*v") + "c-newline", do_c_newline, ES, "*") CMD_DEF_END, }; diff --git a/extras.c b/extras.c index d82df5f..9167a05 100644 --- a/extras.c +++ b/extras.c @@ -324,7 +324,7 @@ static void do_delete_blank_lines(EditState *s) eb_delete_range(b, from, offset); } -static void eb_tabify(EditBuffer *b, int p1, int p2) +static void do_tabify(EditState *s, int p1, int p2) { /* We implement a complete analysis of the region instead of * scanning for certain space patterns (such as / [ \t]/). It is @@ -338,12 +338,16 @@ static void eb_tabify(EditBuffer *b, int p1, int p2) * new buffer reader eb_nextc_style() using colorizer and a * one line cache. */ + EditBuffer *b = s->b; int tw = b->tab_width > 0 ? b->tab_width : 8; int start = max(0, min(p1, p2)); int stop = min(b->total_size, max(p1, p2)); int col; int offset, offset1, offset2, delta; + /* deactivate region hilite */ + s->region_style = 0; + col = 0; offset = eb_goto_bol(b, start); @@ -385,7 +389,7 @@ static void eb_tabify(EditBuffer *b, int p1, int p2) } } } - +#if 0 static void do_tabify_buffer(EditState *s) { /* deactivate region hilite */ @@ -401,19 +405,23 @@ static void do_tabify_region(EditState *s) eb_tabify(s->b, s->b->mark, s->offset); } - -static void eb_untabify(EditBuffer *b, int p1, int p2) +#endif +static void do_untabify(EditState *s, int p1, int p2) { /* We implement a complete analysis of the region instead of * potentially faster scan for '\t'. It is fast enough and even * faster if there are lots of tabs. */ + EditBuffer *b = s->b; int tw = b->tab_width > 0 ? b->tab_width : 8; int start = max(0, min(p1, p2)); int stop = min(b->total_size, max(p1, p2)); int col, col0; int offset, offset1, offset2, delta; + /* deactivate region hilite */ + s->region_style = 0; + col = 0; offset = eb_goto_bol(b, start); @@ -441,7 +449,7 @@ static void eb_untabify(EditBuffer *b, int p1, int p2) stop += delta; } } - +#if 0 static void do_untabify_buffer(EditState *s) { /* deactivate region hilite */ @@ -457,7 +465,7 @@ static void do_untabify_region(EditState *s) eb_untabify(s->b, s->b->mark, s->offset); } - +#endif static void do_indent_region(EditState *s) { int col_num, line1, line2; @@ -988,15 +996,16 @@ void do_apropos(EditState *s, const char *str) while (d != NULL) { while (d->name != NULL) { if (strstr(d->name, str)) { + const char *desc; /* print name and prototype */ qe_get_prototype(d, buf, sizeof(buf)); eb_printf(b, "command: %s%s", d->name, buf); if (qe_list_bindings(d, s->mode, 1, buf, sizeof(buf))) eb_printf(b, " bound to %s", buf); eb_putc(b, '\n'); - if (d->desc && *d->desc) { + if (*(desc = d->spec + strlen(d->spec) + 1)) { /* print short description */ - eb_printf(b, " %s", d->desc); + eb_printf(b, " %s", desc); } eb_putc(b, '\n'); found = 1; @@ -1878,15 +1887,18 @@ static CmdDef extra_commands[] = { "delete-horizontal-space", do_delete_horizontal_space, ES, "*") CMD2( KEY_CTRLX(KEY_CTRL('o')), KEY_NONE, "delete-blank-lines", do_delete_blank_lines, ES, "*") - /* XXX: should take region as argument, implicit from keyboard */ - CMD2( KEY_NONE, KEY_NONE, - "tabify-region", do_tabify_region, ES, "*") - CMD2( KEY_NONE, KEY_NONE, - "untabify-region", do_untabify_region, ES, "*") - CMD2( KEY_NONE, KEY_NONE, - "tabify-buffer", do_tabify_buffer, ES, "*") - CMD2( KEY_NONE, KEY_NONE, - "untabify-buffer", do_untabify_buffer, ES, "*") + CMD3( KEY_NONE, KEY_NONE, + "tabify-region", do_tabify, ESii, 0, "*" "mipi" + "\0" "Convert multiple spaces in region to tabs when possible") + CMD3( KEY_NONE, KEY_NONE, + "untabify-region", do_untabify, ESii, 0, "*" "mipi" + "\0" "Convert all tabs in region to multiple spaces, preserving columns") + CMD3( KEY_NONE, KEY_NONE, + "tabify-buffer", do_tabify, ESii, 0, "*" "ziei" + "\0" "Convert multiple spaces in buffer to tabs when possible") + CMD3( KEY_NONE, KEY_NONE, + "untabify-buffer", do_untabify, ESii, 0, "*" "ziei" + "\0" "Convert all tabs in buffer to multiple spaces, preserving columns") /* XXX: should take region as argument, implicit from keyboard */ CMD2( KEY_META(KEY_CTRL('\\')), KEY_NONE, "indent-region", do_indent_region, ES, "*") diff --git a/parser.c b/parser.c index 282df78..b1c9930 100644 --- a/parser.c +++ b/parser.c @@ -124,11 +124,12 @@ static int qe_parse_script(EditState *s, QEmacsDataSource *ds) QEmacsState *qs = s->qe_state; QErrorContext ec; char line[1024], str[1024]; - char prompt[64], cmd[128], *q, *strp; + char cmd[128], *q, *strp; + CmdArgSpec cas; const char *p, *r; int line_num; CmdDef *d; - int nb_args, sep, i, skip, incomment; + int nb_args, sep, i, skip, incomment, ret; CmdArg args[MAX_CMD_ARGS]; unsigned char args_type[MAX_CMD_ARGS]; @@ -240,7 +241,7 @@ static int qe_parse_script(EditState *s, QEmacsDataSource *ds) nb_args = 0; /* construct argument type list */ - r = d->name + strlen(d->name) + 1; + r = d->spec; if (*r == '*') { r++; if (s->b->flags & BF_READONLY) { @@ -252,23 +253,13 @@ static int qe_parse_script(EditState *s, QEmacsDataSource *ds) /* first argument is always the window */ args_type[nb_args++] = CMD_ARG_WINDOW; - for (;;) { - unsigned char arg_type; - int ret; - - ret = parse_arg(&r, &arg_type, prompt, countof(prompt), - NULL, 0, NULL, 0); - if (ret < 0) - goto badcmd; - if (ret == 0) - break; - if (nb_args >= MAX_CMD_ARGS) { - badcmd: + while ((ret = parse_arg(&r, &cas)) != 0) { + if (ret < 0 || nb_args >= MAX_CMD_ARGS) { put_status(s, "Badly defined command '%s'", cmd); goto fail; } args[nb_args].p = NULL; - args_type[nb_args++] = arg_type & CMD_ARG_TYPE_MASK; + args_type[nb_args++] = cas.arg_type & CMD_ARG_TYPE_MASK; } sep = '\0'; @@ -284,8 +275,9 @@ static int qe_parse_script(EditState *s, QEmacsDataSource *ds) args[i].n = (int)(intptr_t)d->val; continue; case CMD_ARG_STRINGVAL: - /* CG: kludge for xxx-mode functions and named kbd macros */ - args[i].p = prompt; + /* CG: kludge for xxx-mode functions and named kbd macros, + must be last argument */ + args[i].p = cas.prompt; continue; } @@ -298,7 +290,7 @@ static int qe_parse_script(EditState *s, QEmacsDataSource *ds) sep = ','; skip_spaces(&p); - switch (args_type[i]) { + switch (args_type[i] & CMD_ARG_TYPE_MASK) { case CMD_ARG_INT: r = p; args[i].n = strtol(p, (char**)&p, 0); diff --git a/qe.c b/qe.c index 426ed54..2a7914a 100644 --- a/qe.c +++ b/qe.c @@ -183,20 +183,23 @@ void qe_register_mode(ModeDef *m, int flags) /* add a new command to switch to that mode */ if (!(m->flags & MODEF_NOCMD)) { - char buf[64]; - int size; + char name[64]; + char spec[64]; + int spec_len; CmdDef *def; const char *mode_name = m->alt_name ? m->alt_name : m->name; /* lower case convert for C mode, Perl... */ - qe_strtolower(buf, sizeof(buf) - 10, mode_name); - pstrcat(buf, sizeof(buf), "-mode"); - size = strlen(buf) + 1; + qe_strtolower(name, sizeof(name) - 10, mode_name); + pstrcat(name, sizeof(name), "-mode"); + /* constant immediate string parameter */ - size += snprintf(buf + size, sizeof(buf) - size, - "S{%s}", mode_name) + 1; + spec_len = snprintf(spec, sizeof(spec), + "S{%s}%cselect the %s mode for the current buffer", + mode_name, 0, mode_name); def = qe_mallocz_array(CmdDef, 2); - def->name = qe_malloc_dup(buf, size); + def->name = qe_strdup(name); + def->spec = qe_malloc_dup(spec, spec_len + 1); def->key = def->alt_key = KEY_NONE; def->sig = CMD_ESs; def->val = 0; @@ -4761,30 +4764,45 @@ static void get_param(const char **pp, char *param, int param_size, int osep, in } /* return -1 if error, 0 if no more args, 1 if one arg parsed */ -int parse_arg(const char **pp, unsigned char *argtype, - char *prompt, int prompt_size, - char *completion, int completion_size, - char *history, int history_size) +int parse_arg(const char **pp, CmdArgSpec *ap) { int tc, type; const char *p; p = *pp; type = 0; - if (*p == 'k') { - p++; + switch (*p) { + case 'k': type = CMD_ARG_USE_KEY; - } - if (*p == 'u') { p++; + break; + case 'u': type = CMD_ARG_USE_ARGVAL; + p++; + break; + case 'm': + type = CMD_ARG_USE_MARK; + p++; + break; + case 'p': + type = CMD_ARG_USE_POINT; + p++; + break; + case 'z': + type = CMD_ARG_USE_ZERO; + p++; + break; + case 'e': + type = CMD_ARG_USE_BSIZE; + p++; + break; } if (*p == '\0') return 0; tc = *p++; - get_param(&p, prompt, prompt_size, '{', '}'); - get_param(&p, completion, completion_size, '[', ']'); - get_param(&p, history, history_size, '|', '|'); + get_param(&p, ap->prompt, sizeof(ap->prompt), '{', '}'); + get_param(&p, ap->completion, sizeof(ap->completion), '[', ']'); + get_param(&p, ap->history, sizeof(ap->history), '|', '|'); switch (tc) { case 'i': type |= CMD_ARG_INT; @@ -4796,13 +4814,14 @@ int parse_arg(const char **pp, unsigned char *argtype, type |= CMD_ARG_STRING; break; case 'S': /* used in define_kbd_macro, and mode selection */ + /* actual string is in prompt buffer */ type |= CMD_ARG_STRINGVAL; break; default: return -1; } *pp = p; - *argtype = type; + ap->arg_type = type; return 1; } @@ -4811,31 +4830,20 @@ int qe_get_prototype(CmdDef *d, char *buf, int size) buf_t outbuf, *out; const char *r; const char *sep = ""; + CmdArgSpec cas; out = buf_init(&outbuf, buf, size); buf_put_byte(out, '('); /* construct argument type list */ - r = d->name + strlen(d->name) + 1; + r = d->spec; if (*r == '*') { r++; /* buffer modification indicator */ } - for (;;) { - unsigned char arg_type; - char completion[32]; - char history[32]; - int ret; - - ret = parse_arg(&r, &arg_type, NULL, 0, - completion, sizeof(completion), - history, sizeof(history)); - if (ret <= 0) - break; - - /* pseudo arguments: skip them */ - switch (arg_type & CMD_ARG_TYPE_MASK) { + while (parse_arg(&r, &cas) > 0) { + switch (cas.arg_type & CMD_ARG_TYPE_MASK) { case CMD_ARG_INT: buf_printf(out, "%sint ", sep); break; @@ -4849,13 +4857,28 @@ int qe_get_prototype(CmdDef *d, char *buf, int size) continue; } sep = ", "; - if (arg_type & CMD_ARG_USE_KEY) { - buf_puts(out, "key"); - } else - if (arg_type & CMD_ARG_USE_ARGVAL) { - buf_puts(out, "argval"); - } else { - buf_puts(out, *history ? history : completion); + switch (cas.arg_type & ~CMD_ARG_TYPE_MASK) { + case CMD_ARG_USE_ARGVAL: + buf_puts(out, "= argval"); + break; + case CMD_ARG_USE_KEY: + buf_puts(out, "= key"); + break; + case CMD_ARG_USE_MARK: + buf_puts(out, "= mark"); + break; + case CMD_ARG_USE_POINT: + buf_puts(out, "= point"); + break; + case CMD_ARG_USE_ZERO: + buf_puts(out, "= 0"); + break; + case CMD_ARG_USE_BSIZE: + buf_puts(out, "= bufsize"); + break; + default: + buf_puts(out, *cas.history ? cas.history : cas.completion); + break; } } buf_put_byte(out, ')'); @@ -4863,7 +4886,7 @@ int qe_get_prototype(CmdDef *d, char *buf, int size) } static void arg_edit_cb(void *opaque, char *str); -static void parse_args(ExecCmdState *es); +static void parse_arguments(ExecCmdState *es); static void free_cmd(ExecCmdState **esp); void exec_command(EditState *s, CmdDef *d, int argval, int key) @@ -4874,7 +4897,7 @@ void exec_command(EditState *s, CmdDef *d, int argval, int key) if (qe_state.trace_buffer && qe_state.trace_buffer != s->b) eb_trace_bytes(d->name, -1, EB_TRACE_COMMAND); - argdesc = d->name + strlen(d->name) + 1; + argdesc = d->spec; if (*argdesc == '*') { argdesc++; if (s->b->flags & BF_READONLY) { @@ -4899,37 +4922,25 @@ void exec_command(EditState *s, CmdDef *d, int argval, int key) es->nb_args++; es->ptype = argdesc; - parse_args(es); + parse_arguments(es); } /* parse as much arguments as possible. ask value to user if possible */ -static void parse_args(ExecCmdState *es) +static void parse_arguments(ExecCmdState *es) { EditState *s = es->s; QEmacsState *qs = s->qe_state; QErrorContext ec; CmdDef *d = es->d; - char prompt[256]; - char completion_name[64]; - char history[32]; - unsigned char arg_type; - int ret, rep_count, get_arg, type, use_argval, use_key; + CmdArgSpec cas; + int ret, rep_count, get_arg, type, use_flag; int elapsed_time; - for (;;) { - ret = parse_arg(&es->ptype, &arg_type, - prompt, sizeof(prompt), - completion_name, sizeof(completion_name), - history, sizeof(history)); - if (ret < 0) + while ((ret = parse_arg(&es->ptype, &cas)) != 0) { + if (ret < 0 || es->nb_args >= MAX_CMD_ARGS) goto fail; - if (ret == 0) - break; - if (es->nb_args >= MAX_CMD_ARGS) - goto fail; - use_argval = arg_type & CMD_ARG_USE_ARGVAL; - use_key = arg_type & CMD_ARG_USE_KEY; - type = arg_type & CMD_ARG_TYPE_MASK; + use_flag = cas.arg_type & ~CMD_ARG_TYPE_MASK; + type = cas.arg_type & CMD_ARG_TYPE_MASK; es->args_type[es->nb_args] = type; get_arg = 0; switch (type) { @@ -4937,13 +4948,27 @@ static void parse_args(ExecCmdState *es) es->args[es->nb_args].n = d->val; break; case CMD_ARG_STRINGVAL: - es->args[es->nb_args].p = prompt; + /* CG: kludge for xxx-mode functions and named kbd macros, + must be last argument */ + es->args[es->nb_args].p = cas.prompt; break; case CMD_ARG_INT: - if (use_key) { + if (use_flag == CMD_ARG_USE_KEY) { es->args[es->nb_args].n = es->key; } else - if (use_argval && es->argval != NO_ARG) { + if (use_flag == CMD_ARG_USE_MARK) { + es->args[es->nb_args].n = s->b->mark; + } else + if (use_flag == CMD_ARG_USE_POINT) { + es->args[es->nb_args].n = s->offset; + } else + if (use_flag == CMD_ARG_USE_ZERO) { + es->args[es->nb_args].n = 0; + } else + if (use_flag == CMD_ARG_USE_BSIZE) { + es->args[es->nb_args].n = s->b->total_size; + } else + if (use_flag == CMD_ARG_USE_ARGVAL && es->argval != NO_ARG) { es->args[es->nb_args].n = es->argval; es->argval = NO_ARG; } else { @@ -4953,12 +4978,15 @@ static void parse_args(ExecCmdState *es) } break; case CMD_ARG_STRING: - if (use_argval && es->argval != NO_ARG) { +#if 0 + if (use_flag == CMD_ARG_USE_ARGVAL && es->argval != NO_ARG) { char buf[32]; snprintf(buf, sizeof(buf), "%d", es->argval); - es->args[es->nb_args].p = qe_strdup(buf); + es->args[es->nb_args].p = qe_strdup(buf); // XXX: memory leak? es->argval = NO_ARG; - } else { + } else +#endif + { es->args[es->nb_args].p = NULL; get_arg = 1; break; @@ -4966,17 +4994,17 @@ static void parse_args(ExecCmdState *es) } es->nb_args++; /* if no argument specified, try to ask it to the user */ - if (get_arg && prompt[0] != '\0') { + if (get_arg && cas.prompt[0] != '\0') { char def_input[1024]; /* XXX: currently, default input is handled non generically */ /* XXX: should use completion function for default input? */ def_input[0] = '\0'; es->default_input[0] = '\0'; - if (strequal(completion_name, "file")) { + if (strequal(cas.completion, "file")) { get_default_path(s->b, s->offset, def_input, sizeof(def_input)); } else - if (strequal(completion_name, "buffer")) { + if (strequal(cas.completion, "buffer")) { EditBuffer *b; if (d->action.ESs == do_switch_to_buffer) b = predict_switch_to_buffer(s); @@ -4985,12 +5013,12 @@ static void parse_args(ExecCmdState *es) pstrcpy(es->default_input, sizeof(es->default_input), b->name); } if (es->default_input[0] != '\0') { - pstrcat(prompt, sizeof(prompt), "(default "); - pstrcat(prompt, sizeof(prompt), es->default_input); - pstrcat(prompt, sizeof(prompt), ") "); + pstrcat(cas.prompt, sizeof(cas.prompt), "(default "); + pstrcat(cas.prompt, sizeof(cas.prompt), es->default_input); + pstrcat(cas.prompt, sizeof(cas.prompt), ") "); } - minibuffer_edit(s, def_input, prompt, get_history(history), - completion_name, arg_edit_cb, es); + minibuffer_edit(s, def_input, cas.prompt, get_history(cas.history), + cas.completion, arg_edit_cb, es); return; } } @@ -5007,6 +5035,7 @@ static void parse_args(ExecCmdState *es) qs->cmd_start_time = get_clock_ms(); + // XXX: should use while (rep_count-- > 0) do { /* special case for hex mode */ if (d->action.ESii != do_char) { @@ -5090,7 +5119,7 @@ static void arg_edit_cb(void *opaque, char *str) break; } /* now we can parse the following arguments */ - parse_args(es); + parse_arguments(es); } int check_read_only(EditState *s) @@ -5297,11 +5326,10 @@ void do_define_kbd_macro(EditState *s, const char *name, const char *keys, const char *key_bind) { CmdDef *def; - int namelen, size; + int size; char *buf; - namelen = strlen(name); - size = namelen + 1 + 2 + strlen(keys) + 2; + size = 2 + strlen(keys) + 3; buf = qe_malloc_array(char, size); // XXX: should special case "last-kbd-macro" @@ -5309,7 +5337,7 @@ void do_define_kbd_macro(EditState *s, const char *name, const char *keys, /* CG: should parse macro keys to an array and pass index * to do_execute_macro. */ - snprintf(buf, size, "%s%cS{%s}", name, 0, keys); + snprintf(buf, size, "S{%s}%c", keys, 0); def = qe_find_cmd(name); if (def && def->action.ESs == do_execute_macro_keys) { @@ -5317,12 +5345,13 @@ void do_define_kbd_macro(EditState *s, const char *name, const char *keys, /* XXX: freeing the current macro definition may cause a crash if it * is currently executing. */ - qe_free((char **)&def->name); - def->name = buf; + qe_free((char **)&def->spec); + def->spec = buf; } else { def = qe_mallocz_array(CmdDef, 2); def->key = def->alt_key = KEY_NONE; - def->name = buf; + def->name = qe_strdup(name); + def->spec = buf; def->sig = CMD_ESs; def->val = 0; def->action.ESs = do_execute_macro_keys; @@ -5348,9 +5377,8 @@ static void qe_save_macro(EditState *s, CmdDef *def, EditBuffer *b) eb_printf(b, "define_kbd_macro(\"%s\", \"", name); if (def) { - const char *keys = def->name; - keys += strlen(keys) + 1 + 2; - while (keys[1]) { + const char *keys = def->spec + 2; /* skip S{ */ + while (keys[1]) { /* stop at } */ eb_putc(b, utf8_decode(&keys)); } } else { @@ -9397,8 +9425,10 @@ int main(int argc, char **argv) d1++; qs->first_cmd = d1->action.next; /* free xxx-mode commands and macros */ + /* XXX: should use CmdDef flag */ if (d->name && !d[1].name && d[1].val) { qe_free((char **)&d->name); + qe_free((char **)&d->spec); qe_free(&d); } } diff --git a/qe.h b/qe.h index 35b0416..b1a8993 100644 --- a/qe.h +++ b/qe.h @@ -1758,9 +1758,13 @@ enum CmdArgType { CMD_ARG_STRING, CMD_ARG_STRINGVAL, CMD_ARG_WINDOW, - CMD_ARG_TYPE_MASK = 0x3f, - CMD_ARG_USE_KEY = 0x40, - CMD_ARG_USE_ARGVAL = 0x80, + CMD_ARG_TYPE_MASK = 0x0f, + CMD_ARG_USE_ARGVAL = 0x10, + CMD_ARG_USE_KEY = 0x20, + CMD_ARG_USE_MARK = 0x30, + CMD_ARG_USE_POINT = 0x40, + CMD_ARG_USE_ZERO = 0x50, + CMD_ARG_USE_BSIZE = 0x60, }; typedef enum CmdSig { @@ -1783,6 +1787,13 @@ typedef union CmdArg { int n; } CmdArg; +typedef struct CmdArgSpec { + int arg_type; + char completion[32]; + char history[32]; + char prompt[1024]; /* used for keyboard macros */ +} CmdArgSpec; + typedef union CmdProto { void (*func)(void); void (*ES)(EditState *); @@ -1798,7 +1809,7 @@ typedef union CmdProto { typedef struct CmdDef { const char *name; - const char *desc; + const char *spec; unsigned short key; /* normal key */ unsigned short alt_key; /* alternate key */ CmdSig sig : 8; @@ -1806,17 +1817,19 @@ typedef struct CmdDef { CmdProto action; } CmdDef; -/* new command macros */ -#define CMD2(key, key_alt, name, func, sig, args) \ - { name "\0" args, NULL, key, key_alt, CMD_ ## sig, 0, { .sig = func } }, -#define CMD3(key, key_alt, name, func, sig, val, args) \ - { name "\0" args, NULL, key, key_alt, CMD_ ## sig, val, { .sig = func } }, - -/* old macros for compatibility */ +/* command without arguments, no buffer modification */ #define CMD0(key, key_alt, name, func) \ - { name "\0", NULL, key, key_alt, CMD_ES, 0, { .ES = func } }, + { name, "" "\0" "", key, key_alt, CMD_ES, 0, { .ES = func } }, +/* command with a single implicit int argument */ #define CMD1(key, key_alt, name, func, val) \ - { name "\0" "v", NULL, key, key_alt, CMD_ESi, val, { .ESi = func } }, + { name, "v" "\0" "", key, key_alt, CMD_ESi, val, { .ESi = func } }, +/* command with a an argument description string */ +#define CMD2(key, key_alt, name, func, sig, spec) \ + { name, spec "\0" "", key, key_alt, CMD_ ## sig, 0, { .sig = func } }, +/* command with a an argument description string and an int agument */ +#define CMD3(key, key_alt, name, func, sig, val, spec) \ + { name, spec "\0" "", key, key_alt, CMD_ ## sig, val, { .sig = func } }, +/* end of command definitions */ #define CMD_DEF_END \ { NULL, NULL, 0, 0, CMD_void, 0, { NULL } } @@ -2252,10 +2265,7 @@ void do_set_system_font(EditState *s, const char *qe_font_name, void do_set_window_style(EditState *s, const char *stylestr); void call_func(CmdSig sig, CmdProto func, int nb_args, CmdArg *args, unsigned char *args_type); -int parse_arg(const char **pp, unsigned char *argtype, - char *prompt, int prompt_size, - char *completion, int completion_size, - char *history, int history_size); +int parse_arg(const char **pp, CmdArgSpec *ap); void exec_command(EditState *s, CmdDef *d, int argval, int key); void do_execute_command(EditState *s, const char *cmd, int argval); void window_display(EditState *s); diff --git a/qescript.c b/qescript.c index 91a1279..2837d0e 100644 --- a/qescript.c +++ b/qescript.c @@ -817,19 +817,20 @@ done: } static int qe_cfg_call(QEmacsDataSource *ds, QEValue *sp, CmdDef *d) { - char str[1024], prompt[64]; + char str[1024]; char *strp; const char *r; - int nb_args, sep, i; + int nb_args, sep, i, ret; CmdArg args[MAX_CMD_ARGS]; unsigned char args_type[MAX_CMD_ARGS]; EditState *s = ds->s; QEmacsState *qs = s->qe_state; + CmdArgSpec cas; nb_args = 0; /* construct argument type list */ - r = d->name + strlen(d->name) + 1; + r = d->spec; if (*r == '*') { r++; if (s->b->flags & BF_READONLY) { @@ -841,23 +842,13 @@ static int qe_cfg_call(QEmacsDataSource *ds, QEValue *sp, CmdDef *d) { /* first argument is always the window */ args_type[nb_args++] = CMD_ARG_WINDOW; - for (;;) { - unsigned char arg_type; - int ret; - - ret = parse_arg(&r, &arg_type, prompt, countof(prompt), - NULL, 0, NULL, 0); - if (ret < 0) - goto badcmd; - if (ret == 0) - break; - if (nb_args >= MAX_CMD_ARGS) { - badcmd: + while ((ret = parse_arg(&r, &cas)) != 0) { + if (ret < 0 || nb_args >= MAX_CMD_ARGS) { put_status(s, "Badly defined command '%s'", d->name); return -1; } args[nb_args].p = NULL; - args_type[nb_args++] = arg_type & (CMD_ARG_TYPE_MASK | CMD_ARG_USE_ARGVAL); + args_type[nb_args++] = cas.arg_type; } sep = '\0'; @@ -873,15 +864,39 @@ static int qe_cfg_call(QEmacsDataSource *ds, QEValue *sp, CmdDef *d) { args[i].n = (int)(intptr_t)d->val; continue; case CMD_ARG_STRINGVAL: - /* CG: kludge for xxx-mode functions and named kbd macros */ - args[i].p = prompt; + /* CG: kludge for xxx-mode functions and named kbd macros, + must be last argument */ + args[i].p = cas.prompt; continue; - case CMD_ARG_INT | CMD_ARG_USE_ARGVAL: /* XXX: ui should always be last */ + case CMD_ARG_INT | CMD_ARG_USE_ARGVAL: if (ds->tok == ')') { args[i].n = NO_ARG; continue; } - args_type[i] &= ~CMD_ARG_USE_ARGVAL; + break; + case CMD_ARG_INT | CMD_ARG_USE_MARK: + if (ds->tok == ')') { + args[i].n = s->b->mark; + continue; + } + break; + case CMD_ARG_INT | CMD_ARG_USE_POINT: + if (ds->tok == ')') { + args[i].n = s->offset; + continue; + } + break; + case CMD_ARG_INT | CMD_ARG_USE_ZERO: + if (ds->tok == ')') { + args[i].n = 0; + continue; + } + break; + case CMD_ARG_INT | CMD_ARG_USE_BSIZE: + if (ds->tok == ')') { + args[i].n = s->b->total_size; + continue; + } break; } @@ -901,7 +916,7 @@ static int qe_cfg_call(QEmacsDataSource *ds, QEValue *sp, CmdDef *d) { return -1; } - switch (args_type[i]) { + switch (args_type[i] & CMD_ARG_TYPE_MASK) { case CMD_ARG_INT: qe_cfg_tonum(ds, sp); // XXX: should complain about type mismatch? args[i].n = sp->u.value;