- buff = xbt_strbuff_new();\r
- \r
- if(!(context = context_new()))\r
- return -1;\r
- \r
- unit = fstream->unit;\r
- \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
- linelen = 0; \r
- to_be_continued = 0;\r
-\r
- line_num++;\r
- \r
- while(line[linelen] != '\0') \r
- {\r
- if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')\r
- blankline = 0;\r
- \r
- linelen++;\r
- }\r
- \r
- if(blankline) \r
- {\r
- if(!context->command_line && (context->input->used || context->output->used))\r
- {\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, file_pos);\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, file_pos);\r
-\r
- failure(unit);\r
- \r
- }\r
- \r
- unit->is_running_suite = 0;\r
- }\r
- \r
- if(context->command_line)\r
- {\r
- #ifdef _XBT_WIN32\r
- if(!context->is_not_found)\r
- {\r
- #endif\r
- if(fstream_launch_command(fstream, context, mutex) < 0)\r
- break;\r
-\r
- #ifdef _XBT_WIN32\r
- }\r
- #endif\r
- }\r
- \r
- continue;\r
- }\r
- \r
- if(linelen>1 && line[linelen-2]=='\\') \r
- {\r
- if(linelen>2 && line[linelen-3] == '\\') \r
- {\r
- /* Damn. Escaped \ */\r
- line[linelen-2] = '\n';\r
- line[linelen-1] = '\0';\r
- } \r
- else \r
- {\r
- to_be_continued = 1;\r
- line[linelen-2] = '\0';\r
- linelen -= 2; \r
- \r
- if (!buff->used)\r
- buffbegin = line_num;\r
- }\r
- }\r
- \r
- if(buff->used || to_be_continued) \r
- { \r
- xbt_strbuff_append(buff,line);\r
- \r
- if (!to_be_continued) \r
- {\r
- snprintf(file_pos,256,"%s:%d",fstream->name, buffbegin);\r
- fstream_lex_line(fstream, context, mutex, file_pos, buff->data); \r
- xbt_strbuff_empty(buff);\r
- }\r
- } \r
- else \r
- {\r
- snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
- fstream_lex_line(fstream, context, mutex, file_pos, line); \r
- }\r
- }\r
- \r
- /* Check that last command of the file ran well */\r
- if(context->command_line)\r
- {\r
- #ifdef _XBT_WIN32\r
- if(!context->is_not_found)\r
- {\r
- #endif\r
-\r
- if(fstream_launch_command(fstream, context, mutex) < 0)\r
- return -1;\r
-\r
- #ifdef _XBT_WIN32\r
- }\r
- #endif\r
- }\r
- \r
- /* clear buffers */\r
- if(line)\r
- free(line);\r
- \r
- xbt_strbuff_free(buff); \r
- \r
- if(context_free(&context) < 0)\r
- return -1;\r
- \r
- return (exit_code || errno) ? -1 : 0;\r
-}\r
-\r
-\r
-void \r
-fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line) \r
-{\r
- char* line2;\r
- variable_t variable;\r
- unsigned int i;\r
- char exp[PATH_MAX + 1] = {0};\r
- unit_t unit = fstream->unit;\r
- xbt_dynar_t variables = unit->runner->variables;\r
- char* p= NULL;\r
- char* end = NULL;\r
- char* val = NULL;\r
- char buff[PATH_MAX + 1] = {0}; \r
- size_t len;\r
- char delimiters[4] = {' ', '\t', '\n', '\0'}; \r
- \r
- int j;\r
- \r
- if(line[0] == '#')\r
- return;\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, filepos);\r
-\r
- failure(fstream->unit);\r
- }\r
- \r
- context->line = strdup(filepos);\r
- \r
- /* search end */\r
- xbt_str_rtrim(line + 2,"\n");\r
- \r
- line2 = strdup(line);\r
-\r
- len = strlen(line2 + 2) + 1;\r
-\r
- /* replace each variable by its value */\r
- xbt_os_mutex_acquire(unit->mutex);\r
- \r
-\r
- /* replace all existing\r
- ${var}\r
- ${var:=val}\r
- ${var:+val}\r
- ${var:-val}\r
- ${var:?val}\r
- ${#var}\r
- */\r
- \r
- xbt_dynar_foreach(variables, i, variable)\r
- {\r
- if(!(p = strstr(line2 + 2, "${")))\r
- break;\r
-\r
- memset(buff, 0, len);\r
-\r
- sprintf(buff,"${%s",variable->name);\r
- \r
- /* FALSE */\r
- if((p = strstr(line2 + 2, buff)))\r
- {\r
- memset(buff, 0, len);\r
- p--;\r
- j = 0;\r
-\r
- while(*(p++) != '\0')\r
- {\r
- buff[j++] = *p;\r
-\r
- if(*p == '}')\r
- break;\r
- }\r
-\r
- if(buff[j - 1] != '}')\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- \r
- ERROR2("[%s] Syntax error : `%s'.",filepos, p - j);\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- if((p = strstr(buff , ":=")))\r
- {\r
- /* ${var:=val} */\r
- \r
- /* if the value of the variable is empty, update its value by the value*/\r
- p += 2;\r
- \r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == p))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(buff, "${"));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
-\r
- strncpy(val, p,(end - p));\r
- \r
- \r
- /* replace the expression by the expression of the value of the variable*/\r
- sprintf(exp, "${%s:=%s}", variable->name, val);\r
-\r
- if(variable->val)\r
- str_replace_all(&line2, exp, variable->val, NULL);\r
- else\r
- {\r
- str_replace_all(&line2, exp, val, NULL);\r
-\r
- variable->val = strdup(val);\r
- }\r
-\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
-\r
- if(val)\r
- {\r
- free(val);\r
- val = NULL;\r
- }\r
-\r
- }\r
- else if((p = strstr(buff, ":-")))\r
- {\r
- /* ${var:-val} */\r
- \r
- /* if the value of the variable is empty, replace the expression by the value */\r
- p += 2;\r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == p))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
-\r
- strncpy(val, p,(end - p)); \r
-\r
- sprintf(exp, "${%s:-%s}", variable->name, val);\r
- \r
- str_replace_all(&line2, exp, variable->val ? variable->val : val, NULL);\r
- \r
-\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
- \r
- if(val)\r
- {\r
- free(val);\r
- val = NULL;\r
- }\r
-\r
- }\r
- else if((p = strstr(buff, ":+")))\r
- {\r
- /* ${var:+val} */\r
- \r
- /* if the value of the variable is not empty, replace the expression by the value */\r
- p += 2;\r
-\r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == p))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
-\r
- strncpy(val, p,(end - p));\r
-\r
- sprintf(exp, "${%s:+%s}", variable->name, val);\r
-\r
- if(variable->val)\r
- {\r
- str_replace_all(&line2, exp, val, NULL);\r
- }\r
- else\r
- {\r
- str_replace_all(&line2, exp, NULL , NULL);\r
- variable->val = strdup(val);\r
- }\r
- \r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
- \r
- if(val)\r
- {\r
- free(val);\r
- val = NULL;\r
- }\r
- }\r
- else if((p = strstr(buff, ":?")))\r
- {\r
- /* ${var:?val} */\r
- \r
- /* if the value of the variable is not empty, replace the expression by the value */\r
- p += 2;\r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == p))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
-\r
- strncpy(val, p,(end - p));\r
-\r
- sprintf(exp, "${%s:?%s}", variable->name, val);\r
- \r
- if(variable->val)\r
- str_replace_all(&line2, exp, variable->val, NULL);\r
- else\r
- {\r
-\r
- xbt_os_mutex_release(unit->mutex); \r
-\r
- ERROR2("[%s] %s.",filepos, val);\r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
- \r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
- \r
- if(val)\r
- {\r
- free(val);\r
- val = NULL;\r
- }\r
- }\r
- }\r
- }\r
-\r
- /* replace all existing $var */\r
- xbt_dynar_foreach(variables, i, variable)\r
- {\r
- if(!strchr(line2 + 2, '$'))\r
- break;\r
-\r
- if(strstr(line2 + 2, variable->name))\r
- {\r
-\r
- sprintf(exp, "${#%s}", variable->name);\r
- \r
- if(strstr(line2 + 2, exp))\r
- {\r
-\r
- if(variable->val)\r
- {\r
- char slen[4] = {0};\r
- sprintf(slen,"%d", (int)strlen(variable->val));\r
- str_replace_all(&line2, exp, slen, NULL);\r
- }\r
- else\r
- str_replace_all(&line2, exp, "0", NULL);\r
- }\r
-\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
-\r
- sprintf(exp, "${%s}", variable->name);\r
-\r
- if(strstr(line2 + 2, exp))\r
- {\r
- if(variable->val)\r
- str_replace_all(&line2, exp, variable->val, NULL);\r
- else\r
- str_replace_all(&line2, exp, NULL, NULL);\r
- }\r
-\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
-\r
- sprintf(exp, "$%s", variable->name);\r
- \r
- if((p = strstr(line2 + 2, exp)))\r
- {\r
- if((p + strlen(variable->name) + 1)[0] != '\0' && !(isalpha((p + strlen(variable->name) + 1)[0])))\r
- delimiters[0] = (p + strlen(variable->name) + 1)[0];\r
-\r
- if(variable->val)\r
- str_replace_all(&line2, exp, variable->val, delimiters);\r
- else\r
- str_replace_all(&line2, exp, NULL, delimiters);\r
- }\r
-\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
-\r
- }\r
- }\r
-\r
- while((p = strstr(line2 + 2, "${")))\r
- {\r
- /*if(*(p+1) != '{')\r
- {\r
- j = 0;\r
- p --;\r
-\r
- while(*(p++) != '\0')\r
- {\r
- if(*p != ' ' && *p !='\t')\r
- exp[j++] = *p;\r
- else\r
- break;\r
-\r
- }\r
- \r
- str_replace_all(&line2, exp, NULL, " \t\n\r");\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
- }.\r
- else\r
- */\r
- {\r
- char* begin = NULL;\r
- \r
- j = 0;\r
- p --;\r
-\r
- while(*(p++) != '\0')\r
- {\r
- if((!begin && *p != ' ' && *p !='\t') || begin)\r
- {\r
- /* `:' must be before this caracter, bad substitution : exit loop \r
- ||\r
- the current character is already present, bad substitution : exit loop\r
- */\r
- if(\r
- (\r
- *(p - 1) != ':' && (\r
- (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')\r
- )\r
- )\r
- || \r
- (\r
- begin && (\r
- (*p == ':') || (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')\r
- )\r
- )\r
- )\r
- break;\r
- else\r
- exp[j++] = *p;\r
-\r
- if(*p == ':')\r
- {\r
- /* save the begining of the value */\r
- if((*(p+1) == '=') || (*(p+1) == '-') || (*(p+1) == '+') || (*(p+1) == '?'))\r
- {\r
- begin = p + 2;\r
- exp[j++] = *(p+1);\r
- p++;\r
- continue;\r
-\r
- }\r
- else\r
- /* the current char is `:' but the next is invalid, bad substitution : exit loop */\r
- break;\r
- }\r
- /* end of the substitution : exit loop */\r
- else if(*p == '}')\r
- break;\r
- }\r
- else\r
- break;\r
- }\r
- \r
- if(exp[j - 1] == '}')\r
- {\r
- if(exp[2] == '#')\r
- {\r
- /* ${#var} */\r
-\r
-\r
- if(4 == strlen(exp))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
- \r
- str_replace_all(&line2, exp, "0", NULL); \r
- }\r
- else if(strstr(exp,":="))\r
- {\r
- /* ${var:=value} */ \r
- \r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == begin))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- variable = xbt_new0(s_variable_t, 1);\r
-\r
- variable->val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
-\r
- strncpy(variable->val, begin ,(end - begin));\r
-\r
- begin = exp + 2;\r
- end = strchr(exp, ':');\r
-\r
- if(!end || (end == begin))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- variable->name = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
-\r
- strncpy(variable->name, exp + 2 ,(end - begin));\r
-\r
- str_replace_all(&line2, exp, variable->val, NULL);\r
-\r
- xbt_dynar_push(variables, &variable);\r
-\r
- }\r
- else if(strstr(exp,":-"))\r
- {\r
- /* ${var:-value} */ \r
-\r
- \r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == begin))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
-\r
- strncpy(val, begin ,(end - begin));\r
-\r
- str_replace_all(&line2, exp, val, NULL);\r
-\r
- if(val)\r
- free(val);\r
-\r
- }\r
- else if(strstr(exp,":+"))\r
- {\r
- /* ${var:+value} */ \r
-\r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == begin))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- str_replace_all(&line2, exp, NULL, NULL);\r
- }\r
- else if(strstr(exp,":?"))\r
- {\r
- /* ${var:?value} */\r
- \r
- end = strchr(p, '}');\r
-\r
- if(!end || (end == begin))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
-\r
- strncpy(val, begin ,(end - begin));\r
-\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] : `%s'.",filepos, val);\r
-\r
- if(val)\r
- free(val);\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
-\r
- return;\r
- \r
- }\r
- else\r
- {\r
- /* ${var} */\r
-\r
- if(3 == strlen(exp))\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
- \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- str_replace_all(&line2, exp, NULL, NULL);\r
- \r
- }\r
-\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
- }\r
- else\r
- {\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- if(strstr(line2 + 2, "${"))\r
- ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
- else\r
- ERROR2("[%s] Syntax error : `%s'.",filepos, strstr(line2, "${"));\r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(fstream->unit);\r
- return;\r
- }\r
-\r
- }\r
- \r
- }\r
- \r
- while(1)\r
- {\r
- p = line2 + (line2[0] =='<' ? 4 : 2);\r
- \r
- if((p = strchr(p, '$')))\r
- {\r
- if(*(p+1) != ' ')\r
- {\r
- j = 0;\r
- p --;\r
-\r
- while(*(p++) != '\0')\r
- {\r
- if(*p != ' ' && *p !='\t')\r
- exp[j++] = *p;\r
- else\r
- break;\r
-\r
- }\r
- \r
- str_replace_all(&line2, exp, NULL, " \t\n\r");\r
- memset(exp, 0, VAR_NAME_MAX + 1);\r
- }\r
- else\r
- {\r
- /* maybe < $ cmd */\r
- p++;\r
- }\r
- }\r
- else\r
- break;\r
- }\r
-\r
- xbt_os_mutex_release(unit->mutex); \r
- \r
- switch(line2[0]) \r
- {\r
- /*case '#': \r
- break;\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, filepos);\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
- \r
- /* deal with CD commands here, not in context */\r
- if(!strncmp("cd ",line2 + 2, 3)) \r
- {\r
- char* dir = strdup(line2 + 4);\r
- \r
- if(context->command_line)\r
- {\r
- if(fstream_launch_command(fstream, context, mutex) < 0)\r
- return;\r
- }\r
- \r
- /* search begining */\r
- while(*(dir++) == ' ');\r
- \r
- dir--;\r
- \r
- if(!dry_run_flag)\r
- {\r
- if(!silent_flag)\r
- INFO2("[%s] cd %s", filepos, dir);\r
- \r
- if(!just_print_flag)\r
- {\r
- if(chdir(dir))\r
- {\r
- ERROR3("[%s] Chdir to %s failed: %s",filepos, dir,error_to_string(errno, 0));\r
- unit_set_error(fstream->unit, errno, 0, filepos);\r
-\r
- failure(unit);\r
- }\r
- }\r
- }\r
- \r
- break;\r
- }\r
- else\r
- {\r
- fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);\r
- break;\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, filepos);\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
- \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
- {\r
- if (prompt[j] != ' ' && prompt[j] != '\t')\r
- {\r
- is_blank = 0;\r
- break;\r
- }\r
- }\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, filepos);\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
- \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, filepos);\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("[%s] Description already specified `%s'",filepos, line2 + 2); \r
- else\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
-\r
- unit->description = strdup(desc);\r
- }\r
- break;\r
- \r
- default:\r
- ERROR2("[%s] Syntax error `%s'", filepos, line2);\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(unit);\r
- break;\r
- }\r
- \r
- free(line2);\r
-}\r
-\r
-void \r
-fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* filepos, char token, char *line) \r
-{\r
- unit_t unit = fstream->unit;\r
- \r
- switch (token) \r
- {\r
- case '$':\r
- case '&':\r
- \r
- if(context->command_line) \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
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- failure(unit);\r
- return;\r
- }\r
- \r
- if(fstream_launch_command(fstream, context, mutex) < 0)\r
- return;\r
- \r
- VERB1("[%s] More than one command in this chunk of lines",filepos);\r
- }\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- \r
- context->command_line = strdup(line);\r
-\r
- xbt_str_ltrim(context->command_line," ");\r
- \r
- context->line = /*strdup(filepos)*/ filepos;\r
- context->pos = strdup(filepos);\r
- \r
- #ifdef _XBT_WIN32\r
- {\r
-\r
- /* translate the command line */\r
-\r
- char* path = NULL;\r
- char* delimiter;\r
- char command_line[PATH_MAX + 1] = {0};\r
- size_t i = 0;\r
- char* args = NULL;\r
-\r
- \r
-\r
- /*if(strstr(context->command_line,".exe"))\r
- strcpy(command_line,context->command_line);*/\r
- \r
- {\r
- size_t len;\r
- \r
- size_t j = 0;\r
- \r
- len = strlen(context->command_line);\r
- \r
- while(i < len)\r
- {\r
- if(context->command_line[i] != ' ' && context->command_line[i] != '\t' && context->command_line[i] != '>')\r
- command_line[j++] = context->command_line[i];\r
- else\r
- break;\r
- \r
- i++;\r
- }\r
- \r
- if(!strstr(context->command_line,".exe"))\r
- strcat(command_line,".exe");\r
-\r
- args = strdup(context->command_line + i);\r
- }\r
- \r
- if(!is_w32_cmd(command_line, fstream->unit->runner->path) && getpath(command_line, &path) < 0)\r
- {\r
- command_t command;\r
-\r
- ERROR3("[%s] `%s' : NOK (%s)", filepos, command_line, error_to_string(ECMDNOTFOUND, 1));\r
- unit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);\r
-\r
- context->is_not_found = 1;\r
- \r
- command = command_new(fstream->unit, context, mutex);\r
-\r
- command->status = cs_failed;\r
- command->reason = csr_command_not_found;\r
-\r
- failure(unit);\r
- \r
- \r
- return;\r
- }\r
- \r
- delimiter = strrchr(command_line,'/');\r
-\r
- if(!delimiter)\r
- delimiter = strrchr(command_line,'\\');\r
- \r
- /*free(context->command_line);*/\r
- \r
- \r
- if(path)\r
- {\r
- if(args)\r
- {\r
- context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + strlen(args) + 2, sizeof(char));\r
- sprintf(context->t_command_line,"%s\\%s%s",path,delimiter ? delimiter + 1 : command_line, args);\r
-\r
- free(args);\r
-\r
- }\r
- else\r
- {\r
- context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + 2, sizeof(char));\r
- sprintf(context->t_command_line,"%s\\%s",path,delimiter ? delimiter + 1 : command_line);\r
- }\r
- \r
- free(path);\r
- }\r
- else\r
- {\r
- if(args)\r
- {\r
-\r
- context->t_command_line = (char*)calloc(strlen(command_line) + strlen(args) + 1, sizeof(char));\r
- sprintf(context->t_command_line,"%s%s",command_line, args);\r
-\r
- \r
- free(args);\r
-\r
- }\r
- else\r
- {\r
- context->t_command_line = (char*)calloc(strlen(command_line) + 1, sizeof(char));\r
- strcpy(context->t_command_line,command_line);\r
- }\r
- }\r
-\r
-\r
- }\r
- #endif\r
-\r
-\r
- break;\r
- \r
- case '<':\r
- xbt_strbuff_append(context->input,line);\r
- xbt_strbuff_append(context->input,"\n");\r
- break;\r
- \r
- case '>':\r
- xbt_strbuff_append(context->output,line);\r
- xbt_strbuff_append(context->output,"\n");\r
- break;\r
- \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
- VERB1("[%s] (disable timeout)", filepos);\r
- context->timeout = INDEFINITE;\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- \r
- while(p[i] != '\0')\r
- {\r
- if(!isdigit(p[i]))\r
- {\r
- ERROR2("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'", filepos, line + strlen("timeout "));\r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- \r
- failure(unit);\r
- return;\r
- }\r
-\r
- i++;\r
- }\r
- \r
- context->timeout = atoi(line + strlen("timeout"));\r
- VERB2("[%s] (new timeout value: %d)",filepos,context->timeout);\r
- \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, filepos);\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 _XBT_WIN32\r
- if(!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))\r
- {\r
- ERROR2("[%s] Signal `%s' not supported by this platform", filepos, context->signal);\r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\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, filepos);\r
-\r
-\r
- failure(unit);\r
- return;\r
- }\r
-\r
- #endif\r
-\r
- \r
- VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);\r
- \r
- } \r
- else if (!strncmp(line,"expect return ",strlen("expect return "))) \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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- \r
- while(p[i] != '\0')\r
- {\r
- if(!isdigit(p[i]))\r
- {\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
-\r
- i++;\r
- }\r
-\r
- context->exit_code = atoi(line+strlen("expect return "));\r
- VERB2("[%s] (next command must return code %d)",filepos, context->exit_code);\r
- \r
- } \r
- else if (!strncmp(line,"output ignore",strlen("output ignore"))) \r
- {\r
- context->output_handling = oh_ignore;\r
- VERB1("[%s] (ignore output of next command)", filepos);\r
- \r
- } \r
- else if (!strncmp(line,"output display",strlen("output display"))) \r
- {\r
- context->output_handling = oh_display;\r
- VERB1("[%s] (ignore output of next command)", filepos);\r
- \r
- } \r
- else if(!strncmp(line,"include ", strlen("include ")))\r
- {\r
- char* p1;\r
- char* p2;\r
- \r
- p1 = line + strlen("include");\r
- \r
- while(*p1 == ' ' || *p1 == '\t')\r
- p1++;\r
- \r
- \r
- if(p1[0] == '\0')\r
- {\r
- ERROR1("[%s] no file specified : `(usage : include <file> [<description>])'", filepos);\r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- else\r
- {\r
- char file_name[PATH_MAX + 1] = {0};\r
- \r
- p2 = p1;\r
- \r
- while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')\r
- p2++;\r
- \r
- strncpy(file_name, p1, p2 - p1);\r
- \r
- \r
- if(p2[0] != '\0')\r
- while(*p2 == ' ' || *p2 == '\t')\r
- p2++;\r
- \r
- fstream_handle_include(fstream, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);\r
- \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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
-\r
- if(unit->is_running_suite)\r
- {\r
- ERROR1("[%s] Suite already in progress", filepos);\r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- \r
- fstream_handle_suite(fstream, line + strlen("suite "), filepos);\r
- }\r
- else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))\r
- {\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- \r
- xbt_os_mutex_acquire(unit->mutex);\r
- \r
-\r
- xbt_dynar_foreach(unit->runner->variables, i, variable)\r
- {\r
- if(!strcmp(variable->name, name))\r
- {\r
- env = variable->env;\r
- err = variable->err;\r
- exists = 1;\r
- break;\r
- }\r
- }\r
- \r
- if(env)\r
- {\r
- if(exists)\r
- {\r
- #ifndef _XBT_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
- {\r
- ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name); \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- xbt_os_mutex_release(unit->mutex);\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- if(exists)\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, filepos);\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, filepos);\r
- xbt_os_mutex_release(unit->mutex);\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name); \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\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
- }\r
- else if(!strncmp(line,"setenv ", strlen("setenv ")))\r
- {\r
- char* val;\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
- val = strchr(p, '=');\r
- \r
- if(val)\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' || val[0] ==' ' || val[0] =='\t')\r
- {\r
- ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos); \r
-\r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\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, filepos);\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
- xbt_dynar_foreach(unit->runner->variables, i, variable)\r
- {\r
- if(!strcmp(variable->name, name))\r
- {\r
- env = variable->env;\r
- err = variable->err;\r
- exists = 1;\r
- break;\r
- }\r
- }\r
- \r
- /* if the variable is already registred, update its value;\r
- * otherwise register it.\r
- */\r
- if(exists)\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 _XBT_WIN32\r
- SetEnvironmentVariable(variable->name, variable->val);\r
- #else\r
- setenv(variable->name, variable->val, 1);\r
- #endif\r
- }\r
- else\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, filepos);\r
- xbt_os_mutex_release(unit->mutex);\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- else\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, filepos);\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 _XBT_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, filepos);\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- else if(!strncmp(line,"unset ", strlen("unset ")))\r
- {\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
-\r
- \r
- xbt_os_mutex_acquire(unit->mutex);\r
-\r
- xbt_dynar_foreach(unit->runner->variables, i, variable)\r
- {\r
- if(!strcmp(variable->name, name))\r
- {\r
- env = variable->env;\r
- err = variable->err;\r
- exists = 1;\r
- break;\r
- }\r
- }\r
- \r
- if(!env && !err)\r
- {\r
- if(exists)\r
- {\r
- /*xbt_dynar_remove_at(unit->runner->variables, i, NULL);*/\r
- /*xbt_dynar_cursor_rm(unit->runner->variables, &i);*/\r
- if(variable->val)\r
- {\r
- free(variable->val);\r
- variable->val = NULL;\r
- }\r
- else\r
- {\r
- WARN2("[%s] Variable `(%s)' already unseted",filepos, variable->name);\r
- }\r
- } \r
- else\r
- {\r
- ERROR2("[%s] `(%s)' variable not found",filepos, name); \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
- xbt_os_mutex_release(unit->mutex);\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- else if(env)\r
- {\r
- ERROR2("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",filepos, name); \r
- unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\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, filepos);\r
- xbt_os_mutex_release(unit->mutex);\r
- failure(unit);\r
- return;\r
- }\r
- \r
- xbt_os_mutex_release(unit->mutex);\r
- \r
- }\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 + 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, filepos);\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, filepos);\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, filepos);\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, filepos);\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, filepos);\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, filepos);\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
- 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, filepos);\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, filepos);\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, filepos);\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, filepos);\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, filepos);\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, filepos);\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, filepos);\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
- }\r
- else \r
- {\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, filepos);\r
-\r
- failure(unit);\r
- return;\r
- }\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-void\r
-fstream_handle_include(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)\r
-{\r
- directory_t dir;\r
- char* prev_directory = NULL;\r
- fstream_t _fstream = NULL;\r
- struct stat buffer = {0};\r
- unit_t unit = fstream->unit;\r
- \r
- if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
- {\r
- /* the file is in the current directory */\r
- _fstream = fstream_new(getcwd(NULL, 0), file_name);\r
- fstream_open(_fstream);\r
- }\r
- /* the file to include is not in the current directory, check if it is in a include directory */\r
- else\r
- {\r
- unsigned int i;\r
- prev_directory = getcwd(NULL, 0);\r
- \r
- xbt_dynar_foreach(include_dirs, i, dir)\r
- {\r
- chdir(dir->name);\r
- \r
- if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
- {\r
- _fstream = fstream_new(dir->name, file_name);\r
- fstream_open(_fstream);\r
- break;\r
- }\r
- }\r
-\r
- chdir(prev_directory);\r
- free(prev_directory);\r
- }\r
- \r
- /* the file to include is not found handle the failure */\r
- if(!_fstream)\r
- {\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
- /* 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, context->line);\r
-\r
- failure(fstream->unit);\r
-\r
- return;\r
- }\r
- else\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
- \r
- include->mutex = unit->root->mutex;\r
- \r
- if(description)\r
- include->description = strdup(description);\r
- \r
- xbt_dynar_push(unit->includes, &include);\r
- \r
- if(!dry_run_flag)\r
- {\r
- if(description)\r
- INFO2("Include from %s (%s)", _fstream->name, description);\r
- else\r
- INFO1("Include from %s", _fstream->name);\r
-\r
- }\r
- else\r
- INFO1("Checking include %s...",_fstream->name);\r
- \r
- fstream_parse(_fstream, mutex);\r
- }\r
- else\r
- {/* it's a include */\r
-\r
- unit_t* owner;\r
- unit_t include;\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
- \r
- include->mutex = unit->root->mutex;\r
- \r
- if(description)\r
- include->description = strdup(description);\r
- \r
- xbt_dynar_push((*owner)->includes, &include);\r
- \r
- if(!dry_run_flag)\r
- {\r
- if(description)\r
- INFO2("Include from %s (%s)", _fstream->name, description);\r
- else\r
- INFO1("Include from %s", _fstream->name);\r
- }\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, 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
- 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
-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
- if(!dry_run_flag)\r
- {\r
- command_t command;\r
- \r
- if(!(command = command_new(unit, context, mutex)))\r
- {\r
- if(EINVAL == errno)\r
- {\r
- ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno); \r
-\r
- unit_set_error(unit, errno, 0, context->pos);\r
- failure(unit);\r
- return -1;\r
- }\r
- else if(ENOMEM == errno)\r
- {\r
- ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);\r
-\r
- unit_set_error(unit, errno, 0, context->pos);\r
-\r
- failure(unit);\r
- return -1;\r
- }\r
- }\r
- \r
- if(command_run(command) < 0)\r
- {\r
- ERROR3("[%s] Cannot run the command `%s' (%d)",context->pos, strerror(errno), errno); \r
- unit_set_error(unit, errno, 0, context->pos);\r
- failure(unit);\r
- return -1; \r
- }\r
- }\r
- \r
- if(context_reset(context) < 0)\r
- {\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, context->pos);\r
-\r
- failure(unit);\r
- return -1; \r
- }\r
- \r
- return 0;\r
-}\r
-\r
-\r
-\r
-\r
+#ifdef _XBT_WIN32\r
+ if (!context->is_not_found)
+ \r {
+ \r
+#endif /* \r */
+ \rif (fstream_launch_command(fstream, context, mutex) < 0)
+ \rreturn -1;
+ \r\r
+#ifdef _XBT_WIN32\r
+ }
+ \r
+#endif /* \r */
+ }
+ \r\r
+ /* clear buffers */ \r
+ if (line)
+ \rfree(line);
+ \r\rxbt_strbuff_free(buff);
+ \r\rif (context_free(&context) < 0)
+ \rreturn -1;
+ \r\rreturn (exit_code || errno) ? -1 : 0;
+\r}
+
+\r\r\rvoid \r
+fstream_lex_line(fstream_t fstream, context_t context,
+ xbt_os_mutex_t mutex, const char *filepos, char *line) \r
+{
+ \rchar *line2;
+ \rvariable_t variable;
+ \runsigned int i;
+ \rchar exp[PATH_MAX + 1] = { 0 };
+ \runit_t unit = fstream->unit;
+ \rxbt_dynar_t variables = unit->runner->variables;
+ \rchar *p = NULL;
+ \rchar *end = NULL;
+ \rchar *val = NULL;
+ \rchar buff[PATH_MAX + 1] = { 0 };
+ \rsize_t len;
+ \rchar delimiters[4] = { ' ', '\t', '\n', '\0' };
+ \r\rint j;
+ \r\rif (line[0] == '#')
+ \rreturn;
+ \r\rif (unit->is_running_suite
+ && strncmp(line, "! include", strlen("! include")))
+ \r { /* it's the end of a suite */
+ \r\runit_t * current_suite =
+ xbt_dynar_get_ptr(unit->suites,
+ xbt_dynar_length(unit->suites) - 1);
+ \r\rif (!xbt_dynar_length((*current_suite)->includes))
+ \rERROR2("[%s] Malformated suite `(%s)': include missing", filepos,
+ (*current_suite)->description);
+ \r
+ else
+ \rERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos,
+ (*current_suite)->description);
+ \r\runit_set_error(*current_suite, ESYNTAX, 1, filepos);
+ \r\rfailure(fstream->unit);
+ \r}
+ \r\rcontext->line = strdup(filepos);
+ \r\r
+ /* search end */ \r
+ xbt_str_rtrim(line + 2, "\n");
+ \r\rline2 = strdup(line);
+ \r\rlen = strlen(line2 + 2) + 1;
+ \r\r
+ /* replace each variable by its value */ \r
+ xbt_os_mutex_acquire(unit->mutex);
+ \r\r\r
+ /* replace all existing\r
+ ${var}\r
+ ${var:=val}\r
+ ${var:+val}\r
+ ${var:-val}\r
+ ${var:?val}\r
+ ${#var}\r
+ */ \r
+ \rxbt_dynar_foreach(variables, i, variable) \r {
+ \rif (!(p = strstr(line2 + 2, "${")))
+ \rbreak;
+ \r\rmemset(buff, 0, len);
+ \r\rsprintf(buff, "${%s", variable->name);
+ \r\r
+ /* FALSE */ \r
+ if ((p = strstr(line2 + 2, buff)))
+ \r {
+ \rmemset(buff, 0, len);
+ \rp--;
+ \rj = 0;
+ \r\rwhile (*(p++) != '\0')
+ \r {
+ \rbuff[j++] = *p;
+ \r\rif (*p == '}')
+ \rbreak;
+ \r}
+ \r\rif (buff[j - 1] != '}')
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\r\rERROR2("[%s] Syntax error : `%s'.", filepos, p - j);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rif ((p = strstr(buff, ":=")))
+ \r {
+ \r
+ /* ${var:=val} */ \r
+ \r
+ /* if the value of the variable is empty, update its value by the value */ \r
+ p += 2;
+ \r\rend = strchr(p, '}');
+ \r\rif (!end || (end == p))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strstr(buff, "${"));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+ \r\rstrncpy(val, p, (end - p));
+ \r\r\r
+ /* replace the expression by the expression of the value of the variable */ \r
+ sprintf(exp, "${%s:=%s}", variable->name, val);
+ \r\rif (variable->val)
+ \rstr_replace_all(&line2, exp, variable->val, NULL);
+ \r
+ else
+ \r {
+ \rstr_replace_all(&line2, exp, val, NULL);
+ \r\rvariable->val = strdup(val);
+ \r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\rif (val)
+ \r {
+ \rfree(val);
+ \rval = NULL;
+ \r}
+ \r\r}
+ \r
+ else if ((p = strstr(buff, ":-")))
+ \r {
+ \r
+ /* ${var:-val} */ \r
+ \r
+ /* if the value of the variable is empty, replace the expression by the value */ \r
+ p += 2;
+ \rend = strchr(p, '}');
+ \r\rif (!end || (end == p))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strstr(line2, "${"));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+ \r\rstrncpy(val, p, (end - p));
+ \r\rsprintf(exp, "${%s:-%s}", variable->name, val);
+ \r\rstr_replace_all(&line2, exp, variable->val ? variable->val : val,
+ NULL);
+ \r\r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\rif (val)
+ \r {
+ \rfree(val);
+ \rval = NULL;
+ \r}
+ \r\r}
+ \r
+ else if ((p = strstr(buff, ":+")))
+ \r {
+ \r
+ /* ${var:+val} */ \r
+ \r
+ /* if the value of the variable is not empty, replace the expression by the value */ \r
+ p += 2;
+ \r\rend = strchr(p, '}');
+ \r\rif (!end || (end == p))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strstr(line2, "${"));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+ \r\rstrncpy(val, p, (end - p));
+ \r\rsprintf(exp, "${%s:+%s}", variable->name, val);
+ \r\rif (variable->val)
+ \r {
+ \rstr_replace_all(&line2, exp, val, NULL);
+ \r}
+ \r
+ else
+ \r {
+ \rstr_replace_all(&line2, exp, NULL, NULL);
+ \rvariable->val = strdup(val);
+ \r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\rif (val)
+ \r {
+ \rfree(val);
+ \rval = NULL;
+ \r}
+ \r}
+ \r
+ else if ((p = strstr(buff, ":?")))
+ \r {
+ \r
+ /* ${var:?val} */ \r
+ \r
+ /* if the value of the variable is not empty, replace the expression by the value */ \r
+ p += 2;
+ \rend = strchr(p, '}');
+ \r\rif (!end || (end == p))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strstr(line2, "${"));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+ \r\rstrncpy(val, p, (end - p));
+ \r\rsprintf(exp, "${%s:?%s}", variable->name, val);
+ \r\rif (variable->val)
+ \rstr_replace_all(&line2, exp, variable->val, NULL);
+ \r
+ else
+ \r {
+ \r\rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] %s.", filepos, val);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\rif (val)
+ \r {
+ \rfree(val);
+ \rval = NULL;
+ \r}
+ \r}
+ \r}
+ \r}
+ \r\r
+ /* replace all existing $var */ \r
+ xbt_dynar_foreach(variables, i, variable) \r {
+ \rif (!strchr(line2 + 2, '$'))
+ \rbreak;
+ \r\rif (strstr(line2 + 2, variable->name))
+ \r {
+ \r\rsprintf(exp, "${#%s}", variable->name);
+ \r\rif (strstr(line2 + 2, exp))
+ \r {
+ \r\rif (variable->val)
+ \r {
+ \rchar slen[4] = { 0 };
+ \rsprintf(slen, "%d", (int) strlen(variable->val));
+ \rstr_replace_all(&line2, exp, slen, NULL);
+ \r}
+ \r
+ else
+ \rstr_replace_all(&line2, exp, "0", NULL);
+ \r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\rsprintf(exp, "${%s}", variable->name);
+ \r\rif (strstr(line2 + 2, exp))
+ \r {
+ \rif (variable->val)
+ \rstr_replace_all(&line2, exp, variable->val, NULL);
+ \r
+ else
+ \rstr_replace_all(&line2, exp, NULL, NULL);
+ \r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\rsprintf(exp, "$%s", variable->name);
+ \r\rif ((p = strstr(line2 + 2, exp)))
+ \r {
+ \rif ((p + strlen(variable->name) + 1)[0] != '\0'
+ && !(isalpha((p + strlen(variable->name) + 1)[0])))
+ \rdelimiters[0] = (p + strlen(variable->name) + 1)[0];
+ \r\rif (variable->val)
+ \rstr_replace_all(&line2, exp, variable->val, delimiters);
+ \r
+ else
+ \rstr_replace_all(&line2, exp, NULL, delimiters);
+ \r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r\r}
+ \r}
+ \r\rwhile ((p = strstr(line2 + 2, "${")))
+ \r {
+ \r
+ /*if(*(p+1) != '{')\r
+ {\r
+ j = 0;\r
+ p --;\r
+ \r
+ while(*(p++) != '\0')\r
+ {\r
+ if(*p != ' ' && *p !='\t')\r
+ exp[j++] = *p;\r
+ else\r
+ break;\r
+ \r
+ }\r
+ \r
+ str_replace_all(&line2, exp, NULL, " \t\n\r");\r
+ memset(exp, 0, VAR_NAME_MAX + 1);\r
+ }.\r
+ else\r
+ */ \r
+ {
+ \rchar *begin = NULL;
+ \r\rj = 0;
+ \rp--;
+ \r\rwhile (*(p++) != '\0')
+ \r {
+ \rif ((!begin && *p != ' ' && *p != '\t') || begin)
+ \r {
+ \r
+ /* `:' must be before this caracter, bad substitution : exit loop \r
+ ||\r
+ the current character is already present, bad substitution : exit loop\r
+ */ \r
+ if (\r
+ (\r*(p - 1) != ':' && (\r
+ (*p == '=') || (*p == '-')
+ || (*p == '+')
+ || (*p == '?') \r) \r) \r ||\r(\rbegin
+ &&
+ (\r
+ (*p ==
+ ':')
+ || (*p
+ ==
+ '=')
+ || (*p
+ ==
+ '-')
+ || (*p
+ ==
+ '+')
+ || (*p
+ ==
+ '?')
+ \r) \r)
+ \r)
+ \rbreak;
+ \r
+ else
+ \rexp[j++] = *p;
+ \r\rif (*p == ':')
+ \r {
+ \r
+ /* save the begining of the value */ \r
+ if ((*(p + 1) == '=') || (*(p + 1) == '-')
+ || (*(p + 1) == '+') || (*(p + 1) == '?'))
+ \r {
+ \rbegin = p + 2;
+ \rexp[j++] = *(p + 1);
+ \rp++;
+ \rcontinue;
+ \r\r}
+ \r
+ else
+ \r
+ /* the current char is `:' but the next is invalid, bad substitution : exit loop */ \r
+ break;
+ \r}
+ \r
+ /* end of the substitution : exit loop */ \r
+ else if (*p == '}')
+ \rbreak;
+ \r}
+ \r
+ else
+ \rbreak;
+ \r}
+ \r\rif (exp[j - 1] == '}')
+ \r {
+ \rif (exp[2] == '#')
+ \r {
+ \r
+ /* ${#var} */ \r
+ \r\rif (4 == strlen(exp))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rstr_replace_all(&line2, exp, "0", NULL);
+ \r}
+ \r
+ else if (strstr(exp, ":="))
+ \r {
+ \r
+ /* ${var:=value} */ \r
+ \rend = strchr(p, '}');
+ \r\rif (!end || (end == begin))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rvariable = xbt_new0(s_variable_t, 1);
+ \r\rvariable->val =
+ (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+ \r\rstrncpy(variable->val, begin, (end - begin));
+ \r\rbegin = exp + 2;
+ \rend = strchr(exp, ':');
+ \r\rif (!end || (end == begin))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rvariable->name =
+ (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+ \r\rstrncpy(variable->name, exp + 2, (end - begin));
+ \r\rstr_replace_all(&line2, exp, variable->val, NULL);
+ \r\rxbt_dynar_push(variables, &variable);
+ \r\r}
+ \r
+ else if (strstr(exp, ":-"))
+ \r {
+ \r
+ /* ${var:-value} */ \r
+ \r\rend = strchr(p, '}');
+ \r\rif (!end || (end == begin))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rval =
+ (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+ \r\rstrncpy(val, begin, (end - begin));
+ \r\rstr_replace_all(&line2, exp, val, NULL);
+ \r\rif (val)
+ \rfree(val);
+ \r\r}
+ \r
+ else if (strstr(exp, ":+"))
+ \r {
+ \r
+ /* ${var:+value} */ \r
+ \rend = strchr(p, '}');
+ \r\rif (!end || (end == begin))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rstr_replace_all(&line2, exp, NULL, NULL);
+ \r}
+ \r
+ else if (strstr(exp, ":?"))
+ \r {
+ \r
+ /* ${var:?value} */ \r
+ \rend = strchr(p, '}');
+ \r\rif (!end || (end == begin))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rval =
+ (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+ \r\rstrncpy(val, begin, (end - begin));
+ \r\rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] : `%s'.", filepos, val);
+ \r\rif (val)
+ \rfree(val);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \r\rreturn;
+ \r\r}
+ \r
+ else
+ \r {
+ \r
+ /* ${var} */ \r
+ \rif (3 == strlen(exp))
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strchr(line2 + 2, '$'));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\rstr_replace_all(&line2, exp, NULL, NULL);
+ \r\r}
+ \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r}
+ \r
+ else
+ \r {
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rif (strstr(line2 + 2, "${"))
+ \rERROR2("[%s] Bad substitution : `%s'.", filepos,
+ strstr(line2, "${"));
+ \r
+ else
+ \rERROR2("[%s] Syntax error : `%s'.", filepos,
+ strstr(line2, "${"));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(fstream->unit);
+ \rreturn;
+ \r}
+ \r\r}
+ \r\r}
+ \r\rwhile (1)
+ \r {
+ \rp = line2 + (line2[0] == '<' ? 4 : 2);
+ \r\rif ((p = strchr(p, '$')))
+ \r {
+ \rif (*(p + 1) != ' ')
+ \r {
+ \rj = 0;
+ \rp--;
+ \r\rwhile (*(p++) != '\0')
+ \r {
+ \rif (*p != ' ' && *p != '\t')
+ \rexp[j++] = *p;
+ \r
+ else
+ \rbreak;
+ \r\r}
+ \r\rstr_replace_all(&line2, exp, NULL, " \t\n\r");
+ \rmemset(exp, 0, VAR_NAME_MAX + 1);
+ \r}
+ \r
+ else
+ \r {
+ \r
+ /* maybe < $ cmd */ \r
+ p++;
+ \r}
+ \r}
+ \r
+ else
+ \rbreak;
+ \r}
+ \r\rxbt_os_mutex_release(unit->mutex);
+ \r\rswitch (line2[0])
+ \r {
+ \r
+ /*case '#': \r
+ break;\r
+ */ \r
+ \rcase '$':
+ \rcase '&':
+ \r\rif (line[1] != ' ')
+ \r {
+ \r\rif (line2[0] == '$')
+ \rERROR1("[%s] Missing space after `$' `(usage : $ <command>)'",
+ filepos);
+ \r
+ else
+ \rERROR1("[%s] Missing space after & `(usage : & <command>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rcontext->async = (line2[0] == '&');
+ \r\r\r
+ /* further trim useless chars which are significant for in/output */ \r
+ xbt_str_rtrim(line2 + 2, " \t");
+ \r\r
+ /* deal with CD commands here, not in context */ \r
+ if (!strncmp("cd ", line2 + 2, 3))
+ \r {
+ \rchar *dir = strdup(line2 + 4);
+ \r\rif (context->command_line)
+ \r {
+ \rif (fstream_launch_command(fstream, context, mutex) < 0)
+ \rreturn;
+ \r}
+ \r\r
+ /* search begining */ \r
+ while (*(dir++) == ' ');
+ \r\rdir--;
+ \r\rif (!dry_run_flag)
+ \r {
+ \rif (!silent_flag)
+ \rINFO2("[%s] cd %s", filepos, dir);
+ \r\rif (!just_print_flag)
+ \r {
+ \rif (chdir(dir))
+ \r {
+ \rERROR3("[%s] Chdir to %s failed: %s", filepos, dir,
+ error_to_string(errno, 0));
+ \runit_set_error(fstream->unit, errno, 0, filepos);
+ \r\rfailure(unit);
+ \r}
+ \r}
+ \r}
+ \r\rbreak;
+ \r}
+ \r
+ else
+ \r {
+ \rfstream_process_token(fstream, context, mutex, filepos, line2[0],
+ line2 + 2);
+ \rbreak;
+ \r}
+ \r\rcase '<':
+ \rcase '>':
+ \rcase '!':
+ \r\rif (line[0] == '!' && line[1] != ' ')
+ \r {
+ \rERROR1
+ ("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rfstream_process_token(fstream, context, mutex, filepos, line2[0],
+ line2 + 2);
+ \rbreak;
+ \r\rcase 'p':
+ \r\r {
+ \runsigned int j;
+ \rint is_blank = 1;
+ \r\rchar *prompt = line2 + 2;
+ \r\rfor (j = 0; j < strlen(prompt); j++)
+ \r {
+ \rif (prompt[j] != ' ' && prompt[j] != '\t')
+ \r {
+ \ris_blank = 0;
+ \rbreak;
+ \r}
+ \r}
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rif (!dry_run_flag)
+ \rINFO2("[%s] %s", filepos, prompt);
+ \r}
+ \r\r\rbreak;
+ \r\rcase 'P':
+ \r\r {
+ \runsigned int j;
+ \rint is_blank = 1;
+ \r\rchar *prompt = line2 + 2;
+ \r\rfor (j = 0; j < strlen(prompt); j++)
+ \rif (prompt[j] != ' ' && prompt[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rif (!dry_run_flag)
+ \rCRITICAL2("[%s] %s", filepos, prompt);
+ \r}
+ \r\rbreak;
+ \r\rcase 'D':
+ \rif (unit->description)
+ \rWARN2("[%s] Description already specified `%s'", filepos,
+ line2 + 2);
+ \r
+ else
+ \r {
+ \runsigned int j;
+ \rint is_blank = 1;
+ \r\rchar *desc = line2 + 2;
+ \r\rfor (j = 0; j < strlen(desc); j++)
+ \rif (desc[j] != ' ' && desc[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand D `(usage : D <Description>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\runit->description = strdup(desc);
+ \r}
+ \rbreak;
+ \r\rdefault:
+ \rERROR2("[%s] Syntax error `%s'", filepos, line2);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rbreak;
+ \r}
+ \r\rfree(line2);
+\r}
+
+\r\rvoid \r
+fstream_process_token(fstream_t fstream, context_t context,
+ xbt_os_mutex_t mutex, const char *filepos,
+ char token, char *line) \r
+{
+ \runit_t unit = fstream->unit;
+ \r\rswitch (token)
+ \r {
+ \rcase '$':
+ \rcase '&':
+ \r\rif (context->command_line)
+ \r {
+ \r\rif (context->output->used || context->input->used)
+ \r {
+ \rERROR2
+ ("[%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\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rif (fstream_launch_command(fstream, context, mutex) < 0)
+ \rreturn;
+ \r\rVERB1("[%s] More than one command in this chunk of lines",
+ filepos);
+ \r}
+ \r\r {
+ \rsize_t j, \ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(line); j++)
+ \rif (line[j] != ' ' && line[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rif (token == '$')
+ \rERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'",
+ filepos);
+ \r
+ else
+ \rERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r\rcontext->command_line = strdup(line);
+ \r\rxbt_str_ltrim(context->command_line, " ");
+ \r\rcontext->line = /*strdup(filepos) */ filepos;
+ \rcontext->pos = strdup(filepos);
+ \r\r
+#ifdef _XBT_WIN32\r
+ {
+ \r\r
+ /* translate the command line */ \r
+ \rchar *path = NULL;
+ \rchar *delimiter;
+ \rchar command_line[PATH_MAX + 1] = { 0 };
+ \rsize_t i = 0;
+ \rchar *args = NULL;
+ \r\r\r\r
+ /*if(strstr(context->command_line,".exe"))\r
+ strcpy(command_line,context->command_line); */ \r
+ \r {
+ \rsize_t len;
+ \r\rsize_t j = 0;
+ \r\rlen = strlen(context->command_line);
+ \r\rwhile (i < len)
+ \r {
+ \rif (context->command_line[i] != ' '
+ && context->command_line[i] != '\t'
+ && context->command_line[i] != '>')
+ \rcommand_line[j++] = context->command_line[i];
+ \r
+ else
+ \rbreak;
+ \r\ri++;
+ \r}
+ \r\rif (!strstr(context->command_line, ".exe"))
+ \rstrcat(command_line, ".exe");
+ \r\rargs = strdup(context->command_line + i);
+ \r}
+ \r\rif (!is_w32_cmd(command_line, fstream->unit->runner->path)
+ && getpath(command_line, &path) < 0)
+ \r {
+ \rcommand_t command;
+ \r\rERROR3("[%s] `%s' : NOK (%s)", filepos, command_line,
+ error_to_string(ECMDNOTFOUND, 1));
+ \runit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);
+ \r\rcontext->is_not_found = 1;
+ \r\rcommand = command_new(fstream->unit, context, mutex);
+ \r\rcommand->status = cs_failed;
+ \rcommand->reason = csr_command_not_found;
+ \r\rfailure(unit);
+ \r\r\rreturn;
+ \r}
+ \r\rdelimiter = strrchr(command_line, '/');
+ \r\rif (!delimiter)
+ \rdelimiter = strrchr(command_line, '\\');
+ \r\r
+ /*free(context->command_line); */ \r
+ \r\rif (path)
+ \r {
+ \rif (args)
+ \r {
+ \rcontext->t_command_line =
+ (char *) calloc(strlen(path) +
+ strlen(delimiter ? delimiter +
+ 1 : command_line) + strlen(args) + 2,
+ sizeof(char));
+ \rsprintf(context->t_command_line, "%s\\%s%s", path,
+ delimiter ? delimiter + 1 : command_line, args);
+ \r\rfree(args);
+ \r\r}
+ \r
+ else
+ \r {
+ \rcontext->t_command_line =
+ (char *) calloc(strlen(path) +
+ strlen(delimiter ? delimiter +
+ 1 : command_line) + 2, sizeof(char));
+ \rsprintf(context->t_command_line, "%s\\%s", path,
+ delimiter ? delimiter + 1 : command_line);
+ \r} \r\rfree(path);
+ \r}
+ \r
+ else
+ \r {
+ \rif (args)
+ \r {
+ \r\rcontext->t_command_line =
+ (char *) calloc(strlen(command_line) + strlen(args) + 1,
+ sizeof(char));
+ \rsprintf(context->t_command_line, "%s%s", command_line, args);
+ \r\r\rfree(args);
+ \r\r}
+ \r
+ else
+ \r {
+ \rcontext->t_command_line =
+ (char *) calloc(strlen(command_line) + 1, sizeof(char));
+ \rstrcpy(context->t_command_line, command_line);
+ \r} \r} \r\r\r} \r
+#endif /* \r */
+ \r\rbreak;
+ \r\rcase '<':
+ \rxbt_strbuff_append(context->input, line);
+ \rxbt_strbuff_append(context->input, "\n");
+ \rbreak;
+ \r\rcase '>':
+ \rxbt_strbuff_append(context->output, line);
+ \rxbt_strbuff_append(context->output, "\n");
+ \rbreak;
+ \r\rcase '!':
+ \r\rif (context->command_line)
+ \r {
+ \rif (fstream_launch_command(fstream, context, mutex) < 0)
+ \rreturn;
+ \r}
+ \r\rif (!strncmp(line, "timeout no", strlen("timeout no")))
+ \r {
+ \rVERB1("[%s] (disable timeout)", filepos);
+ \rcontext->timeout = INDEFINITE;
+ \r}
+ \r
+ else if (!strncmp(line, "timeout ", strlen("timeout ")))
+ \r {
+ \rint i = 0;
+ \runsigned int j;
+ \rint is_blank = 1;
+ \rchar *p = line + strlen("timeout ");
+ \r\r\rfor (j = 0; j < strlen(p); j++)
+ \rif (p[j] != ' ' && p[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Undefinite timeout value `(usage :timeout <seconds>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rwhile (p[i] != '\0')
+ \r {
+ \rif (!isdigit(p[i]))
+ \r {
+ \rERROR2
+ ("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'",
+ filepos, line + strlen("timeout "));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\ri++;
+ \r}
+ \r\rcontext->timeout = atoi(line + strlen("timeout"));
+ \rVERB2("[%s] (new timeout value: %d)", filepos, context->timeout);
+ \r\r}
+ \r
+ else if (!strncmp(line, "expect signal ", strlen("expect signal ")))
+ \r {
+ \runsigned int j;
+ \rint is_blank = 1;
+ \r\r\rchar *p = line + strlen("expect signal ");
+ \r\r\rfor (j = 0; j < strlen(p); j++)
+ \rif (p[j] != ' ' && p[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Undefinite signal name `(usage :expect signal <signal name>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rcontext->signal = strdup(line + strlen("expect signal "));
+ \r\rxbt_str_trim(context->signal, " \n");
+ \r\r
+#ifdef _XBT_WIN32\r
+ if (!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))
+ \r {
+ \rERROR2("[%s] Signal `%s' not supported by this platform", filepos,
+ context->signal);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+#else /* \r */
+ if (!sig_exists(context->signal))
+ \r {
+ \rERROR2("[%s] Signal `%s' not supported by Tesh", filepos,
+ context->signal);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\r
+#endif /* \r */
+ \r\rVERB2("[%s] (next command must raise signal %s)", filepos,
+ context->signal);
+ \r\r}
+ \r
+ else if (!strncmp(line, "expect return ", strlen("expect return ")))
+ \r {
+ \r\rint i = 0;
+ \runsigned int j;
+ \rint is_blank = 1;
+ \rchar *p = line + strlen("expect return ");
+ \r\r\rfor (j = 0; j < strlen(p); j++)
+ \rif (p[j] != ' ' && p[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Undefinite return value `(usage :expect return <return value>)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rwhile (p[i] != '\0')
+ \r {
+ \rif (!isdigit(p[i]))
+ \r {
+ \rERROR2
+ ("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255",
+ filepos, line + strlen("expect return "));
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\ri++;
+ \r}
+ \r\rcontext->exit_code = atoi(line + strlen("expect return "));
+ \rVERB2("[%s] (next command must return code %d)", filepos,
+ context->exit_code);
+ \r\r}
+ \r
+ else if (!strncmp(line, "output ignore", strlen("output ignore")))
+ \r {
+ \rcontext->output_handling = oh_ignore;
+ \rVERB1("[%s] (ignore output of next command)", filepos);
+ \r\r}
+ \r
+ else if (!strncmp(line, "output display", strlen("output display")))
+ \r {
+ \rcontext->output_handling = oh_display;
+ \rVERB1("[%s] (ignore output of next command)", filepos);
+ \r\r}
+ \r
+ else if (!strncmp(line, "include ", strlen("include ")))
+ \r {
+ \rchar *p1;
+ \rchar *p2;
+ \r\rp1 = line + strlen("include");
+ \r\rwhile (*p1 == ' ' || *p1 == '\t')
+ \rp1++;
+ \r\r\rif (p1[0] == '\0')
+ \r {
+ \rERROR1
+ ("[%s] no file specified : `(usage : include <file> [<description>])'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else
+ \r {
+ \rchar file_name[PATH_MAX + 1] = { 0 };
+ \r\rp2 = p1;
+ \r\rwhile (*p2 != '\0' && *p2 != ' ' && *p2 != '\t')
+ \rp2++;
+ \r\rstrncpy(file_name, p1, p2 - p1);
+ \r\r\rif (p2[0] != '\0')
+ \rwhile (*p2 == ' ' || *p2 == '\t')
+ \rp2++;
+ \r\rfstream_handle_include(fstream, context, mutex, file_name,
+ p2[0] != '\0' ? p2 : NULL);
+ \r\r}
+ \r}
+ \r
+ else if (!strncmp(line, "suite ", strlen("suite ")))
+ \r {
+ \runsigned int j;
+ \rint is_blank = 1;
+ \rchar *p = line + strlen("suite ");
+ \r\r\rfor (j = 0; j < strlen(p); j++)
+ \rif (p[j] != ' ' && p[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Undefinite suit description : `(usage : suite <description>)",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rif (unit->is_running_suite)
+ \r {
+ \rERROR1("[%s] Suite already in progress", filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rfstream_handle_suite(fstream, line + strlen("suite "), filepos);
+ \r}
+ \r
+ else if (!strncmp(line, "unsetenv ", strlen("unsetenv ")))
+ \r {
+ \runsigned int i, j;
+ \rint exists = 0;
+ \rint env = 0;
+ \rint err = 0;
+ \rvariable_t variable;
+ \rint is_blank;
+ \r\rchar *name = line + strlen("unsetenv ");
+ \r\ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(name); j++)
+ \rif (name[j] != ' ' && name[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rxbt_os_mutex_acquire(unit->mutex);
+ \r\r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+ \rif (!strcmp(variable->name, name))
+ \r {
+ \renv = variable->env;
+ \rerr = variable->err;
+ \rexists = 1;
+ \rbreak;
+ \r}
+ \r}
+ \r\rif (env)
+ \r {
+ \rif (exists)
+ \r {
+ \r
+#ifndef _XBT_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 {
+ \rERROR2
+ ("[%s] `(%s)' environment variable not found : impossible to unset it",
+ filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r
+ else
+ \r {
+ \rif (exists)
+ \r {
+ \rif (!err)
+ \r {
+ \rERROR2
+ ("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",
+ filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rreturn;
+ \r}
+ \r
+ else
+ \r {
+ \rERROR2
+ ("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",
+ filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r
+ else
+ \r {
+ \rERROR2
+ ("[%s] `(%s)' environment variable not found : impossible to unset it",
+ filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r\rxbt_os_mutex_release(unit->mutex);
+ \r\r\r}
+ \r
+ else if (!strncmp(line, "setenv ", strlen("setenv ")))
+ \r {
+ \rchar *val;
+ \rchar name[PATH_MAX + 1] = { 0 };
+ \rchar *p;
+ \runsigned int i;
+ \rint is_blank;
+ \runsigned int j;
+ \r\rp = line + strlen("setenv ");
+ \r\rval = strchr(p, '=');
+ \r\rif (val)
+ \r {
+ \rvariable_t variable;
+ \rint exists = 0;
+ \rint env = 0;
+ \rint err = 0;
+ \rval++;
+ \r\r
+ /* syntax error */ \r
+ if (val[0] == '\0' || val[0] == ' ' || val[0] == '\t')
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\r\r\rstrncpy(name, p, (val - p - 1));
+ \r\ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(name); j++)
+ \rif (name[j] != ' ' && name[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \r\rERROR1
+ ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\r
+ /* test if the variable is already registred */ \r
+ xbt_os_mutex_acquire(unit->mutex);
+ \r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+ \rif (!strcmp(variable->name, name))
+ \r {
+ \renv = variable->env;
+ \rerr = variable->err;
+ \rexists = 1;
+ \rbreak;
+ \r}
+ \r}
+ \r\r
+ /* if the variable is already registred, update its value;\r
+ * otherwise register it.\r
+ */ \r
+ if (exists)
+ \r {
+ \rif (env)
+ \r {
+ \rif (!strcmp(val, variable->val))
+ \rWARN3
+ ("[%s] This environment variable `(%s)' is already set with the value `(%s)'",
+ filepos, name, val);
+ \r\rfree(variable->val);
+ \rvariable->val = strdup(val);
+ \r\r
+#ifdef _XBT_WIN32\r
+ SetEnvironmentVariable(variable->name, variable->val);
+ \r
+#else /* \r */
+ setenv(variable->name, variable->val, 1);
+ \r
+#endif /* \r */
+ }
+ \r
+ else
+ \r {
+ \rif (err)
+ \rERROR2
+ ("[%s] Conflict : a system variable `(%s)' already exists",
+ filepos, name);
+ \r
+ else
+ \rERROR2
+ ("[%s] Conflict : (none environment) variable `(%s)' already exists",
+ filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r
+ else
+ \r {
+ \rif (err)
+ \r {
+ \rERROR2("[%s] A system variable named `(%s)' already exists",
+ filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else
+ \r {
+ \rvariable = variable_new(name, val);
+ \rvariable->env = 1;
+ \r\rxbt_dynar_push(unit->runner->variables, &variable);
+ \r\r
+#ifdef _XBT_WIN32\r
+ SetEnvironmentVariable(variable->name, variable->val);
+ \r
+#else /* \r */
+ setenv(variable->name, variable->val, 0);
+ \r
+#endif /* \r */
+ }
+ \r}
+ \r\rxbt_os_mutex_release(unit->mutex);
+ \r\r}
+ \r
+ else
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r
+ else if (!strncmp(line, "unset ", strlen("unset ")))
+ \r {
+ \runsigned int i, j;
+ \rint exists = 0;
+ \rint env = 0;
+ \rint err = 0;
+ \rvariable_t variable;
+ \rint is_blank;
+ \r\rchar *name = line + strlen("unset ");
+ \r\ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(name); j++)
+ \rif (name[j] != ' ' && name[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \r\rERROR1
+ ("[%s] Bad usage of the metacommand unset `(usage : unset variable)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\r\rxbt_os_mutex_acquire(unit->mutex);
+ \r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+ \rif (!strcmp(variable->name, name))
+ \r {
+ \renv = variable->env;
+ \rerr = variable->err;
+ \rexists = 1;
+ \rbreak;
+ \r}
+ \r}
+ \r\rif (!env && !err)
+ \r {
+ \rif (exists)
+ \r {
+ \r
+ /*xbt_dynar_remove_at(unit->runner->variables, i, NULL); */ \r
+ /*xbt_dynar_cursor_rm(unit->runner->variables, &i); */ \r
+ if (variable->val)
+ \r {
+ \rfree(variable->val);
+ \rvariable->val = NULL;
+ \r}
+ \r
+ else
+ \r {
+ \rWARN2("[%s] Variable `(%s)' already unseted", filepos,
+ variable->name);
+ \r}
+ \r}
+ \r
+ else
+ \r {
+ \rERROR2("[%s] `(%s)' variable not found", filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r
+ else if (env)
+ \r {
+ \rERROR2
+ ("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",
+ filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else if (err)
+ \r {
+ \rERROR2("[%s] `(%s)' is system variable : you can unset it",
+ filepos, name);
+ \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rxbt_os_mutex_release(unit->mutex);
+ \r\r}
+ \r
+ else if (!strncmp(line, "set ", strlen("set ")))
+ \r {
+ \rchar *val;
+ \rchar name[PATH_MAX + 1] = { 0 };
+ \runsigned int j;
+ \rint is_blank;
+ \r\rval = strchr(line + strlen("set "), '=');
+ \r\rif (val)
+ \r {
+ \rvariable_t variable;
+ \rint exists = 0;
+ \runsigned int i;
+ \rint err;
+ \rint env;
+ \r\rval++;
+ \r\r\r
+ /* syntax error */ \r
+ if (val[0] == '\0')
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else if (val[0] == ' ' || val[0] == '\t')
+ \r {
+ \rstrncpy(name, line + strlen("set "),
+ (val - (line + strlen("set "))));
+ \r\rERROR2("[%s] No space avaible after`(%s)'", filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\r\r
+ /* assume it's a varibale */ \r
+ \rstrncpy(name, line + strlen("set "),
+ (val - (line + strlen("set ")) - 1));
+ \r\ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(name); j++)
+ \rif (name[j] != ' ' && name[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \r\rERROR1
+ ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rxbt_os_mutex_acquire(unit->mutex);
+ \r\r
+ /* test if the variable is already registred */ \r
+ xbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+ \rif (!strcmp(variable->name, name))
+ \r {
+ \rexists = 1;
+ \rerr = variable->err;
+ \renv = variable->env;
+ \rbreak;
+ \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 {
+ \rif (err)
+ \r {
+ \rERROR2("[%s] A system variable named `(%s)' already exists",
+ filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \rif (env)
+ \r {
+ \rERROR2
+ ("[%s] `(%s)' is an environment variable use `setenv' instead `set'",
+ filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else
+ \r {
+ \rif (!strcmp(val, variable->val))
+ \rWARN3("[%s] Variable `(%s)' already contains value `<%s>'",
+ filepos, variable->name, val);
+ \r\rfree(variable->val);
+ \rvariable->val = strdup(val);
+ \r}
+ \r}
+ \r
+ else
+ \r {
+ \rvariable_t new_var = variable_new(name, val);
+ \rxbt_dynar_push(unit->runner->variables, &new_var);
+ \r}
+ \r\r\rxbt_os_mutex_release(unit->mutex);
+ \r}
+ \r
+ else
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r
+ else
+ \r { /* assume it's a variable */
+ \rchar *val;
+ \rchar name[PATH_MAX + 1] = { 0 };
+ \runsigned int i, j;
+ \rint is_blank;
+ \r\rval = strchr(line, '=');
+ \r\rif (val)
+ \r {
+ \rvariable_t variable;
+ \rint exists = 0;
+ \rint err;
+ \rint env;
+ \rval++;
+ \r\r\r
+ /* syntax error */ \r
+ if (val[0] == '\0')
+ \r {
+ \rstrncpy(name, line, (val - line - 1));
+ \r\ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(name); j++)
+ \rif (name[j] != ' ' && name[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \rERROR1
+ ("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'",
+ filepos);
+ \r
+ else if (!strcmp("setenv", name))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+ filepos);
+ \r
+ else if (!strcmp("set", name))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+ filepos);
+ \r
+ else
+ \rERROR2("[%s] Undefined variable `(%s)'", filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else if (val[0] == ' ' || val[0] == '\t')
+ \r {
+ \rstrncpy(name, line, (val - line));
+ \r\rERROR2("[%s] No space avaible after`(%s)'", filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \r}
+ \r\r\r
+ /* assume it's a varibale */ \r
+ \rstrncpy(name, line, (val - line - 1));
+ \r\ris_blank = 1;
+ \r\rfor (j = 0; j < strlen(name); j++)
+ \rif (name[j] != ' ' && name[j] != '\t')
+ \ris_blank = 0;
+ \r\rif (is_blank)
+ \r {
+ \r\rERROR1
+ ("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rif (!strcmp("set", name))
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else if (!strcmp("setenv", name))
+ \r {
+ \rERROR1
+ ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+ filepos);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \r\rxbt_os_mutex_acquire(unit->mutex);
+ \r\r
+ /* test if the variable is already registred */ \r
+ xbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+ \rif (!strcmp(variable->name, name))
+ \r {
+ \rexists = 1;
+ \rerr = variable->err;
+ \renv = variable->env;
+ \rbreak;
+ \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 {
+ \rif (err)
+ \r {
+ \rERROR2("[%s] A system variable named `(%s)' already exists",
+ filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \rfailure(unit);
+ \rreturn;
+ \r}
+ \rif (env)
+ \r {
+ \rERROR2
+ ("[%s] `(%s)' is an environment variable use `setenv' metacommand",
+ filepos, name);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \rxbt_os_mutex_release(unit->mutex);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r
+ else
+ \r {
+ \rif (!strcmp(val, variable->val))
+ \rWARN3("[%s] Variable `(%s)' already contains value `<%s>'",
+ filepos, variable->name, val);
+ \r\rfree(variable->val);
+ \rvariable->val = strdup(val);
+ \r}
+ \r}
+ \r
+ else
+ \r {
+ \rvariable_t new_var = variable_new(name, val);
+ \rxbt_dynar_push(unit->runner->variables, &new_var);
+ \r}
+ \r\r\rxbt_os_mutex_release(unit->mutex);
+ \r\r}
+ \r
+ else
+ \r {
+ \rif (!strncmp("setenv", line, strlen("setenv")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'",
+ filepos);
+ \r
+ else if (!strncmp("set", line, strlen("set")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'",
+ filepos);
+ \r
+ else if (!strncmp("unsetenv", line, strlen("unsetenv")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'",
+ filepos);
+ \r
+ else if (!strncmp("unset", line, strlen("unset")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'",
+ filepos);
+ \r
+ else if (!strncmp("timeout", line, strlen("timeout")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'",
+ filepos);
+ \r
+ else if (!strncmp("expect signal", line, strlen("expect signal")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'",
+ filepos);
+ \r
+ else if (!strncmp("expect return", line, strlen("expect return")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'",
+ filepos);
+ \r
+ else if (!strncmp("include", line, strlen("include")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand include :`(usage : include <file> [<description>])'",
+ filepos);
+ \r
+ else if (!strncmp("suite", line, strlen("suite")))
+ \rERROR1
+ ("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'",
+ filepos);
+ \r
+ else
+ \rERROR2("[%s] Unknown metacommand: `%s'", filepos, line);
+ \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+ \r\rfailure(unit);
+ \rreturn;
+ \r}
+ \r}
+ \r\rbreak;
+ \r}
+\r}
+
+\r\rvoid \r
+fstream_handle_include(fstream_t fstream, context_t context,
+ xbt_os_mutex_t mutex, const char *file_name,
+ const char *description) \r
+{
+ \rdirectory_t dir;
+ \rchar *prev_directory = NULL;
+ \rfstream_t _fstream = NULL;
+ \rstruct stat buffer = { 0 };
+ \runit_t unit = fstream->unit;
+ \r\rif (!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
+ \r {
+ \r
+ /* the file is in the current directory */ \r
+ _fstream = fstream_new(getcwd(NULL, 0), file_name);
+ \rfstream_open(_fstream);
+ \r}
+ \r
+ /* the file to include is not in the current directory, check if it is in a include directory */ \r
+ else
+ \r {
+ \runsigned int i;
+ \rprev_directory = getcwd(NULL, 0);
+ \r\rxbt_dynar_foreach(include_dirs, i, dir) \r {
+ \rchdir(dir->name);
+ \r\rif (!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
+ \r {
+ \r_fstream = fstream_new(dir->name, file_name);
+ \rfstream_open(_fstream);
+ \rbreak;
+ \r}
+ \r}
+ \r\rchdir(prev_directory);
+ \rfree(prev_directory);
+ \r}
+ \r\r
+ /* the file to include is not found handle the failure */ \r
+ if (!_fstream)
+ \r {
+ \rif (file_name[0] == '$')
+ \r {
+ \rERROR3
+ ("[%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
+ /* may be a variable */ \r
+ variable_t variable;
+ \rint exists = 0;
+ \runsigned int i;
+ \r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+ \rif (!strcmp(variable->name, file_name))
+ \r {
+ \rexists = 1;
+ \rbreak;
+ \r}
+ \r}
+ \r\rif (exists)
+ \rERROR3
+ ("[%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
+ \rERROR2("[%s] Include file `(%s)' not found", context->line,
+ file_name);
+ \r}
+ \r\runit_set_error(fstream->unit, EINCLUDENOTFOUND, 1, context->line);
+ \r\rfailure(fstream->unit);
+ \r\rreturn;
+ \r}
+ \r
+ else
+ \r {
+ \rif (!unit->is_running_suite)
+ \r { /* it's the unit of a suite */
+ \runit_t include = unit_new(unit->runner, unit->root, unit, _fstream);
+ \r\rinclude->mutex = unit->root->mutex;
+ \r\rif (description)
+ \rinclude->description = strdup(description);
+ \r\rxbt_dynar_push(unit->includes, &include);
+ \r\rif (!dry_run_flag)
+ \r {
+ \rif (description)
+ \rINFO2("Include from %s (%s)", _fstream->name, description);
+ \r
+ else
+ \rINFO1("Include from %s", _fstream->name);
+ \r\r}
+ \r
+ else
+ \rINFO1("Checking include %s...", _fstream->name);
+ \r\rfstream_parse(_fstream, mutex);
+ \r}
+ \r
+ else
+ \r { /* it's a include */
+ \r\runit_t * owner;
+ \runit_t include;
+ \r\rowner =
+ xbt_dynar_get_ptr(unit->suites,
+ xbt_dynar_length(unit->suites) - 1);
+ \r\rinclude = unit_new(unit->runner, unit->root, *owner, _fstream);
+ \r\rinclude->mutex = unit->root->mutex;
+ \r\rif (description)
+ \rinclude->description = strdup(description);
+ \r\rxbt_dynar_push((*owner)->includes, &include);
+ \r\rif (!dry_run_flag)
+ \r {
+ \rif (description)
+ \rINFO2("Include from %s (%s)", _fstream->name, description);
+ \r
+ else
+ \rINFO1("Include from %s", _fstream->name);
+ \r}
+ \r
+ else
+ \rINFO1("Checking include %s...", _fstream->name);
+ \r\rfstream_parse(_fstream, mutex);
+ \r}
+ \r}
+\r}
+
+\r\rvoid \r
+fstream_handle_suite(fstream_t fstream, const char *description,
+ const char *filepos) \r
+{
+ \runit_t unit = fstream->unit;
+ \runit_t suite = unit_new(unit->runner, unit->root, unit, NULL);
+ \r\rif (description)
+ \rsuite->description = strdup(description);
+ \r\rsuite->filepos = strdup(filepos);
+ \r\rxbt_dynar_push(unit->suites, &suite);
+ \runit->is_running_suite = 1;
+ \r\rif (!dry_run_flag)
+ \rINFO1("Test suite %s", description);
+ \r
+ else
+ \rINFO1("Checking suite %s...", description);
+\r\r}
+
+\r\rint \r
+fstream_launch_command(fstream_t fstream, context_t context,
+ xbt_os_mutex_t mutex) \r
+{
+ \runit_t unit = fstream->unit;
+ \r\rif (!dry_run_flag)
+ \r {
+ \rcommand_t command;
+ \r\rif (!(command = command_new(unit, context, mutex)))
+ \r {
+ \rif (EINVAL == errno)
+ \r {
+ \rERROR3("[%s] Cannot instantiate the command `%s' (%d)",
+ context->pos, strerror(errno), errno);
+ \r\runit_set_error(unit, errno, 0, context->pos);
+ \rfailure(unit);
+ \rreturn -1;
+ \r}
+ \r
+ else if (ENOMEM == errno)
+ \r {
+ \rERROR3("[%s] Cannot instantiate the command `%s' (%d)",
+ context->pos, strerror(errno), errno);
+ \r\runit_set_error(unit, errno, 0, context->pos);
+ \r\rfailure(unit);
+ \rreturn -1;
+ \r}
+ \r}
+ \r\rif (command_run(command) < 0)
+ \r {
+ \rERROR3("[%s] Cannot run the command `%s' (%d)", context->pos,
+ strerror(errno), errno);
+ \runit_set_error(unit, errno, 0, context->pos);
+ \rfailure(unit);
+ \rreturn -1;
+ \r}
+ \r}
+ \r\rif (context_reset(context) < 0)
+ \r {
+ \rERROR3("[%s] Cannot reset the context of the command `%s' (%d)",
+ context->pos, strerror(errno), errno);
+ \r\runit_set_error(fstream->unit, errno, 0, context->pos);
+ \r\rfailure(unit);
+ \rreturn -1;
+ \r}
+ \r\rreturn 0;
+\r}
+
+\r\r\r\r\r