#include <str_replace.h>\r
#include <variable.h>\r
\r
+#include <readline.h>\r
+\r
+#include <is_cmd.h>\r
+\r
+#ifndef WIN32\r
+#include <xsignal.h>\r
+#endif\r
+\r
\r
\r
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
\r
+\r
+\r
+\r
+long fstream_getline(fstream_t fstream, char **buf, size_t *n) {\r
+\r
+ return readline(fstream->stream, buf, n);\r
+ \r
+}\r
+\r
static void\r
failure(unit_t unit)\r
{\r
- \r
if(!keep_going_unit_flag)\r
{\r
unit_t root = unit->root ? unit->root : unit;\r
}\r
}\r
\r
-static void\r
-syntax_error(unit_t unit)\r
-{\r
- error_register("Unit failure", ESYNTAX, NULL, unit->fstream->name);\r
- \r
- failure(unit);\r
- \r
-}\r
-\r
-static void\r
-internal_error(unit_t unit)\r
-{\r
- failure(unit);\r
-}\r
-\r
-static void\r
-sys_error(unit_t unit)\r
-{\r
- unit_t root;\r
- \r
- error_register("System error", errno, NULL, unit->fstream->name);\r
- \r
- root = unit->root ? unit->root : unit;\r
- \r
- if(!root->interrupted)\r
- {\r
- /* the unit interrupted (exit for the loop) */\r
- root->interrupted = 1;\r
-\r
- /* release the unit */\r
- xbt_os_sem_release(root->sem);\r
- }\r
- \r
- if(!interrupted)\r
- {\r
- /* request an global interruption by the runner */\r
- interrupted = 1;\r
-\r
- /* release the runner */\r
- xbt_os_sem_release(units_sem);\r
- }\r
-}\r
-\r
fstream_t\r
fstream_new(const char* directory, const char* name)\r
{\r
\r
fstream->stream = NULL;\r
fstream->unit = NULL;\r
+ fstream->parsed = 0;\r
\r
\r
return fstream;\r
if((*ptr)->stream)\r
fclose((*ptr)->stream);\r
\r
- free((*ptr)->name);\r
+ if((*ptr)->name)\r
+ free((*ptr)->name);\r
\r
if((*ptr)->directory)\r
free((*ptr)->directory);\r
\r
unit = fstream->unit;\r
\r
- while(!(unit->root->interrupted) && getline(&line, &len, fstream->stream) != -1)\r
+ /*while(!(unit->root->interrupted) && getline(&line, &len, fstream->stream) != -1)*/\r
+ while(!(unit->root->interrupted) && fstream_getline(fstream, &line, &len) != -1)\r
{\r
\r
blankline=1;\r
{\r
if(!context->command_line && (context->input->used || context->output->used))\r
{\r
- ERROR1("[%d] Error: no command found in this chunk of lines.",buffbegin);\r
- syntax_error(unit);\r
+ snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
+ ERROR1("[%s] Error : no command found in the last chunk of lines", file_pos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
break;\r
}\r
else if(unit->is_running_suite)\r
{/* it's the end of a suite */\r
+ \r
+ unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
+\r
+ if(!xbt_dynar_length((*current_suite)->includes))\r
+ {\r
+ ERROR2("[%s] Malformated suite `(%s)' : include missing", file_pos, (*current_suite)->description);\r
+ \r
+ unit_set_error(*current_suite, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ \r
+ }\r
+ \r
unit->is_running_suite = 0;\r
}\r
\r
char name[VAR_NAME_MAX + 1] = {0};\r
unit_t unit = fstream->unit;\r
xbt_dynar_t variables = unit->runner->variables;\r
+\r
+ if(unit->is_running_suite && strncmp(line, "! include", strlen("! include")))\r
+ {/* it's the end of a suite */\r
+ \r
+ unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
+\r
+ if(!xbt_dynar_length((*current_suite)->includes))\r
+ ERROR2("[%s] Malformated suite `(%s)': include missing", filepos, (*current_suite)->description);\r
+ else\r
+ ERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos, (*current_suite)->description);\r
+ \r
+ unit_set_error(*current_suite, ESYNTAX, 1);\r
+\r
+ failure(fstream->unit);\r
+ \r
+ \r
+ }\r
+ \r
+ context->line = strdup(filepos);\r
+ \r
\r
/* search end */\r
xbt_str_rtrim(line + 2,"\n");\r
}\r
\r
xbt_os_mutex_release(unit->mutex);\r
+\r
\r
switch(line2[0]) \r
{\r
\r
case '$':\r
case '&':\r
+\r
+ if(line[1] != ' ')\r
+ {\r
+ \r
+ if(line2[0] == '$')\r
+ ERROR1("[%s] Missing space after `$' `(usage : $ <command>)'", filepos);\r
+ else\r
+ ERROR1("[%s] Missing space after & `(usage : & <command>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
context->async = (line2[0] == '&');\r
+\r
\r
/* further trim useless chars which are significant for in/output */\r
xbt_str_rtrim(line2 + 2," \t");\r
if(!dry_run_flag)\r
{\r
if(!silent_flag)\r
- INFO1("tesh cd %s",dir);\r
+ INFO2("[%s] cd %s", filepos, dir);\r
\r
if(!just_print_flag)\r
{\r
if(chdir(dir))\r
{\r
- ERROR1("chdir failed to set the directory to %s", dir);\r
- error_register("Unit failure", errno, NULL, unit->fstream->name);\r
+ ERROR3("[%s] Chdir to %s failed: %s",filepos, dir,error_to_string(errno, 0));\r
+ unit_set_error(fstream->unit, errno, 0);\r
+\r
failure(unit);\r
}\r
}\r
case '<':\r
case '>':\r
case '!':\r
+ \r
+ if(line[0] == '!' && line[1] != ' ')\r
+ {\r
+ ERROR1("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2); \r
break;\r
\r
case 'p':\r
- if(!dry_run_flag)\r
- INFO2("[%s] %s",filepos,line2+2);\r
+ \r
+ {\r
+ unsigned int j;\r
+ int is_blank = 1;\r
+ \r
+ char* prompt = line2 + 2;\r
+\r
+ for(j = 0; j < strlen(prompt); j++) \r
+ if (prompt[j] != ' ' && prompt[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
+ if(!dry_run_flag)\r
+ INFO2("[%s] %s",filepos,prompt);\r
+ }\r
+\r
+ \r
break;\r
\r
case 'P':\r
- if(!dry_run_flag)\r
- CRITICAL2("[%s] %s",filepos,line2+2);\r
+ \r
+ {\r
+ unsigned int j;\r
+ int is_blank = 1;\r
+ \r
+ char* prompt = line2 + 2;\r
+\r
+ for(j = 0; j < strlen(prompt); j++) \r
+ if (prompt[j] != ' ' && prompt[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
+ if(!dry_run_flag) \r
+ CRITICAL2("[%s] %s",filepos, prompt);\r
+ }\r
+\r
break;\r
\r
case 'D':\r
if(unit->description)\r
- WARN2("Description already specified %s at %s", line2, filepos); \r
+ WARN2("[%s] Description already specified `%s'",filepos, line2 + 2); \r
else\r
- unit->description = strdup(line2 + 2);\r
+ {\r
+ unsigned int j;\r
+ int is_blank = 1;\r
+ \r
+ char* desc = line2 + 2;\r
+\r
+ for(j = 0; j < strlen(desc); j++) \r
+ if (desc[j] != ' ' && desc[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand D `(usage : D <Description>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
+ unit->description = strdup(desc);\r
+ }\r
break;\r
\r
default:\r
- error_register("Unit failure", errno, NULL, unit->fstream->name);\r
- syntax_error(unit);\r
+ ERROR2("[%s] Syntax error `%s'", filepos, line2);\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
break;\r
}\r
\r
\r
if(context->output->used || context->input->used) \r
{\r
- ERROR2("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",filepos,context->command_line);\r
- syntax_error(unit);\r
+ ERROR2("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",filepos, context->command_line);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
return;\r
}\r
\r
VERB1("[%s] More than one command in this chunk of lines",filepos);\r
}\r
\r
- context->command_line = strdup(line);\r
- context->line = strdup(filepos);\r
- \r
+ {\r
+ size_t j,\r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(line); j++) \r
+ if (line[j] != ' ' && line[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ if(token == '$')\r
+ ERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'", filepos);\r
+ else\r
+ ERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'", filepos);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ }\r
\r
+ context->command_line = strdup(line);\r
+ context->line = /*strdup(filepos)*/ filepos;\r
+ context->pos = strdup(filepos);\r
break;\r
\r
case '<':\r
case '!':\r
\r
if(context->command_line)\r
+ {\r
if(fstream_launch_command(fstream, context, mutex) < 0)\r
return;\r
+ }\r
\r
if(!strncmp(line,"timeout no",strlen("timeout no"))) \r
{\r
else if(!strncmp(line,"timeout ",strlen("timeout "))) \r
{\r
int i = 0;\r
+ unsigned int j;\r
+ int is_blank = 1;\r
char* p = line + strlen("timeout ");\r
+\r
+\r
+ for(j = 0; j < strlen(p); j++) \r
+ if (p[j] != ' ' && p[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Undefinite timeout value `(usage :timeout <seconds>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
while(p[i] != '\0')\r
{\r
if(!isdigit(p[i]))\r
{\r
- ERROR2("Invalid timeout value `%s' at %s ", line + strlen("timeout "), filepos);\r
- syntax_error(unit);\r
+ ERROR2("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'", filepos, line + strlen("timeout "));\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ \r
failure(unit);\r
+ return;\r
}\r
\r
i++;\r
} \r
else if (!strncmp(line,"expect signal ",strlen("expect signal "))) \r
{\r
+ unsigned int j;\r
+ int is_blank = 1;\r
+\r
+ \r
+ char* p = line + strlen("expect signal ");\r
+\r
+\r
+ for(j = 0; j < strlen(p); j++) \r
+ if (p[j] != ' ' && p[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Undefinite signal name `(usage :expect signal <signal name>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
context->signal = strdup(line + strlen("expect signal "));\r
\r
+ xbt_str_trim(context->signal," \n");\r
+\r
#ifdef WIN32\r
if(!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))\r
{\r
- ERROR2("Incompatible signal \'%s\' detected at %s", context->signal, filepos);\r
- syntax_error(unit);\r
+ ERROR2("[%s] Signal `%s' not supported by this platform", filepos, context->signal);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ #else\r
+ if(!sig_exists(context->signal))\r
+ {\r
+ ERROR2("[%s] Signal `%s' not supported by Tesh", filepos, context->signal);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+\r
+ failure(unit);\r
+ return;\r
}\r
+\r
#endif\r
\r
- xbt_str_trim(context->signal," \n");\r
+ \r
VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);\r
\r
} \r
{\r
\r
int i = 0;\r
+ unsigned int j;\r
+ int is_blank = 1;\r
char* p = line + strlen("expect return ");\r
+\r
+\r
+ for(j = 0; j < strlen(p); j++) \r
+ if (p[j] != ' ' && p[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Undefinite return value `(usage :expect return <return value>)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
while(p[i] != '\0')\r
{\r
if(!isdigit(p[i]))\r
{\r
- ERROR2("Invalid exit code value `%s' at %s ", line + strlen("expect return "), filepos);\r
- syntax_error(unit);\r
+ ERROR2("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255", filepos, line + strlen("expect return "));\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
}\r
\r
i++;\r
\r
if(p1[0] == '\0')\r
{\r
- ERROR1("include file not specified %s ", filepos);\r
- syntax_error(unit);\r
+ ERROR1("[%s] no file specified : `(usage : include <file> [<description>])'", filepos);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
}\r
else\r
{\r
}\r
else if(!strncmp(line,"suite ", strlen("suite ")))\r
{\r
+ unsigned int j;\r
+ int is_blank = 1;\r
+ char* p = line + strlen("suite ");\r
+\r
+\r
+ for(j = 0; j < strlen(p); j++) \r
+ if (p[j] != ' ' && p[j] != '\t')\r
+ is_blank = 0;\r
+ \r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Undefinite suit description : `(usage : suite <description>)", filepos);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
if(unit->is_running_suite)\r
{\r
- ERROR1("Suite already in process at %s", filepos);\r
- syntax_error(unit);\r
+ ERROR1("[%s] Suite already in progress", filepos);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
return;\r
}\r
\r
- fstream_handle_suite(fstream, context, mutex, line + strlen("suite "));\r
+ fstream_handle_suite(fstream, line + strlen("suite "), filepos);\r
}\r
else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))\r
{\r
- unsigned int i;\r
+ unsigned int i, j;\r
int exists = 0;\r
int env = 0;\r
+ int err = 0;\r
variable_t variable;\r
+ int is_blank;\r
+\r
char* name = line + strlen("unsetenv ");\r
+\r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(name); j++) \r
+ if (name[j] != ' ' && name[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
xbt_os_mutex_acquire(unit->mutex);\r
\r
if(!strcmp(variable->name, name))\r
{\r
env = variable->env;\r
+ err = variable->err;\r
exists = 1;\r
break;\r
}\r
if(env)\r
{\r
if(exists)\r
- /*xbt_dynar_remove_at(unit->runner->variables, i - 1, NULL);*/\r
+ {\r
+ #ifndef WIN32\r
+ unsetenv(name);\r
+ #else\r
+ SetEnvironmentVariable(name, NULL);\r
+ #endif\r
xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
+ }\r
else\r
- WARN3("environment variable %s not found %s %s at", name, line, filepos); \r
+ {\r
+ ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
}\r
else\r
{\r
if(exists)\r
- WARN3("%s is an not environment variable use unset metacommand to delete it %s %s", name, line, filepos);\r
+ {\r
+ if(!err)\r
+ {\r
+ ERROR2("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ERROR2("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
+ }\r
else\r
- WARN3("%s environment variable not found %s %s", name, line, filepos);\r
+ {\r
+ ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
}\r
\r
xbt_os_mutex_release(unit->mutex); \r
char name[PATH_MAX + 1] = {0};\r
char* p;\r
unsigned int i;\r
+ int is_blank;\r
+ unsigned int j;\r
\r
p = line + strlen("setenv ");\r
\r
variable_t variable;\r
int exists = 0;\r
int env = 0;\r
+ int err = 0;\r
val++;\r
\r
/* syntax error */\r
- if(val[0] == '\0')\r
+ if(val[0] == '\0' || val[0] ==' ' || val[0] =='\t')\r
{\r
- ERROR2("Indefinite variable value %s %s", line, filepos);\r
- syntax_error(unit);\r
- failure(unit); \r
+ ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos); \r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
}\r
\r
\r
+ \r
strncpy(name, p, (val - p -1));\r
+\r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(name); j++) \r
+ if (name[j] != ' ' && name[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ \r
+ ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
/* test if the variable is already registred */\r
xbt_os_mutex_acquire(unit->mutex);\r
{\r
if(!strcmp(variable->name, name))\r
{\r
- variable->env = 1;\r
+ env = variable->env;\r
+ err = variable->err;\r
exists = 1;\r
break;\r
}\r
{\r
if(env)\r
{\r
+ if(!strcmp(val, variable->val))\r
+ WARN3("[%s] This environment variable `(%s)' is already set with the value `(%s)'", filepos, name, val);\r
+\r
free(variable->val);\r
variable->val = strdup(val);\r
+\r
#ifdef WIN32\r
SetEnvironmentVariable(variable->name, variable->val);\r
#else\r
#endif\r
}\r
else\r
- WARN3("%s variable already exists %s %s", name, line, filepos); \r
+ {\r
+ if(err)\r
+ ERROR2("[%s] Conflict : a system variable `(%s)' already exists", filepos, name);\r
+ else\r
+ ERROR2("[%s] Conflict : (none environment) variable `(%s)' already exists", filepos, name); \r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
}\r
else\r
{\r
- variable = variable_new(name, val);\r
- variable->env = 1;\r
- \r
- xbt_dynar_push(unit->runner->variables, &variable);\r
+ if(err)\r
+ {\r
+ ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
\r
- #ifdef WIN32\r
- SetEnvironmentVariable(variable->name, variable->val);\r
- #else\r
- setenv(variable->name, variable->val, 0);\r
- #endif\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ variable = variable_new(name, val);\r
+ variable->env = 1;\r
+ \r
+ xbt_dynar_push(unit->runner->variables, &variable);\r
+ \r
+ #ifdef WIN32\r
+ SetEnvironmentVariable(variable->name, variable->val);\r
+ #else\r
+ setenv(variable->name, variable->val, 0);\r
+ #endif\r
+ }\r
}\r
\r
xbt_os_mutex_release(unit->mutex);\r
\r
}\r
+ else\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
+ return;\r
+ }\r
}\r
else if(!strncmp(line,"unset ", strlen("unset ")))\r
{\r
- unsigned int i;\r
+ unsigned int i, j;\r
int exists = 0;\r
int env = 0;\r
int err = 0;\r
variable_t variable;\r
+ int is_blank;\r
+\r
char* name = line + strlen("unset ");\r
+\r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(name); j++) \r
+ if (name[j] != ' ' && name[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ \r
+ ERROR1("[%s] Bad usage of the metacommand unset `(usage : unset variable)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
\r
xbt_os_mutex_acquire(unit->mutex);\r
\r
}\r
}\r
\r
- if(!env)\r
+ if(!env && !err)\r
{\r
if(exists)\r
/*xbt_dynar_remove_at(unit->runner->variables, i, NULL);*/\r
xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
else\r
- WARN3("variable %s not found %s %s", name, line, filepos); \r
+ {\r
+ ERROR2("[%s] `(%s)' variable not found",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
}\r
else if(env)\r
- WARN3("%s is an environment variable use unsetenv metacommand to delete it %s %s", name, line, filepos); \r
- else\r
- WARN3("%s is an error variable : you are not allowed to delete it %s %s", name, line, filepos);\r
+ {\r
+ ERROR2("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else if(err)\r
+ {\r
+ ERROR2("[%s] `(%s)' is system variable : you can unset it",filepos, name); \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
-\r
xbt_os_mutex_release(unit->mutex);\r
\r
}\r
- else\r
+ else if(!strncmp(line,"set ", strlen("set ")))\r
{\r
char* val;\r
char name[PATH_MAX + 1] = {0};\r
+ unsigned int j; \r
+ int is_blank;\r
\r
- val = strchr(line, '=');\r
+ val = strchr(line + strlen("set "), '=');\r
\r
if(val)\r
{\r
variable_t variable;\r
int exists = 0;\r
unsigned int i;\r
+ int err;\r
+ int env;\r
+\r
+ val++;\r
+ \r
+ \r
+ /* syntax error */\r
+ if(val[0] == '\0')\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else if(val[0] ==' ' || val[0] =='\t')\r
+ {\r
+ strncpy(name, line + strlen("set "), (val - (line + strlen("set "))));\r
+\r
+ ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ \r
+ \r
+ /* assume it's a varibale */\r
+ \r
+ strncpy(name, line + strlen("set "), (val - (line + strlen("set ")) -1));\r
+ \r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(name); j++) \r
+ if (name[j] != ' ' && name[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ \r
+ ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
+ xbt_os_mutex_acquire(unit->mutex);\r
+ \r
+ /* test if the variable is already registred */\r
+ xbt_dynar_foreach(unit->runner->variables, i, variable)\r
+ {\r
+ if(!strcmp(variable->name, name))\r
+ {\r
+ exists = 1;\r
+ err = variable->err;\r
+ env = variable->env;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ /* if the variable is already registred, update its value (if same value warns);\r
+ * otherwise register it.\r
+ */\r
+ if(exists)\r
+ {\r
+ if(err)\r
+ {\r
+ ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ if(env)\r
+ {\r
+ ERROR2("[%s] `(%s)' is an environment variable use `setenv' instead `set'", filepos, name);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ if(!strcmp(val, variable->val))\r
+ WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
+\r
+ free(variable->val);\r
+ variable->val = strdup(val);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ variable_t new_var = variable_new(name, val);\r
+ xbt_dynar_push(unit->runner->variables, &new_var);\r
+ }\r
+\r
+ \r
+ xbt_os_mutex_release(unit->mutex);\r
+ }\r
+ else\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {/* assume it's a variable */\r
+ char* val;\r
+ char name[PATH_MAX + 1] = {0};\r
+ unsigned int i, j; \r
+ int is_blank;\r
+ \r
+ val = strchr(line, '=');\r
+\r
+ if(val)\r
+ {\r
+ variable_t variable;\r
+ int exists = 0;\r
+ int err;\r
+ int env;\r
val++;\r
\r
\r
/* syntax error */\r
if(val[0] == '\0')\r
{\r
- ERROR2("Indefinite variable value %s %s", line, filepos);\r
- syntax_error(unit);\r
+ strncpy(name, line, (val - line -1));\r
+\r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(name); j++) \r
+ if (name[j] != ' ' && name[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ ERROR1("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'", filepos);\r
+ else if(!strcmp("setenv", name))\r
+ ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
+ else if(!strcmp("set", name))\r
+ ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
+ else\r
+ ERROR2("[%s] Undefined variable `(%s)'", filepos, name);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else if(val[0] ==' ' || val[0] =='\t')\r
+ {\r
+ strncpy(name, line, (val - line));\r
+\r
+ ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit); \r
}\r
\r
\r
/* assume it's a varibale */\r
+ \r
strncpy(name, line, (val - line -1));\r
+\r
+ is_blank = 1;\r
+\r
+ for(j = 0; j < strlen(name); j++) \r
+ if (name[j] != ' ' && name[j] != '\t')\r
+ is_blank = 0;\r
+\r
+ if(is_blank)\r
+ {\r
+ \r
+ ERROR1("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'", filepos);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
\r
+ if(!strcmp("set", name))\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else if(!strcmp("setenv", name))\r
+ {\r
+ ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ failure(unit);\r
+ return;\r
+ }\r
+\r
xbt_os_mutex_acquire(unit->mutex);\r
\r
/* test if the variable is already registred */\r
if(!strcmp(variable->name, name))\r
{\r
exists = 1;\r
+ err = variable->err;\r
+ env = variable->env;\r
break;\r
}\r
}\r
\r
- /* if the variable is already registred, update its value;\r
+ /* if the variable is already registred, update its value (if same value warns);\r
* otherwise register it.\r
*/\r
if(exists)\r
{\r
- free(variable->val);\r
- variable->val = strdup(val);\r
+ if(err)\r
+ {\r
+ ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+ failure(unit);\r
+ return;\r
+ }\r
+ if(env)\r
+ {\r
+ ERROR2("[%s] `(%s)' is an environment variable use `setenv' metacommand", filepos, name);\r
+ \r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+ xbt_os_mutex_release(unit->mutex);\r
+\r
+ failure(unit);\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ if(!strcmp(val, variable->val))\r
+ WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
+\r
+ free(variable->val);\r
+ variable->val = strdup(val);\r
+ }\r
}\r
else\r
{\r
}\r
else \r
{\r
- ERROR2("%s: Malformed metacommand: %s",filepos,line);\r
- syntax_error(unit);\r
+ if(!strncmp("setenv", line, strlen("setenv")))\r
+ ERROR1("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'", filepos);\r
+ else if(!strncmp("set", line, strlen("set")))\r
+ ERROR1("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'", filepos);\r
+ else if(!strncmp("unsetenv", line, strlen("unsetenv")))\r
+ ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
+ else if(!strncmp("unset", line, strlen("unset")))\r
+ ERROR1("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'", filepos);\r
+ else if(!strncmp("timeout", line, strlen("timeout")))\r
+ ERROR1("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'", filepos);\r
+ else if(!strncmp("expect signal", line, strlen("expect signal")))\r
+ ERROR1("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'", filepos);\r
+ else if(!strncmp("expect return", line, strlen("expect return")))\r
+ ERROR1("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'", filepos);\r
+ else if(!strncmp("include", line, strlen("include")))\r
+ ERROR1("[%s] Bad usage of the metacommand include :`(usage : include <file> [<description>])'", filepos);\r
+ else if(!strncmp("suite", line, strlen("suite")))\r
+ ERROR1("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'", filepos);\r
+ else\r
+ ERROR2("[%s] Unknown metacommand: `%s'",filepos,line);\r
+\r
+ unit_set_error(fstream->unit, ESYNTAX, 1);\r
+\r
+ failure(unit);\r
return;\r
}\r
}\r
\r
- \r
break;\r
}\r
}\r
free(prev_directory);\r
}\r
\r
- \r
- \r
/* the file to include is not found handle the failure */\r
if(!_fstream)\r
{\r
- exit_code = EINCLUDENOTFOUND;\r
- ERROR1("Include file %s not found",file_name);\r
+ if(file_name[0] == '$')\r
+ {\r
+ ERROR3("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",context->line, file_name, file_name + 1);\r
+ \r
+ }\r
+ else\r
+ {\r
+\r
+ /* may be a variable */\r
+ variable_t variable;\r
+ int exists = 0;\r
+ unsigned int i;\r
+\r
+ xbt_dynar_foreach(unit->runner->variables, i, variable)\r
+ {\r
+ if(!strcmp(variable->name, file_name))\r
+ {\r
+ exists = 1;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if(exists)\r
+ ERROR3("[%s] Include file `(%s)' not found (if you want to use the variable <%s> add the prefix `$')",context->line, file_name, file_name);\r
+ else\r
+ ERROR2("[%s] Include file `(%s)' not found",context->line, file_name);\r
+ }\r
+ \r
+ unit_set_error(fstream->unit, EINCLUDENOTFOUND, 1);\r
+\r
failure(unit);\r
}\r
else\r
{\r
- \r
if(!unit->is_running_suite)\r
{/* it's the unit of a suite */\r
- unit_t include = unit_new(unit->runner,unit->root, unit, _fstream);\r
+ unit_t include = unit_new(unit->runner, unit->root, unit, _fstream);\r
\r
include->mutex = unit->root->mutex;\r
\r
include->description = strdup(description);\r
\r
xbt_dynar_push(unit->includes, &include);\r
- \r
+ \r
+ if(!dry_run_flag)\r
+ INFO1("Include from %s", _fstream->name);\r
+ else\r
+ INFO1("Checking include %s...",_fstream->name);\r
+ \r
fstream_parse(_fstream, mutex);\r
}\r
else\r
\r
owner = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
\r
- include = unit_new(unit->runner,unit->root, *owner, _fstream);\r
+ include = unit_new(unit->runner, unit->root, *owner, _fstream);\r
\r
include->mutex = unit->root->mutex;\r
\r
include->description = strdup(description);\r
\r
xbt_dynar_push((*owner)->includes, &include);\r
- fstream_parse(_fstream, mutex); \r
\r
+ if(!dry_run_flag)\r
+ INFO1("Include from %s", _fstream->name);\r
+ else\r
+ INFO1("Checking include %s...",_fstream->name);\r
+ \r
+ fstream_parse(_fstream, mutex);\r
}\r
}\r
}\r
\r
void\r
-fstream_handle_suite(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* description)\r
+fstream_handle_suite(fstream_t fstream, const char* description, const char* filepos)\r
{\r
unit_t unit = fstream->unit;\r
unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);\r
+ \r
+ if(description)\r
+ suite->description = strdup(description);\r
+\r
+ suite->filepos = strdup(filepos); \r
\r
- suite->description = strdup(description);\r
xbt_dynar_push(unit->suites, &suite);\r
unit->is_running_suite = 1;\r
\r
+ if(!dry_run_flag)\r
+ INFO1("Test suite %s", description);\r
+ else\r
+ INFO1("Checking suite %s...",description);\r
+ \r
}\r
\r
-\r
int\r
fstream_launch_command(fstream_t fstream, context_t context, xbt_os_mutex_t mutex)\r
{\r
unit_t unit = fstream->unit;\r
- \r
- /* TODO : check the parameters */\r
- \r
+\r
if(!dry_run_flag)\r
{\r
command_t command;\r
{\r
if(EINVAL == errno)\r
{\r
- ERROR2("Internal error : command_new() failed with the error %s (%d)",strerror(errno), errno); \r
- internal_error(unit);\r
+ ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno); \r
+\r
+ unit_set_error(unit, errno, 0);\r
+ failure(unit);\r
return -1;\r
}\r
else if(ENOMEM == errno)\r
{\r
- ERROR1("System error : command_new() failed with the error code %d",errno); \r
- sys_error(unit);\r
+ ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);\r
+\r
+ unit_set_error(unit, errno, 0);\r
+\r
+ failure(unit);\r
return -1;\r
}\r
}\r
\r
if(command_run(command) < 0)\r
{\r
- ERROR2("Internal error : command_run() failed with the error %s (%d)",strerror(errno), errno); \r
- internal_error(unit);\r
+ ERROR3("[%s] Cannot run the command `%s' (%d)",context->pos, strerror(errno), errno); \r
+ unit_set_error(unit, errno, 0);\r
+ failure(unit);\r
return -1; \r
}\r
}\r
\r
if(context_reset(context) < 0)\r
{\r
- ERROR2("Internal error : command_run() failed with the error %s (%d)",strerror(errno), errno); \r
- internal_error(unit);\r
+ ERROR3("[%s] Cannot reset the context of the command `%s' (%d)",context->pos, strerror(errno), errno); \r
+\r
+ unit_set_error(fstream->unit, errno, 0);\r
+\r
+ failure(unit);\r
return -1; \r
}\r
\r