Fix up designer cgi

This commit is contained in:
Neale Pickett 2010-07-19 17:23:30 -06:00
parent 39169bf352
commit ea84c67517
7 changed files with 155 additions and 22 deletions

View File

@ -1,6 +1,7 @@
CFLAGS = -Wall
LDFLAGS = -lm LDFLAGS = -lm
all: test all: run-tanks
test: test-tanks test: test-tanks
./test-tanks | m4 round.html.m4 - > round.html ./test-tanks | m4 round.html.m4 - > round.html
@ -10,4 +11,4 @@ test-tanks: test-tanks.o ctanks.o
run-tanks: run-tanks.o ctanks.o cforf.o run-tanks: run-tanks.o ctanks.o cforf.o
clean: clean:
rm -f test-tanks *.o rm -f test-tanks run-tanks *.o

View File

@ -211,6 +211,8 @@ forf_pop_stack(struct forf_env *env)
case forf_type_stack_begin: case forf_type_stack_begin:
depth -= 1; depth -= 1;
break; break;
default:
break;
} }
} }
s.top = s.size; s.top = s.size;
@ -287,6 +289,8 @@ forf_stack_move_value(struct forf_env *env,
case forf_type_stack_end: case forf_type_stack_end:
depth -= 1; depth -= 1;
break; break;
default:
break;
} }
} while (depth > 0); } while (depth > 0);

View File

@ -119,7 +119,11 @@ void forf_env_init(struct forf_env *env,
/** The type of a getch function (used for parsing) */ /** The type of a getch function (used for parsing) */
typedef int (forf_getch_func)(void *); typedef int (forf_getch_func)(void *);
/** Parse something by calling getch(datum) */ /** Parse something by calling getch(datum)
*
* Returns the character at which an error was encountered, or
* 0 for successful parse.
*/
int forf_parse_stream(struct forf_env *env, int forf_parse_stream(struct forf_env *env,
forf_getch_func *getch, forf_getch_func *getch,
void *datum); void *datum);

View File

@ -10,7 +10,7 @@
#define TANK_CANNON_RECHARGE 20 /* Turns to recharge cannon */ #define TANK_CANNON_RECHARGE 20 /* Turns to recharge cannon */
#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2) #define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2)
#define TANK_MAX_ACCEL 35 #define TANK_MAX_ACCEL 35
#define TANK_MAX_TURRET_ROT (PI/3) #define TANK_MAX_TURRET_ROT (PI/10)
#define TANK_TOP_SPEED 7 #define TANK_TOP_SPEED 7
/* (tank radius + tank radius)^2 */ /* (tank radius + tank radius)^2 */
@ -75,6 +75,8 @@ struct tank {
}; };
void tank_init(struct tank *tank, tank_run_func *run, void *udata); void tank_init(struct tank *tank, tank_run_func *run, void *udata);
void tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks);
/* /*
* *
@ -103,4 +105,5 @@ int tank_get_sensor(struct tank *tank, int sensor_num);
/** Set the LED state */ /** Set the LED state */
void tank_set_led(struct tank *tank, int active); void tank_set_led(struct tank *tank, int active);
#endif /* __CTANKS_H__ */ #endif /* __CTANKS_H__ */

View File

