diff options
| -rw-r--r-- | lib/Makefile.am | 2 | ||||
| -rw-r--r-- | lib/ccdbg-debug.c | 5 | ||||
| -rw-r--r-- | lib/ccdbg-debug.h | 2 | ||||
| -rw-r--r-- | lib/ccdbg-flash.c | 8 | ||||
| -rw-r--r-- | lib/ccdbg-memory.c | 54 | ||||
| -rw-r--r-- | lib/ccdbg-rom.c | 63 | ||||
| -rw-r--r-- | lib/ccdbg-state.c | 128 | ||||
| -rw-r--r-- | lib/ccdbg.h | 43 | ||||
| -rw-r--r-- | s51/s51-command.c | 74 | ||||
| -rw-r--r-- | s51/s51-parse.c | 71 | ||||
| -rw-r--r-- | s51/s51.h | 23 | 
11 files changed, 396 insertions, 77 deletions
| diff --git a/lib/Makefile.am b/lib/Makefile.am index 16f5b921..ba6f9725 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,5 +11,7 @@ libcc_a_SOURCES = \  	ccdbg-io.c \  	ccdbg-manual.c \  	ccdbg-memory.c \ +	ccdbg-rom.c \ +	ccdbg-state.c \  	cp-usb.c \  	cp-usb-async.c diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c index 8f6f9e11..847361c7 100644 --- a/lib/ccdbg-debug.c +++ b/lib/ccdbg-debug.c @@ -47,7 +47,8 @@ ccdbg_debug(int level, char *format, ...)  }  void -ccdbg_flush(void) +ccdbg_flush(int level)  { -	fflush(stdout); +	if (ccdbg_level & level) +		fflush(stdout);  } diff --git a/lib/ccdbg-debug.h b/lib/ccdbg-debug.h index a09148d3..0b5b44c1 100644 --- a/lib/ccdbg-debug.h +++ b/lib/ccdbg-debug.h @@ -39,6 +39,6 @@ void  ccdbg_clear_debug(int level);  void -ccdbg_flush(void); +ccdbg_flush(int level);  #endif /* _CCDBG_DEBUG_H_ */ diff --git a/lib/ccdbg-flash.c b/lib/ccdbg-flash.c index 8b3390c7..8a586a21 100644 --- a/lib/ccdbg-flash.c +++ b/lib/ccdbg-flash.c @@ -288,13 +288,14 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)  		ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr);  		ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time); - +#if 0  		ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in ram\n", this_time);  		ccdbg_read_memory(dbg, ram_addr, verify, this_time);  		if (memcmp (image->data + start, verify, this_time) != 0) {  			fprintf(stderr, "ram verify failed\n");  			return 1;  		} +#endif  		flash_addr = image->address + start;  		flash_word_addr = flash_addr >> 1; @@ -324,10 +325,13 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)  		status = ccdbg_resume(dbg);  		for (times = 0; times < 10; times++) {  			status = ccdbg_read_status(dbg); -			ccdbg_debug(CC_DEBUG_FLASH, "chip status is 0x%02x\n", status); +			ccdbg_debug(CC_DEBUG_FLASH, "."); +			ccdbg_flush(CC_DEBUG_FLASH);  			if ((status & CC_STATUS_CPU_HALTED) != 0)  				break; +			usleep(10000);  		} +		ccdbg_debug(CC_DEBUG_FLASH, "\n");  		if (times == 10) {  			fprintf(stderr, "flash page timed out\n");  			return 1; diff --git a/lib/ccdbg-memory.c b/lib/ccdbg-memory.c index d74726fb..20a24799 100644 --- a/lib/ccdbg-memory.c +++ b/lib/ccdbg-memory.c @@ -23,14 +23,9 @@   */  static uint8_t	memory_init[] = { -	2,	MOV_direct_A,		0x7f, -	3,	MOV_direct1_direct2,	0x7e, SFR_DPL0, -	3,	MOV_direct1_direct2,	0x7d, SFR_DPH0, -	3,	MOV_direct1_direct2,	0x7c, SFR_DPL1, -	3,	MOV_direct1_direct2,	0x7b, SFR_DPH1,  	3,	MOV_DPTR_data16,	0,	0, -#define HIGH_START	21 -#define LOW_START	22 +#define HIGH_START	2 +#define LOW_START	3  	0,  }; @@ -49,19 +44,13 @@ static uint8_t read8[] = {  	0,  }; -static uint8_t	memory_fini[] = { -	2,	MOV_A_direct,		0x7f, -	3,	MOV_direct1_direct2,	SFR_DPL0, 0x7e, -	3,	MOV_direct1_direct2,	SFR_DPH0, 0x7d, -	3,	MOV_direct1_direct2,	SFR_DPL1, 0x7c, -	3,	MOV_direct1_direct2,	SFR_DPH1, 0x7b, -	0, -}; -  uint8_t  ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  {  	int i, nl = 0; +	struct ccstate state; + +	ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);  	memory_init[HIGH_START] = addr >> 8;  	memory_init[LOW_START] = addr;  	(void) ccdbg_execute(dbg, memory_init); @@ -70,7 +59,7 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  		ccdbg_execute(dbg, write8);  		if ((i & 0xf) == 0xf) {  			ccdbg_debug(CC_DEBUG_MEMORY, "."); -			ccdbg_flush(); +			ccdbg_flush(CC_DEBUG_MEMORY);  			nl = 1;  		}  		if ((i & 0xff) == 0xff) { @@ -78,7 +67,7 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  			nl = 0;  		}  	} -	(void) ccdbg_execute(dbg, memory_fini); +	ccdbg_state_restore(dbg, &state);  	if (nl)  		ccdbg_debug(CC_DEBUG_MEMORY, "\n");  	return 0; @@ -88,6 +77,13 @@ uint8_t  ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  {  	int i, nl = 0; +	struct ccstate state; + +	if (ccdbg_rom_contains(dbg, addr, nbytes)) { +		ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes); +		return 0; +	} +	ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);  	memory_init[HIGH_START] = addr >> 8;  	memory_init[LOW_START] = addr;  	(void) ccdbg_execute(dbg, memory_init); @@ -95,7 +91,7 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  		*bytes++ = ccdbg_execute(dbg, read8);  		if ((i & 0xf) == 0xf) {  			ccdbg_debug(CC_DEBUG_MEMORY, "."); -			ccdbg_flush(); +			ccdbg_flush(CC_DEBUG_MEMORY);  			nl = 1;  		}  		if ((i & 0xff) == 0xff) { @@ -103,7 +99,8 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  			nl = 0;  		}  	} -	(void) ccdbg_execute(dbg, memory_fini); +	ccdbg_state_replace_xmem(dbg, &state, addr, bytes, nbytes); +	ccdbg_state_restore(dbg, &state);  	if (nl)  		ccdbg_debug(CC_DEBUG_MEMORY, "\n");  	return 0; @@ -135,16 +132,6 @@ ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)  	return image;  } -static uint8_t sfr_init[] = { -	2,	MOV_direct_A,		0x7f, -	0, -}; - -static uint8_t sfr_fini[] = { -	2,	MOV_A_direct,		0x7f, -	0, -}; -  static uint8_t sfr_read[] = {  	2,	MOV_A_direct,		0,  #define SFR_READ_ADDR	2 @@ -162,12 +149,15 @@ uint8_t  ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)  {  	int	i; -	(void) ccdbg_execute(dbg, sfr_init); +	struct ccstate state; + +	ccdbg_state_save(dbg, &state, CC_STATE_ACC);  	for (i = 0; i < nbytes; i++) {  		sfr_read[SFR_READ_ADDR] = addr + i;  		*bytes++ = ccdbg_execute(dbg, sfr_read);  	} -	(void) ccdbg_execute(dbg, sfr_fini); +	ccdbg_state_replace_sfr(dbg, &state, addr, bytes, nbytes); +	ccdbg_state_restore(dbg, &state);  	return 0;  } diff --git a/lib/ccdbg-rom.c b/lib/ccdbg-rom.c new file mode 100644 index 00000000..4559b4e7 --- /dev/null +++ b/lib/ccdbg-rom.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ccdbg.h" + +uint8_t +ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom) +{ +	if (dbg->rom) +		ccdbg_hex_image_free(dbg->rom); +	dbg->rom = rom; +	return 0; +} + +uint8_t +ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes) +{ +	struct hex_image *rom = dbg->rom; +	if (!rom) +		return 0; +	if (addr < rom->address || rom->address + rom->length < addr + nbytes) +		return 0; +	return 1; +} + +uint8_t +ccdbg_rom_replace_xmem(struct ccdbg *dbg, +		       uint16_t addr, uint8_t *bytes, int nbytes) +{ +	struct hex_image *rom = dbg->rom; +	if (!rom) +		return 0; +	 +	if (rom->address < addr + nbytes && addr < rom->address + rom->length) { +		int	start, stop; + +		start = addr; +		if (addr < rom->address) +			start = rom->address; +		stop = addr + nbytes; +		if (rom->address + rom->length < stop) +			stop = rom->address + rom->length; +		memcpy(bytes + start - addr, rom->data + start - rom->address, +		       stop - start); +		return 1; +	} +	return 0; +} diff --git a/lib/ccdbg-state.c b/lib/ccdbg-state.c new file mode 100644 index 00000000..9aca8d2e --- /dev/null +++ b/lib/ccdbg-state.c @@ -0,0 +1,128 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ccdbg.h" + +static uint8_t save_acc[] = { +	1,	NOP, +	0 +}; + +static uint8_t save_sfr[] = { +	2,	MOV_A_direct,	0, +#define SAVE_SFR_ADDR	2 +	0, +}; + +struct sfr_state { +	uint8_t		address; +	uint16_t	mask; +	char		*name; +}; + +static struct sfr_state	sfrs[CC_STATE_NSFR] = { +	{ SFR_DPL0,	CC_STATE_DP,	"dpl0" }, +	{ SFR_DPH0,	CC_STATE_DP,	"dph0" }, +	{ SFR_DPL1,	CC_STATE_DP,	"dpl1" }, +	{ SFR_DPH1,	CC_STATE_DP,	"dph1" }, +	{ PSW(0),	CC_STATE_PSW,	"psw"  }, +}; + +uint8_t +ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask) +{ +	int	i; + +	mask |= CC_STATE_ACC; +	if (mask & CC_STATE_ACC) +		state->acc = ccdbg_execute(dbg, save_acc); +	for (i = 0; i < CC_STATE_NSFR; i++) { +		if (sfrs[i].mask & mask) { +			save_sfr[SAVE_SFR_ADDR] = sfrs[i].address; +			state->sfr[i] = ccdbg_execute(dbg, save_sfr); +		} +	} +	state->mask = mask; +	return 0; +} + +static uint8_t restore_sfr[] = { +	3,	MOV_direct_data,	0,	0, +#define RESTORE_SFR_ADDR	2 +#define RESTORE_SFR_DATA	3 +	0 +}; + +static uint8_t restore_acc[] = { +	2,	MOV_A_data,	0, +#define RESTORE_ACC_DATA	2 +	0 +}; + +uint8_t +ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state) +{ +	int i; +	for (i = CC_STATE_NSFR - 1; i >= 0; i--) { +		if (sfrs[i].mask & state->mask) { +			restore_sfr[RESTORE_SFR_ADDR] = sfrs[i].address; +			restore_sfr[RESTORE_SFR_DATA] = state->sfr[i]; +			ccdbg_execute(dbg, restore_sfr); +		} +	} +	if (state->mask & CC_STATE_ACC) { +		restore_acc[RESTORE_ACC_DATA] = state->acc; +		ccdbg_execute(dbg, restore_acc); +	} +	state->mask = 0; +	return 0; +} + +static void +ccdbg_state_replace(uint16_t sfr_addr, uint8_t sfr, char *name, +		    uint16_t addr, uint8_t *bytes, int nbytes) +{ +	sfr_addr += 0xdf00; + +	if (addr <= sfr_addr && sfr_addr < addr + nbytes) { +		fprintf(stderr, "replacing %s at 0x%04x - read 0x%02x saved 0x%02x\n", +			name, sfr_addr, bytes[sfr_addr - addr], sfr); +		bytes[sfr_addr - addr] = sfr; +	} +} + +void +ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, +			 uint16_t addr, uint8_t *bytes, int nbytes) +{ +	int i; +	if (state->mask & CC_STATE_ACC) +		ccdbg_state_replace(ACC(0), state->acc, "acc", +				    addr, bytes, nbytes); +	for (i = 0; i < CC_STATE_NSFR; i++) +		if (state->mask & sfrs[i].mask) +			ccdbg_state_replace(sfrs[i].address, state->sfr[i], +					    sfrs[i].name, addr, bytes, nbytes); +} + +void +ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, +			uint8_t addr, uint8_t *bytes, int nbytes) +{ +	ccdbg_state_replace_xmem(dbg, state, (uint16_t) addr + 0xdf00, bytes, nbytes); +} diff --git a/lib/ccdbg.h b/lib/ccdbg.h index 203b5aeb..241c4eec 100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@ -39,6 +39,7 @@  /* 8051 instructions   */ +#define NOP			0x00  #define MOV_direct_data		0x75  #define LJMP			0x02  #define MOV_Rn_data(n)		(0x78 | (n)) @@ -99,6 +100,9 @@  /* Bit-addressable accumulator */  #define ACC(bit)		(0xE0 | (bit)) +/* Bit-addressable status word */ +#define PSW(bit)		(0xD0 | (bit)) +  #define CP_USB_ASYNC  struct ccdbg { @@ -107,6 +111,7 @@ struct ccdbg {  #else  	struct cp_usb *cp;  #endif +	struct hex_image *rom;  };  /* Intel hex file format data @@ -130,6 +135,18 @@ struct hex_image {  	uint8_t		data[0];  }; +#define CC_STATE_ACC	0x1 +#define CC_STATE_PSW	0x2 +#define CC_STATE_DP	0x4 + +#define CC_STATE_NSFR	5 + +struct ccstate { +	uint16_t	mask; +	uint8_t		acc; +	uint8_t		sfr[CC_STATE_NSFR]; +}; +  #define HEX_RECORD_NORMAL		0x00  #define HEX_RECORD_EOF			0x01  #define HEX_RECORD_EXTENDED_ADDRESS	0x02 @@ -337,4 +354,30 @@ ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes);  uint8_t  ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); +/* ccdbg-rom.c */ +uint8_t +ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom); + +uint8_t +ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes); + +uint8_t +ccdbg_rom_replace_xmem(struct ccdbg *dbg, +		       uint16_t addrp, uint8_t *bytesp, int nbytes); + +/* ccdbg-state.c */ +uint8_t +ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask); + +uint8_t +ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state); + +void +ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, +			 uint16_t addr, uint8_t *bytes, int nbytes); + +void +ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, +			uint8_t addr, uint8_t *bytes, int nbytes); +  #endif /* _CCDBG_H_ */ diff --git a/s51/s51-command.c b/s51/s51-command.c index 25328f1e..63d142f4 100644 --- a/s51/s51-command.c +++ b/s51/s51-command.c @@ -69,12 +69,12 @@ command_quit (int argc, char **argv)  }  static void -dump_bytes(uint8_t *memory, int length, uint16_t start) +dump_bytes(uint8_t *memory, int length, uint16_t start, char *format)  {  	int group, i;  	for (group = 0; group < length; group += 8) { -		s51_printf("0x%04x ", start + group); +		s51_printf(format, start + group);  		for (i = group; i < length && i < group + 8; i++)  			s51_printf("%02x ", memory[i]);  		for (; i < group + 8; i++) @@ -105,7 +105,7 @@ command_di (int argc, char **argv)  		return command_error;  	length = (int) end - (int) start + 1;  	status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length); -	dump_bytes(memory, length, start); +	dump_bytes(memory, length, start, "0x%02x ");  	return command_success;  } @@ -125,7 +125,7 @@ command_ds (int argc, char **argv)  		return command_error;  	length = (int) end - (int) start + 1;  	status = ccdbg_read_sfr(s51_dbg, start, memory, length); -	dump_bytes(memory, length, start); +	dump_bytes(memory, length, start, "0x%02x ");  	return command_success;  } @@ -145,7 +145,7 @@ command_dx (int argc, char **argv)  		return command_error;  	length = (int) end - (int) start + 1;  	status = ccdbg_read_memory(s51_dbg, start, memory, length); -	dump_bytes(memory, length, start); +	dump_bytes(memory, length, start, "0x%04x ");  	return command_success;  } @@ -174,6 +174,7 @@ enum command_result  command_file (int argc, char **argv)  {  	struct hex_file *hex; +	struct hex_image *image;  	FILE *file;  	if (argc != 2) @@ -189,7 +190,10 @@ command_file (int argc, char **argv)  		ccdbg_hex_file_free(hex);  		return command_error;  	} -	start_address = hex->records[0]->address; +	image = ccdbg_hex_image_create(hex); +	ccdbg_hex_file_free(hex); +	start_address = image->address; +	ccdbg_set_rom(s51_dbg, image);  	return command_success;  } @@ -474,6 +478,12 @@ command_halt (int argc, char **argv)  }  enum command_result +command_stop (int argc, char **argv) +{ +	return command_success; +} + +enum command_result  command_reset (int argc, char **argv)  {  	ccdbg_debug_mode(s51_dbg); @@ -511,6 +521,58 @@ command_status(int argc, char **argv)  	return command_success;  } +static enum command_result +info_breakpoints(int argc, char **argv) +{ +	int b; +	uint16_t address; +	enum command_result result; + +	if (argc == 1) { +		s51_printf("Num Type       Disp Hit   Cnt   Address  What\n"); +		for (b = 0; b < CC_NUM_BREAKPOINTS; b++) +			if (breakpoints[b].enabled) { +				s51_printf("%-3d fetch      %s 1     1     0x%04x   uc::disass() unimplemented\n", +					   b, +					   breakpoints[b].temporary ? "del " : "keep", +					   breakpoints[b].address); +			} +		return command_success; +	} +	 +} + +static enum command_result +info_help(int argc, char **argv); + +static struct command_function infos[] = { +	{ "breakpoints", "b", info_breakpoints, "[b]reakpoints", +		"List current breakpoints\n" }, +	{ "help",   "?",  info_help,	"help", +		"Print this list\n" }, +	 +	{ NULL, NULL, NULL, NULL, NULL }, +}; + +static enum command_result +info_help(int argc, char **argv) +{ +	return command_function_help(infos, argc, argv); +} + +enum command_result +command_info(int argc, char **argv) +{ +	struct command_function *func; +	 +	if (argc < 2) +		return command_error; +	func = command_string_to_function(infos, argv[1]); +	if (!func) +		return command_syntax; +	return (*func->func)(argc-1, argv+1); +} +  enum command_result  cc_wait(void)  { diff --git a/s51/s51-parse.c b/s51/s51-parse.c index d0bfb45b..749d7bd8 100644 --- a/s51/s51-parse.c +++ b/s51/s51-parse.c @@ -18,14 +18,6 @@  #include "s51.h" -struct command_function { -	char			*name; -	char			*alias; -	enum command_result	(*func)(int argc, char **argv); -	char			*usage; -	char			*help; -}; -  static struct command_function functions[] = {  	{ "help",   "?",  command_help,	"help",		"Print this list\n" },  	{ "quit",   "q",  command_quit,	"[q]uit",	"Quit\n" }, @@ -50,6 +42,8 @@ static struct command_function functions[] = {  		"Clear break point\n" },  	{ "run",    "r",  command_run, "[r]un [start] [stop]",  		"Run with optional start and temp breakpoint addresses\n" }, +	{ "go",     "g",  command_run, "[g]o [start] [stop]", +		"Run with optional start and temp breakpoint addresses\n" },  	{ "next",   "n",  command_next, "[n]ext",  		"Step over one instruction, past any call\n" },  	{ "step",   "s",  command_step, "[s]tep", @@ -62,10 +56,13 @@ static struct command_function functions[] = {  		"Reset the CPU\n" },  	{ "status","status",command_status, "status",  		"Display CC1111 debug status\n" }, +	{ "info",   "i",  command_info, "[i]info", +		"Get information\n" }, +	{ "stop",  "stop", command_stop, "stop", +		"Ignored\n" }, +	{ NULL, NULL, NULL, NULL, NULL },  }; -#define NUM_FUNCTIONS (sizeof functions / sizeof functions[0]) -  #ifndef FALSE  #define FALSE 0  #define TRUE 1 @@ -106,17 +103,41 @@ string_to_int(char *s, int *v)      return TRUE;  } -static struct command_function * -command_string_to_function(char *name) +struct command_function * +command_string_to_function(struct command_function *functions, char *name)  {  	int i; -	for (i = 0; i < NUM_FUNCTIONS; i++) +	for (i = 0; functions[i].name; i++)  		if (!strcmp(name, functions[i].name) ||  		    !strcmp(name, functions[i].alias))  			return &functions[i];  	return NULL;  }     +enum command_result +command_function_help(struct command_function *functions, int argc, char **argv) +{ +	int i; +	struct command_function *func; + +	if (argc == 1) { +		for (i = 0; functions[i].name; i++) +			s51_printf("%-10s%s\n", functions[i].name, +			       functions[i].usage); +	} else { +		for (i = 1; i < argc; i++) { +			func = command_string_to_function(functions, argv[i]); +			if (!func) { +				s51_printf("%-10s unknown command\n", argv[i]); +				return command_syntax; +			} +			s51_printf("%-10s %s\n%s", func->name, +			       func->usage, func->help); +		} +	} +	return command_debug; +} +  static int  command_split_into_words(char *line, char **argv)  { @@ -153,28 +174,10 @@ command_split_into_words(char *line, char **argv)  enum command_result  command_help(int argc, char **argv)  { -	int i; -	struct command_function *func; - -	if (argc == 1) { -		for (i = 0; i < NUM_FUNCTIONS; i++) -			s51_printf("%-10s%s\n", functions[i].name, -			       functions[i].usage); -	} else { -		for (i = 1; i < argc; i++) { -			func = command_string_to_function(argv[i]); -			if (!func) { -				s51_printf("%-10s unknown command\n", argv[i]); -				return command_syntax; -			} -			s51_printf("%-10s %s\n%s", func->name, -			       func->usage, func->help); -		} -	} -	return command_debug; +	return command_function_help(functions, argc, argv);  } -static void +void  command_syntax_error(int argc, char **argv)  {  	s51_printf("Syntax error in:"); @@ -206,7 +209,7 @@ command_read (void)  		s51_interrupted = 0;  		argc = command_split_into_words(line, argv);  		if (argc > 0) { -			func = command_string_to_function(argv[0]); +			func = command_string_to_function(functions, argv[0]);  			if (!func)  				command_syntax_error(argc, argv);  			else @@ -27,6 +27,23 @@ enum command_result {  	command_success, command_debug, command_syntax, command_interrupt, command_error,  }; +struct command_function { +	char			*name; +	char			*alias; +	enum command_result	(*func)(int argc, char **argv); +	char			*usage; +	char			*help; +}; + +struct command_function * +command_string_to_function(struct command_function *functions, char *name); + +enum command_result +command_function_help(struct command_function *functions, int argc, char **argv); + +void +command_syntax_error(int argc, char **argv); +  enum command_result  command_quit (int argc, char **argv); @@ -34,6 +51,9 @@ enum command_result  command_help (int argc, char **argv);  enum command_result +command_stop (int argc, char **argv); + +enum command_result  command_di (int argc, char **argv);  enum command_result @@ -82,6 +102,9 @@ enum command_result  command_status (int argc, char **argv);  enum command_result +command_info (int argc, char **argv); + +enum command_result  cc_wait(void);  void | 
