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
33 static int
\r is_w32_cmd(char *cmd, char **path)
\r
36 \rstruct stat stat_buff = { 0 };
37 \rchar buff[PATH_MAX + 1] = { 0 };
43 \r\rif (stat(cmd, &stat_buff) || !S_ISREG(stat_buff.st_mode))
47 \rfor (i = 0; path[i] != NULL; i++)
50 /* use Cat.exe on Windows */
\r
51 if (!strcmp(cmd, "cat"))
53 \r\rsprintf(buff, "%s\\%s", path[i], cmd);
54 \r\rif (!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))
67 \r\rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
68 \r\r\rlong fstream_getline(fstream_t fstream, char **buf, size_t * n)
70 \r\rreturn readline(fstream->stream, buf, n);
73 \r\rstatic void
\r failure(unit_t unit)
\r
75 \rif (!keep_going_unit_flag)
77 \runit_t root = unit->root ? unit->root : unit;
78 \r\rif (!root->interrupted)
81 /* the unit interrupted (exit for the loop) */
\r
82 root->interrupted = 1;
84 /* release the unit */
\r
85 xbt_os_sem_release(root->sem);
88 /* if the --keep-going option is not specified */
\r
94 /* request an global interruption by the runner */
\r
97 /* release the runner */
\r
98 xbt_os_sem_release(units_sem);
104 \r\rfstream_t
\r fstream_new(const char *directory, const char *name)
\r
112 \r\rif (!directory && !strcmp("stdin", name))
114 \rfstream = xbt_new0(s_fstream_t, 1);
115 \rfstream->name = strdup("stdin");
124 \r\rfstream = xbt_new0(s_fstream_t, 1);
125 \r\rif (!(fstream->name = strdup(name)))
130 \r\rif (!(fstream->directory = strdup(directory)))
132 \rfree(fstream->name);
136 \r\rfstream->stream = NULL;
137 \rfstream->unit = NULL;
138 \rfstream->parsed = 0;
139 \r\r\rreturn fstream;
142 \r\rint
\r fstream_open(fstream_t fstream)
\r
144 \rchar path[PATH_MAX + 1] = { 0 };
146 /* check the parameter */
\r
152 \r\rif (!fstream || fstream->stream)
157 \r\rif (!strcmp(fstream->name, "stdin"))
159 \rfstream->stream = stdin;
164 sprintf(path, "%s/%s", fstream->directory, fstream->name);
167 sprintf(path, "%s\\%s", fstream->directory, fstream->name);
170 \rif (!(fstream->stream = fopen(path, "r")))
177 \r\rint
\r fstream_close(fstream_t fstream)
\r
180 /* check the parameter */
\r
181 if (!(fstream) || !strcmp(fstream->name, "stdin"))
186 \r\rif (!fstream->stream)
188 \r\rif (EOF == fclose(fstream->stream))
190 \r\rfstream->stream = NULL;
194 \r\rint
\r fstream_free(fstream_t * ptr)
\r
197 /* check the parameter */
\r
205 \r\rif ((*ptr)->stream)
206 \rfclose((*ptr)->stream);
207 \r\rif ((*ptr)->name)
208 \rfree((*ptr)->name);
209 \r\rif ((*ptr)->directory)
210 \rfree((*ptr)->directory);
216 \r\rint
\r fstream_parse(fstream_t fstream, xbt_os_mutex_t mutex)
\r
221 \rchar file_pos[256];
222 \rxbt_strbuff_t buff;
227 /* Count the line length while checking wheather it's blank */
\r
231 /* Deal with \ at the end of the line, and call handle_line on result */
\r
234 /* check the parameter */
\r
235 if (!(fstream) || !mutex)
240 \r\rbuff = xbt_strbuff_new();
241 \r\rif (!(context = context_new()))
243 \r\runit = fstream->unit;
245 /*while(!(unit->root->interrupted) && getline(&line, &len, fstream->stream) != -1) */
\r
246 while (!(unit->root->interrupted)
247 && fstream_getline(fstream, &line, &len) != -1)
251 \rto_be_continued = 0;
253 \r\rwhile (line[linelen] != '\0')
255 \rif (line[linelen] != ' ' && line[linelen] != '\t'
256 && line[linelen] != '\n' && line[linelen] != '\r')
262 \rif (!context->command_line
263 && (context->input->used || context->output->used))
265 \rsnprintf(file_pos, 256, "%s:%d", fstream->name, line_num);
266 \rERROR1("[%s] Error : no command found in the last chunk of lines",
268 \r\runit_set_error(fstream->unit, ESYNTAX, 1, file_pos);
273 else if (unit->is_running_suite)
274 \r { /* it's the end of a suite */
275 \r\runit_t * current_suite =
276 xbt_dynar_get_ptr(unit->suites,
277 xbt_dynar_length(unit->suites) - 1);
278 \r\rif (!xbt_dynar_length((*current_suite)->includes))
280 \rERROR2("[%s] Malformated suite `(%s)' : include missing",
281 file_pos, (*current_suite)->description);
282 \r\runit_set_error(*current_suite, ESYNTAX, 1, file_pos);
285 \r\runit->is_running_suite = 0;
287 \r\rif (context->command_line)
291 if (!context->is_not_found)
295 if (fstream_launch_command(fstream, context, mutex) < 0)
305 \r\rif (linelen > 1 && line[linelen - 2] == '\\')
307 \rif (linelen > 2 && line[linelen - 3] == '\\')
310 /* Damn. Escaped \ */
\r
311 line[linelen - 2] = '\n';
312 \rline[linelen - 1] = '\0';
317 \rto_be_continued = 1;
318 \rline[linelen - 2] = '\0';
321 \rbuffbegin = line_num;
324 \r\rif (buff->used || to_be_continued)
326 \rxbt_strbuff_append(buff, line);
327 \r\rif (!to_be_continued)
329 \rsnprintf(file_pos, 256, "%s:%d", fstream->name, buffbegin);
330 \rfstream_lex_line(fstream, context, mutex, file_pos, buff->data);
331 \rxbt_strbuff_empty(buff);
337 \rsnprintf(file_pos, 256, "%s:%d", fstream->name, line_num);
338 \rfstream_lex_line(fstream, context, mutex, file_pos, line);
342 /* Check that last command of the file ran well */
\r
343 if (context->command_line)
347 if (!context->is_not_found)
351 \rif (fstream_launch_command(fstream, context, mutex) < 0)
360 /* clear buffers */
\r
363 \r\rxbt_strbuff_free(buff);
364 \r\rif (context_free(&context) < 0)
366 \r\rreturn (exit_code || errno) ? -1 : 0;
370 fstream_lex_line(fstream_t fstream, context_t context,
371 xbt_os_mutex_t mutex, const char *filepos, char *line)
\r
374 \rvariable_t variable;
376 \rchar exp[PATH_MAX + 1] = { 0 };
377 \runit_t unit = fstream->unit;
378 \rxbt_dynar_t variables = unit->runner->variables;
382 \rchar buff[PATH_MAX + 1] = { 0 };
384 \rchar delimiters[4] = { ' ', '\t', '\n', '\0' };
386 \r\rif (line[0] == '#')
388 \r\rif (unit->is_running_suite
389 && strncmp(line, "! include", strlen("! include")))
390 \r { /* it's the end of a suite */
391 \r\runit_t * current_suite =
392 xbt_dynar_get_ptr(unit->suites,
393 xbt_dynar_length(unit->suites) - 1);
394 \r\rif (!xbt_dynar_length((*current_suite)->includes))
395 \rERROR2("[%s] Malformated suite `(%s)': include missing", filepos,
396 (*current_suite)->description);
399 \rERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos,
400 (*current_suite)->description);
401 \r\runit_set_error(*current_suite, ESYNTAX, 1, filepos);
402 \r\rfailure(fstream->unit);
404 \r\rcontext->line = strdup(filepos);
407 xbt_str_rtrim(line + 2, "\n");
408 \r\rline2 = strdup(line);
409 \r\rlen = strlen(line2 + 2) + 1;
411 /* replace each variable by its value */
\r
412 xbt_os_mutex_acquire(unit->mutex);
414 /* replace all existing
\r
422 \rxbt_dynar_foreach(variables, i, variable)
\r {
423 \rif (!(p = strstr(line2 + 2, "${")))
425 \r\rmemset(buff, 0, len);
426 \r\rsprintf(buff, "${%s", variable->name);
429 if ((p = strstr(line2 + 2, buff)))
431 \rmemset(buff, 0, len);
434 \r\rwhile (*(p++) != '\0')
440 \r\rif (buff[j - 1] != '}')
442 \rxbt_os_mutex_release(unit->mutex);
443 \r\r\rERROR2("[%s] Syntax error : `%s'.", filepos, p - j);
444 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
445 \rfailure(fstream->unit);
448 \r\rif ((p = strstr(buff, ":=")))
453 /* if the value of the variable is empty, update its value by the value */
\r
455 \r\rend = strchr(p, '}');
456 \r\rif (!end || (end == p))
458 \rxbt_os_mutex_release(unit->mutex);
459 \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
461 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
462 \rfailure(fstream->unit);
465 \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
466 \r\rstrncpy(val, p, (end - p));
468 /* replace the expression by the expression of the value of the variable */
\r
469 sprintf(exp, "${%s:=%s}", variable->name, val);
470 \r\rif (variable->val)
471 \rstr_replace_all(&line2, exp, variable->val, NULL);
475 \rstr_replace_all(&line2, exp, val, NULL);
476 \r\rvariable->val = strdup(val);
478 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
486 else if ((p = strstr(buff, ":-")))
491 /* if the value of the variable is empty, replace the expression by the value */
\r
493 \rend = strchr(p, '}');
494 \r\rif (!end || (end == p))
496 \rxbt_os_mutex_release(unit->mutex);
497 \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
498 strstr(line2, "${"));
499 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
500 \rfailure(fstream->unit);
503 \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
504 \r\rstrncpy(val, p, (end - p));
505 \r\rsprintf(exp, "${%s:-%s}", variable->name, val);
506 \r\rstr_replace_all(&line2, exp, variable->val ? variable->val : val,
508 \r\r\rmemset(exp, 0, VAR_NAME_MAX + 1);
516 else if ((p = strstr(buff, ":+")))
521 /* if the value of the variable is not empty, replace the expression by the value */
\r
523 \r\rend = strchr(p, '}');
524 \r\rif (!end || (end == p))
526 \rxbt_os_mutex_release(unit->mutex);
527 \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
528 strstr(line2, "${"));
529 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
530 \rfailure(fstream->unit);
533 \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
534 \r\rstrncpy(val, p, (end - p));
535 \r\rsprintf(exp, "${%s:+%s}", variable->name, val);
536 \r\rif (variable->val)
538 \rstr_replace_all(&line2, exp, val, NULL);
543 \rstr_replace_all(&line2, exp, NULL, NULL);
544 \rvariable->val = strdup(val);
546 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
554 else if ((p = strstr(buff, ":?")))
559 /* if the value of the variable is not empty, replace the expression by the value */
\r
561 \rend = strchr(p, '}');
562 \r\rif (!end || (end == p))
564 \rxbt_os_mutex_release(unit->mutex);
565 \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
566 strstr(line2, "${"));
567 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
568 \rfailure(fstream->unit);
571 \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
572 \r\rstrncpy(val, p, (end - p));
573 \r\rsprintf(exp, "${%s:?%s}", variable->name, val);
574 \r\rif (variable->val)
575 \rstr_replace_all(&line2, exp, variable->val, NULL);
579 \r\rxbt_os_mutex_release(unit->mutex);
580 \r\rERROR2("[%s] %s.", filepos, val);
581 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
582 \rfailure(fstream->unit);
585 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
595 /* replace all existing $var */
\r
596 xbt_dynar_foreach(variables, i, variable)
\r {
597 \rif (!strchr(line2 + 2, '$'))
599 \r\rif (strstr(line2 + 2, variable->name))
601 \r\rsprintf(exp, "${#%s}", variable->name);
602 \r\rif (strstr(line2 + 2, exp))
604 \r\rif (variable->val)
606 \rchar slen[4] = { 0 };
607 \rsprintf(slen, "%d", (int) strlen(variable->val));
608 \rstr_replace_all(&line2, exp, slen, NULL);
612 \rstr_replace_all(&line2, exp, "0", NULL);
614 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
615 \r\rsprintf(exp, "${%s}", variable->name);
616 \r\rif (strstr(line2 + 2, exp))
619 \rstr_replace_all(&line2, exp, variable->val, NULL);
622 \rstr_replace_all(&line2, exp, NULL, NULL);
624 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
625 \r\rsprintf(exp, "$%s", variable->name);
626 \r\rif ((p = strstr(line2 + 2, exp)))
628 \rif ((p + strlen(variable->name) + 1)[0] != '\0'
629 && !(isalpha((p + strlen(variable->name) + 1)[0])))
630 \rdelimiters[0] = (p + strlen(variable->name) + 1)[0];
631 \r\rif (variable->val)
632 \rstr_replace_all(&line2, exp, variable->val, delimiters);
635 \rstr_replace_all(&line2, exp, NULL, delimiters);
637 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
640 \r\rwhile ((p = strstr(line2 + 2, "${")))
643 /*if(*(p+1) != '{')
\r
648 while(*(p++) != '\0')
\r
650 if(*p != ' ' && *p !='\t')
\r
657 str_replace_all(&line2, exp, NULL, " \t\n\r");
\r
658 memset(exp, 0, VAR_NAME_MAX + 1);
\r
663 \rchar *begin = NULL;
666 \r\rwhile (*(p++) != '\0')
668 \rif ((!begin && *p != ' ' && *p != '\t') || begin)
671 /* `:' must be before this caracter, bad substitution : exit loop
\r
673 the current character is already present, bad substitution : exit loop
\r
676 (
\r*(p - 1) != ':' && (
\r
677 (*p == '=') || (*p == '-')
679 || (*p == '?')
\r)
\r)
\r ||
\r(
\rbegin
705 /* save the begining of the value */
\r
706 if ((*(p + 1) == '=') || (*(p + 1) == '-')
707 || (*(p + 1) == '+') || (*(p + 1) == '?'))
710 \rexp[j++] = *(p + 1);
717 /* the current char is `:' but the next is invalid, bad substitution : exit loop */
\r
721 /* end of the substitution : exit loop */
\r
729 \r\rif (exp[j - 1] == '}')
735 \r\rif (4 == strlen(exp))
737 \rxbt_os_mutex_release(unit->mutex);
738 \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
739 strchr(line2 + 2, '$'));
740 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
741 \rfailure(fstream->unit);
744 \r\rstr_replace_all(&line2, exp, "0", NULL);
747 else if (strstr(exp, ":="))
750 /* ${var:=value} */
\r
751 \rend = strchr(p, '}');
752 \r\rif (!end || (end == begin))
754 \rxbt_os_mutex_release(unit->mutex);
755 \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
756 strchr(line2 + 2, '$'));
757 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
758 \rfailure(fstream->unit);
761 \r\rvariable = xbt_new0(s_variable_t, 1);
763 (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
764 \r\rstrncpy(variable->val, begin, (end - begin));
766 \rend = strchr(exp, ':');
767 \r\rif (!end || (end == begin))
769 \rxbt_os_mutex_release(unit->mutex);
770 \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
771 strchr(line2 + 2, '$'));
772 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
773 \rfailure(fstream->unit);
777 (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
778 \r\rstrncpy(variable->name, exp + 2, (end - begin));
779 \r\rstr_replace_all(&line2, exp, variable->val, NULL);
780 \r\rxbt_dynar_push(variables, &variable);
783 else if (strstr(exp, ":-"))
786 /* ${var:-value} */
\r
787 \r\rend = strchr(p, '}');
788 \r\rif (!end || (end == begin))
790 \rxbt_os_mutex_release(unit->mutex);
791 \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
792 strchr(line2 + 2, '$'));
793 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
794 \rfailure(fstream->unit);
798 (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
799 \r\rstrncpy(val, begin, (end - begin));
800 \r\rstr_replace_all(&line2, exp, val, NULL);
805 else if (strstr(exp, ":+"))
808 /* ${var:+value} */
\r
809 \rend = strchr(p, '}');
810 \r\rif (!end || (end == begin))
812 \rxbt_os_mutex_release(unit->mutex);
813 \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
814 strchr(line2 + 2, '$'));
815 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
816 \rfailure(fstream->unit);
819 \r\rstr_replace_all(&line2, exp, NULL, NULL);
822 else if (strstr(exp, ":?"))
825 /* ${var:?value} */
\r
826 \rend = strchr(p, '}');
827 \r\rif (!end || (end == begin))
829 \rxbt_os_mutex_release(unit->mutex);
830 \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
831 strchr(line2 + 2, '$'));
832 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
833 \rfailure(fstream->unit);
837 (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
838 \r\rstrncpy(val, begin, (end - begin));
839 \r\rxbt_os_mutex_release(unit->mutex);
840 \r\rERROR2("[%s] : `%s'.", filepos, val);
843 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
844 \rfailure(fstream->unit);
852 \rif (3 == strlen(exp))
854 \rxbt_os_mutex_release(unit->mutex);
855 \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
856 strchr(line2 + 2, '$'));
857 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
858 \rfailure(fstream->unit);
861 \r\rstr_replace_all(&line2, exp, NULL, NULL);
863 \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
868 \rxbt_os_mutex_release(unit->mutex);
869 \r\rif (strstr(line2 + 2, "${"))
870 \rERROR2("[%s] Bad substitution : `%s'.", filepos,
871 strstr(line2, "${"));
874 \rERROR2("[%s] Syntax error : `%s'.", filepos,
875 strstr(line2, "${"));
876 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
877 \rfailure(fstream->unit);
884 \rp = line2 + (line2[0] == '<' ? 4 : 2);
885 \r\rif ((p = strchr(p, '$')))
887 \rif (*(p + 1) != ' ')
891 \r\rwhile (*(p++) != '\0')
893 \rif (*p != ' ' && *p != '\t')
899 \r\rstr_replace_all(&line2, exp, NULL, " \t\n\r");
900 \rmemset(exp, 0, VAR_NAME_MAX + 1);
906 /* maybe < $ cmd */
\r
914 \r\rxbt_os_mutex_release(unit->mutex);
915 \r\rswitch (line2[0])
923 \r\rif (line[1] != ' ')
925 \r\rif (line2[0] == '$')
926 \rERROR1("[%s] Missing space after `$' `(usage : $ <command>)'",
930 \rERROR1("[%s] Missing space after & `(usage : & <command>)'",
932 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
936 \r\rcontext->async = (line2[0] == '&');
938 /* further trim useless chars which are significant for in/output */
\r
939 xbt_str_rtrim(line2 + 2, " \t");
941 /* deal with CD commands here, not in context */
\r
942 if (!strncmp("cd ", line2 + 2, 3))
944 \rchar *dir = strdup(line2 + 4);
945 \r\rif (context->command_line)
947 \rif (fstream_launch_command(fstream, context, mutex) < 0)
951 /* search begining */
\r
952 while (*(dir++) == ' ');
954 \r\rif (!dry_run_flag)
957 \rINFO2("[%s] cd %s", filepos, dir);
958 \r\rif (!just_print_flag)
962 \rERROR3("[%s] Chdir to %s failed: %s", filepos, dir,
963 error_to_string(errno, 0));
964 \runit_set_error(fstream->unit, errno, 0, filepos);
974 \rfstream_process_token(fstream, context, mutex, filepos, line2[0],
981 \r\rif (line[0] == '!' && line[1] != ' ')
984 ("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'",
986 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
990 \r\rfstream_process_token(fstream, context, mutex, filepos, line2[0],
997 \r\rchar *prompt = line2 + 2;
998 \r\rfor (j = 0; j < strlen(prompt); j++)
1000 \rif (prompt[j] != ' ' && prompt[j] != '\t')
1009 ("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'",
1011 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1015 \r\rif (!dry_run_flag)
1016 \rINFO2("[%s] %s", filepos, prompt);
1023 \r\rchar *prompt = line2 + 2;
1024 \r\rfor (j = 0; j < strlen(prompt); j++)
1025 \rif (prompt[j] != ' ' && prompt[j] != '\t')
1030 ("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'",
1032 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1036 \r\rif (!dry_run_flag)
1037 \rCRITICAL2("[%s] %s", filepos, prompt);
1041 \rif (unit->description)
1042 \rWARN2("[%s] Description already specified `%s'", filepos,
1049 \r\rchar *desc = line2 + 2;
1050 \r\rfor (j = 0; j < strlen(desc); j++)
1051 \rif (desc[j] != ' ' && desc[j] != '\t')
1056 ("[%s] Bad usage of the metacommand D `(usage : D <Description>)'",
1058 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1062 \r\runit->description = strdup(desc);
1066 \rERROR2("[%s] Syntax error `%s'", filepos, line2);
1067 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1075 fstream_process_token(fstream_t fstream, context_t context,
1076 xbt_os_mutex_t mutex, const char *filepos,
1077 char token, char *line)
\r
1079 \runit_t unit = fstream->unit;
1084 \r\rif (context->command_line)
1086 \r\rif (context->output->used || context->input->used)
1089 ("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",
1090 filepos, context->command_line);
1091 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1095 \r\rif (fstream_launch_command(fstream, context, mutex) < 0)
1097 \r\rVERB1("[%s] More than one command in this chunk of lines",
1101 \rsize_t j,
\ris_blank = 1;
1102 \r\rfor (j = 0; j < strlen(line); j++)
1103 \rif (line[j] != ' ' && line[j] != '\t')
1108 \rERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'",
1112 \rERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'",
1114 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1119 \r\rcontext->command_line = strdup(line);
1120 \r\rxbt_str_ltrim(context->command_line, " ");
1121 \r\rcontext->line = /*strdup(filepos) */ filepos;
1122 \rcontext->pos = strdup(filepos);
1127 /* translate the command line */
\r
1128 \rchar *path = NULL;
1130 \rchar command_line[PATH_MAX + 1] = { 0 };
1132 \rchar *args = NULL;
1134 /*if(strstr(context->command_line,".exe"))
\r
1135 strcpy(command_line,context->command_line); */
\r
1139 \r\rlen = strlen(context->command_line);
1142 \rif (context->command_line[i] != ' '
1143 && context->command_line[i] != '\t'
1144 && context->command_line[i] != '>')
1145 \rcommand_line[j++] = context->command_line[i];
1151 \r\rif (!strstr(context->command_line, ".exe"))
1152 \rstrcat(command_line, ".exe");
1153 \r\rargs = strdup(context->command_line + i);
1155 \r\rif (!is_w32_cmd(command_line, fstream->unit->runner->path)
1156 && getpath(command_line, &path) < 0)
1158 \rcommand_t command;
1159 \r\rERROR3("[%s] `%s' : NOK (%s)", filepos, command_line,
1160 error_to_string(ECMDNOTFOUND, 1));
1161 \runit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);
1162 \r\rcontext->is_not_found = 1;
1163 \r\rcommand = command_new(fstream->unit, context, mutex);
1164 \r\rcommand->status = cs_failed;
1165 \rcommand->reason = csr_command_not_found;
1169 \r\rdelimiter = strrchr(command_line, '/');
1171 \rdelimiter = strrchr(command_line, '\\');
1173 /*free(context->command_line); */
\r
1178 \rcontext->t_command_line =
1179 (char *) calloc(strlen(path) +
1180 strlen(delimiter ? delimiter +
1181 1 : command_line) + strlen(args) + 2,
1183 \rsprintf(context->t_command_line, "%s\\%s%s", path,
1184 delimiter ? delimiter + 1 : command_line, args);
1190 \rcontext->t_command_line =
1191 (char *) calloc(strlen(path) +
1192 strlen(delimiter ? delimiter +
1193 1 : command_line) + 2, sizeof(char));
1194 \rsprintf(context->t_command_line, "%s\\%s", path,
1195 delimiter ? delimiter + 1 : command_line);
1203 \r\rcontext->t_command_line =
1204 (char *) calloc(strlen(command_line) + strlen(args) + 1,
1206 \rsprintf(context->t_command_line, "%s%s", command_line, args);
1212 \rcontext->t_command_line =
1213 (char *) calloc(strlen(command_line) + 1, sizeof(char));
1214 \rstrcpy(context->t_command_line, command_line);
1219 \rxbt_strbuff_append(context->input, line);
1220 \rxbt_strbuff_append(context->input, "\n");
1223 \rxbt_strbuff_append(context->output, line);
1224 \rxbt_strbuff_append(context->output, "\n");
1227 \r\rif (context->command_line)
1229 \rif (fstream_launch_command(fstream, context, mutex) < 0)
1232 \r\rif (!strncmp(line, "timeout no", strlen("timeout no")))
1234 \rVERB1("[%s] (disable timeout)", filepos);
1235 \rcontext->timeout = INDEFINITE;
1238 else if (!strncmp(line, "timeout ", strlen("timeout ")))
1243 \rchar *p = line + strlen("timeout ");
1244 \r\r\rfor (j = 0; j < strlen(p); j++)
1245 \rif (p[j] != ' ' && p[j] != '\t')
1250 ("[%s] Undefinite timeout value `(usage :timeout <seconds>)'",
1252 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1256 \r\rwhile (p[i] != '\0')
1258 \rif (!isdigit(p[i]))
1261 ("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'",
1262 filepos, line + strlen("timeout "));
1263 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1269 \r\rcontext->timeout = atoi(line + strlen("timeout"));
1270 \rVERB2("[%s] (new timeout value: %d)", filepos, context->timeout);
1273 else if (!strncmp(line, "expect signal ", strlen("expect signal ")))
1277 \r\r\rchar *p = line + strlen("expect signal ");
1278 \r\r\rfor (j = 0; j < strlen(p); j++)
1279 \rif (p[j] != ' ' && p[j] != '\t')
1284 ("[%s] Undefinite signal name `(usage :expect signal <signal name>)'",
1286 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1290 \r\rcontext->signal = strdup(line + strlen("expect signal "));
1291 \r\rxbt_str_trim(context->signal, " \n");
1294 if (!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))
1296 \rERROR2("[%s] Signal `%s' not supported by this platform", filepos,
1298 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1299 \r\r\rfailure(unit);
1304 if (!sig_exists(context->signal))
1306 \rERROR2("[%s] Signal `%s' not supported by Tesh", filepos,
1308 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1309 \r\r\rfailure(unit);
1314 \r\rVERB2("[%s] (next command must raise signal %s)", filepos,
1318 else if (!strncmp(line, "expect return ", strlen("expect return ")))
1323 \rchar *p = line + strlen("expect return ");
1324 \r\r\rfor (j = 0; j < strlen(p); j++)
1325 \rif (p[j] != ' ' && p[j] != '\t')
1330 ("[%s] Undefinite return value `(usage :expect return <return value>)'",
1332 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1336 \r\rwhile (p[i] != '\0')
1338 \rif (!isdigit(p[i]))
1341 ("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255",
1342 filepos, line + strlen("expect return "));
1343 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1349 \r\rcontext->exit_code = atoi(line + strlen("expect return "));
1350 \rVERB2("[%s] (next command must return code %d)", filepos,
1351 context->exit_code);
1354 else if (!strncmp(line, "output ignore", strlen("output ignore")))
1356 \rcontext->output_handling = oh_ignore;
1357 \rVERB1("[%s] (ignore output of next command)", filepos);
1360 else if (!strncmp(line, "output display", strlen("output display")))
1362 \rcontext->output_handling = oh_display;
1363 \rVERB1("[%s] (ignore output of next command)", filepos);
1366 else if (!strncmp(line, "include ", strlen("include ")))
1370 \r\rp1 = line + strlen("include");
1371 \r\rwhile (*p1 == ' ' || *p1 == '\t')
1373 \r\r\rif (p1[0] == '\0')
1376 ("[%s] no file specified : `(usage : include <file> [<description>])'",
1378 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1385 \rchar file_name[PATH_MAX + 1] = { 0 };
1387 \r\rwhile (*p2 != '\0' && *p2 != ' ' && *p2 != '\t')
1389 \r\rstrncpy(file_name, p1, p2 - p1);
1390 \r\r\rif (p2[0] != '\0')
1391 \rwhile (*p2 == ' ' || *p2 == '\t')
1393 \r\rfstream_handle_include(fstream, context, mutex, file_name,
1394 p2[0] != '\0' ? p2 : NULL);
1398 else if (!strncmp(line, "suite ", strlen("suite ")))
1402 \rchar *p = line + strlen("suite ");
1403 \r\r\rfor (j = 0; j < strlen(p); j++)
1404 \rif (p[j] != ' ' && p[j] != '\t')
1409 ("[%s] Undefinite suit description : `(usage : suite <description>)",
1411 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1415 \r\rif (unit->is_running_suite)
1417 \rERROR1("[%s] Suite already in progress", filepos);
1418 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1422 \r\rfstream_handle_suite(fstream, line + strlen("suite "), filepos);
1425 else if (!strncmp(line, "unsetenv ", strlen("unsetenv ")))
1427 \runsigned int i, j;
1431 \rvariable_t variable;
1433 \r\rchar *name = line + strlen("unsetenv ");
1435 \r\rfor (j = 0; j < strlen(name); j++)
1436 \rif (name[j] != ' ' && name[j] != '\t')
1441 ("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'",
1443 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1447 \r\rxbt_os_mutex_acquire(unit->mutex);
1448 \r\r\rxbt_dynar_foreach(unit->runner->variables, i, variable)
\r {
1449 \rif (!strcmp(variable->name, name))
1451 \renv = variable->env;
1452 \rerr = variable->err;
1462 #ifndef _XBT_WIN32
\r
1466 SetEnvironmentVariable(name, NULL);
1469 xbt_dynar_cursor_rm(unit->runner->variables, &i);
1475 ("[%s] `(%s)' environment variable not found : impossible to unset it",
1477 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1478 \rxbt_os_mutex_release(unit->mutex);
1491 ("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",
1493 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1495 \rxbt_os_mutex_release(unit->mutex);
1502 ("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",
1504 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1505 \rxbt_os_mutex_release(unit->mutex);
1514 ("[%s] `(%s)' environment variable not found : impossible to unset it",
1516 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1517 \rxbt_os_mutex_release(unit->mutex);
1522 \r\rxbt_os_mutex_release(unit->mutex);
1525 else if (!strncmp(line, "setenv ", strlen("setenv ")))
1528 \rchar name[PATH_MAX + 1] = { 0 };
1533 \r\rp = line + strlen("setenv ");
1534 \r\rval = strchr(p, '=');
1537 \rvariable_t variable;
1543 /* syntax error */
\r
1544 if (val[0] == '\0' || val[0] == ' ' || val[0] == '\t')
1547 ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
1549 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1553 \r\r\r\rstrncpy(name, p, (val - p - 1));
1555 \r\rfor (j = 0; j < strlen(name); j++)
1556 \rif (name[j] != ' ' && name[j] != '\t')
1561 ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
1563 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1568 /* test if the variable is already registred */
\r
1569 xbt_os_mutex_acquire(unit->mutex);
1570 \r\rxbt_dynar_foreach(unit->runner->variables, i, variable)
\r {
1571 \rif (!strcmp(variable->name, name))
1573 \renv = variable->env;
1574 \rerr = variable->err;
1580 /* if the variable is already registred, update its value;
\r
1581 * otherwise register it.
\r
1587 \rif (!strcmp(val, variable->val))
1589 ("[%s] This environment variable `(%s)' is already set with the value `(%s)'",
1590 filepos, name, val);
1591 \r\rfree(variable->val);
1592 \rvariable->val = strdup(val);
1595 SetEnvironmentVariable(variable->name, variable->val);
1598 setenv(variable->name, variable->val, 1);
1607 ("[%s] Conflict : a system variable `(%s)' already exists",
1612 ("[%s] Conflict : (none environment) variable `(%s)' already exists",
1614 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1615 \rxbt_os_mutex_release(unit->mutex);
1625 \rERROR2("[%s] A system variable named `(%s)' already exists",
1627 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1628 \rxbt_os_mutex_release(unit->mutex);
1635 \rvariable = variable_new(name, val);
1636 \rvariable->env = 1;
1637 \r\rxbt_dynar_push(unit->runner->variables, &variable);
1640 SetEnvironmentVariable(variable->name, variable->val);
1643 setenv(variable->name, variable->val, 0);
1648 \r\rxbt_os_mutex_release(unit->mutex);
1654 ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
1656 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1662 else if (!strncmp(line, "unset ", strlen("unset ")))
1664 \runsigned int i, j;
1668 \rvariable_t variable;
1670 \r\rchar *name = line + strlen("unset ");
1672 \r\rfor (j = 0; j < strlen(name); j++)
1673 \rif (name[j] != ' ' && name[j] != '\t')
1678 ("[%s] Bad usage of the metacommand unset `(usage : unset variable)'",
1680 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1684 \r\r\rxbt_os_mutex_acquire(unit->mutex);
1685 \r\rxbt_dynar_foreach(unit->runner->variables, i, variable)
\r {
1686 \rif (!strcmp(variable->name, name))
1688 \renv = variable->env;
1689 \rerr = variable->err;
1694 \r\rif (!env && !err)
1699 /*xbt_dynar_remove_at(unit->runner->variables, i, NULL); */
\r
1700 /*xbt_dynar_cursor_rm(unit->runner->variables, &i); */
\r
1703 \rfree(variable->val);
1704 \rvariable->val = NULL;
1709 \rWARN2("[%s] Variable `(%s)' already unseted", filepos,
1716 \rERROR2("[%s] `(%s)' variable not found", filepos, name);
1717 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1718 \rxbt_os_mutex_release(unit->mutex);
1727 ("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",
1729 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1730 \rxbt_os_mutex_release(unit->mutex);
1737 \rERROR2("[%s] `(%s)' is system variable : you can unset it",
1739 \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1740 \rxbt_os_mutex_release(unit->mutex);
1744 \r\rxbt_os_mutex_release(unit->mutex);
1747 else if (!strncmp(line, "set ", strlen("set ")))
1750 \rchar name[PATH_MAX + 1] = { 0 };
1753 \r\rval = strchr(line + strlen("set "), '=');
1756 \rvariable_t variable;
1763 /* syntax error */
\r
1767 ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
1769 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1774 else if (val[0] == ' ' || val[0] == '\t')
1776 \rstrncpy(name, line + strlen("set "),
1777 (val - (line + strlen("set "))));
1778 \r\rERROR2("[%s] No space avaible after`(%s)'", filepos, name);
1779 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1784 /* assume it's a varibale */
\r
1785 \rstrncpy(name, line + strlen("set "),
1786 (val - (line + strlen("set ")) - 1));
1788 \r\rfor (j = 0; j < strlen(name); j++)
1789 \rif (name[j] != ' ' && name[j] != '\t')
1794 ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
1796 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1800 \r\rxbt_os_mutex_acquire(unit->mutex);
1802 /* test if the variable is already registred */
\r
1803 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r {
1804 \rif (!strcmp(variable->name, name))
1807 \rerr = variable->err;
1808 \renv = variable->env;
1813 /* if the variable is already registred, update its value (if same value warns);
\r
1814 * otherwise register it.
\r
1820 \rERROR2("[%s] A system variable named `(%s)' already exists",
1822 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1823 \rxbt_os_mutex_release(unit->mutex);
1830 ("[%s] `(%s)' is an environment variable use `setenv' instead `set'",
1832 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1833 \rxbt_os_mutex_release(unit->mutex);
1840 \rif (!strcmp(val, variable->val))
1841 \rWARN3("[%s] Variable `(%s)' already contains value `<%s>'",
1842 filepos, variable->name, val);
1843 \r\rfree(variable->val);
1844 \rvariable->val = strdup(val);
1850 \rvariable_t new_var = variable_new(name, val);
1851 \rxbt_dynar_push(unit->runner->variables, &new_var);
1853 \r\r\rxbt_os_mutex_release(unit->mutex);
1859 ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
1861 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1868 \r { /* assume it's a variable */
1870 \rchar name[PATH_MAX + 1] = { 0 };
1871 \runsigned int i, j;
1873 \r\rval = strchr(line, '=');
1876 \rvariable_t variable;
1882 /* syntax error */
\r
1885 \rstrncpy(name, line, (val - line - 1));
1887 \r\rfor (j = 0; j < strlen(name); j++)
1888 \rif (name[j] != ' ' && name[j] != '\t')
1892 ("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'",
1895 else if (!strcmp("setenv", name))
1897 ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
1900 else if (!strcmp("set", name))
1902 ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
1906 \rERROR2("[%s] Undefined variable `(%s)'", filepos, name);
1907 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1912 else if (val[0] == ' ' || val[0] == '\t')
1914 \rstrncpy(name, line, (val - line));
1915 \r\rERROR2("[%s] No space avaible after`(%s)'", filepos, name);
1916 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1920 /* assume it's a varibale */
\r
1921 \rstrncpy(name, line, (val - line - 1));
1923 \r\rfor (j = 0; j < strlen(name); j++)
1924 \rif (name[j] != ' ' && name[j] != '\t')
1929 ("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'",
1931 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1935 \r\rif (!strcmp("set", name))
1938 ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
1940 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1945 else if (!strcmp("setenv", name))
1948 ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
1950 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1954 \r\rxbt_os_mutex_acquire(unit->mutex);
1956 /* test if the variable is already registred */
\r
1957 xbt_dynar_foreach(unit->runner->variables, i, variable)
\r {
1958 \rif (!strcmp(variable->name, name))
1961 \rerr = variable->err;
1962 \renv = variable->env;
1967 /* if the variable is already registred, update its value (if same value warns);
\r
1968 * otherwise register it.
\r
1974 \rERROR2("[%s] A system variable named `(%s)' already exists",
1976 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1977 \rxbt_os_mutex_release(unit->mutex);
1984 ("[%s] `(%s)' is an environment variable use `setenv' metacommand",
1986 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
1987 \rxbt_os_mutex_release(unit->mutex);
1994 \rif (!strcmp(val, variable->val))
1995 \rWARN3("[%s] Variable `(%s)' already contains value `<%s>'",
1996 filepos, variable->name, val);
1997 \r\rfree(variable->val);
1998 \rvariable->val = strdup(val);
2004 \rvariable_t new_var = variable_new(name, val);
2005 \rxbt_dynar_push(unit->runner->variables, &new_var);
2007 \r\r\rxbt_os_mutex_release(unit->mutex);
2012 \rif (!strncmp("setenv", line, strlen("setenv")))
2014 ("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'",
2017 else if (!strncmp("set", line, strlen("set")))
2019 ("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'",
2022 else if (!strncmp("unsetenv", line, strlen("unsetenv")))
2024 ("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'",
2027 else if (!strncmp("unset", line, strlen("unset")))
2029 ("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'",
2032 else if (!strncmp("timeout", line, strlen("timeout")))
2034 ("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'",
2037 else if (!strncmp("expect signal", line, strlen("expect signal")))
2039 ("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'",
2042 else if (!strncmp("expect return", line, strlen("expect return")))
2044 ("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'",
2047 else if (!strncmp("include", line, strlen("include")))
2049 ("[%s] Bad usage of the metacommand include :`(usage : include <file> [<description>])'",
2052 else if (!strncmp("suite", line, strlen("suite")))
2054 ("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'",
2058 \rERROR2("[%s] Unknown metacommand: `%s'", filepos, line);
2059 \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
2069 fstream_handle_include(fstream_t fstream, context_t context,
2070 xbt_os_mutex_t mutex, const char *file_name,
2071 const char *description)
\r
2074 \rchar *prev_directory = NULL;
2075 \rfstream_t _fstream = NULL;
2076 \rstruct stat buffer = { 0 };
2077 \runit_t unit = fstream->unit;
2078 \r\rif (!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
2081 /* the file is in the current directory */
\r
2082 _fstream = fstream_new(getcwd(NULL, 0), file_name);
2083 \rfstream_open(_fstream);
2086 /* the file to include is not in the current directory, check if it is in a include directory */
\r
2090 \rprev_directory = getcwd(NULL, 0);
2091 \r\rxbt_dynar_foreach(include_dirs, i, dir)
\r {
2093 \r\rif (!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
2095 \r_fstream = fstream_new(dir->name, file_name);
2096 \rfstream_open(_fstream);
2100 \r\rchdir(prev_directory);
2101 \rfree(prev_directory);
2104 /* the file to include is not found handle the failure */
\r
2107 \rif (file_name[0] == '$')
2110 ("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",
2111 context->line, file_name, file_name + 1);
2117 /* may be a variable */
\r
2118 variable_t variable;
2121 \r\rxbt_dynar_foreach(unit->runner->variables, i, variable)
\r {
2122 \rif (!strcmp(variable->name, file_name))
2130 ("[%s] Include file `(%s)' not found (if you want to use the variable <%s> add the prefix `$')",
2131 context->line, file_name, file_name);
2134 \rERROR2("[%s] Include file `(%s)' not found", context->line,
2137 \r\runit_set_error(fstream->unit, EINCLUDENOTFOUND, 1, context->line);
2138 \r\rfailure(fstream->unit);
2144 \rif (!unit->is_running_suite)
2145 \r { /* it's the unit of a suite */
2146 \runit_t include = unit_new(unit->runner, unit->root, unit, _fstream);
2147 \r\rinclude->mutex = unit->root->mutex;
2148 \r\rif (description)
2149 \rinclude->description = strdup(description);
2150 \r\rxbt_dynar_push(unit->includes, &include);
2151 \r\rif (!dry_run_flag)
2154 \rINFO2("Include from %s (%s)", _fstream->name, description);
2157 \rINFO1("Include from %s", _fstream->name);
2161 \rINFO1("Checking include %s...", _fstream->name);
2162 \r\rfstream_parse(_fstream, mutex);
2166 \r { /* it's a include */
2170 xbt_dynar_get_ptr(unit->suites,
2171 xbt_dynar_length(unit->suites) - 1);
2172 \r\rinclude = unit_new(unit->runner, unit->root, *owner, _fstream);
2173 \r\rinclude->mutex = unit->root->mutex;
2174 \r\rif (description)
2175 \rinclude->description = strdup(description);
2176 \r\rxbt_dynar_push((*owner)->includes, &include);
2177 \r\rif (!dry_run_flag)
2180 \rINFO2("Include from %s (%s)", _fstream->name, description);
2183 \rINFO1("Include from %s", _fstream->name);
2187 \rINFO1("Checking include %s...", _fstream->name);
2188 \r\rfstream_parse(_fstream, mutex);
2194 fstream_handle_suite(fstream_t fstream, const char *description,
2195 const char *filepos)
\r
2197 \runit_t unit = fstream->unit;
2198 \runit_t suite = unit_new(unit->runner, unit->root, unit, NULL);
2199 \r\rif (description)
2200 \rsuite->description = strdup(description);
2201 \r\rsuite->filepos = strdup(filepos);
2202 \r\rxbt_dynar_push(unit->suites, &suite);
2203 \runit->is_running_suite = 1;
2204 \r\rif (!dry_run_flag)
2205 \rINFO1("Test suite %s", description);
2208 \rINFO1("Checking suite %s...", description);
2212 fstream_launch_command(fstream_t fstream, context_t context,
2213 xbt_os_mutex_t mutex)
\r
2215 \runit_t unit = fstream->unit;
2216 \r\rif (!dry_run_flag)
2218 \rcommand_t command;
2219 \r\rif (!(command = command_new(unit, context, mutex)))
2221 \rif (EINVAL == errno)
2223 \rERROR3("[%s] Cannot instantiate the command `%s' (%d)",
2224 context->pos, strerror(errno), errno);
2225 \r\runit_set_error(unit, errno, 0, context->pos);
2230 else if (ENOMEM == errno)
2232 \rERROR3("[%s] Cannot instantiate the command `%s' (%d)",
2233 context->pos, strerror(errno), errno);
2234 \r\runit_set_error(unit, errno, 0, context->pos);
2239 \r\rif (command_run(command) < 0)
2241 \rERROR3("[%s] Cannot run the command `%s' (%d)", context->pos,
2242 strerror(errno), errno);
2243 \runit_set_error(unit, errno, 0, context->pos);
2248 \r\rif (context_reset(context) < 0)
2250 \rERROR3("[%s] Cannot reset the context of the command `%s' (%d)",
2251 context->pos, strerror(errno), errno);
2252 \r\runit_set_error(fstream->unit, errno, 0, context->pos);