added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / dsys / script.c
diff --git a/src/3dengfx/src/dsys/script.c b/src/3dengfx/src/dsys/script.c
new file mode 100644 (file)
index 0000000..c40daca
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+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 demo 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 "3dengfx_config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <assert.h>
+#include "script.h"
+
+#define NEED_COMMAND_STRINGS
+#include "cmd.h"
+
+#define BUF_LEN                1024
+
+static char *cmd_symb[] = {COMMANDS, 0};
+
+DemoScript *open_script(const char *fname) {
+       DemoScript *script = malloc(sizeof(DemoScript));
+       
+       if(!(script->file = fopen(fname, "r"))) {
+               free(script);
+               return 0;
+       }               
+       script->fname = malloc(strlen(fname)+1);
+       strcpy(script->fname, fname);
+
+       script->line_buffer = malloc(BUF_LEN);
+       script->line_buffer[0] = 0;
+
+       script->line = 0;
+
+       return script;
+}
+
+void close_script(DemoScript *ds) {
+       fclose(ds->file);
+       free(ds->fname);
+       free(ds);
+}
+
+
+static char *skip_spaces(char *ptr) {
+       while(*ptr && *ptr != '\n' && isspace(*ptr)) ptr++;
+       return ptr;
+}
+
+int get_next_command(DemoScript *ds, DemoCommand *cmd, unsigned long time) {
+       char *ptr;
+       char *cmd_tok;
+       int i;
+       
+       /* get next line if one is available */
+       if(ds->line_buffer[0] == 0) {
+               if(!fgets(ds->line_buffer, BUF_LEN, ds->file)) {
+                       return EOF;
+               }
+               ds->line++;
+       }
+
+       ptr = skip_spaces(ds->line_buffer);
+
+       /* skip comments and empty lines */
+       if(*ptr == '#' || *ptr == '\n') {
+               ds->line_buffer[0] = 0;
+               return get_next_command(ds, cmd, time);
+       }
+
+       /* retrieve command time */
+       cmd->time = atoi(ptr);
+       
+       /* skip timestamp and following whitespace */
+       while(*ptr && *ptr != '\n' && (isdigit(*ptr) || isspace(*ptr) || (isdigit(*(ptr-1)) && *ptr == 's'))) {
+               if(*ptr == 's') cmd->time *= 1000;
+               ptr++;
+       }
+       if(!*ptr || *ptr == '\n') {
+               fprintf(stderr, "Skipping invalid line %ld: %s\n", ds->line, ds->line_buffer);
+               ds->line_buffer[0] = 0;
+               return get_next_command(ds, cmd, time);
+       }
+       
+       if(cmd->time > time) {
+               return 1;       /* time is in the future */
+       }
+
+       /* seperate command name substring (cmd_tok), ptr keeps the rest */
+       cmd_tok = ptr;
+       while(*ptr && !isspace(*ptr)) ptr++;
+       *ptr++ = 0;
+
+       /* make the command name upper-case */
+       for(i=0; cmd_tok[i]; i++) {
+               cmd_tok[i] = toupper(cmd_tok[i]);
+       }
+
+       /* match the command string with the available commands */
+       cmd->type = (CommandType)UINT_MAX;
+       for(i=0; cmd_symb[i]; i++) {
+               if(!strcmp(cmd_tok, cmd_symb[i])) {
+                       cmd->type = i;
+                       break;
+               }
+       }
+       
+       if(cmd->type == (CommandType)UINT_MAX) {
+               fprintf(stderr, "Skipping invalid line %ld: Unrecognized command %s\n", ds->line, cmd_tok);
+               ds->line_buffer[0] = 0;
+               return get_next_command(ds, cmd, time);
+       }
+
+       /* tokenize the rest of the arguments and put them into argv */
+       cmd_tok = ptr = skip_spaces(ptr);
+       cmd->argc = *ptr ? 1 : 0;
+
+       while(*ptr && *ptr != '\n') {
+               if(isspace(*ptr)) {
+                       ptr = skip_spaces(ptr);
+                       if(*ptr && *ptr != '\n') cmd->argc++;
+               } else {
+                       ptr++;
+               }
+       }
+       
+       cmd->argv = malloc((cmd->argc + 1) * sizeof(char*));
+       for(i=0; i<cmd->argc; i++) {
+               ptr = strtok(i ? 0 : cmd_tok, " \t\n");
+               assert(ptr);
+
+               cmd->argv[i] = malloc(strlen(ptr) + 1);
+               strcpy((char*)cmd->argv[i], ptr);
+       }
+       cmd->argv[i] = 0;
+       
+       /*
+       if(!*ptr || *ptr == '\n') {
+               cmd->args = 0;
+       } else {
+               unsigned int len = strlen(ptr);
+               cmd->args = malloc(len + 1);
+               strcpy(cmd->args, ptr);
+               if(cmd->args[len - 1] == '\n') {
+                       cmd->args[len - 1] = 0;
+               }
+       }
+       */
+       ds->line_buffer[0] = 0;
+       
+       return 0;
+}
+
+void free_command(DemoCommand *cmd) {
+       int i;
+       for(i=0; i<cmd->argc; i++) {
+               free((void*)cmd->argv[i]);
+       }
+       free(cmd->argv);
+}
+
+long str_to_time(const char *str) {
+       long time;
+       
+       if(!isdigit(*str)) return -1;
+
+       time = atol(str);
+
+       while(isdigit(*str)) str++;
+       
+       return *str == 's' ? time * 1000 : time;
+}