#include <stdio.h> #include <string.h> #include <ctype.h> #include "db.h" #include "externs.h" #include "softcode.h" static void show_obj_prog_summary(OBJ *player, OBJ *thing) { PROG *p; PROGLINE *pline; int num_lines; if(!thing->program) { notify(player, tprintf("%s contains no programs.", unparse_object(player, thing))); return; } notify(player, tprintf("|+B|.%s.", my_string("-", 60))); notify(player, tprintf("|+B|| |+W|%s |+B||", my_center(tprintf("Program Summary for %s", unparse_object(player, thing)), 58))); notify(player, tprintf("|+B||%s|", my_string("-", 60))); notify(player, tprintf("|+B|||+W|%s|+B|||+W|%s|+B|||+W| Lines |+B|||+W| Running |+B||", my_center("Name", 20), my_center("Trigger", 20))); notify(player, tprintf("|+B||%s|", my_string("-", 60))); for(p = thing->program;p;p = p->next) { num_lines = 0; for(pline = p->program;pline;pline = pline->next) num_lines++; notify(player, tprintf("|+B|| |+G|%s|+B|| |+G|%s|+B|| |+G|%6d |+B|||+G|%s|+B||", my_ljust(p->name, 19), my_ljust((*p->trigger)?p->trigger:"NONE", 19), num_lines, my_center((is_running(p))?"YES":"NO", 9))); } notify(player, tprintf("|+B|`%s'", my_string("-", 60))); } PROG *find_prog(OBJ *thing, char *progname) { PROG *p; for(p = thing->program;p;p = p->next) if(!string_compare(p->name, progname)) break; return(p); } int next_line_num(PROG *program) { PROGLINE *pline; if(!program->program) return(10); for(pline = program->program;pline->next;pline = pline->next); if(pline->line >= 65526) return(0); return((pline->line)+10); } void del_prog_line(PROG *program, int line_num) { PROGLINE *pline, *plineprev = NULL; for(pline = program->program;pline;pline = pline->next) { if(pline->line == line_num) break; plineprev = pline; } if(!pline) return; stack_free(pline->code); if(!plineprev) program->program = pline->next; else plineprev->next = pline->next; stack_free(pline); } void add_new_prog_line(OBJ *player, OBJ *thing, char *progname) { PROG *program; char *p, *q; int line_num; char *code; if(!controls(player, thing, POW_MODIFY)) { notify(player, perm_denied()); return; } if(!(p = strchr(progname, ','))) { notify(player, "Type 'help +code' for help."); return; } *p++ = '\0'; if(!(program = find_prog(thing, progname))) { notify(player, tprintf("Program %s doesn't exist on %s.", progname, unparse_object(player, thing))); return; } if(is_running(program)) { notify(player, "You may not modify a program while it is running."); return; } for(q = p;isdigit(*q);++q); if(*q == ',' || !*q) { if(*q) *q++ = '\0'; line_num = atoi(p); if(line_num < 1 || line_num > 65535) { notify(player, "Valid line numbers are 1 through 65535."); return; } code = q; } else { if(!(line_num = next_line_num(program))) { notify(player, "Error! Next line number would exceed 65535."); return; } code = p; } if(!*code) del_prog_line(program, line_num); else add_prog_line(program, line_num, code); notify(player, "Program modified."); } static int ok_prog_name(char *progname) { char *p; if(!*progname || strlen(progname) > 50) return(0); for(p = progname;*p;++p) if(*p == ' ' || *p == ',') return(0); return(1); } void add_new_prog(OBJ *player, OBJ *thing, char *progname) { PROG *program; if(!controls(player, thing, POW_MODIFY)) { notify(player, perm_denied()); return; } if(!ok_prog_name(progname)) { notify(player, "Invalid program name."); return; } if((program = find_prog(thing, progname))) { notify(player, tprintf("%s already has a program called %s.", unparse_object(player, thing), progname)); return; } program = new_program(thing); program->name = stack_string_alloc(progname, 1); notify(player, tprintf("Program %s added to %s.", progname, unparse_object(player, thing))); } static void del_prog(OBJ *player, OBJ *thing, char *progname) { PROG *program, *programprev = NULL; PROGLINE *pline, *plinenext; if(!controls(player, thing, POW_MODIFY)) { notify(player, perm_denied()); return; } for(program = thing->program;program;program = program->next) { if(!string_compare(program->name, progname)) break; programprev = program; } if(!program) { notify(player, tprintf("Program %s doesn't exist on %s.", progname, unparse_object(player, thing))); return; } if(is_running(program)) { notify(player, "You may not modify a program while it is running."); return; } for(pline = program->program;pline;pline = plinenext) { plinenext = pline->next; stack_free(pline->code); stack_free(pline); } if(!programprev) thing->program = program->next; else programprev->next = program->next; stack_free(program->trigger); stack_free(program->name); stack_free(program); notify(player, tprintf("Program %s removed from %s.", progname, unparse_object(player, thing))); } static void list_prog(OBJ *player, OBJ *thing, char *progname) { PROG *program; PROGLINE *pline; int high = 65535, low = 1; char *p; char buf[4096]; char *b; if(!controls(player, thing, POW_MODIFY) && !(thing->flags & VISIBLE)) { notify(player, perm_denied()); return; } if((p = strchr(progname, ','))) { *p++ = '\0'; b = buf; while(isdigit(*p)) *b++ = *p++; *b = '\0'; if(!*buf) low = 1; else { low = atoi(buf); if(low < 1 || low > 65535) { notify(player, "Valid line numbers are 1 through 65535."); return; } } if(*p == '-') { p++; b = buf; while(isdigit(*p)) *b++ = *p++; *b = '\0'; if(!*buf) high = 65535; else { high = atoi(buf); if(high < 1 || high > 65535) { notify(player, "Valid line numbers are 1 through 65535."); return; } if(high < low) { notify(player, "The lowest number cannot be higher than the highest."); return; } } } } if(!(program = find_prog(thing, progname))) { notify(player, tprintf("Program %s doesn't exist on %s.", progname, unparse_object(player, thing))); return; } notify(player, tprintf("|+B|Listing of program |+Y|%s|+B| on %s|+W|:", program->name, unparse_object(player, thing))); for(pline = program->program;pline;pline = pline->next) if(pline->line >= low && pline->line <= high) notify(player, tprintf("%d %s", pline->line, pline->code)); notify(player, "|+W|-- |+B|End of list|+W|--"); } static void renum_prog(OBJ *player, OBJ *thing, char *progname) { PROG *program; PROGLINE *pline, *pline2; int step, num_lines; char *p, *q; char command[4096]; if(!*progname) { notify(player, "Usage: +code renum=<object>,<program>[,<step>]"); return; } if(!(p = strchr(progname, ','))) step = 10; else { *p++ = '\0'; for(q = p;*q;q++) if(!isdigit(*q)) { notify(player, "Invalid step!"); return; } step = atoi(p); } if(step < 1 || step > 65535) { notify(player, "Invalid step!"); return; } if(!(program = find_prog(thing, progname))) { notify(player, tprintf("Program %s doesn't exist on %s.", progname, unparse_object(player, thing))); return; } num_lines = step; for(pline = program->program;pline;pline = pline->next) { num_lines += step; if(num_lines > 65535) { notify(player, tprintf("With a step of %d, line numbers would exceed 65535.", step)); return; } } num_lines = step; for(pline = program->program;pline;pline = pline->next) { for(pline2 = program->program;pline2;pline2 = pline2->next) { if((p = strchr(pline2->code, ' '))) { strncpy(command, pline2->code, p-pline2->code); *(command+(p-pline2->code)) = '\0'; } else continue; if(!string_compare(command, "goto") || !string_compare(command, "gosub")) { if(atoi(++p) == pline->line) add_prog_line(program, pline2->line, tprintf("%s %d", command, num_lines)); } } pline->line = num_lines; num_lines += step; } notify(player, tprintf("Program %s modified.", program->name)); } static void set_prog_trigger(OBJ *player, OBJ *thing, char *progname) { PROG *program; char *p; if(!(p = strchr(progname, ','))) { notify(player, "Type 'help +code' for help."); return; } *p++ = '\0'; if(!(program = find_prog(thing, progname))) { notify(player, tprintf("Program |+Y|%s|n| doesn't exist on %s.", progname, unparse_object(player, thing))); return; } program->trigger = stack_string_realloc(program->trigger, p); notify(player, tprintf("Program |+Y|%s|n| on %s set to '%s'.", program->name, unparse_object(player, thing), p)); } void do_code(OBJ *player, char *option, char *arg) { OBJ *thing; char *arg2; SUBCOMMAND *sc, commands[] = { { "add", add_new_prog_line, 0 }, { "create", add_new_prog, 0 }, { "delete", del_prog, 0 }, { "list", list_prog, 0 }, { "renum", renum_prog, 0 }, { "summary", show_obj_prog_summary, 0 }, { "trigger", set_prog_trigger, 0 }, { NULL } }; if(!*option || !*arg) { notify(player, "Type 'help +code' for help."); return; } if((arg2 = strchr(arg, ','))) *arg2++ = '\0'; else arg2 = ""; if(!(thing = match_object(player, arg, NOTYPE))) { notify(player, no_match(arg)); return; } if(!(sc = subcommand_match(player, option, commands, NULL))) subcommand_print(player, "+code", commands); else sc->func(player, thing, arg2); } PROG *new_program(OBJ *thing) { PROG *p, *newp; newp = (PROG *)stack_alloc(sizeof(PROG), 1, 0); if(!thing->program) thing->program = newp; else { for(p = thing->program;p->next;p = p->next); p->next = newp; } newp->trigger = stack_string_alloc("", 1); newp->program = NULL; newp->next = NULL; return(newp); } static PROGLINE *new_prog_line(PROG *program, int line_num) { PROGLINE *p, *newpline, *pprev = NULL; newpline = (PROGLINE *)stack_alloc(sizeof(PROGLINE), 1, 0); newpline->next = NULL; if(!program->program) program->program = newpline; else { for(p = program->program;p->next;p = p->next) { if(p->line >= line_num) break; pprev = p; } if(p->line == line_num) { stack_free(newpline); stack_free(p->code); return(p); } if(p->line > line_num) /* We're going to insert */ { newpline->next = p; if(!pprev) program->program = newpline; else pprev->next = newpline; } else p->next = newpline; } newpline->line = line_num; return(newpline); } void add_prog_line(PROG *program, int line, char *codestr) { PROGLINE *pline; pline = new_prog_line(program, line); pline->code = stack_string_alloc(codestr, 1); } void free_progs(OBJ *player) { PROG *p, *pnext; for(p = player->program;p;p = pnext) { pnext = p->next; del_prog(player, player, p->name); } }