@ -1,7 +1,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#define BASE_PATH "/tmp/"
struct string { struct string {
char *s; char *s;
size_t size; size_t size;
@ -71,6 +74,8 @@ read_item(FILE *f, struct string *str)
{ {
int c; int c;
str->len = 0;
while (1) { while (1) {
c = fgetc(f); c = fgetc(f);
switch (c) { switch (c) {
@ -100,6 +105,7 @@ read_pair(FILE *f, struct string *key, struct string *val)
return read_item(f, val); return read_item(f, val);
} }
/* This is ugly and I dislike it. */
#define new_string(name, size) \ #define new_string(name, size) \
char _##name[size]; \ char _##name[size]; \
struct string name = {_##name, size, 0 } struct string name = {_##name, size, 0 }
@ -111,13 +117,58 @@ main(int argc, char *argv[])
new_string(key, 20); new_string(key, 20);
new_string(val, 8192); new_string(val, 8192);
new_string(token, 40);
new_string(name, 20); new_string(name, 20);
new_string(author, 20); new_string(author, 60);
new_string(color, 10);
new_string(program, 8192);
printf("Content-type: text/plain\n\n"); printf("Content-type: text/plain\n\n");
while (! feof(stdin)) { while (! feof(stdin)) {
read_pair(stdin, &key, &val); read_pair(stdin, &key, &val);
if (0 == string_cmp(&key, "token", 5)) {
string_cpy(&token, &key);
} else if (0 == string_cmp(&key, "name", 4)) {
string_cpy(&name, &key);
} else if (0 == string_cmp(&key, "author", 6)) {
string_cpy(&author, &key);
} else if (0 == string_cmp(&key, "color", 5)) {
string_cpy(&color, &key);
} else if (0 == string_cmp(&key, "program", 7)) {
string_cpy(&program, &key);
} else if ((3 == key.len) && ('s' == key.s[0])) {
/* sensor dealie, key = "s[0-9][rawt]" */
int n = key.s[1] - '0';
int i;
int p;
if (! (n >= 0) && (n <= 9)) {
break;
}
if (val.len > 3) {
break;
}
val.s[val.len] = '\0';
i = atoi(val.s);
switch (key.s[2]) {
case 'r':
p = 0;
break;
case 'a':
p = 1;
break;
case 'w':
p = 2;
break;
default:
p = 3;
break;
}
sensor[n][p] = i;
}
write(1, key.s, key.len); write(1, key.s, key.len);
write(1, "=", 1); write(1, "=", 1);
write(1, val.s, val.len); write(1, val.s, val.len);

38
rank.awk Normal file
View File

@ -0,0 +1,38 @@
BEGIN {
FS = "\t";
}
function esc(s) {
gsub(/&/, "&amp;", s);
gsub(/</, "&lt;", s);
gsub(/>/, "&gt;", s);
return s;
}
{
tanks[i++] = $1;
reason[$1] = $3;
killer[$1] = $4;
errchar[$1] = $5;
lasterr[$1] = $6;
kills[$4] += 1;
getline < ($2 "/name");
name[$1] = $0;
}
END {
print "<table id=\"results\">";
print "<tr><th>Name</th><th>Kills</th><th>Cause of Death</th><th>Killer</th><th>Last Error</th><th>Parse error @</th></tr>";
for (me in name) {
print "<tr>";
print "<td>" esc(name[me]) "</td>";
print "<td>" kills[me] "</td>";
print "<td>" reason[me] "</td>";
print "<td>" esc(name[killer[me]]) "</td>";
print "<td>" lasterr[me] "</td>";
print "<td>" errchar[me] "</td>";
print "</tr>";
}
print "</table>";
}

View File

@ -20,8 +20,10 @@
struct forftank { struct forftank {
struct forf_env env; struct forf_env env;
int error_pos;
char color[7]; /* "ff0088" */ char color[7]; /* "ff0088" */
char name[50]; char name[50];
char *path;
struct forf_stack _prog; struct forf_stack _prog;
struct forf_value _progvals[CSTACK_SIZE]; struct forf_value _progvals[CSTACK_SIZE];
@ -40,7 +42,7 @@ forf_print_val(struct forf_value *val)
{ {
switch (val->type) { switch (val->type) {
case forf_type_number: case forf_type_number:
printf("%d", val->v.i); printf("%ld", val->v.i);
break; break;
case forf_type_proc: case forf_type_proc:
printf("[proc %p]", val->v.p); printf("[proc %p]", val->v.p);
@ -232,7 +234,6 @@ ft_read_program(struct forftank *ftank,
struct forf_lexical_env *lenv, struct forf_lexical_env *lenv,
char *path) char *path)
{ {
int ret;
char progpath[256]; char progpath[256];
FILE *f; FILE *f;
@ -242,13 +243,9 @@ ft_read_program(struct forftank *ftank,
if (! f) return 0; if (! f) return 0;
/* Parse program */ /* Parse program */
ret = forf_parse_file(&ftank->env, f); ftank->error_pos = forf_parse_file(&ftank->env, f);
fclose(f); fclose(f);
if (ret) { if (ftank->error_pos) {
fprintf(stderr, "Parse error in %s, character %d: %s\n",
progpath,
ret,
forf_error_str[ftank->env.error]);
return 0; return 0;
} }
@ -320,6 +317,8 @@ ft_read_tank(struct forftank *ftank,
{ {
int ret; int ret;
ftank->path = path;
/* What is your name? */ /* What is your name? */
ret = ft_read_file(ftank->name, sizeof(ftank->name), path, "name"); ret = ft_read_file(ftank->name, sizeof(ftank->name), path, "name");
if (! ret) { if (! ret) {
@ -384,7 +383,6 @@ print_footer(FILE *f)
void void
print_rounds(FILE *f, print_rounds(FILE *f,
struct tanks_game *game, struct tanks_game *game,
struct forftank *forftanks,
struct tank *tanks, struct tank *tanks,
int ntanks) int ntanks)
{ {
@ -396,15 +394,15 @@ print_rounds(FILE *f,
for (i = 0; (alive > 1) && (i < ROUNDS); i += 1) { for (i = 0; (alive > 1) && (i < ROUNDS); i += 1) {
int j; int j;
tanks_run_turn(&game, mytanks, ntanks); tanks_run_turn(game, tanks, ntanks);
fprintf(stdout, "[\n"); fprintf(f, "[\n");
alive = ntanks; alive = ntanks;
for (j = 0; j < ntanks; j += 1) { for (j = 0; j < ntanks; j += 1) {
struct tank *t = &(mytanks[j]); struct tank *t = &(tanks[j]);
if (t->killer) { if (t->killer) {
alive -= 1; alive -= 1;
fprintf(stdout, " 0,\n"); fprintf(f, " 0,\n");
} else { } else {
int k; int k;
int flags = 0; int flags = 0;
@ -421,7 +419,7 @@ print_rounds(FILE *f,
if (t->led) { if (t->led) {
flags |= 2; flags |= 2;
} }
fprintf(stdout, " [%d,%d,%.2f,%.2f,%d,%d],\n", fprintf(f, " [%d,%d,%.2f,%.2f,%d,%d],\n",
(int)(t->position[0]), (int)(t->position[0]),
(int)(t->position[1]), (int)(t->position[1]),
t->angle, t->angle,
@ -430,7 +428,27 @@ print_rounds(FILE *f,
sensors); sensors);
} }
} }
fprintf(stdout, "],\n"); fprintf(f, "],\n");
}
}
void
print_standings(FILE *f,
struct forftank *ftanks,
struct tank *tanks,
int ntanks)
{
int i;
for (i = 0; i < ntanks; i += 1) {
/* &tank path cause &killer parse_error_pos lasterr */
fprintf(f, "%p\t%s\t%s\t%p\t%d\t%s\n",
&(tanks[i]),
ftanks[i].path,
tanks[i].cause_death,
tanks[i].killer,
ftanks[i].error_pos,
forf_error_str[ftanks[i].env.error]);
} }
} }
@ -527,9 +545,23 @@ main(int argc, char *argv[])
} }
print_header(stdout, &game, myftanks, mytanks, ntanks); print_header(stdout, &game, myftanks, mytanks, ntanks);
print_rounds(stdout, &game, myftanks, mytanks, ntanks); print_rounds(stdout, &game, mytanks, ntanks);
print_footer(stdout); print_footer(stdout);
/* Output standings to fd3.
*
* fd 3 is normally closed, so this won't normally do anything.
* To output to fd3 from the shell, you'll need to do something like this:
*
* ./run-tanks 3>standing
**/
{
FILE *standings = fdopen(3, "w");
if (standings) {
print_standings(standings, myftanks, mytanks, ntanks);
}
}
return 0; return 0;
} }