Files
HxCFloppyEmulator/libhxcfe/sources/misc/script_exec.c
T
2025-02-10 19:03:07 +01:00

1557 lines
29 KiB
C

/*
//
// Copyright (C) 2006-2025 Jean-François DEL NERO
//
// This file is part of the HxCFloppyEmulator library
//
// HxCFloppyEmulator may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// HxCFloppyEmulator 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.
//
// HxCFloppyEmulator 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 HxCFloppyEmulator; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
*/
///////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------//
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
//----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------//
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
//-------------------------------------------------------------------------------//
//----------------------------------------------------- http://hxc2001.free.fr --//
///////////////////////////////////////////////////////////////////////////////////
// File : script_exec.c
// Contains: Script engine.
//
// Written by: Jean-François DEL NERO
//
// Change History (most recent first):
///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "script_exec.h"
#include "internal_libhxcfe.h"
#include "tracks/track_generator.h"
#include "sector_search.h"
#include "libhxcfe.h"
#include "floppy_loader.h"
#include "libhxcadaptor.h"
#include "env.h"
#include "version.h"
#define SCRIPT_NO_ERROR HXCFE_NOERROR
#define SCRIPT_CMD_NOT_FOUND HXCFE_INTERNALERROR
#define SCRIPT_NOT_FOUND HXCFE_ACCESSERROR
#define SCRIPT_CMD_BAD_PARAMETER HXCFE_BADPARAMETER
#define SCRIPT_BAD_CMD HXCFE_INTERNALERROR
#define SCRIPT_INTERNAL_ERROR HXCFE_INTERNALERROR
#define SCRIPT_ACCESS_ERROR HXCFE_ACCESSERROR
#define SCRIPT_MEM_ERROR HXCFE_INTERNALERROR
#ifndef _script_cmd_func_
typedef int (* CMD_FUNC)( script_ctx * ctx, char * line);
#define _script_cmd_func_
#endif
typedef struct cmd_list_
{
char * command;
CMD_FUNC func;
}cmd_list;
typedef struct label_list_
{
char * label;
unsigned int file_offset;
}label_list;
extern cmd_list script_commands_list[];
static int dummy_script_printf(void * ctx, int MSGTYPE, char * string, ... )
{
return 0;
}
static int is_end_line(char c)
{
if( c == 0 || c == '#' || c == '\r' || c == '\n' )
{
return 1;
}
else
{
return 0;
}
}
static int is_space(char c)
{
if( c == ' ' || c == '\t' )
{
return 1;
}
else
{
return 0;
}
}
static int is_label(char * command)
{
int i;
i = 0;
while(command[i])
{
i++;
}
if(i>1)
{
if(command[i - 1] == ':')
return 1;
}
return 0;
}
static int is_variable(char * command)
{
if(strlen(command)>1)
{
if(command[0] == '$' && command[1] && (command[1] != ' ' && command[1] != '\t') )
return 1;
else
return 0;
}
return 0;
}
static int get_next_word(char * line, int offset)
{
while( !is_end_line(line[offset]) && ( line[offset] == ' ' || line[offset] == '\t' ) )
{
offset++;
}
return offset;
}
static int copy_param(char * dest, char * line, int offs)
{
int i,insidequote;
i = 0;
insidequote = 0;
while( !is_end_line(line[offs]) && ( insidequote || !is_space(line[offs]) ) && (i < (DEFAULT_BUFLEN - 1)) )
{
if(line[offs] != '"')
{
if(dest)
dest[i] = line[offs];
i++;
}
else
{
if(insidequote)
insidequote = 0;
else
insidequote = 1;
}
offs++;
}
if(dest)
dest[i] = 0;
return offs;
}
static int get_param_offset(char * line, int param)
{
int param_cnt, offs;
offs = 0;
offs = get_next_word(line, offs);
if( param )
{
param_cnt = 0;
do
{
offs = copy_param(NULL, line, offs);
offs = get_next_word( line, offs );
if(line[offs] == 0 || line[offs] == '#' || line[offs] == '\r' || line[offs] == '\n')
return -1;
param_cnt++;
}while( param_cnt < param );
}
return offs;
}
static int get_param( script_ctx * ctx, char * line, int param_offset,char * param)
{
int offs;
char var_str[DEFAULT_BUFLEN];
offs = get_param_offset(line, param_offset);
if(offs>=0)
{
if(line[offs] != '$')
{
offs = copy_param(param, line, offs);
}
else
{
copy_param(var_str, line, offs);
if(!strcmp(var_str,"$LASTDATA"))
{
sprintf(param,"0x"LONGHEXSTR,ctx->last_data_value);
return 1;
}
if(!strcmp(var_str,"$LASTFLAGS"))
{
sprintf(param,"0x%X",ctx->last_flags);
return 1;
}
if(!strcmp(var_str,"$LASTERROR"))
{
sprintf(param,"%d",ctx->last_error_code);
return 1;
}
if( !getEnvVarDat( (envvar_entry *)ctx->env, (char*)&var_str[1], param, DEFAULT_BUFLEN) )
{
copy_param(param, line, offs);
}
}
return 1;
}
return -1;
}
static int get_param_str( script_ctx * ctx, char * line, int param_offset,char * param)
{
int offs;
offs = get_param_offset(line, param_offset);
if(offs>=0)
{
offs = copy_param(param, line, offs);
return 1;
}
return -1;
}
env_var_value strbin_to_val( char * str )
{
int l;
env_var_value val;
env_var_value mask;
val = 0;
// -> end of the string
l = 0;
while(str[l])
{
l++;
}
// -> find the lowest bit
while(l)
{
if( str[l] == '1' || str[l] == '0' )
{
break;
}
l--;
};
mask = 0x1;
// convert
while(l >= 0)
{
if( str[l] != '1' && str[l] != '0' )
{
break;
}
if( str[l] == '1')
{
val |= mask;
}
mask <<= 1;
l--;
}
return val;
}
static env_var_value str_to_int(char * str)
{
env_var_value value;
value = 0;
if(str)
{
if( strlen(str) > 2 )
{
if( str[0]=='0' )
{
switch( str[1] )
{
// hex
case 'x':
case 'X':
value = (env_var_value)STRTOVALUE(str, NULL, 0);
break;
// binary
case 'b':
case 'B':
value = strbin_to_val(str);
break;
// decimal
default:
value = atoi(str);
break;
}
}
else
{
value = atoi(str);
}
}
else
{
value = atoi(str);
}
}
return value;
}
static env_var_value get_script_variable( script_ctx * ctx, char * varname)
{
env_var_value value;
if(!strcmp(varname,"$LASTDATA"))
{
return ctx->last_data_value;
}
if(!strcmp(varname,"$LASTFLAGS"))
{
return ctx->last_flags;
}
if(!strcmp(varname,"$LASTERROR"))
{
return (env_var_value)(ctx->last_error_code);
}
if(varname[0] == '$')
value = getEnvVarValue( (envvar_entry *)ctx->env, (char*)&varname[1]);
else
value = str_to_int((char*)varname);
return value;
}
static void set_script_variable( script_ctx * ctx, char * varname, env_var_value value)
{
char tmp_str[64];
if(!strcmp(varname,"$LASTDATA"))
{
ctx->last_data_value = value;
return;
}
if(!strcmp(varname,"$LASTFLAGS"))
{
ctx->last_flags = value;
return;
}
if(!strcmp(varname,"$LASTERROR"))
{
ctx->last_error_code = value;
return;
}
if(varname[0] == '$' && varname[1])
{
sprintf(tmp_str,"0x"LONGHEXSTR,value);
setEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname[1], tmp_str );
return;
}
}
script_ctx * init_script(void * app_ctx, unsigned int flags, void * env)
{
script_ctx * ctx;
ctx = malloc(sizeof(script_ctx));
if(ctx)
{
memset(ctx,0,sizeof(script_ctx));
ctx->env = (envvar_entry*)env;
setOutputFunc_script( ctx, dummy_script_printf );
ctx->app_ctx = (void*)app_ctx;
ctx->cur_label_index = 0;
ctx->cmdlist = (void*)script_commands_list;
ctx->script_file = NULL;
}
return ctx;
}
void * setget_env_script(script_ctx * ctx, void * env)
{
void * ret_env;
ret_env = NULL;
if(ctx)
{
ret_env = ctx->env;
if( env )
ctx->env = (envvar_entry*)env;
}
return ret_env;
}
static int extract_cmd( script_ctx * ctx, char * line, char * command)
{
int offs,i;
i = 0;
offs = 0;
offs = get_next_word(line, offs);
if( !is_end_line(line[offs]) )
{
while( !is_end_line(line[offs]) && !is_space(line[offs]) && i < (DEFAULT_BUFLEN - 1) )
{
command[i] = line[offs];
offs++;
i++;
}
command[i] = 0;
return i;
}
return 0;
}
static int exec_cmd( script_ctx * ctx, char * command,char * line)
{
int i;
cmd_list * cmdlist;
cmdlist = (cmd_list*)ctx->cmdlist;
if(!cmdlist)
return SCRIPT_INTERNAL_ERROR;
i = 0;
while(cmdlist[i].func)
{
if( !strcmp(cmdlist[i].command,command) )
{
return cmdlist[i].func(ctx,line);
}
i++;
}
return SCRIPT_CMD_NOT_FOUND;
}
static int add_label( script_ctx * ctx, char * label )
{
int i,j;
char tmp_label[MAX_LABEL_SIZE];
if(ctx->cur_label_index < MAX_LABEL)
{
i = 0;
while(i<(MAX_LABEL_SIZE - 1) && label[i] && label[i] != ':')
{
tmp_label[i] = label[i];
i++;
}
tmp_label[i] = 0;
i = 0;
while(i<ctx->cur_label_index)
{
if( !strcmp( tmp_label, ctx->labels[i].label_name ) )
{
break;
}
i++;
}
j = i;
i = 0;
while(i<(MAX_LABEL_SIZE - 1) && label[i])
{
ctx->labels[j].label_name[i] = tmp_label[i];
i++;
}
ctx->labels[j].label_name[i] = 0;
ctx->labels[j].offset = ctx->cur_script_offset;
if(ctx->cur_label_index == j)
{
ctx->cur_label_index++;
}
}
return 0;
}
static int goto_label( script_ctx * ctx, char * label )
{
int i;
char tmp_label[MAX_LABEL_SIZE];
i = 0;
while(i<(MAX_LABEL_SIZE - 1) && label[i] && label[i] != ':')
{
tmp_label[i] = label[i];
i++;
}
tmp_label[i] = 0;
i = 0;
while(i<ctx->cur_label_index)
{
if( !strcmp( tmp_label, ctx->labels[i].label_name ) )
{
break;
}
i++;
}
if( i != ctx->cur_label_index)
{
ctx->cur_script_offset = ctx->labels[i].offset;
if(ctx->script_file)
fseek(ctx->script_file,ctx->cur_script_offset,SEEK_SET);
return SCRIPT_NO_ERROR;
}
else
{
ctx->script_printf( ctx, MSG_ERROR, "Label %s not found\n", tmp_label );
return SCRIPT_CMD_NOT_FOUND;
}
}
///////////////////////////////////////////////////////////////////////////////
static int alu_operations( script_ctx * ctx, char * line)
{
int i;
int valid;
env_var_value data_value;
env_var_value value_1,value_2;
char params_str[5][DEFAULT_BUFLEN];
for(i=0;i<5;i++)
{
params_str[i][0] = 0;
}
valid = 0;
for(i=0;i<5;i++)
{
get_param_str( ctx, line, i, (char*)&params_str[i] );
if(strlen((char*)&params_str[i]))
valid++;
}
data_value = 0;
if( ( (valid == 3) || (valid == 5) ) && params_str[1][0] == '=' && params_str[0][0] == '$')
{
value_1 = get_script_variable( ctx, params_str[2]);
if(valid == 5)
{
value_2 = get_script_variable( ctx, params_str[4]);
if(!strcmp(params_str[3],"+"))
data_value = value_1 + value_2;
if(!strcmp(params_str[3],"-"))
data_value = value_1 - value_2;
if(!strcmp(params_str[3],"*"))
data_value = value_1 * value_2;
if(!strcmp(params_str[3],"/") && value_2)
data_value = value_1 / value_2;
if(!strcmp(params_str[3],"&"))
data_value = value_1 & value_2;
if(!strcmp(params_str[3],"^"))
data_value = value_1 ^ value_2;
if(!strcmp(params_str[3],"|"))
data_value = value_1 | value_2;
if(!strcmp(params_str[3],">>"))
data_value = value_1 >> value_2;
if(!strcmp(params_str[3],"<<"))
data_value = value_1 << value_2;
}
else
{
data_value = value_1;
}
if(data_value)
ctx->last_flags = 1;
else
ctx->last_flags = 0;
set_script_variable( ctx, (char*)&params_str[0], data_value);
return SCRIPT_NO_ERROR;
}
return SCRIPT_CMD_BAD_PARAMETER;
}
void setOutputFunc_script( script_ctx * ctx, SCRIPT_PRINTF_FUNC ext_printf )
{
ctx->script_printf = ext_printf;
return;
}
int execute_line_script( script_ctx * ctx, char * line )
{
char command[DEFAULT_BUFLEN];
command[0] = 0;
if( extract_cmd(ctx, line, command) )
{
if(strlen(command))
{
if(!is_label(command))
{
if(!ctx->dry_run)
{
if(!is_variable(command))
{
ctx->last_error_code = exec_cmd(ctx,command,line);
if( ctx->last_error_code == SCRIPT_CMD_NOT_FOUND )
{
ctx->script_printf( ctx, MSG_ERROR, "Command not found ! : %s\n", line );
return ctx->last_error_code;
}
}
else
{
ctx->last_error_code = alu_operations(ctx,line);
}
}
else
ctx->last_error_code = SCRIPT_NO_ERROR;
}
else
{
add_label(ctx,command);
ctx->last_error_code = SCRIPT_NO_ERROR;
}
return ctx->last_error_code;
}
}
ctx->last_error_code = SCRIPT_BAD_CMD;
return ctx->last_error_code;
}
int execute_file_script( script_ctx * ctx, char * filename )
{
int err;
char line[DEFAULT_BUFLEN];
err = SCRIPT_INTERNAL_ERROR;
ctx->script_file = hxc_fopen(filename,"rb");
if(ctx->script_file)
{
strncpy(ctx->script_file_path,filename,DEFAULT_BUFLEN);
ctx->script_file_path[DEFAULT_BUFLEN-1] = 0;
// Dry run -> populate the labels...
ctx->dry_run++;
do
{
if(!fgets(line,sizeof(line),ctx->script_file))
break;
ctx->cur_script_offset = ftell(ctx->script_file);
if(feof(ctx->script_file))
break;
execute_line_script(ctx, line);
}while(1);
fseek(ctx->script_file,0,SEEK_SET);
ctx->cur_script_offset = ftell(ctx->script_file);
ctx->dry_run--;
if(!ctx->dry_run)
{
if(strlen(ctx->pre_command))
{
err = execute_line_script(ctx, ctx->pre_command);
if(err != SCRIPT_NO_ERROR)
{
hxc_fclose(ctx->script_file);
return err;
}
}
do
{
if(!fgets(line,sizeof(line),ctx->script_file))
break;
ctx->cur_script_offset = ftell(ctx->script_file);
if(feof(ctx->script_file))
break;
err = execute_line_script(ctx, line);
}while(1);
}
hxc_fclose(ctx->script_file);
err = SCRIPT_NO_ERROR;
}
else
{
ctx->script_printf( ctx, MSG_ERROR, "Can't open %s !", filename );
ctx->script_file_path[0] = 0;
err = SCRIPT_ACCESS_ERROR;
}
return err;
}
int execute_ram_script( script_ctx * ctx, unsigned char * script_buffer, int buffersize )
{
int err = 0;
int buffer_offset,line_offset;
char line[DEFAULT_BUFLEN];
int cont;
ctx->dry_run++;
cont = 1;
while( cont )
{
buffer_offset = 0;
line_offset = 0;
ctx->cur_script_offset = 0;
do
{
memset(line,0,DEFAULT_BUFLEN);
line_offset = 0;
while( (buffer_offset < buffersize) && script_buffer[buffer_offset] && script_buffer[buffer_offset]!='\n' && script_buffer[buffer_offset]!='\r' && (line_offset < DEFAULT_BUFLEN - 1))
{
line[line_offset++] = script_buffer[buffer_offset++];
}
while( (buffer_offset < buffersize) && script_buffer[buffer_offset] && (script_buffer[buffer_offset]=='\n' || script_buffer[buffer_offset]=='\r') )
{
buffer_offset++;
}
ctx->cur_script_offset = buffer_offset;
execute_line_script(ctx, line);
buffer_offset = ctx->cur_script_offset;
if( (buffer_offset >= buffersize) || !script_buffer[buffer_offset])
break;
}while(buffer_offset < buffersize);
if( !ctx->dry_run || (ctx->dry_run > 1) )
{
cont = 0;
}
else
{
ctx->dry_run = 0;
if(strlen(ctx->pre_command))
execute_line_script(ctx, ctx->pre_command);
}
}
return err;
}
script_ctx * deinit_script(script_ctx * ctx)
{
free(ctx);
ctx = NULL;
return ctx;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////// Generic commands/operations /////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static int cmd_goto( script_ctx * ctx, char * line)
{
int i;
char label_str[DEFAULT_BUFLEN];
i = get_param( ctx, line, 1, label_str );
if(i>=0)
{
return goto_label( ctx, label_str );
}
return SCRIPT_CMD_BAD_PARAMETER;
}
static int cmd_if( script_ctx * ctx, char * line)
{
//"if" command example :
// if $VARIABLE > 0x2222 then goto label
int i;
int eval;
int ret;
//int valid;
char params_str[5][DEFAULT_BUFLEN];
env_var_value value_1,value_2,tmp_val;
int op_offset;
ret = SCRIPT_CMD_BAD_PARAMETER;
eval = 0;
for(i=0;i<5;i++)
{
params_str[i][0] = 0;
}
//valid = 0;
for(i=0;i<5;i++)
{
get_param( ctx, line, i, (char*)&params_str[i] );
//if(strlen((char*)&params_str[i]))
// valid++;
}
i = 0;
while( i < 5 && strcmp((char*)&params_str[i],"then") )
{
i++;
}
if( i < 5 )
{
if( i == 2)
{
value_1 = get_script_variable( ctx, params_str[1]);
if(value_1)
eval = 1;
ret = SCRIPT_NO_ERROR;
}
if ( i == 4 )
{
value_1 = get_script_variable( ctx, params_str[1]);
value_2 = get_script_variable( ctx, params_str[3]);
if(!strcmp((char*)&params_str[2],">=") && ( (signed_env_var_value)value_1 >= (signed_env_var_value)value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"<=") && ( (signed_env_var_value)value_1 <= (signed_env_var_value)value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],">") && ( (signed_env_var_value)value_1 > (signed_env_var_value)value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"<") && ( (signed_env_var_value)value_1 < (signed_env_var_value)value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"==") && ( value_1 == value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"!=") && ( value_1 != value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"&") && ( value_1 & value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"^") && ( value_1 ^ value_2 ) )
eval = 1;
if(!strcmp((char*)&params_str[2],"|") && ( value_1 | value_2 ) )
eval = 1;
tmp_val = value_1 >> value_2;
if(!strcmp((char*)&params_str[2],">>") && tmp_val )
eval = 1;
tmp_val = value_1 << value_2;
if(!strcmp((char*)&params_str[2],"<<") && tmp_val )
eval = 1;
ret = SCRIPT_NO_ERROR;
}
if( eval )
{
op_offset = get_param_offset(line, i + 1);
if(op_offset >= 0)
{
ret = execute_line_script( ctx, (char*)&line[op_offset] );
}
}
return ret;
}
return SCRIPT_CMD_BAD_PARAMETER;
}
static int cmd_return( script_ctx * ctx, char * line )
{
if(ctx->script_file)
{
fseek(ctx->script_file,0,SEEK_END);
}
return SCRIPT_NO_ERROR;
}
static int cmd_system( script_ctx * ctx, char * line )
{
int offs;
int ret;
offs = get_param_offset(line, 1);
if(offs>=0)
{
ret = system(&line[offs]);
if( ret != 1 )
return SCRIPT_NO_ERROR;
else
return SCRIPT_CMD_NOT_FOUND;
}
return SCRIPT_CMD_BAD_PARAMETER;
}
static int cmd_print_env_var( script_ctx * ctx, char * line )
{
int i;
char varname[DEFAULT_BUFLEN];
char varvalue[DEFAULT_BUFLEN];
char * ptr;
i = get_param( ctx, line, 1, varname );
if(i>=0)
{
ptr = getEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname, (char*)&varvalue, DEFAULT_BUFLEN );
if(ptr)
{
ctx->script_printf( ctx, MSG_INFO_1, "%s = %s", varname, varvalue );
return SCRIPT_NO_ERROR;
}
return SCRIPT_CMD_NOT_FOUND;
}
else
{
return SCRIPT_CMD_BAD_PARAMETER;
}
}
static int cmd_version( script_ctx * ctx, char * line)
{
ctx->script_printf( ctx, MSG_INFO_0, "Lib version : %s, Date : "__DATE__" "__TIME__"\n", "v"STR_FILE_VERSION2 );
return SCRIPT_NO_ERROR;
}
static int cmd_print( script_ctx * ctx, char * line)
{
int i,j,s;
char tmp_str[DEFAULT_BUFLEN];
char str[DEFAULT_BUFLEN*2];
char * ptr;
str[0] = 0;
j = 1;
do
{
ptr = NULL;
i = get_param_offset(line, j);
s = 0;
if(i>=0)
{
get_param( ctx, line, j, (char *)&tmp_str );
s = strlen(tmp_str);
if(s)
{
if(tmp_str[0] != '$')
{
strncat((char*)str,tmp_str,sizeof(str) - 1);
strncat((char*)str," ",sizeof(str) - 1);
}
else
{
ptr = getEnvVarDat( (envvar_entry *)ctx->env, &tmp_str[1], NULL, 0);
if( ptr )
{
strncat((char*)str,ptr,sizeof(str) - 1);
strncat((char*)str," ",sizeof(str) - 1);
}
else
{
strncat((char*)str,tmp_str,sizeof(str) - 1);
strncat((char*)str," ",sizeof(str) - 1);
}
}
}
}
j++;
}while(s);
ctx->script_printf( ctx, MSG_NONE, "%s\n", str );
return SCRIPT_NO_ERROR;
}
static int cmd_pause( script_ctx * ctx, char * line)
{
int i;
char delay_str[DEFAULT_BUFLEN];
i = get_param( ctx, line, 1, delay_str );
if(i>=0)
{
hxc_pause(str_to_int(delay_str));
return SCRIPT_NO_ERROR;
}
ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line );
return SCRIPT_CMD_BAD_PARAMETER;
}
static int cmd_help( script_ctx * ctx, char * line)
{
int i;
cmd_list * cmdlist;
cmdlist = (cmd_list*)ctx->cmdlist;
ctx->script_printf( ctx, MSG_INFO_0, "Supported Commands :\n\n" );
i = 0;
while(cmdlist[i].func)
{
ctx->script_printf( ctx, MSG_NONE, "%s\n", cmdlist[i].command );
i++;
}
return SCRIPT_NO_ERROR;
}
static int cmd_call( script_ctx * ctx, char * line )
{
int offs;
char path[DEFAULT_BUFLEN];
char function[DEFAULT_BUFLEN];
script_ctx * new_ctx;
int ret;
HXCFE * hxcfectx;
hxcfectx = (HXCFE *)ctx->app_ctx;
get_param( ctx, line, 1, (char*)&path );
offs = get_param_offset(line, 1);
if(offs>=0)
{
ret = SCRIPT_INTERNAL_ERROR;
new_ctx = init_script((void*)hxcfectx,0x00000000,(void*)hxcfectx->envvar);
if(new_ctx)
{
new_ctx->script_printf = ctx->script_printf;
function[0] = 0;
get_param( ctx, line, 2, (char*)&function );
if(!strcmp(path,"."))
{
if(strlen(function))
{
snprintf(new_ctx->pre_command,sizeof(new_ctx->pre_command),"goto %s",function);
ret = execute_file_script( new_ctx, (char*)&ctx->script_file_path );
new_ctx->pre_command[0] = 0;
if( ret == SCRIPT_ACCESS_ERROR )
{
ctx->script_printf( ctx, MSG_ERROR, "call : script not found ! : %s\n", path );
}
}
}
else
{
if(strlen(function))
{
snprintf(new_ctx->pre_command,sizeof(new_ctx->pre_command),"goto %s",function);
ret = execute_file_script( new_ctx, (char*)&path );
new_ctx->pre_command[0] = 0;
if( ret == SCRIPT_ACCESS_ERROR )
{
ctx->script_printf( ctx, MSG_ERROR, "call : script/function not found ! : %s %s\n", path,function );
}
}
else
{
ret = execute_file_script( new_ctx, (char*)&path );
if( ret == SCRIPT_ACCESS_ERROR )
{
ctx->script_printf( ctx, MSG_ERROR, "call : script not found ! : %s\n", path );
}
}
}
deinit_script(new_ctx);
}
ctx->last_error_code = ret;
return ret;
}
return SCRIPT_CMD_BAD_PARAMETER;
}
static int cmd_set_env_var( script_ctx * ctx, char * line )
{
int i,j,ret;
char varname[DEFAULT_BUFLEN];
char varvalue[DEFAULT_BUFLEN];
ret = SCRIPT_CMD_BAD_PARAMETER;
i = get_param( ctx, line, 1, varname );
j = get_param( ctx, line, 2, varvalue );
if(i>=0 && j>=0)
{
if( setEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname, (char*)&varvalue ) >= 0)
{
ret = SCRIPT_NO_ERROR;
}
else
ret = SCRIPT_MEM_ERROR;
}
return ret;
}
static int cmd_rand( script_ctx * ctx, char * line)
{
int i;
uint32_t seed;
char rand_seed[DEFAULT_BUFLEN];
seed = ctx->rand_seed;
i = get_param( ctx, line, 1, rand_seed );
if(i>=0)
{
seed = str_to_int((char*)rand_seed);
}
/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
ctx->rand_seed = seed;
ctx->last_data_value = seed;
return SCRIPT_NO_ERROR;
}
int is_valid_hex_quartet(char c)
{
if( (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') )
return 1;
else
return 0;
}
int is_valid_hex_byte(char *str)
{
if( is_valid_hex_quartet(str[0]) && is_valid_hex_quartet(str[1]) )
return 1;
else
return 0;
}
char * arrayresize(char * array, int size, unsigned char c)
{
int cursize;
char * ptr;
if(array)
{
if( array[0] == '0' && (array[1] == 'x' || array[1] == 'X') )
{
ptr = (array + 2);
}
else
{
ptr = (array);
}
}
else
{
array = malloc(DEFAULT_BUFLEN);
if(array)
{
memset(array,0,DEFAULT_BUFLEN);
}
ptr = array;
}
if(ptr)
{
cursize = 0;
while(is_valid_hex_byte(&ptr[cursize*2]))
{
cursize++;
}
if( cursize < size )
{
while( cursize < size )
{
sprintf(&ptr[(cursize*2) + 0],"%.2X",c);
//ptr[(cursize*2) + 0] = '0';
//ptr[(cursize*2) + 1] = '0';
cursize++;
}
}
else
{
ptr[ (size * 2) ] = 0;
}
}
return array;
}
static int cmd_initarray( script_ctx * ctx, char * line)
{
//initarray $VARIABLE_1_TEST $BYTES $VALUE
int i,j,ret;
char varname[DEFAULT_BUFLEN];
char varsize[DEFAULT_BUFLEN];
char varvalue[DEFAULT_BUFLEN];
char * ptr;
int size;
ret = SCRIPT_CMD_BAD_PARAMETER;
strcpy(varvalue,"0");
i = get_param_str( ctx, line, 1, varname );
j = get_param( ctx, line, 2, varsize );
get_param( ctx, line, 3, varvalue );
if(i>=0 && j>=0)
{
size = atoi(varsize);
if(size)
{
ptr = getEnvVarDat( (envvar_entry *)ctx->env,(char*)&varname, NULL, 0);
if(ptr)
{
arrayresize(ptr, size, (unsigned char)(str_to_int((char*)&varvalue)&0xFF));
}
else
{
ptr = malloc( DEFAULT_BUFLEN );
if(ptr)
{
memset(ptr,0x00, DEFAULT_BUFLEN);
arrayresize(ptr, size, (unsigned char)(str_to_int((char*)&varvalue)&0xFF));
}
}
if(ptr)
setEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname[1], ptr );
}
ret = SCRIPT_NO_ERROR;
}
return ret;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////// Floppy commands/operations //////////////////////////////
///////////////////////////////////////////////////////////////////////////////
cmd_list script_commands_list[] =
{
{"print", cmd_print},
{"help", cmd_help},
{"?", cmd_help},
{"version", cmd_version},
{"pause", cmd_pause},
{"set", cmd_set_env_var},
{"print_env_var", cmd_print_env_var},
{"call", cmd_call},
{"system", cmd_system},
{"if", cmd_if},
{"goto", cmd_goto},
{"return", cmd_return},
{"rand", cmd_rand},
{"init_array", cmd_initarray},
{ 0, 0 }
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int hxcfe_initScript(HXCFE * hxcfectx)
{
hxcfectx->scriptctx = init_script((void*)hxcfectx,0x00000000,(void*)hxcfectx->envvar);
if(!hxcfectx->scriptctx)
return SCRIPT_INTERNAL_ERROR;
else
return SCRIPT_NO_ERROR;
}
void hxcfe_setScriptOutputFunc( HXCFE * hxcfectx, SCRIPT_PRINTF_FUNC ext_printf )
{
setOutputFunc_script(hxcfectx->scriptctx, ext_printf);
}
int hxcfe_execScriptLine( HXCFE * hxcfe,char * line )
{
if(!hxcfe)
return SCRIPT_INTERNAL_ERROR;
if(!hxcfe->scriptctx)
return SCRIPT_INTERNAL_ERROR;
return execute_line_script( hxcfe->scriptctx, line );
}
int hxcfe_execScriptFile( HXCFE* hxcfe, char * script_path )
{
if(!hxcfe)
return SCRIPT_INTERNAL_ERROR;
if(!hxcfe->scriptctx)
return SCRIPT_INTERNAL_ERROR;
return execute_file_script( hxcfe->scriptctx, script_path );
}
int hxcfe_execScriptRam( HXCFE* hxcfe, unsigned char * script_buffer, int buffersize )
{
if(!hxcfe)
return SCRIPT_INTERNAL_ERROR;
if(!hxcfe->scriptctx)
return SCRIPT_INTERNAL_ERROR;
return execute_ram_script( hxcfe->scriptctx, script_buffer, buffersize );
}
int hxcfe_deinitScript( HXCFE* hxcfe )
{
if(!hxcfe)
return SCRIPT_CMD_BAD_PARAMETER;
if(!hxcfe->scriptctx)
return SCRIPT_INTERNAL_ERROR;
deinit_script(hxcfe->scriptctx);
hxcfe->scriptctx = NULL;
return SCRIPT_NO_ERROR;
}
int hxcfe_setEnvVar( HXCFE* hxcfe, char * varname, char * varvalue )
{
if( setEnvVarDat( hxcfe->envvar, varname, varvalue ) >= 0 )
{
return SCRIPT_NO_ERROR;
}
else
{
return SCRIPT_MEM_ERROR;
}
}
char * hxcfe_getEnvVar( HXCFE* hxcfe, char * varname, char * varvalue)
{
return getEnvVarDat( hxcfe->envvar, varname, varvalue, DEFAULT_BUFLEN);
}
char * hxcfe_getEnvVarIndex( HXCFE* hxcfe, int index, char * varvalue)
{
return getEnvVarDatIndex( hxcfe->envvar, index, varvalue, DEFAULT_BUFLEN);
}
int hxcfe_getEnvVarValue( HXCFE* hxcfe, char * varname)
{
return getEnvVarValue( hxcfe->envvar, varname);
}
int hxcfe_setEnvVarValue( HXCFE* hxcfe, char * varname, int value )
{
if( setEnvVarValue( hxcfe->envvar, varname, value ) >= 0 )
{
return SCRIPT_NO_ERROR;
}
else
{
return SCRIPT_MEM_ERROR;
}
}