#include "cutils/cstring.h"
#include "command.h"
-array_t *read_word(command_t *self, char *line, int pstart, int pstop);
+array_t *read_word(command_t *self,const char line[],int pstart,int pstop);
command_t *new_command(command_type type) {
command_t *self = malloc(sizeof(command_t));
}
}
-int command_read_str(command_t *self, char *line, int pstart, int pstop) {
+int command_read_count(command_t *self, const char line[]) {
+ int howmany_read = 0;
+ int in_params = 0;
+ int escaped = 0;
+ for (size_t i = 0 ; line[i] ; i++) {
+ if (!in_params) {
+ if (line[i] == ':')
+ in_params = 1;
+
+ continue;
+ }
+
+ if (line[i] == '"')
+ escaped = !escaped;
+ if (escaped)
+ continue;
+
+ if (line[i] == ',') {
+ // parameter found
+ howmany_read++;
+ }
+ }
+
+ // Final parameter
+ if (in_params)
+ howmany_read++;
+
+ return howmany_read;
+}
+
+int command_read_str(command_t *self,const char line[],int pstart,int pstop) {
if (!self->data)
self->data = new_array(sizeof(char *), 1);
return ok;
}
-int command_read_int(command_t *self, char *line, int pstart, int pstop) {
+int command_read_int(command_t *self,const char line[],int pstart,int pstop) {
if (!self->data)
self->data = new_array(sizeof(char *), 1);
return ok;
}
-int command_read_file(command_t *self, char *line, int pstart, int pstop) {
+int command_read_file(command_t *self,const char line[],int pstart,int pstop) {
if (!self->data)
self->data = new_array(sizeof(char *), 1);
return ok;
}
-array_t *read_word(command_t *self, char *line, int pstart, int pstop) {
+array_t *read_word(command_t *self,const char line[],int pstart,int pstop) {
array_t *tmp = new_array(sizeof(char *), 1);
int howmany_read = 0;
* blablabla
*/
typedef enum {
- TICK,
- DISPLAY,
- READFILE,
- UNKNOWN,
- INVALID,
- FILE404,
- QUIT
+ COMMAND_TICK,
+ COMMAND_DISPLAY,
+ COMMAND_READFILE,
+ COMMAND_MAP,
+ COMMAND_LIFE,
+ COMMAND_BITS,
+ COMMAND_PATH,
+ COMMAND_QUIT,
+
+ // error management:
+ COMMAND_UNKNOWN,
+ COMMAND_INVALID,
+ COMMAND_FILE404
} command_type;
/**
// COMMAND:param1,param2,...
// pstop 0 -> continue until no more param
// white space ignored (trimmed)
-int command_read_str(command_t *self, char *line, int pstart, int pstop);
+int command_read_count(command_t *self, const char line[]);
-int command_read_int(command_t *self, char *line, int pstart, int pstop);
+int command_read_str(command_t *self,const char line[],int pstart,int pstop);
-int command_read_file(command_t *self, char *line, int pstart, int pstop);
+int command_read_int(command_t *self,const char line[],int pstart,int pstop);
+
+int command_read_file(command_t *self,const char line[],int pstart,int pstop);
#endif /* COMMAND_H */
#include "cutils/cstring.h"
#include "reader.h"
+// Commands are given in the form of:
+// KEYWORD
+// or:
+// KEYWORD: [parameters]
+//
+// Parameters are given in the form of:
+// int_parameter1, int_parameter2...
+// or:
+// "string parameter", "file parameter"
+//
+// Note that white space around the separators (':' or ',') are allowed.
+//
+// Known commands:
+// > . = will process a tick in the game engine
+// > display = will toggle display (debug) mode
+// > readfile : "file1..." = will read commands from the given file(s)
+// > map : width, height = will setup the map (and reset the path)
+// > life : lives = will set the number of life points
+// > bits : bit_amount = will set the current bits (money) balance
+// > path : x1,y1,x2,y2.. = will setup the enemies path (cumulative)
+// > quit = will immediately exit the game
// TODO: configuration:
-// map size
-// path: 1,1;1,2;1,3;
-// basic: setMoney, setLife, start...
// tower: configTower('1', ...)
// enemy: configEnemy('a', ...)
+int is_cmd(cstring_t *line, const char cmd[]) {
+ if (cstring_starts_with(line->string, cmd, 0)) {
+ int first_non_space = strlen(cmd);
+ while (line->string[first_non_space] == ' ')
+ first_non_space++;
+
+ char car = line->string[first_non_space];
+ if ((car == ':') || (car == '\0'))
+ return 1;
+ }
+
+ return 0;
+}
+
command_t *reader_readnext(FILE *file) {
static cstring_t *line = NULL;
if (!line)
command_t *cmd = NULL;
if (cstring_readline(line, file)) {
- cmd = new_command(UNKNOWN);
+ cmd = new_command(COMMAND_UNKNOWN);
- if (!strcmp(".", line->string)) {
- cmd->type = TICK;
- } else if (cstring_starts_with(line->string, "display", 0)) {
- cmd->type = DISPLAY;
- } else if (cstring_starts_with(line->string, "readfile", 0)) {
- cmd->type = READFILE;
+ if (is_cmd(line, ".")) {
+ cmd->type = COMMAND_TICK;
+ if (command_read_count(cmd, line->string))
+ cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "display")) {
+ cmd->type = COMMAND_DISPLAY;
+ if (command_read_count(cmd, line->string))
+ cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "readfile")) {
+ cmd->type = COMMAND_READFILE;
if (!command_read_file(cmd, line->string, 0, -1)) {
- cmd->type = INVALID;
+ cmd->type = COMMAND_INVALID;
if (command_read_str(cmd, line->string, 0, -1))
- cmd->type = FILE404;
+ cmd->type = COMMAND_FILE404;
}
- } else if (cstring_starts_with("quit", line->string, 0)) {
- cmd->type = QUIT;
+ } else if (is_cmd(line, "map")) {
+ cmd->type = COMMAND_MAP;
+ if (!command_read_int(cmd, line->string, 0, 1))
+ cmd->type = COMMAND_INVALID;
+ if (command_read_count(cmd, line->string) > 2)
+ cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "life")) {
+ cmd->type = COMMAND_LIFE;
+ if (!command_read_int(cmd, line->string, 0, 0))
+ cmd->type = COMMAND_INVALID;
+ if (command_read_count(cmd, line->string) > 2)
+ cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "bits")) {
+ cmd->type = COMMAND_BITS;
+ if (!command_read_int(cmd, line->string, 0, 0))
+ cmd->type = COMMAND_INVALID;
+ if (command_read_count(cmd, line->string) > 2)
+ cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "path")) {
+ cmd->type = COMMAND_PATH;
+ if (!command_read_int(cmd, line->string, 0, -1))
+ cmd->type = COMMAND_INVALID;
+ if ((command_read_count(cmd, line->string) % 2) == 1)
+ cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "quit")) {
+ cmd->type = COMMAND_QUIT;
+ if (command_read_count(cmd, line->string))
+ cmd->type = COMMAND_INVALID;
}
}
out = new_cstring();
switch(cmd->type) {
- case TICK:
+ case COMMAND_TICK:
engine_tick(engine);
break;
- case DISPLAY:
+ case COMMAND_DISPLAY:
displayMode = !displayMode;
break;
- case READFILE:
+ case COMMAND_READFILE:
array_loop (cmd->data, ptr, char*) {
char *subname = *ptr;
FILE *sub = fopen(subname, "r");
fprintf(stdout, "Done reading: %s\n",subname);
}
break;
- case FILE404:
+ case COMMAND_FILE404:
fprintf(stderr, "Unknown file(s):\n");
array_loop_i (cmd->data, ptr, char*, i) {
fprintf(stderr, "%zu. \"%s\"\n", (i+1), *ptr);
}
break;
- case UNKNOWN:
+ case COMMAND_UNKNOWN:
fprintf(stderr, "Unrecognized command\n");
break;
- case INVALID:
+ case COMMAND_INVALID:
fprintf(stderr, "Invalid command\n");
break;
- case QUIT:
+ case COMMAND_QUIT:
return 0;
}
array_clear(engine->events);
// display mode
- if ((cmd->type == TICK || cmd->type == DISPLAY) && (displayMode)) {
+ if ((cmd->type == COMMAND_TICK || cmd->type == COMMAND_DISPLAY)
+ && (displayMode)) {
fprintf(stderr,
"Tick is: %zu\n", engine->current_tick);
display(engine->map);