Implemented command aliases.

This commit is contained in:
Daniel Beer 2011-04-04 17:09:11 +12:00
parent 5e5b118e74
commit f6ecf7bd56
8 changed files with 280 additions and 19 deletions

View File

@ -64,7 +64,7 @@ mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
reader.o vector.o output_util.o expr.o fet_error.o binfile.o \
fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o \
cmddb.o stdcmd.o prog.o flash_bsl.o list.o simio.o simio_tracer.o \
simio_timer.o simio_wdt.o simio_hwmult.o simio_gpio.o
simio_timer.o simio_wdt.o simio_hwmult.o simio_gpio.o aliasdb.o
$(CC) $(LDFLAGS) $(PORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
.c.o:

180
aliasdb.c Normal file
View File

@ -0,0 +1,180 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 Daniel Beer
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "aliasdb.h"
#include "vector.h"
#include "output.h"
#include "util.h"
struct alias {
char src[256];
char dst[256];
};
static struct vector alias_list = {
.ptr = NULL,
.capacity = 0,
.size = 0,
.elemsize = sizeof(struct alias)
};
static int list_is_sorted;
static struct alias *find_alias(const char *name)
{
int i;
for (i = 0; i < alias_list.size; i++) {
struct alias *a =
VECTOR_PTR(alias_list, i, struct alias);
if (!strcasecmp(name, a->src))
return a;
}
return NULL;
}
struct recurse_list {
const char *cmd;
struct recurse_list *next;
};
static int translate_rec(struct recurse_list *l,
const char *command, const char *args,
char *out_cmd, int max_len)
{
struct recurse_list *c;
const struct alias *a;
if (*command == '\\') {
snprintf(out_cmd, max_len, "%s %s", command + 1, args);
return 0;
}
for (c = l; c; c = c->next)
if (!strcasecmp(c->cmd, command)) {
printc_err("recursive alias: %s\n", command);
return -1;
}
a = find_alias(command);
if (a) {
struct recurse_list r;
char tmp_buf[1024];
char *new_args = tmp_buf;
char *cmd;
snprintf(tmp_buf, sizeof(tmp_buf), "%s %s", a->dst, args);
r.next = l;
r.cmd = command;
cmd = get_arg(&new_args);
return translate_rec(&r, cmd, new_args, out_cmd, max_len);
}
snprintf(out_cmd, max_len, "%s %s", command, args);
return 0;
}
int translate_alias(const char *command, const char *args,
char *out_cmd, int max_len)
{
return translate_rec(NULL, command, args, out_cmd, max_len);
}
static int cmp_alias(const void *a, const void *b)
{
const struct alias *aa = (const struct alias *)a;
const struct alias *ab = (const struct alias *)b;
return strcasecmp(aa->src, ab->src);
}
int cmd_alias(char **arg)
{
const char *src = get_arg(arg);
const char *dst = get_arg(arg);
struct alias *a;
struct alias na;
if (!src) { /* List aliases */
int i;
if (!list_is_sorted) {
qsort(alias_list.ptr, alias_list.size,
alias_list.elemsize, cmp_alias);
list_is_sorted = 1;
}
printf("%d aliases defined:\n", alias_list.size);
for (i = 0; i < alias_list.size; i++) {
struct alias *a =
VECTOR_PTR(alias_list, i, struct alias);
printc(" %20s = %s\n", a->src, a->dst);
}
return 0;
}
a = find_alias(src);
if (!dst) { /* Delete alias */
struct alias *end = VECTOR_PTR(alias_list,
alias_list.size - 1, struct alias);
if (!a) {
printc_err("alias: no such alias defined: %s\n", src);
return -1;
}
if (end != a)
memcpy(a, end, sizeof(*a));
vector_pop(&alias_list);
list_is_sorted = 0;
return 0;
}
if (a) { /* Overwrite old alias */
strncpy(a->dst, dst, sizeof(a->dst));
a->dst[sizeof(a->dst) - 1] = 0;
return 0;
}
/* New alias */
strncpy(na.src, src, sizeof(na.src));
na.src[sizeof(na.src) - 1] = 0;
strncpy(na.dst, dst, sizeof(na.dst));
na.dst[sizeof(na.dst) - 1] = 0;
if (vector_push(&alias_list, &na, 1) < 0) {
printc_err("alias: can't allocate memory: %s\n",
strerror(errno));
return -1;
}
list_is_sorted = 0;
return 0;
}

29
aliasdb.h Normal file
View File

@ -0,0 +1,29 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 Daniel Beer
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ALIASDB_H_
#define ALIASDB_H_
/* "alias" command */
int cmd_alias(char **arg);
/* Translate a command using the aliases table. */
int translate_alias(const char *command, const char *args,
char *out_cmd, int max_len);
#endif

12
cmddb.c
View File

@ -27,6 +27,7 @@
#include "sym.h"
#include "stdcmd.h"
#include "simio.h"
#include "aliasdb.h"
const struct cmddb_record commands[] = {
{
@ -260,6 +261,17 @@ const struct cmddb_record commands[] = {
" Change settings of an attached device.\n"
"simio info <name>\n"
" Print status information for an attached device.\n"
},
{
.name = "alias",
.func = cmd_alias,
.help =
"alias\n"
" List all defined aliases.\n"
"alias <name>\n"
" Remove an alias definition.\n"
"alias <name> <command>\n"
" Define a new alias.\n"
}
};

View File

@ -143,6 +143,16 @@ question.
See the section marked \fBADDRESS EXPRESSIONS\fR for more information on
the syntax of expressions.
.IP "\fBalias\fR"
Show a list of defined command aliases.
.IP "\fBalias\fR \fIname\fR"
Remove a previously defined command alias.
.IP "\fBalias\fR \fIname\fR \fIcommand\fR"
Define a command alias. The text \fIcommand\fR will be substituted for
\fIname\fR when looking up commands. The given command text may contain
a command plus arguments, if the entire text is wrapped in quotes when
defining the alias. To avoid alias substitution when interpreting
commands, prefix the command with \\ (a backslash character).
.IP "\fBbreak\fR"
Show a list of active breakpoints. Breakpoints can be added and removed
with the \fBsetbreak\fR and \fBdelbreak\fR commands. Each breakpoint is

View File

@ -35,6 +35,7 @@
#include "stdcmd.h"
#include "reader.h"
#include "opdb.h"
#include "aliasdb.h"
#define MAX_READER_LINE 1024
@ -124,8 +125,16 @@ static int do_command(char *arg, int interactive)
cmd_text = get_arg(&arg);
if (cmd_text) {
char translated[1024];
struct cmddb_record cmd;
if (translate_alias(cmd_text, arg,
translated, sizeof(translated)) < 0)
return -1;
arg = translated;
cmd_text = get_arg(&arg);
if (!cmddb_get(cmd_text, &cmd)) {
int old = in_reader_loop;
int ret;

View File

@ -57,30 +57,39 @@ int vector_realloc(struct vector *v, int capacity)
return 0;
}
static int size_for(struct vector *v, int needed)
{
int cap = needed;
/* Find the smallest power of 2 which is greater than the
* necessary capacity.
*/
while (cap & (cap - 1))
cap &= (cap - 1);
if (cap < needed)
cap <<= 1;
/* Don't allocate fewer than 8 elements */
if (cap < 8)
cap = 8;
if (v->capacity >= cap && v->capacity <= cap * 2)
return 0;
if (vector_realloc(v, cap) < 0)
return -1;
return 0;
}
int vector_push(struct vector *v, const void *data, int count)
{
int needed = v->size + count;
assert (count >= 0);
if (needed > v->capacity) {
int cap = needed;
/* Find the smallest power of 2 which is greater than the
* necessary capacity.
*/
while (cap & (cap - 1))
cap &= (cap - 1);
if (cap < needed)
cap <<= 1;
/* Don't allocate fewer than 8 elements */
if (cap < 8)
cap = 8;
if (vector_realloc(v, cap) < 0)
return -1;
}
if (size_for(v, needed) < 0)
return -1;
memcpy((char *)v->ptr + v->size * v->elemsize,
data,
@ -89,3 +98,12 @@ int vector_push(struct vector *v, const void *data, int count)
return 0;
}
void vector_pop(struct vector *v)
{
if (v->size <= 0)
return;
size_for(v, v->size - 1);
v->size--;
}

View File

@ -47,6 +47,9 @@ int vector_realloc(struct vector *v, int capacity);
*/
int vector_push(struct vector *v, const void *data, int count);
/* Remove the last element from a vector. */
void vector_pop(struct vector *v);
/* Dereference a vector, giving an expression for the element of type t at
* position i in vector v. Use as follows:
*