2 This file is part of the 3dengfx demo system.
4 Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program demo is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "3dengfx_config.h"
31 #define NEED_COMMAND_STRINGS
36 static char *cmd_symb[] = {COMMANDS, 0};
38 DemoScript *open_script(const char *fname) {
39 DemoScript *script = malloc(sizeof(DemoScript));
41 if(!(script->file = fopen(fname, "r"))) {
45 script->fname = malloc(strlen(fname)+1);
46 strcpy(script->fname, fname);
48 script->line_buffer = malloc(BUF_LEN);
49 script->line_buffer[0] = 0;
56 void close_script(DemoScript *ds) {
63 static char *skip_spaces(char *ptr) {
64 while(*ptr && *ptr != '\n' && isspace(*ptr)) ptr++;
68 int get_next_command(DemoScript *ds, DemoCommand *cmd, unsigned long time) {
73 /* get next line if one is available */
74 if(ds->line_buffer[0] == 0) {
75 if(!fgets(ds->line_buffer, BUF_LEN, ds->file)) {
81 ptr = skip_spaces(ds->line_buffer);
83 /* skip comments and empty lines */
84 if(*ptr == '#' || *ptr == '\n') {
85 ds->line_buffer[0] = 0;
86 return get_next_command(ds, cmd, time);
89 /* retrieve command time */
90 cmd->time = atoi(ptr);
92 /* skip timestamp and following whitespace */
93 while(*ptr && *ptr != '\n' && (isdigit(*ptr) || isspace(*ptr) || (isdigit(*(ptr-1)) && *ptr == 's'))) {
94 if(*ptr == 's') cmd->time *= 1000;
97 if(!*ptr || *ptr == '\n') {
98 fprintf(stderr, "Skipping invalid line %ld: %s\n", ds->line, ds->line_buffer);
99 ds->line_buffer[0] = 0;
100 return get_next_command(ds, cmd, time);
103 if(cmd->time > time) {
104 return 1; /* time is in the future */
107 /* seperate command name substring (cmd_tok), ptr keeps the rest */
109 while(*ptr && !isspace(*ptr)) ptr++;
112 /* make the command name upper-case */
113 for(i=0; cmd_tok[i]; i++) {
114 cmd_tok[i] = toupper(cmd_tok[i]);
117 /* match the command string with the available commands */
118 cmd->type = (CommandType)UINT_MAX;
119 for(i=0; cmd_symb[i]; i++) {
120 if(!strcmp(cmd_tok, cmd_symb[i])) {
126 if(cmd->type == (CommandType)UINT_MAX) {
127 fprintf(stderr, "Skipping invalid line %ld: Unrecognized command %s\n", ds->line, cmd_tok);
128 ds->line_buffer[0] = 0;
129 return get_next_command(ds, cmd, time);
132 /* tokenize the rest of the arguments and put them into argv */
133 cmd_tok = ptr = skip_spaces(ptr);
134 cmd->argc = *ptr ? 1 : 0;
136 while(*ptr && *ptr != '\n') {
138 ptr = skip_spaces(ptr);
139 if(*ptr && *ptr != '\n') cmd->argc++;
145 cmd->argv = malloc((cmd->argc + 1) * sizeof(char*));
146 for(i=0; i<cmd->argc; i++) {
147 ptr = strtok(i ? 0 : cmd_tok, " \t\n");
150 cmd->argv[i] = malloc(strlen(ptr) + 1);
151 strcpy((char*)cmd->argv[i], ptr);
156 if(!*ptr || *ptr == '\n') {
159 unsigned int len = strlen(ptr);
160 cmd->args = malloc(len + 1);
161 strcpy(cmd->args, ptr);
162 if(cmd->args[len - 1] == '\n') {
163 cmd->args[len - 1] = 0;
167 ds->line_buffer[0] = 0;
172 void free_command(DemoCommand *cmd) {
174 for(i=0; i<cmd->argc; i++) {
175 free((void*)cmd->argv[i]);
180 long str_to_time(const char *str) {
183 if(!isdigit(*str)) return -1;
187 while(isdigit(*str)) str++;
189 return *str == 's' ? time * 1000 : time;