2 * src/fstream.c - type representing the tesh file stream.
\r
4 * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved.
\r
6 * This program is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the license (GNU LGPL) which comes with this package.
\r
10 * This file contains all the definitions of the functions related with
\r
11 * the tesh file stream type.
\r
15 #include <fstream.h>
\r
17 #include <context.h>
\r
18 #include <command.h>
\r
20 #include <str_replace.h>
\r
21 #include <variable.h>
\r
23 #include <readline.h>
\r
26 #include <getpath.h>
\r
29 #include <xsignal.h>
\r
34 is_w32_cmd(char* cmd, char** path)
\r
37 struct stat stat_buff = {0};
\r
38 char buff[PATH_MAX + 1] = {0};
\r
48 if(stat(cmd, &stat_buff) || !S_ISREG(stat_buff.st_mode))
\r
52 for (i = 0; path[i] != NULL; i++)
\r
54 /* use Cat.exe on Windows */
\r
55 if(!strcmp(cmd, "cat"))
\r
58 sprintf(buff,"%s\\%s",path[i], cmd);
\r
60 if(!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))
\r
74 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
\r
77 long fstream_getline(fstream_t fstream, char **buf, size_t *n) {
\r
79 return readline(fstream->stream, buf, n);
\r
84 failure(unit_t unit)
\r
86 if(!keep_going_unit_flag)
\r
88 unit_t root = unit->root ? unit->root : unit;
\r
90 if(!root->interrupted)
\r
92 /* the unit interrupted (exit for the loop) */
\r
93 root->interrupted = 1;
\r
95 /* release the unit */
\r
96 xbt_os_sem_release(root->sem);
\r
99 /* if the --keep-going option is not specified */
\r
100 if(!keep_going_flag)
\r
104 /* request an global interruption by the runner */
\r
107 /* release the runner */
\r
108 xbt_os_sem_release(units_sem);
\r
115 fstream_new(const char* directory, const char* name)
\r
125 if(!directory && !strcmp("stdin", name))
\r
127 fstream = xbt_new0(s_fstream_t, 1);
\r
128 fstream->name = strdup("stdin");
\r
131 else if(!directory)
\r
137 fstream = xbt_new0(s_fstream_t, 1);
\r
139 if(!(fstream->name = strdup(name)))
\r
145 if(!(fstream->directory = strdup(directory)))
\r
147 free(fstream->name);
\r
152 fstream->stream = NULL;
\r
153 fstream->unit = NULL;
\r
154 fstream->parsed = 0;
\r
161 fstream_open(fstream_t fstream)
\r
163 char path[PATH_MAX + 1] = {0};
\r
165 /* check the parameter */
\r
172 if(!fstream || fstream->stream)
\r
178 if(!strcmp(fstream->name, "stdin"))
\r
180 fstream->stream = stdin;
\r
185 sprintf(path,"%s/%s",fstream->directory, fstream->name);
\r
187 sprintf(path,"%s\\%s",fstream->directory, fstream->name);
\r
190 if(!(fstream->stream = fopen(path, "r")))
\r
199 fstream_close(fstream_t fstream)
\r
201 /* check the parameter */
\r
202 if(!(fstream) || !strcmp(fstream->name, "stdin") )
\r
208 if(!fstream->stream)
\r
211 if(EOF == fclose(fstream->stream))
\r
214 fstream->stream = NULL;
\r
220 fstream_free(fstream_t* ptr)
\r
223 /* check the parameter */
\r
234 fclose((*ptr)->stream);
\r
237 free((*ptr)->name);
\r
239 if((*ptr)->directory)
\r
240 free((*ptr)->directory);
\r
251 fstream_parse(fstream_t fstream, xbt_os_mutex_t mutex)
\r
254 char * line = NULL;
\r
256 char file_pos[256];
\r
257 xbt_strbuff_t buff;
\r
258 int buffbegin = 0;
\r
262 /* Count the line length while checking wheather it's blank */
\r
265 /* Deal with \ at the end of the line, and call handle_line on result */
\r
266 int to_be_continued;
\r
268 /* check the parameter */
\r
269 if(!(fstream) || !mutex)
\r
275 buff = xbt_strbuff_new();
\r
277 if(!(context = context_new()))
\r
280 unit = fstream->unit;
\r
282 /*while(!(unit->root->interrupted) && getline(&line, &len, fstream->stream) != -1)*/
\r
283 while(!(unit->root->interrupted) && fstream_getline(fstream, &line, &len) != -1)
\r
288 to_be_continued = 0;
\r
292 while(line[linelen] != '\0')
\r
294 if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')
\r
302 if(!context->command_line && (context->input->used || context->output->used))
\r
304 snprintf(file_pos,256,"%s:%d",fstream->name, line_num);
\r
305 ERROR1("[%s] Error : no command found in the last chunk of lines", file_pos);
\r
307 unit_set_error(fstream->unit, ESYNTAX, 1, file_pos);
\r
312 else if(unit->is_running_suite)
\r
313 {/* it's the end of a suite */
\r
315 unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);
\r
317 if(!xbt_dynar_length((*current_suite)->includes))
\r
319 ERROR2("[%s] Malformated suite `(%s)' : include missing", file_pos, (*current_suite)->description);
\r
321 unit_set_error(*current_suite, ESYNTAX, 1, file_pos);
\r
327 unit->is_running_suite = 0;
\r
330 if(context->command_line)
\r
333 if(!context->is_not_found)
\r
336 if(fstream_launch_command(fstream, context, mutex) < 0)
\r
347 if(linelen>1 && line[linelen-2]=='\\')
\r
349 if(linelen>2 && line[linelen-3] == '\\')
\r
351 /* Damn. Escaped \ */
\r
352 line[linelen-2] = '\n';
\r
353 line[linelen-1] = '\0';
\r
357 to_be_continued = 1;
\r
358 line[linelen-2] = '\0';
\r
362 buffbegin = line_num;
\r
366 if(buff->used || to_be_continued)
\r
368 xbt_strbuff_append(buff,line);
\r
370 if (!to_be_continued)
\r
372 snprintf(file_pos,256,"%s:%d",fstream->name, buffbegin);
\r
373 fstream_lex_line(fstream, context, mutex, file_pos, buff->data);
\r
374 xbt_strbuff_empty(buff);
\r
379 snprintf(file_pos,256,"%s:%d",fstream->name, line_num);
\r
380 fstream_lex_line(fstream, context, mutex, file_pos, line);
\r
384 /* Check that last command of the file ran well */
\r
385 if(context->command_line)
\r
388 if(!context->is_not_found)
\r
392 if(fstream_launch_command(fstream, context, mutex) < 0)
\r
400 /* clear buffers */
\r
404 xbt_strbuff_free(buff);
\r
406 if(context_free(&context) < 0)
\r
409 return (exit_code || errno) ? -1 : 0;
\r
414 fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line)
\r
417 variable_t variable;
\r
419 char exp[PATH_MAX + 1] = {0};
\r
420 unit_t unit = fstream->unit;
\r
421 xbt_dynar_t variables = unit->runner->variables;
\r
425 char buff[PATH_MAX + 1] = {0};
\r
427 char delimiters[4] = {' ', '\t', '\n', '\0'};
\r
434 if(unit->is_running_suite && strncmp(line, "! include", strlen("! include")))
\r
435 {/* it's the end of a suite */
\r
437 unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);
\r
439 if(!xbt_dynar_length((*current_suite)->includes))
\r
440 ERROR2("[%s] Malformated suite `(%s)': include missing", filepos, (*current_suite)->description);
\r
442 ERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos, (*current_suite)->description);
\r
444 unit_set_error(*current_suite, ESYNTAX, 1, filepos);
\r
446 failure(fstream->unit);
\r
449 context->line = strdup(filepos);
\r
452 xbt_str_rtrim(line + 2,"\n");
\r
454 line2 = strdup(line);
\r
456 len = strlen(line2 + 2) + 1;
\r
458 /* replace each variable by its value */
\r
459 xbt_os_mutex_acquire(unit->mutex);
\r
462 /* replace all existing
\r
471 xbt_dynar_foreach(variables, i, variable)
\r
473 if(!(p = strstr(line2 + 2, "${")))
\r
476 memset(buff, 0, len);
\r
478 sprintf(buff,"${%s",variable->name);
\r
481 if((p = strstr(line2 + 2, buff)))
\r
483 memset(buff, 0, len);
\r
487 while(*(p++) != '\0')
\r
495 if(buff[j - 1] != '}')
\r
497 xbt_os_mutex_release(unit->mutex);
\r
500 ERROR2("[%s] Syntax error : `%s'.",filepos, p - j);
\r
502 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
503 failure(fstream->unit);
\r
507 if((p = strstr(buff , ":=")))
\r
511 /* if the value of the variable is empty, update its value by the value*/
\r
514 end = strchr(p, '}');
\r
516 if(!end || (end == p))
\r
518 xbt_os_mutex_release(unit->mutex);
\r
521 ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(buff, "${"));
\r
523 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
524 failure(fstream->unit);
\r
528 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));
\r
530 strncpy(val, p,(end - p));
\r
533 /* replace the expression by the expression of the value of the variable*/
\r
534 sprintf(exp, "${%s:=%s}", variable->name, val);
\r
537 str_replace_all(&line2, exp, variable->val, NULL);
\r
540 str_replace_all(&line2, exp, val, NULL);
\r
542 variable->val = strdup(val);
\r
545 memset(exp, 0, VAR_NAME_MAX + 1);
\r
554 else if((p = strstr(buff, ":-")))
\r
558 /* if the value of the variable is empty, replace the expression by the value */
\r
560 end = strchr(p, '}');
\r
562 if(!end || (end == p))
\r
564 xbt_os_mutex_release(unit->mutex);
\r
566 ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));
\r
568 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
569 failure(fstream->unit);
\r
573 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));
\r
575 strncpy(val, p,(end - p));
\r
577 sprintf(exp, "${%s:-%s}", variable->name, val);
\r
579 str_replace_all(&line2, exp, variable->val ? variable->val : val, NULL);
\r
582 memset(exp, 0, VAR_NAME_MAX + 1);
\r
591 else if((p = strstr(buff, ":+")))
\r
595 /* if the value of the variable is not empty, replace the expression by the value */
\r
598 end = strchr(p, '}');
\r
600 if(!end || (end == p))
\r
602 xbt_os_mutex_release(unit->mutex);
\r
605 ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));
\r
607 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
608 failure(fstream->unit);
\r
612 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));
\r
614 strncpy(val, p,(end - p));
\r
616 sprintf(exp, "${%s:+%s}", variable->name, val);
\r
620 str_replace_all(&line2, exp, val, NULL);
\r
624 str_replace_all(&line2, exp, NULL , NULL);
\r
625 variable->val = strdup(val);
\r
628 memset(exp, 0, VAR_NAME_MAX + 1);
\r
636 else if((p = strstr(buff, ":?")))
\r
640 /* if the value of the variable is not empty, replace the expression by the value */
\r
642 end = strchr(p, '}');
\r
644 if(!end || (end == p))
\r
646 xbt_os_mutex_release(unit->mutex);
\r
648 ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));
\r
650 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
651 failure(fstream->unit);
\r
655 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));
\r
657 strncpy(val, p,(end - p));
\r
659 sprintf(exp, "${%s:?%s}", variable->name, val);
\r
662 str_replace_all(&line2, exp, variable->val, NULL);
\r
666 xbt_os_mutex_release(unit->mutex);
\r
668 ERROR2("[%s] %s.",filepos, val);
\r
670 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
671 failure(fstream->unit);
\r
675 memset(exp, 0, VAR_NAME_MAX + 1);
\r
686 /* replace all existing $var */
\r
687 xbt_dynar_foreach(variables, i, variable)
\r
689 if(!strchr(line2 + 2, '$'))
\r
692 if(strstr(line2 + 2, variable->name))
\r
695 sprintf(exp, "${#%s}", variable->name);
\r
697 if(strstr(line2 + 2, exp))
\r
702 char slen[4] = {0};
\r
703 sprintf(slen,"%d", (int)strlen(variable->val));
\r
704 str_replace_all(&line2, exp, slen, NULL);
\r
707 str_replace_all(&line2, exp, "0", NULL);
\r
710 memset(exp, 0, VAR_NAME_MAX + 1);
\r
712 sprintf(exp, "${%s}", variable->name);
\r
714 if(strstr(line2 + 2, exp))
\r
717 str_replace_all(&line2, exp, variable->val, NULL);
\r
719 str_replace_all(&line2, exp, NULL, NULL);
\r
722 memset(exp, 0, VAR_NAME_MAX + 1);
\r
724 sprintf(exp, "$%s", variable->name);
\r
726 if((p = strstr(line2 + 2, exp)))
\r
728 if((p + strlen(variable->name) + 1)[0] != '\0' && !(isalpha((p + strlen(variable->name) + 1)[0])))
\r
729 delimiters[0] = (p + strlen(variable->name) + 1)[0];
\r
732 str_replace_all(&line2, exp, variable->val, delimiters);
\r
734 str_replace_all(&line2, exp, NULL, delimiters);
\r
737 memset(exp, 0, VAR_NAME_MAX + 1);
\r
742 while((p = strstr(line2 + 2, "${")))
\r
744 /*if(*(p+1) != '{')
\r
749 while(*(p++) != '\0')
\r
751 if(*p != ' ' && *p !='\t')
\r
758 str_replace_all(&line2, exp, NULL, " \t\n\r");
\r
759 memset(exp, 0, VAR_NAME_MAX + 1);
\r
764 char* begin = NULL;
\r
769 while(*(p++) != '\0')
\r
771 if((!begin && *p != ' ' && *p !='\t') || begin)
\r
773 /* `:' must be before this caracter, bad substitution : exit loop
\r
775 the current character is already present, bad substitution : exit loop
\r
779 *(p - 1) != ':' && (
\r
780 (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')
\r
786 (*p == ':') || (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')
\r
796 /* save the begining of the value */
\r
797 if((*(p+1) == '=') || (*(p+1) == '-') || (*(p+1) == '+') || (*(p+1) == '?'))
\r
806 /* the current char is `:' but the next is invalid, bad substitution : exit loop */
\r
809 /* end of the substitution : exit loop */
\r
817 if(exp[j - 1] == '}')
\r
824 if(4 == strlen(exp))
\r
826 xbt_os_mutex_release(unit->mutex);
\r
828 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
830 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
831 failure(fstream->unit);
\r
835 str_replace_all(&line2, exp, "0", NULL);
\r
837 else if(strstr(exp,":="))
\r
839 /* ${var:=value} */
\r
841 end = strchr(p, '}');
\r
843 if(!end || (end == begin))
\r
845 xbt_os_mutex_release(unit->mutex);
\r
848 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
850 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
851 failure(fstream->unit);
\r
855 variable = xbt_new0(s_variable_t, 1);
\r
857 variable->val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));
\r
859 strncpy(variable->val, begin ,(end - begin));
\r
862 end = strchr(exp, ':');
\r
864 if(!end || (end == begin))
\r
866 xbt_os_mutex_release(unit->mutex);
\r
869 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
871 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
872 failure(fstream->unit);
\r
876 variable->name = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));
\r
878 strncpy(variable->name, exp + 2 ,(end - begin));
\r
880 str_replace_all(&line2, exp, variable->val, NULL);
\r
882 xbt_dynar_push(variables, &variable);
\r
885 else if(strstr(exp,":-"))
\r
887 /* ${var:-value} */
\r
890 end = strchr(p, '}');
\r
892 if(!end || (end == begin))
\r
894 xbt_os_mutex_release(unit->mutex);
\r
897 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
899 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
900 failure(fstream->unit);
\r
904 val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));
\r
906 strncpy(val, begin ,(end - begin));
\r
908 str_replace_all(&line2, exp, val, NULL);
\r
914 else if(strstr(exp,":+"))
\r
916 /* ${var:+value} */
\r
918 end = strchr(p, '}');
\r
920 if(!end || (end == begin))
\r
922 xbt_os_mutex_release(unit->mutex);
\r
924 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
926 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
927 failure(fstream->unit);
\r
931 str_replace_all(&line2, exp, NULL, NULL);
\r
933 else if(strstr(exp,":?"))
\r
935 /* ${var:?value} */
\r
937 end = strchr(p, '}');
\r
939 if(!end || (end == begin))
\r
941 xbt_os_mutex_release(unit->mutex);
\r
943 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
945 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
946 failure(fstream->unit);
\r
950 val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));
\r
952 strncpy(val, begin ,(end - begin));
\r
954 xbt_os_mutex_release(unit->mutex);
\r
956 ERROR2("[%s] : `%s'.",filepos, val);
\r
961 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
962 failure(fstream->unit);
\r
971 if(3 == strlen(exp))
\r
973 xbt_os_mutex_release(unit->mutex);
\r
975 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));
\r
977 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
978 failure(fstream->unit);
\r
982 str_replace_all(&line2, exp, NULL, NULL);
\r
986 memset(exp, 0, VAR_NAME_MAX + 1);
\r
990 xbt_os_mutex_release(unit->mutex);
\r
992 if(strstr(line2 + 2, "${"))
\r
993 ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));
\r
995 ERROR2("[%s] Syntax error : `%s'.",filepos, strstr(line2, "${"));
\r
997 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
998 failure(fstream->unit);
\r
1008 p = line2 + (line2[0] =='<' ? 4 : 2);
\r
1010 if((p = strchr(p, '$')))
\r
1017 while(*(p++) != '\0')
\r
1019 if(*p != ' ' && *p !='\t')
\r
1026 str_replace_all(&line2, exp, NULL, " \t\n\r");
\r
1027 memset(exp, 0, VAR_NAME_MAX + 1);
\r
1031 /* maybe < $ cmd */
\r
1039 xbt_os_mutex_release(unit->mutex);
\r
1050 if(line[1] != ' ')
\r
1053 if(line2[0] == '$')
\r
1054 ERROR1("[%s] Missing space after `$' `(usage : $ <command>)'", filepos);
\r
1056 ERROR1("[%s] Missing space after & `(usage : & <command>)'", filepos);
\r
1058 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1064 context->async = (line2[0] == '&');
\r
1067 /* further trim useless chars which are significant for in/output */
\r
1068 xbt_str_rtrim(line2 + 2," \t");
\r
1070 /* deal with CD commands here, not in context */
\r
1071 if(!strncmp("cd ",line2 + 2, 3))
\r
1073 char* dir = strdup(line2 + 4);
\r
1075 if(context->command_line)
\r
1077 if(fstream_launch_command(fstream, context, mutex) < 0)
\r
1081 /* search begining */
\r
1082 while(*(dir++) == ' ');
\r
1089 INFO2("[%s] cd %s", filepos, dir);
\r
1091 if(!just_print_flag)
\r
1095 ERROR3("[%s] Chdir to %s failed: %s",filepos, dir,error_to_string(errno, 0));
\r
1096 unit_set_error(fstream->unit, errno, 0, filepos);
\r
1107 fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);
\r
1115 if(line[0] == '!' && line[1] != ' ')
\r
1117 ERROR1("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'", filepos);
\r
1119 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1125 fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);
\r
1134 char* prompt = line2 + 2;
\r
1136 for(j = 0; j < strlen(prompt); j++)
\r
1138 if (prompt[j] != ' ' && prompt[j] != '\t')
\r
1147 ERROR1("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'", filepos);
\r
1149 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1156 INFO2("[%s] %s",filepos,prompt);
\r
1168 char* prompt = line2 + 2;
\r
1170 for(j = 0; j < strlen(prompt); j++)
\r
1171 if (prompt[j] != ' ' && prompt[j] != '\t')
\r
1176 ERROR1("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'", filepos);
\r
1178 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1184 if(!dry_run_flag)
\r
1185 CRITICAL2("[%s] %s",filepos, prompt);
\r
1191 if(unit->description)
\r
1192 WARN2("[%s] Description already specified `%s'",filepos, line2 + 2);
\r
1198 char* desc = line2 + 2;
\r
1200 for(j = 0; j < strlen(desc); j++)
\r
1201 if (desc[j] != ' ' && desc[j] != '\t')
\r
1206 ERROR1("[%s] Bad usage of the metacommand D `(usage : D <Description>)'", filepos);
\r
1208 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1214 unit->description = strdup(desc);
\r
1219 ERROR2("[%s] Syntax error `%s'", filepos, line2);
\r
1220 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1229 fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* filepos, char token, char *line)
\r
1231 unit_t unit = fstream->unit;
\r
1238 if(context->command_line)
\r
1241 if(context->output->used || context->input->used)
\r
1243 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
1245 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1250 if(fstream_launch_command(fstream, context, mutex) < 0)
\r
1253 VERB1("[%s] More than one command in this chunk of lines",filepos);
\r
1260 for(j = 0; j < strlen(line); j++)
\r
1261 if (line[j] != ' ' && line[j] != '\t')
\r
1267 ERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'", filepos);
\r
1269 ERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'", filepos);
\r
1271 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1278 context->command_line = strdup(line);
\r
1280 xbt_str_ltrim(context->command_line," ");
\r
1282 context->line = /*strdup(filepos)*/ filepos;
\r
1283 context->pos = strdup(filepos);
\r
1288 /* translate the command line */
\r
1290 char* path = NULL;
\r
1292 char command_line[PATH_MAX + 1] = {0};
\r
1294 char* args = NULL;
\r
1298 /*if(strstr(context->command_line,".exe"))
\r
1299 strcpy(command_line,context->command_line);*/
\r
1306 len = strlen(context->command_line);
\r
1310 if(context->command_line[i] != ' ' && context->command_line[i] != '\t' && context->command_line[i] != '>')
\r
1311 command_line[j++] = context->command_line[i];
\r
1318 if(!strstr(context->command_line,".exe"))
\r
1319 strcat(command_line,".exe");
\r
1321 args = strdup(context->command_line + i);
\r
1324 if(!is_w32_cmd(command_line, fstream->unit->runner->path) && getpath(command_line, &path) < 0)
\r
1326 command_t command;
\r
1328 ERROR3("[%s] `%s' : NOK (%s)", filepos, command_line, error_to_string(ECMDNOTFOUND, 1));
\r
1329 unit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);
\r
1331 context->is_not_found = 1;
\r
1333 command = command_new(fstream->unit, context, mutex);
\r
1335 command->status = cs_failed;
\r
1336 command->reason = csr_command_not_found;
\r
1344 delimiter = strrchr(command_line,'/');
\r
1347 delimiter = strrchr(command_line,'\\');
\r
1349 /*free(context->command_line);*/
\r
1356 context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + strlen(args) + 2, sizeof(char));
\r
1357 sprintf(context->t_command_line,"%s\\%s%s",path,delimiter ? delimiter + 1 : command_line, args);
\r
1364 context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + 2, sizeof(char));
\r
1365 sprintf(context->t_command_line,"%s\\%s",path,delimiter ? delimiter + 1 : command_line);
\r
1375 context->t_command_line = (char*)calloc(strlen(command_line) + strlen(args) + 1, sizeof(char));
\r
1376 sprintf(context->t_command_line,"%s%s",command_line, args);
\r
1384 context->t_command_line = (char*)calloc(strlen(command_line) + 1, sizeof(char));
\r
1385 strcpy(context->t_command_line,command_line);
\r
1397 xbt_strbuff_append(context->input,line);
\r
1398 xbt_strbuff_append(context->input,"\n");
\r
1402 xbt_strbuff_append(context->output,line);
\r
1403 xbt_strbuff_append(context->output,"\n");
\r
1408 if(context->command_line)
\r
1410 if(fstream_launch_command(fstream, context, mutex) < 0)
\r
1414 if(!strncmp(line,"timeout no",strlen("timeout no")))
\r
1416 VERB1("[%s] (disable timeout)", filepos);
\r
1417 context->timeout = INDEFINITE;
\r
1419 else if(!strncmp(line,"timeout ",strlen("timeout ")))
\r
1424 char* p = line + strlen("timeout ");
\r
1427 for(j = 0; j < strlen(p); j++)
\r
1428 if (p[j] != ' ' && p[j] != '\t')
\r
1433 ERROR1("[%s] Undefinite timeout value `(usage :timeout <seconds>)'", filepos);
\r
1435 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1441 while(p[i] != '\0')
\r
1443 if(!isdigit(p[i]))
\r
1445 ERROR2("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'", filepos, line + strlen("timeout "));
\r
1447 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1456 context->timeout = atoi(line + strlen("timeout"));
\r
1457 VERB2("[%s] (new timeout value: %d)",filepos,context->timeout);
\r
1460 else if (!strncmp(line,"expect signal ",strlen("expect signal ")))
\r
1466 char* p = line + strlen("expect signal ");
\r
1469 for(j = 0; j < strlen(p); j++)
\r
1470 if (p[j] != ' ' && p[j] != '\t')
\r
1475 ERROR1("[%s] Undefinite signal name `(usage :expect signal <signal name>)'", filepos);
\r
1477 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1483 context->signal = strdup(line + strlen("expect signal "));
\r
1485 xbt_str_trim(context->signal," \n");
\r
1488 if(!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))
\r
1490 ERROR2("[%s] Signal `%s' not supported by this platform", filepos, context->signal);
\r
1492 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1499 if(!sig_exists(context->signal))
\r
1501 ERROR2("[%s] Signal `%s' not supported by Tesh", filepos, context->signal);
\r
1503 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1513 VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);
\r
1516 else if (!strncmp(line,"expect return ",strlen("expect return ")))
\r
1522 char* p = line + strlen("expect return ");
\r
1525 for(j = 0; j < strlen(p); j++)
\r
1526 if (p[j] != ' ' && p[j] != '\t')
\r
1531 ERROR1("[%s] Undefinite return value `(usage :expect return <return value>)'", filepos);
\r
1533 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1539 while(p[i] != '\0')
\r
1541 if(!isdigit(p[i]))
\r
1543 ERROR2("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255", filepos, line + strlen("expect return "));
\r
1545 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1554 context->exit_code = atoi(line+strlen("expect return "));
\r
1555 VERB2("[%s] (next command must return code %d)",filepos, context->exit_code);
\r
1558 else if (!strncmp(line,"output ignore",strlen("output ignore")))
\r
1560 context->output_handling = oh_ignore;
\r
1561 VERB1("[%s] (ignore output of next command)", filepos);
\r
1564 else if (!strncmp(line,"output display",strlen("output display")))
\r
1566 context->output_handling = oh_display;
\r
1567 VERB1("[%s] (ignore output of next command)", filepos);
\r
1570 else if(!strncmp(line,"include ", strlen("include ")))
\r
1575 p1 = line + strlen("include");
\r
1577 while(*p1 == ' ' || *p1 == '\t')
\r
1583 ERROR1("[%s] no file specified : `(usage : include <file> [<description>])'", filepos);
\r
1585 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1592 char file_name[PATH_MAX + 1] = {0};
\r
1596 while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')
\r
1599 strncpy(file_name, p1, p2 - p1);
\r
1603 while(*p2 == ' ' || *p2 == '\t')
\r
1606 fstream_handle_include(fstream, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);
\r
1610 else if(!strncmp(line,"suite ", strlen("suite ")))
\r
1614 char* p = line + strlen("suite ");
\r
1617 for(j = 0; j < strlen(p); j++)
\r
1618 if (p[j] != ' ' && p[j] != '\t')
\r
1623 ERROR1("[%s] Undefinite suit description : `(usage : suite <description>)", filepos);
\r
1625 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1631 if(unit->is_running_suite)
\r
1633 ERROR1("[%s] Suite already in progress", filepos);
\r
1635 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1641 fstream_handle_suite(fstream, line + strlen("suite "), filepos);
\r
1643 else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))
\r
1645 unsigned int i, j;
\r
1649 variable_t variable;
\r
1652 char* name = line + strlen("unsetenv ");
\r
1656 for(j = 0; j < strlen(name); j++)
\r
1657 if (name[j] != ' ' && name[j] != '\t')
\r
1662 ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);
\r
1664 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1670 xbt_os_mutex_acquire(unit->mutex);
\r
1673 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r
1675 if(!strcmp(variable->name, name))
\r
1677 env = variable->env;
\r
1678 err = variable->err;
\r
1691 SetEnvironmentVariable(name, NULL);
\r
1693 xbt_dynar_cursor_rm(unit->runner->variables, &i);
\r
1697 ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);
\r
1698 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1699 xbt_os_mutex_release(unit->mutex);
\r
1710 ERROR2("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",filepos, name);
\r
1711 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1713 xbt_os_mutex_release(unit->mutex);
\r
1718 ERROR2("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",filepos, name);
\r
1719 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1720 xbt_os_mutex_release(unit->mutex);
\r
1727 ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);
\r
1728 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1729 xbt_os_mutex_release(unit->mutex);
\r
1735 xbt_os_mutex_release(unit->mutex);
\r
1739 else if(!strncmp(line,"setenv ", strlen("setenv ")))
\r
1742 char name[PATH_MAX + 1] = {0};
\r
1748 p = line + strlen("setenv ");
\r
1750 val = strchr(p, '=');
\r
1754 variable_t variable;
\r
1760 /* syntax error */
\r
1761 if(val[0] == '\0' || val[0] ==' ' || val[0] =='\t')
\r
1763 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);
\r
1765 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1773 strncpy(name, p, (val - p -1));
\r
1777 for(j = 0; j < strlen(name); j++)
\r
1778 if (name[j] != ' ' && name[j] != '\t')
\r
1784 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);
\r
1786 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1792 /* test if the variable is already registred */
\r
1793 xbt_os_mutex_acquire(unit->mutex);
\r
1795 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r
1797 if(!strcmp(variable->name, name))
\r
1799 env = variable->env;
\r
1800 err = variable->err;
\r
1806 /* if the variable is already registred, update its value;
\r
1807 * otherwise register it.
\r
1813 if(!strcmp(val, variable->val))
\r
1814 WARN3("[%s] This environment variable `(%s)' is already set with the value `(%s)'", filepos, name, val);
\r
1816 free(variable->val);
\r
1817 variable->val = strdup(val);
\r
1820 SetEnvironmentVariable(variable->name, variable->val);
\r
1822 setenv(variable->name, variable->val, 1);
\r
1828 ERROR2("[%s] Conflict : a system variable `(%s)' already exists", filepos, name);
\r
1830 ERROR2("[%s] Conflict : (none environment) variable `(%s)' already exists", filepos, name);
\r
1832 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1833 xbt_os_mutex_release(unit->mutex);
\r
1842 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);
\r
1844 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1845 xbt_os_mutex_release(unit->mutex);
\r
1851 variable = variable_new(name, val);
\r
1852 variable->env = 1;
\r
1854 xbt_dynar_push(unit->runner->variables, &variable);
\r
1857 SetEnvironmentVariable(variable->name, variable->val);
\r
1859 setenv(variable->name, variable->val, 0);
\r
1864 xbt_os_mutex_release(unit->mutex);
\r
1869 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);
\r
1871 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1876 else if(!strncmp(line,"unset ", strlen("unset ")))
\r
1878 unsigned int i, j;
\r
1882 variable_t variable;
\r
1885 char* name = line + strlen("unset ");
\r
1889 for(j = 0; j < strlen(name); j++)
\r
1890 if (name[j] != ' ' && name[j] != '\t')
\r
1896 ERROR1("[%s] Bad usage of the metacommand unset `(usage : unset variable)'", filepos);
\r
1898 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1905 xbt_os_mutex_acquire(unit->mutex);
\r
1907 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r
1909 if(!strcmp(variable->name, name))
\r
1911 env = variable->env;
\r
1912 err = variable->err;
\r
1922 /*xbt_dynar_remove_at(unit->runner->variables, i, NULL);*/
\r
1923 /*xbt_dynar_cursor_rm(unit->runner->variables, &i);*/
\r
1926 free(variable->val);
\r
1927 variable->val = NULL;
\r
1931 WARN2("[%s] Variable `(%s)' already unseted",filepos, variable->name);
\r
1936 ERROR2("[%s] `(%s)' variable not found",filepos, name);
\r
1937 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1938 xbt_os_mutex_release(unit->mutex);
\r
1945 ERROR2("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",filepos, name);
\r
1946 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1947 xbt_os_mutex_release(unit->mutex);
\r
1953 ERROR2("[%s] `(%s)' is system variable : you can unset it",filepos, name);
\r
1954 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1955 xbt_os_mutex_release(unit->mutex);
\r
1960 xbt_os_mutex_release(unit->mutex);
\r
1963 else if(!strncmp(line,"set ", strlen("set ")))
\r
1966 char name[PATH_MAX + 1] = {0};
\r
1970 val = strchr(line + strlen("set "), '=');
\r
1974 variable_t variable;
\r
1983 /* syntax error */
\r
1984 if(val[0] == '\0')
\r
1986 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);
\r
1988 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
1993 else if(val[0] ==' ' || val[0] =='\t')
\r
1995 strncpy(name, line + strlen("set "), (val - (line + strlen("set "))));
\r
1997 ERROR2("[%s] No space avaible after`(%s)'", filepos, name);
\r
1999 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2006 /* assume it's a varibale */
\r
2008 strncpy(name, line + strlen("set "), (val - (line + strlen("set ")) -1));
\r
2012 for(j = 0; j < strlen(name); j++)
\r
2013 if (name[j] != ' ' && name[j] != '\t')
\r
2019 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);
\r
2021 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2027 xbt_os_mutex_acquire(unit->mutex);
\r
2029 /* test if the variable is already registred */
\r
2030 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r
2032 if(!strcmp(variable->name, name))
\r
2035 err = variable->err;
\r
2036 env = variable->env;
\r
2041 /* if the variable is already registred, update its value (if same value warns);
\r
2042 * otherwise register it.
\r
2048 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);
\r
2050 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2051 xbt_os_mutex_release(unit->mutex);
\r
2058 ERROR2("[%s] `(%s)' is an environment variable use `setenv' instead `set'", filepos, name);
\r
2060 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2061 xbt_os_mutex_release(unit->mutex);
\r
2068 if(!strcmp(val, variable->val))
\r
2069 WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);
\r
2071 free(variable->val);
\r
2072 variable->val = strdup(val);
\r
2077 variable_t new_var = variable_new(name, val);
\r
2078 xbt_dynar_push(unit->runner->variables, &new_var);
\r
2082 xbt_os_mutex_release(unit->mutex);
\r
2086 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);
\r
2088 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2094 {/* assume it's a variable */
\r
2096 char name[PATH_MAX + 1] = {0};
\r
2097 unsigned int i, j;
\r
2100 val = strchr(line, '=');
\r
2104 variable_t variable;
\r
2111 /* syntax error */
\r
2112 if(val[0] == '\0')
\r
2114 strncpy(name, line, (val - line -1));
\r
2118 for(j = 0; j < strlen(name); j++)
\r
2119 if (name[j] != ' ' && name[j] != '\t')
\r
2123 ERROR1("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'", filepos);
\r
2124 else if(!strcmp("setenv", name))
\r
2125 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);
\r
2126 else if(!strcmp("set", name))
\r
2127 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);
\r
2129 ERROR2("[%s] Undefined variable `(%s)'", filepos, name);
\r
2131 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2136 else if(val[0] ==' ' || val[0] =='\t')
\r
2138 strncpy(name, line, (val - line));
\r
2140 ERROR2("[%s] No space avaible after`(%s)'", filepos, name);
\r
2142 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2148 /* assume it's a varibale */
\r
2150 strncpy(name, line, (val - line -1));
\r
2154 for(j = 0; j < strlen(name); j++)
\r
2155 if (name[j] != ' ' && name[j] != '\t')
\r
2161 ERROR1("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'", filepos);
\r
2163 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2169 if(!strcmp("set", name))
\r
2171 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);
\r
2173 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2177 else if(!strcmp("setenv", name))
\r
2179 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);
\r
2181 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2186 xbt_os_mutex_acquire(unit->mutex);
\r
2188 /* test if the variable is already registred */
\r
2189 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r
2191 if(!strcmp(variable->name, name))
\r
2194 err = variable->err;
\r
2195 env = variable->env;
\r
2200 /* if the variable is already registred, update its value (if same value warns);
\r
2201 * otherwise register it.
\r
2207 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);
\r
2209 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2210 xbt_os_mutex_release(unit->mutex);
\r
2216 ERROR2("[%s] `(%s)' is an environment variable use `setenv' metacommand", filepos, name);
\r
2218 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2219 xbt_os_mutex_release(unit->mutex);
\r
2226 if(!strcmp(val, variable->val))
\r
2227 WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);
\r
2229 free(variable->val);
\r
2230 variable->val = strdup(val);
\r
2235 variable_t new_var = variable_new(name, val);
\r
2236 xbt_dynar_push(unit->runner->variables, &new_var);
\r
2240 xbt_os_mutex_release(unit->mutex);
\r
2245 if(!strncmp("setenv", line, strlen("setenv")))
\r
2246 ERROR1("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'", filepos);
\r
2247 else if(!strncmp("set", line, strlen("set")))
\r
2248 ERROR1("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'", filepos);
\r
2249 else if(!strncmp("unsetenv", line, strlen("unsetenv")))
\r
2250 ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);
\r
2251 else if(!strncmp("unset", line, strlen("unset")))
\r
2252 ERROR1("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'", filepos);
\r
2253 else if(!strncmp("timeout", line, strlen("timeout")))
\r
2254 ERROR1("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'", filepos);
\r
2255 else if(!strncmp("expect signal", line, strlen("expect signal")))
\r
2256 ERROR1("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'", filepos);
\r
2257 else if(!strncmp("expect return", line, strlen("expect return")))
\r
2258 ERROR1("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'", filepos);
\r
2259 else if(!strncmp("include", line, strlen("include")))
\r
2260 ERROR1("[%s] Bad usage of the metacommand include :`(usage : include <file> [<description>])'", filepos);
\r
2261 else if(!strncmp("suite", line, strlen("suite")))
\r
2262 ERROR1("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'", filepos);
\r
2264 ERROR2("[%s] Unknown metacommand: `%s'",filepos,line);
\r
2266 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);
\r
2278 fstream_handle_include(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)
\r
2281 char* prev_directory = NULL;
\r
2282 fstream_t _fstream = NULL;
\r
2283 struct stat buffer = {0};
\r
2284 unit_t unit = fstream->unit;
\r
2286 if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
\r
2288 /* the file is in the current directory */
\r
2289 _fstream = fstream_new(getcwd(NULL, 0), file_name);
\r
2290 fstream_open(_fstream);
\r
2292 /* the file to include is not in the current directory, check if it is in a include directory */
\r
2296 prev_directory = getcwd(NULL, 0);
\r
2298 xbt_dynar_foreach(include_dirs, i, dir)
\r
2302 if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
\r
2304 _fstream = fstream_new(dir->name, file_name);
\r
2305 fstream_open(_fstream);
\r
2310 chdir(prev_directory);
\r
2311 free(prev_directory);
\r
2314 /* the file to include is not found handle the failure */
\r
2317 if(file_name[0] == '$')
\r
2319 ERROR3("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",context->line, file_name, file_name + 1);
\r
2324 /* may be a variable */
\r
2325 variable_t variable;
\r
2329 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r
2331 if(!strcmp(variable->name, file_name))
\r
2339 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
2341 ERROR2("[%s] Include file `(%s)' not found",context->line, file_name);
\r
2344 unit_set_error(fstream->unit, EINCLUDENOTFOUND, 1, context->line);
\r
2346 failure(fstream->unit);
\r
2352 if(!unit->is_running_suite)
\r
2353 {/* it's the unit of a suite */
\r
2354 unit_t include = unit_new(unit->runner, unit->root, unit, _fstream);
\r
2356 include->mutex = unit->root->mutex;
\r
2359 include->description = strdup(description);
\r
2361 xbt_dynar_push(unit->includes, &include);
\r
2366 INFO2("Include from %s (%s)", _fstream->name, description);
\r
2368 INFO1("Include from %s", _fstream->name);
\r
2372 INFO1("Checking include %s...",_fstream->name);
\r
2374 fstream_parse(_fstream, mutex);
\r
2377 {/* it's a include */
\r
2382 owner = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);
\r
2384 include = unit_new(unit->runner, unit->root, *owner, _fstream);
\r
2386 include->mutex = unit->root->mutex;
\r
2389 include->description = strdup(description);
\r
2391 xbt_dynar_push((*owner)->includes, &include);
\r
2396 INFO2("Include from %s (%s)", _fstream->name, description);
\r
2398 INFO1("Include from %s", _fstream->name);
\r
2401 INFO1("Checking include %s...",_fstream->name);
\r
2403 fstream_parse(_fstream, mutex);
\r
2409 fstream_handle_suite(fstream_t fstream, const char* description, const char* filepos)
\r
2411 unit_t unit = fstream->unit;
\r
2412 unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);
\r
2415 suite->description = strdup(description);
\r
2417 suite->filepos = strdup(filepos);
\r
2419 xbt_dynar_push(unit->suites, &suite);
\r
2420 unit->is_running_suite = 1;
\r
2423 INFO1("Test suite %s", description);
\r
2425 INFO1("Checking suite %s...",description);
\r
2430 fstream_launch_command(fstream_t fstream, context_t context, xbt_os_mutex_t mutex)
\r
2432 unit_t unit = fstream->unit;
\r
2436 command_t command;
\r
2438 if(!(command = command_new(unit, context, mutex)))
\r
2440 if(EINVAL == errno)
\r
2442 ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);
\r
2444 unit_set_error(unit, errno, 0, context->pos);
\r
2448 else if(ENOMEM == errno)
\r
2450 ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);
\r
2452 unit_set_error(unit, errno, 0, context->pos);
\r
2459 if(command_run(command) < 0)
\r
2461 ERROR3("[%s] Cannot run the command `%s' (%d)",context->pos, strerror(errno), errno);
\r
2462 unit_set_error(unit, errno, 0, context->pos);
\r
2468 if(context_reset(context) < 0)
\r
2470 ERROR3("[%s] Cannot reset the context of the command `%s' (%d)",context->pos, strerror(errno), errno);
\r
2472 unit_set_error(fstream->unit, errno, 0, context->pos);
\r