summaryrefslogtreecommitdiff
path: root/phpdbg_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'phpdbg_cmd.c')
-rw-r--r--phpdbg_cmd.c201
1 files changed, 111 insertions, 90 deletions
diff --git a/phpdbg_cmd.c b/phpdbg_cmd.c
index b678d393ab..4e6ef048b8 100644
--- a/phpdbg_cmd.c
+++ b/phpdbg_cmd.c
@@ -26,6 +26,23 @@
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
+static inline const char *phpdbg_command_name(const phpdbg_command_t *command, char *buffer) {
+ size_t pos = 0;
+
+ if (command->parent) {
+ memcpy(&buffer[pos], command->parent->name, command->parent->name_len);
+ pos += command->parent->name_len;
+ memcpy(&buffer[pos], " ", sizeof(" ")-1);
+ pos += (sizeof(" ")-1);
+ }
+
+ memcpy(&buffer[pos], command->name, command->name_len);
+ pos += command->name_len;
+ buffer[pos] = 0;
+
+ return buffer;
+}
+
PHPDBG_API const char *phpdbg_get_param_type(const phpdbg_param_t *param TSRMLS_DC) /* {{{ */
{
switch (param->type) {
@@ -493,115 +510,87 @@ PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param)
PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack, char **why TSRMLS_DC) {
if (command && command->args) {
+ char buffer[128] = {0,};
const phpdbg_param_t *top = (stack != NULL) ? *stack : NULL;
const char *arg = command->args;
- size_t expected = strlen(command->args),
- received = 0L;
+ size_t least = 0L,
+ received = 0L,
+ current = 0L;
zend_bool optional = 0;
- if (*arg == '|') {
- expected--;
- optional = 1;
+ /* check for arg spec */
+ if (!(arg) || !(*arg))
+ return SUCCESS;
+
+ least = 0L;
+
+ /* count least amount of arguments */
+ while (arg && *arg) {
+ if (arg[0] == '|') {
+ break;
+ }
+ least++;
arg++;
}
- if (arg && !top && !optional) {
- asprintf(why,
- "%s expected arguments and received none", command->name);
- return FAILURE;
- }
-
- while (top && arg) {
+ arg = command->args;
+
+#define verify_arg(e, a, t) if (!(a)) { \
+ if (!optional) { \
+ asprintf(why, \
+ "%s expected %s and got nothing at parameter %lu", \
+ phpdbg_command_name(command, buffer), \
+ (e), \
+ current); \
+ return FAILURE;\
+ } \
+} else if ((a)->type != (t)) { \
+ asprintf(why, \
+ "%s expected %s and got %s at parameter %lu", \
+ phpdbg_command_name(command, buffer), \
+ (e),\
+ phpdbg_get_param_type((a) TSRMLS_CC), \
+ current); \
+ return FAILURE; \
+}
+ while (arg) {
+ current++;
+
switch (*arg) {
- case '|': {
- expected--;
+ case '|': {
+ current--;
optional = 1;
arg++;
} continue;
- case 'i': if (top->type != STR_PARAM) {
- asprintf(why,
- "%s expected raw input and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 's': if (top->type != STR_PARAM) {
- asprintf(why,
- "%s expected string and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 'n': if (top->type != NUMERIC_PARAM) {
- asprintf(why,
- "%s expected number and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 'm': if (top->type != METHOD_PARAM) {
- asprintf(why,
- "%s expected method and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 'a': if (top->type != ADDR_PARAM) {
- asprintf(why,
- "%s expected address and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 'f': if (top->type != FILE_PARAM) {
- asprintf(why,
- "%s expected file:line and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 'c': if (top->type != COND_PARAM) {
- asprintf(why,
- "%s expected condition and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } break;
-
- case 'b': if (top->type != NUMERIC_PARAM) {
- asprintf(why,
- "%s expected boolean and got %s at parameter %lu",
- command->name, phpdbg_get_param_type(top TSRMLS_CC),
- (command->args - arg) + 1);
- return FAILURE;
- } else if (top->num > 1 || top->num < 0) {
- asprintf(why,
- "%s expected boolean and got number at parameter %lu",
- command->name,
- (command->args - arg) + 1);
- return FAILURE;
- } break;
+ case 'i': verify_arg("raw input", top, STR_PARAM); break;
+ case 's': verify_arg("string", top, STR_PARAM); break;
+ case 'n': verify_arg("number", top, NUMERIC_PARAM); break;
+ case 'm': verify_arg("method", top, METHOD_PARAM); break;
+ case 'a': verify_arg("address", top, ADDR_PARAM); break;
+ case 'f': verify_arg("file:line", top, FILE_PARAM); break;
+ case 'c': verify_arg("condition", top, COND_PARAM); break;
+ case 'b': verify_arg("boolean", top, NUMERIC_PARAM); break;
case '*': { /* do nothing */ } break;
}
- top = top->next;
+
+ if (top ) {
+ top = top->next;
+ } else break;
+
received++;
arg++;
}
- if ((received < expected) && (arg && *arg) && !optional) {
+#undef verify_arg
+
+ if ((received < least)) {
asprintf(why,
- "%s expected %lu arguments (%s) and received %lu",
- command->name,
- expected,
+ "%s expected at least %lu arguments (%s) and received %lu",
+ phpdbg_command_name(command, buffer),
+ least,
command->args,
received);
return FAILURE;
@@ -627,15 +616,21 @@ PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *
matches++;
}
} else {
+
/* match full command name */
if (memcmp(command->name, name->str, name->len) == SUCCESS) {
if (matches < 3) {
matched[matches] = command;
matches++;
+
+ /* exact match */
+ if (name->len == command->name_len)
+ break;
} else break;
}
}
}
+
command++;
}
@@ -655,10 +650,36 @@ PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *
} break;
default: {
+ char *list = NULL;
+ zend_uint it = 0;
+ size_t pos = 0;
+
+ while (it < matches) {
+ if (!list) {
+ list = malloc(
+ matched[it]->name_len + 1 +
+ ((it+1) < matches ? sizeof(", ")-1 : 0));
+ } else {
+ list = realloc(list,
+ (pos + matched[it]->name_len) + 1 +
+ ((it+1) < matches ? sizeof(", ")-1 : 0));
+ }
+ memcpy(&list[pos], matched[it]->name, matched[it]->name_len);
+ pos += matched[it]->name_len;
+ if ((it+1) < matches) {
+ memcpy(&list[pos], ", ", sizeof(", ")-1);
+ pos += (sizeof(", ") - 1);
+ }
+
+ list[pos] = 0;
+ it++;
+ }
+
asprintf(
why,
- "The command %s is ambigious, matching %lu commands",
- name->str, matches);
+ "The command %s is ambigious, matching %lu commands (%s)",
+ name->str, matches, list);
+ free(list);
} return NULL;
}