Better vars naming, Add e cmd.fcn.{new|rename|delete}

- Bump sdb from git
This commit is contained in:
pancake 2015-03-16 02:52:26 +01:00
parent 813d13d589
commit d991769935
13 changed files with 326 additions and 199 deletions

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2014 - pancake, nibble */
/* radare - LGPL - Copyright 2009-2015 - pancake, nibble */
#include <r_anal.h>
#include <r_util.h>

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2014 - nibble, pancake */
/* radare - LGPL - Copyright 2010-2015 - nibble, pancake */
#include <r_anal.h>
#include <r_util.h>
@ -175,16 +175,16 @@ static int bbsum(RAnalFunction *fcn) {
}
#endif
static RAnalBlock* appendBasicBlock (RAnalFunction *fcn, ut64 addr) {
static RAnalBlock* appendBasicBlock (RAnal *anal, RAnalFunction *fcn, ut64 addr) {
RAnalBlock *bb;
#if 0
RListIter *iter;
// TODO: check if its already there
r_list_foreach (fcn->bbs, iter, bb) {
if (bb->addr == addr)
return bb;
}
#endif
// TODO: echeck if its already there
bb = r_anal_bb_new ();
if (!bb) return NULL;
bb->addr = addr;
@ -193,6 +193,9 @@ static RAnalBlock* appendBasicBlock (RAnalFunction *fcn, ut64 addr) {
bb->fail = UT64_MAX;
bb->type = 0; // TODO
r_list_append (fcn->bbs, bb);
if (anal->cb.on_fcn_bb_new) {
anal->cb.on_fcn_bb_new (anal, anal->user, fcn, bb);
}
return bb;
}
//fcn->addr += n; fcn->size -= n; } else
@ -206,6 +209,20 @@ static RAnalBlock* appendBasicBlock (RAnalFunction *fcn, ut64 addr) {
#define MAXBBSIZE 8096
#define VARPREFIX "local"
//#define VARPREFIX "var"
#define ARGPREFIX "arg"
static char *get_varname (RAnal *a, const char *pfx, int idx) {
char *s;
int word = a->bits / 8;
if (idx%word) {
s = r_str_newf ("%s_%d_%d", pfx, idx/word, R_ABS(idx%word));
} else {
s = r_str_newf ("%s_%d", pfx, idx/word);
}
return s;
}
#define gotoBeach(x) ret=x;goto beach;
static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int depth) {
int continue_after_jump = anal->afterjmp;
@ -239,13 +256,13 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut6
#endif
bb = bbget (fcn, addr);
if (bb) {
r_anal_fcn_split_bb (fcn, bb, addr);
r_anal_fcn_split_bb (anal, fcn, bb, addr);
if (anal->recont)
return R_ANAL_RET_END;
return R_ANAL_RET_ERROR; // MUST BE NOT DUP
}
bb = appendBasicBlock (fcn, addr);
bb = appendBasicBlock (anal, fcn, addr);
VERBOSE_ANAL eprintf ("Append bb at 0x%08"PFMT64x
" (fcn 0x%08llx)\n", addr, fcn->addr);
@ -345,27 +362,26 @@ repeat:
// TODO: use fcn->stack to know our stackframe
case R_ANAL_STACK_SET:
if ((int)op.ptr > 0) {
varname = r_str_newf ("arg_%x", op.ptr);
varname = get_varname (anal, ARGPREFIX, R_ABS(op.ptr));
r_anal_var_add (anal, fcn->addr, 1, op.ptr,
'a', NULL, anal->bits/8, varname);
// TODO: DIR_IN?
} else {
varname = r_str_newf ("local_%x", -op.ptr);
varname = get_varname (anal, VARPREFIX, R_ABS(op.ptr));
r_anal_var_add (anal, fcn->addr, 1, -op.ptr,
'v', NULL,
anal->bits/8, varname);
'v', NULL, anal->bits/8, varname);
}
free (varname);
break;
// TODO: use fcn->stack to know our stackframe
case R_ANAL_STACK_GET:
if (((int)op.ptr) > 0) {
varname = r_str_newf ("arg_%x", op.ptr);
varname = get_varname (anal, ARGPREFIX, R_ABS(op.ptr));
r_anal_var_add (anal, fcn->addr, 1, op.ptr, 'a', NULL, anal->bits/8, varname);
r_anal_var_access (anal, fcn->addr, 'a', 0, op.ptr, 0, op.addr); //, NULL, varname, 0);
//R_ANAL_VAR_SCOPE_ARG|R_ANAL_VAR_DIR_IN, NULL, varname, 0);
} else {
varname = r_str_newf ("local_%x", -op.ptr);
varname = get_varname (anal, VARPREFIX, R_ABS(op.ptr));
r_anal_var_add (anal, fcn->addr, 1, -op.ptr, 'v', NULL, anal->bits/8, varname);
r_anal_var_access (anal, fcn->addr, 'v', 0, -op.ptr, 0, -op.addr); //, 'v', NULL, varname, 0);
//R_ANAL_VAR_SCOPE_LOCAL|R_ANAL_VAR_DIR_NONE, NULL, varname, 0);
@ -585,6 +601,9 @@ fcn.<offset>.bbs
sdb_set (DB, sdb_fmt (0, "fcn.0x%"PFMT64x"", "", 0));
#endif
r_list_append (anal->fcns, fcn);
if (anal->cb.on_fcn_new) {
anal->cb.on_fcn_new (anal, anal->user, fcn);
}
return R_TRUE;
}
@ -660,6 +679,9 @@ R_API int r_anal_fcn_del(RAnal *a, ut64 addr) {
RListIter *iter, *iter_tmp;
r_list_foreach_safe (a->fcns, iter, iter_tmp, fcni) {
if (addr >= fcni->addr && addr < fcni->addr+fcni->size) {
if (a->cb.on_fcn_delete) {
a->cb.on_fcn_delete (a, a->user, fcni);
}
r_list_delete (a->fcns, iter);
}
}
@ -705,7 +727,7 @@ R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name) {
}
/* rename RAnalFunctionBB.add() */
R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, int type, RAnalDiff *diff) {
R_API int r_anal_fcn_add_bb(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, int type, RAnalDiff *diff) {
RAnalBlock *bb = NULL, *bbi;
RListIter *iter;
int mid = 0;
@ -728,7 +750,7 @@ R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump,
//return R_FALSE;
}
if (bb == NULL) {
bb = appendBasicBlock (fcn, addr);
bb = appendBasicBlock (anal, fcn, addr);
if (!bb) {
eprintf ("appendBasicBlock failed\n");
return R_FALSE;
@ -751,7 +773,7 @@ R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump,
// TODO: rename fcn_bb_split()
// bb seems to be ignored
R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr) {
R_API int r_anal_fcn_split_bb(RAnal *anal, RAnalFunction *fcn, RAnalBlock *bb, ut64 addr) {
RAnalBlock *bbi;
#if R_ANAL_BB_HAS_OPS
RAnalOp *opi;
@ -764,7 +786,7 @@ R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr) {
if (addr == bbi->addr)
return R_ANAL_RET_DUP;
if (addr > bbi->addr && addr < bbi->addr + bbi->size) {
bb = appendBasicBlock (fcn, addr);
bb = appendBasicBlock (anal, fcn, addr);
//r_list_append (fcn->bbs, bb);
//bb->addr = addr+bbi->size;
bb->size = bbi->addr + bbi->size - addr;

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2014 - pancake */
/* radare - LGPL - Copyright 2010-2015 - pancake */
#include <r_anal.h>
#include <r_util.h>
@ -66,6 +66,7 @@ R_API int r_anal_var_add (RAnal *a, ut64 addr, int scope, int delta, char kind,
char *var_def = sdb_fmt (2,"%c.%s,%d,%s", kind, type, size, name);
sdb_array_add (DB, var_global, var_def, 0);
}
// ls_sort (DB->ht->list, mystrcmp);
return R_TRUE;
}

View File

@ -540,11 +540,14 @@ R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head) {
return R_FALSE;
if (!(bb = r_anal_bb_new ()))
return R_FALSE;
if (split) ret = r_anal_fcn_split_bb (fcn, bb, at);
else r_list_foreach (fcn->bbs, iter, bbi) {
if (split) {
ret = r_anal_fcn_split_bb (core->anal, fcn, bb, at);
} else {
r_list_foreach (fcn->bbs, iter, bbi) {
if (at == bbi->addr)
ret = R_ANAL_RET_DUP;
}
}
if (ret == R_ANAL_RET_DUP) { /* Dupped bb */
goto error;
}

View File

@ -495,7 +495,8 @@ static int anal_fcn_add_bb (RCore *core, const char *input) {
}
fcn = r_anal_get_fcn_in (core->anal, fcnaddr, 0);
if (fcn) {
int ret = r_anal_fcn_add_bb (fcn, addr, size, jump, fail, type, diff);
int ret = r_anal_fcn_add_bb (core->anal, fcn, addr,
size, jump, fail, type, diff);
if (!ret) {
eprintf ("Cannot add basic block\n");
}
@ -508,6 +509,7 @@ static int anal_fcn_add_bb (RCore *core, const char *input) {
}
static int setFunctionName(RCore *core, ut64 off, const char *name) {
char *oname;
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off,
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM|R_ANAL_FCN_TYPE_LOC);
if (!fcn)
@ -516,8 +518,12 @@ static int setFunctionName(RCore *core, ut64 off, const char *name) {
// fcn->name, name, off);
r_core_cmdf (core, "fr %s %s@ 0x%"PFMT64x,
fcn->name, name, off);
free (fcn->name);
oname = fcn->name;
fcn->name = strdup (name);
if (core->anal->cb.on_fcn_rename) {
core->anal->cb.on_fcn_rename (core->anal, core->anal->user, fcn, oname);
}
free (oname);
return 1;
}
@ -1690,7 +1696,7 @@ static void cmd_anal_calls(RCore *core, const char *input) {
if (op.size<1)
op.size = minop; // XXX must be +4 on arm/mips/.. like we do in disasm.c
if (op.type == R_ANAL_OP_TYPE_CALL) {
eprintf ("af @ 0x%08"PFMT64x"\n", op.jump);
// eprintf ("af @ 0x%08"PFMT64x"\n", op.jump);
r_core_cmdf (core, "af@0x%08"PFMT64x, op.jump);
}
} else {
@ -2399,7 +2405,7 @@ static int cmd_anal(void *data, const char *input) {
break;
}
break;
case 'c':
case 'c': // "ac"
cmd_anal_calls (core, input + 1);
break;
case 'C':

View File

@ -1135,6 +1135,9 @@ R_API int r_core_config_init(RCore *core) {
SETPREF("cmd.open", "", "Command executed when file its opened");
SETPREF("cmd.prompt", "", "Prompt commands");
SETCB("cmd.repeat", "true", &cb_cmdrepeat, "Alias newline (empty command) as '..'");
SETPREF("cmd.fcn.new", "", "Run command when new function is analyzed");
SETPREF("cmd.fcn.delete", "", "Run command when a function is deleted");
SETPREF("cmd.fcn.rename", "", "Run command when a function is renamed");
SETPREF("cmd.visual", "", "Replace current print mode");
SETPREF("cmd.vprompt", "", "Visual prompt commands");

View File

@ -11,6 +11,46 @@
R_LIB_VERSION(r_core);
static int on_fcn_new(void *_anal, void* _user, RAnalFunction *fcn) {
RCore *core = (RCore*)_user;
const char *cmd = r_config_get (core->config, "cmd.fcn.new");
if (cmd && *cmd) {
ut64 oaddr = core->offset;
ut64 addr = fcn->addr;
r_core_seek (core, addr, 1);
r_core_cmd0 (core, cmd);
r_core_seek (core, oaddr, 1);
}
return 0;
}
static int on_fcn_delete (void *_anal, void* _user, RAnalFunction *fcn) {
RCore *core = (RCore*)_user;
const char *cmd = r_config_get (core->config, "cmd.fcn.delete");
if (cmd && *cmd) {
ut64 oaddr = core->offset;
ut64 addr = fcn->addr;
r_core_seek (core, addr, 1);
r_core_cmd0 (core, cmd);
r_core_seek (core, oaddr, 1);
}
return 0;
}
static int on_fcn_rename(void *_anal, void* _user, RAnalFunction *fcn, const char *oname) {
RCore *core = (RCore*)_user;
const char *cmd = r_config_get (core->config, "cmd.fcn.rename");
if (cmd && *cmd) {
// XXX: wat do with old name here?
ut64 oaddr = core->offset;
ut64 addr = fcn->addr;
r_core_seek (core, addr, 1);
r_core_cmd0 (core, cmd);
r_core_seek (core, oaddr, 1);
}
return 0;
}
static void r_core_debug_breakpoint_hit(RCore *core, RBreakpointItem *bpi) {
const char *cmdbp;
int oecho = core->cons->echo; // should be configurable by user?
@ -204,6 +244,12 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
break;
default:
if (*str>'A') {
// NOTE: functions override flags
RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, str);
if (fcn) {
if (ok) *ok = R_TRUE;
return fcn->addr;
}
#if 0
ut64 addr = r_anal_fcn_label_get (core->anal, core->offset, str);
if (addr != 0) {
@ -812,6 +858,9 @@ R_API int r_core_init(RCore *core) {
core->assembler->num = core->num;
r_asm_set_user_ptr (core->assembler, core);
core->anal = r_anal_new ();
core->anal->cb.on_fcn_new = on_fcn_new;
core->anal->cb.on_fcn_delete = on_fcn_delete;
core->anal->cb.on_fcn_rename = on_fcn_rename;
core->assembler->syscall = \
core->anal->syscall; // BIND syscall anal/asm
r_anal_set_user_ptr (core->anal, core);

View File

@ -690,12 +690,16 @@ static void handle_show_xrefs (RCore *core, RDisasmState *ds) {
}
static void handle_atabs_option(RCore *core, RDisasmState *ds) {
if (ds->atabs) {
int n, i = 0, comma = 0, word = 0;
int brackets = 0;
int size, brackets = 0;
char *t, *b;
if (!ds || !ds->atabs)
return;
size = strlen (ds->asmop.buf_asm)* (ds->atabs+1)*4;
if (size<1)
return;
free (ds->opstr);
ds->opstr = b = malloc (strlen (ds->asmop.buf_asm)* (ds->atabs+1)*4);
ds->opstr = b = malloc (size);
strcpy (b, ds->asmop.buf_asm);
for (; *b; b++, i++) {
if (*b=='(' || *b=='[') brackets++;
@ -717,7 +721,6 @@ static void handle_atabs_option(RCore *core, RDisasmState *ds) {
word++;
}
}
}
static void handle_print_show_cursor (RCore *core, RDisasmState *ds) {
int q = core->print->cur_enabled &&
@ -728,11 +731,16 @@ static void handle_print_show_cursor (RCore *core, RDisasmState *ds) {
}
static void handle_show_functions (RCore *core, RDisasmState *ds) {
if (ds->show_functions) {
RAnalFunction *f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
if (f) {
if (f->addr == ds->at) {
char *sign = r_anal_fcn_to_string (core->anal, f);
RAnalFunction *f;
char *sign;
if (!core || !ds || !ds->show_functions)
return;
f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
if (!f) return;
if (f->addr != ds->at) {
return;
}
sign = r_anal_fcn_to_string (core->anal, f);
if (f->type == R_ANAL_FCN_TYPE_LOC) {
if (ds->show_color) {
r_cons_printf ("%s%s ", ds->color_fline,
@ -777,30 +785,39 @@ static void handle_show_functions (RCore *core, RDisasmState *ds) {
ds->pre = r_str_concat (ds->pre, " ");
ds->stackptr = 0;
if (ds->vars) {
char spaces[32];
RList *args = r_anal_var_list (core->anal, f, 'a');
RList *vars = r_anal_var_list (core->anal, f, 'v');
r_list_join (vars, args);
RAnalVar *var;
RListIter *iter;
// TODO: show first args, and then vars
r_list_foreach (vars, iter, var) {
int idx;
memset (spaces, ' ', sizeof(spaces));
idx = 12-strlen (var->name);
if (idx<0)idx = 0;
spaces[idx] = 0;
if (ds->show_color) {
r_cons_printf ("%s%s %s"Color_RESET,
ds->color_fline, core->cons->vline[LINE_VERT], ds->refline2);
r_cons_printf ("%s; %s %s %s @ %s%s0x%x"Color_RESET"\n",
r_cons_printf ("%s; %s %s %s %s@ %s%s0x%x"Color_RESET"\n",
ds->color_other,
var->kind=='v'?"var":"arg",
var->type,
var->name,
spaces,
core->anal->reg->name[R_REG_NAME_BP],
(var->kind=='v')?"-":"+",
var->delta);
} else {
r_cons_printf ("%s %s",
core->cons->vline[LINE_VERT], ds->refline2);
r_cons_printf ("; %s %s %s @ %s%s0x%x\n",
r_cons_printf ("; %s %s %s %s@ %s%s0x%x\n",
var->kind=='v'?"var":"arg",
var->type,
var->name,
spaces,
core->anal->reg->name[R_REG_NAME_BP],
(var->kind=='v')?"-":"+",
var->delta);
@ -811,9 +828,6 @@ static void handle_show_functions (RCore *core, RDisasmState *ds) {
r_list_free (args);
}
}
}
}
}
static void handle_print_pre (RCore *core, RDisasmState *ds) {
if (ds->show_functions) {
@ -854,18 +868,23 @@ static void handle_print_pre (RCore *core, RDisasmState *ds) {
}
static void handle_show_comments_right (RCore *core, RDisasmState *ds) {
int linelen, maxclen ;
RAnalFunction *f;
RFlagItem *item;
/* show comment at right? */
ds->show_comment_right = 0;
if (ds->show_comments) {
RAnalFunction *f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
RFlagItem *item = r_flag_get_i (core->flags, ds->at);
if (!ds->show_comments)
return;
f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
item = r_flag_get_i (core->flags, ds->at);
ds->comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ds->at);
if (!ds->comment && item && item->comment) {
ds->ocomment = item->comment;
ds->comment = strdup (item->comment);
}
if (ds->comment) {
int linelen, maxclen = strlen (ds->comment)+5;
if (!ds->comment)
return;
maxclen = strlen (ds->comment)+5;
linelen = maxclen;
if (ds->show_comment_right_default) {
if (ds->ocols+maxclen < core->cons->columns) {
@ -923,8 +942,6 @@ static void handle_show_comments_right (RCore *core, RDisasmState *ds) {
}
}
}
}
}
static void handle_show_flags_option(RCore *core, RDisasmState *ds) {
if (ds->show_flags) {

View File

@ -531,6 +531,17 @@ typedef struct r_anal_switch_obj_t {
RList *cases;
} RAnalSwitchOp;
#define RANAL void*
//struct r_anal_t*
#define RANAL_BLOCK void*
//struct r_anal_bb_t*
typedef struct r_anal_callbacks_t {
int (*on_fcn_new) (RANAL, void *user, RAnalFunction *fcn);
int (*on_fcn_delete) (RANAL , void *user, RAnalFunction *fcn);
int (*on_fcn_rename) (RANAL, void *user, RAnalFunction *fcn, const char *oldname);
int (*on_fcn_bb_new) (RANAL, void *user, RAnalFunction *fcn, RANAL_BLOCK bb);
} RAnalCallbacks;
typedef struct r_anal_t {
char *cpu;
int bits;
@ -585,6 +596,7 @@ typedef struct r_anal_t {
#endif
Sdb *sdb_hints; // OK
//RList *hints; // XXX use better data structure here (slist?)
RAnalCallbacks cb;
} RAnal;
typedef struct r_anal_hint_t {
@ -1063,7 +1075,8 @@ R_API int r_anal_fcn_add(RAnal *anal, ut64 addr, ut64 size,
const char *name, int type, RAnalDiff *diff);
R_API int r_anal_fcn_del(RAnal *anal, ut64 addr);
R_API int r_anal_fcn_del_locs(RAnal *anal, ut64 addr);
R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size,
R_API int r_anal_fcn_add_bb(RAnal *anal, RAnalFunction *fcn,
ut64 addr, ut64 size,
ut64 jump, ut64 fail, int type, RAnalDiff *diff);
/* locals */
@ -1095,7 +1108,7 @@ R_API int r_anal_fcn_var_del_byindex (RAnal *a, ut64 fna, const char kind,
R_API int r_anal_fcn_cc(RAnalFunction *fcn);
R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr);
R_API int r_anal_fcn_split_bb(RAnal *anal, RAnalFunction *fcn, RAnalBlock *bb, ut64 addr);
R_API int r_anal_fcn_bb_overlaps(RAnalFunction *fcn, RAnalBlock *bb);
R_API RAnalVar *r_anal_fcn_get_var(RAnalFunction *fs, int num, int dir);
R_API void r_anal_fcn_fit_overlaps (RAnal *anal, RAnalFunction *fcn);

View File

@ -37,7 +37,7 @@ SDB_API SdbList *ls_new(void);
SDB_API SdbListIter *ls_append(SdbList *list, void *data);
SDB_API SdbListIter *ls_prepend(SdbList *list, void *data);
SDB_API int ls_length(SdbList *list);
SDB_API void ls_add_sorted(SdbList *list, void *data, SdbListComparator cmp);
//SDB_API void ls_add_sorted(SdbList *list, void *data, SdbListComparator cmp);
SDB_API void ls_sort(SdbList *list, SdbListComparator cmp);
SDB_API void ls_delete (SdbList *list, SdbListIter *iter);

View File

@ -14,6 +14,19 @@ SDB_API SdbList *ls_new() {
return list;
}
SDB_API void ls_sort(SdbList *list, SdbListComparator cmp) {
SdbListIter *it, *it2;
for (it = list->head; it && it->data; it = it->n) {
for (it2 = it->n; it2 && it2->data; it2 = it2->n) {
if (cmp (it->data, it2->data)>0) {
void *t = it->data;
it->data = it2->data;
it2->data = t;
}
}
}
}
SDB_API void ls_delete (SdbList *list, SdbListIter *iter) {
if (!list || !iter) return;
ls_split_iter (list, iter);

View File

@ -37,7 +37,7 @@ SDB_API SdbList *ls_new(void);
SDB_API SdbListIter *ls_append(SdbList *list, void *data);
SDB_API SdbListIter *ls_prepend(SdbList *list, void *data);
SDB_API int ls_length(SdbList *list);
SDB_API void ls_add_sorted(SdbList *list, void *data, SdbListComparator cmp);
//SDB_API void ls_add_sorted(SdbList *list, void *data, SdbListComparator cmp);
SDB_API void ls_sort(SdbList *list, SdbListComparator cmp);
SDB_API void ls_delete (SdbList *list, SdbListIter *iter);

View File

@ -343,7 +343,7 @@ next_quote:
} else {
/* +[idx]key --> key[idx] + 1 */
/* -[idx]key --> key[idx] - 1 */
char *nstr, numstr[32];
char *nstr, numstr[128];
if (*cmd=='+') {
curnum ++;
} else if (*cmd=='-') {