Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Last corrections of Tesh tool.
[simgrid.git] / tools / tesh2 / src / fstream.c
1 /*\r
2  * src/fstream.c - type representing the tesh file stream.\r
3  *\r
4  * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. \r
5  *\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
8  *\r
9  * Purpose:\r
10  *              This file contains all the definitions of the functions related with\r
11  *              the tesh file stream type.\r
12  *\r
13  */\r
14 \r
15 #include <fstream.h>\r
16 #include <xerrno.h>\r
17 #include <context.h>\r
18 #include <command.h>\r
19 #include <unit.h>\r
20 #include <str_replace.h>\r
21 #include <variable.h>\r
22 \r
23 #include <readline.h>\r
24 \r
25 #include <is_cmd.h>\r
26 \r
27 #ifndef WIN32\r
28 #include <xsignal.h>\r
29 #endif\r
30 \r
31 \r
32 \r
33 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
34 \r
35 \r
36 \r
37 \r
38 long fstream_getline(fstream_t fstream, char **buf, size_t *n) {\r
39 \r
40         return readline(fstream->stream, buf, n);\r
41         \r
42 }\r
43 \r
44 static void\r
45 failure(unit_t unit)\r
46 {\r
47         if(!keep_going_unit_flag)\r
48         {\r
49                 unit_t root = unit->root ? unit->root : unit;\r
50                         \r
51                 if(!root->interrupted)\r
52                 {\r
53                         /* the unit interrupted (exit for the loop) */\r
54                         root->interrupted = 1;\r
55 \r
56                         /* release the unit */\r
57                         xbt_os_sem_release(root->sem);\r
58                 }\r
59 \r
60                 /* if the --keep-going option is not specified */\r
61                 if(!keep_going_flag)\r
62                 {\r
63                         if(!interrupted)\r
64                         {\r
65                                 /* request an global interruption by the runner */\r
66                                 interrupted = 1;\r
67 \r
68                                 /* release the runner */\r
69                                 xbt_os_sem_release(units_sem);\r
70                         }\r
71                 }\r
72         }\r
73 }\r
74 \r
75 fstream_t\r
76 fstream_new(const char* directory, const char* name)\r
77 {\r
78         fstream_t fstream;\r
79         \r
80         if(!name)\r
81         {\r
82                 errno = EINVAL;\r
83                 return NULL;\r
84         }\r
85         \r
86         if(!directory && !strcmp("stdin", name))\r
87         {\r
88                 fstream = xbt_new0(s_fstream_t, 1);\r
89                 fstream->name = strdup("stdin");\r
90                 return fstream;\r
91         }\r
92         else if(!directory)\r
93         {\r
94                 errno = EINVAL;\r
95                 return NULL;\r
96         }\r
97         \r
98         fstream = xbt_new0(s_fstream_t, 1);\r
99         \r
100         if(!(fstream->name = strdup(name)))\r
101         {\r
102                 free(fstream);\r
103                 return NULL;\r
104         }\r
105         \r
106         if(!(fstream->directory = strdup(directory)))\r
107         {\r
108                 free(fstream->name);\r
109                 free(fstream);\r
110                 return NULL;\r
111         }\r
112         \r
113         fstream->stream = NULL;\r
114         fstream->unit = NULL;\r
115         fstream->parsed = 0;\r
116         \r
117         \r
118         return fstream;\r
119 }\r
120 \r
121 int\r
122 fstream_open(fstream_t fstream)\r
123 {\r
124         char path[PATH_MAX + 1] = {0};\r
125         \r
126         /* check the parameter */\r
127         if(!(fstream))\r
128     {\r
129         errno = EINVAL;\r
130         return -1;\r
131     }\r
132         \r
133         if(!fstream || fstream->stream)\r
134         {\r
135                 errno = EALREADY;\r
136                 return -1;\r
137         }\r
138                 \r
139         if(!strcmp(fstream->name, "stdin"))\r
140         {\r
141                 fstream->stream = stdin;\r
142                 return 0;\r
143         }\r
144         \r
145         #ifndef WIN32\r
146         sprintf(path,"%s/%s",fstream->directory, fstream->name);\r
147         #else\r
148         sprintf(path,"%s\\%s",fstream->directory, fstream->name);\r
149     #endif\r
150 \r
151         if(!(fstream->stream = fopen(path, "r")))\r
152                 return -1;\r
153         \r
154         return 0;\r
155 }\r
156 \r
157 int\r
158 fstream_close(fstream_t fstream)\r
159 {\r
160         /* check the parameter */\r
161         if(!(fstream) || !strcmp(fstream->name, "stdin") )\r
162     {\r
163         errno = EINVAL;\r
164         return -1;\r
165     }\r
166                 \r
167         if(!fstream->stream)\r
168                 return EBADF;   \r
169         \r
170         if(EOF == fclose(fstream->stream))\r
171                 return -1;\r
172                 \r
173         fstream->stream = NULL;\r
174         \r
175         return 0;\r
176 }\r
177 \r
178 int\r
179 fstream_free(fstream_t* ptr)\r
180 {\r
181         \r
182         /* check the parameter */\r
183         if(!(*ptr))\r
184     {\r
185         errno = EINVAL;\r
186         return -1;\r
187     }\r
188     \r
189         if(!(*ptr))\r
190                 return EINVAL;\r
191                 \r
192         if((*ptr)->stream)\r
193                 fclose((*ptr)->stream);\r
194         \r
195         if((*ptr)->name)\r
196                 free((*ptr)->name);\r
197         \r
198         if((*ptr)->directory)\r
199                 free((*ptr)->directory);\r
200                 \r
201         free(*ptr);\r
202 \r
203         *ptr = NULL;\r
204         \r
205         return 0;\r
206                 \r
207 }\r
208 \r
209 int\r
210 fstream_parse(fstream_t fstream, xbt_os_mutex_t mutex)\r
211 {\r
212         size_t len;\r
213         char * line = NULL;\r
214         int line_num = 0;\r
215         char file_pos[256];\r
216         xbt_strbuff_t buff;\r
217         int buffbegin = 0; \r
218         context_t context;\r
219         unit_t unit;\r
220         \r
221         /* Count the line length while checking wheather it's blank */\r
222         int blankline;\r
223         int linelen;    \r
224         /* Deal with \ at the end of the line, and call handle_line on result */\r
225         int to_be_continued;\r
226         \r
227         /* check the parameter */\r
228         if(!(fstream) || !mutex)\r
229     {\r
230         errno = EINVAL;\r
231         return -1;\r
232     }\r
233     \r
234         buff = xbt_strbuff_new();\r
235         \r
236         if(!(context = context_new()))\r
237                 return -1;\r
238                 \r
239         unit = fstream->unit;\r
240         \r
241         /*while(!(unit->root->interrupted)  && getline(&line, &len, fstream->stream) != -1)*/\r
242         while(!(unit->root->interrupted)  && fstream_getline(fstream, &line, &len) != -1)\r
243         {\r
244                 \r
245                 blankline=1;\r
246                 linelen = 0;    \r
247                 to_be_continued = 0;\r
248 \r
249                 line_num++;\r
250                 \r
251                 while(line[linelen] != '\0') \r
252                 {\r
253                         if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')\r
254                                 blankline = 0;\r
255                         \r
256                         linelen++;\r
257                 }\r
258         \r
259                 if(blankline) \r
260                 {\r
261                         if(!context->command_line && (context->input->used || context->output->used))\r
262                         {\r
263                                 snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
264                                 ERROR1("[%s] Error : no command found in the last chunk of lines", file_pos);\r
265                                 \r
266                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
267 \r
268                                 failure(unit);\r
269                                 break;\r
270                         }\r
271                         else if(unit->is_running_suite)\r
272                         {/* it's the end of a suite */\r
273                                 \r
274                                 unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
275 \r
276                                 if(!xbt_dynar_length((*current_suite)->includes))\r
277                                 {\r
278                                         ERROR2("[%s] Malformated suite `(%s)' : include missing", file_pos, (*current_suite)->description);\r
279                                 \r
280                                         unit_set_error(*current_suite, ESYNTAX, 1);\r
281 \r
282                                         failure(unit);\r
283                                         \r
284                                 }\r
285                         \r
286                                 unit->is_running_suite = 0;\r
287                         }\r
288                                 \r
289                         if(context->command_line)\r
290                         {\r
291                                 if(fstream_launch_command(fstream, context, mutex) < 0)\r
292                                                 break;\r
293                         }\r
294                 \r
295                         continue;\r
296                 }\r
297                 \r
298                 if(linelen>1 && line[linelen-2]=='\\') \r
299                 {\r
300                         if(linelen>2 && line[linelen-3] == '\\') \r
301                         {\r
302                                 /* Damn. Escaped \ */\r
303                                 line[linelen-2] = '\n';\r
304                                 line[linelen-1] = '\0';\r
305                         } \r
306                         else \r
307                         {\r
308                                 to_be_continued = 1;\r
309                                 line[linelen-2] = '\0';\r
310                                 linelen -= 2;  \r
311                                 \r
312                                 if (!buff->used)\r
313                                         buffbegin = line_num;\r
314                         }\r
315                 }\r
316         \r
317                 if(buff->used || to_be_continued) \r
318                 { \r
319                         xbt_strbuff_append(buff,line);\r
320         \r
321                         if (!to_be_continued) \r
322                         {\r
323                                 snprintf(file_pos,256,"%s:%d",fstream->name, buffbegin);\r
324                                 fstream_lex_line(fstream, context, mutex, file_pos, buff->data);    \r
325                                 xbt_strbuff_empty(buff);\r
326                         }\r
327                 } \r
328                 else \r
329                 {\r
330                         snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
331                         fstream_lex_line(fstream, context, mutex, file_pos, line);      \r
332                 }\r
333         }\r
334         \r
335         /* Check that last command of the file ran well */\r
336         if(context->command_line)\r
337         {\r
338                 if(fstream_launch_command(fstream, context, mutex) < 0)\r
339                         return -1;\r
340         }\r
341         \r
342         /* clear buffers */\r
343         if(line)\r
344                 free(line);\r
345                 \r
346         xbt_strbuff_free(buff); \r
347         \r
348         if(context_free(&context) < 0)\r
349                 return -1;\r
350         \r
351         return (exit_code || errno) ? -1 : 0;\r
352 }\r
353 \r
354 \r
355 void \r
356 fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line) \r
357 {\r
358         char* line2;\r
359         variable_t variable;\r
360         unsigned int i;\r
361         char name[VAR_NAME_MAX + 1] = {0};\r
362         unit_t unit = fstream->unit;\r
363         xbt_dynar_t variables = unit->runner->variables;\r
364 \r
365         if(unit->is_running_suite && strncmp(line, "! include", strlen("! include")))\r
366         {/* it's the end of a suite */\r
367                 \r
368                 unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
369 \r
370                 if(!xbt_dynar_length((*current_suite)->includes))\r
371                         ERROR2("[%s] Malformated suite `(%s)': include missing", filepos, (*current_suite)->description);\r
372                 else\r
373                         ERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos, (*current_suite)->description);\r
374                 \r
375                 unit_set_error(*current_suite, ESYNTAX, 1);\r
376 \r
377                 failure(fstream->unit);\r
378                         \r
379                 \r
380         }\r
381         \r
382         context->line = strdup(filepos);\r
383         \r
384         \r
385         /* search end */\r
386         xbt_str_rtrim(line + 2,"\n");\r
387         \r
388         line2 = strdup(line);\r
389         \r
390         /* replace each variable by its value */\r
391         xbt_os_mutex_acquire(unit->mutex);\r
392 \r
393         xbt_dynar_foreach(variables, i, variable)\r
394         {\r
395                 sprintf(name, "$%s", variable->name);\r
396                 str_replace_all(&line2, name, variable->val);\r
397                 memset(name, 0, VAR_NAME_MAX + 1);\r
398         }\r
399         \r
400         xbt_os_mutex_release(unit->mutex);\r
401 \r
402         \r
403         switch(line2[0]) \r
404         {\r
405                 case '#': \r
406                 break;\r
407                 \r
408                 case '$':\r
409                 case '&':\r
410 \r
411                 if(line[1] != ' ')\r
412                 {\r
413                         \r
414                         if(line2[0] == '$')\r
415                                 ERROR1("[%s] Missing space after `$' `(usage : $ <command>)'", filepos);\r
416                         else\r
417                                 ERROR1("[%s] Missing space after & `(usage : & <command>)'", filepos);\r
418                 \r
419                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
420 \r
421                         failure(unit);\r
422                         return;\r
423                 }\r
424                         \r
425                 context->async = (line2[0] == '&');\r
426 \r
427                 \r
428                 /* further trim useless chars which are significant for in/output */\r
429                 xbt_str_rtrim(line2 + 2," \t");\r
430                 \r
431                 /* deal with CD commands here, not in context */\r
432                 if(!strncmp("cd ",line2 + 2, 3)) \r
433                 {\r
434                         char* dir = strdup(line2 + 4);\r
435                         \r
436                         if(context->command_line)\r
437                         {\r
438                                 if(fstream_launch_command(fstream, context, mutex) < 0)\r
439                                         return;\r
440                         }\r
441                 \r
442                         /* search begining */\r
443                         while(*(dir++) == ' ');\r
444                         \r
445                         dir--;\r
446                         \r
447                         if(!dry_run_flag)\r
448                         {\r
449                                 if(!silent_flag)\r
450                                         INFO2("[%s] cd %s", filepos, dir);\r
451                                 \r
452                                 if(!just_print_flag)\r
453                                 {\r
454                                         if(chdir(dir))\r
455                                         {\r
456                                                 ERROR3("[%s] Chdir to %s failed: %s",filepos, dir,error_to_string(errno, 0));\r
457                                                 unit_set_error(fstream->unit, errno, 0);\r
458 \r
459                                                 failure(unit);\r
460                                         }\r
461                                 }\r
462                         }\r
463                         \r
464                         break;\r
465                 }\r
466                 else\r
467                 {\r
468                         fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);\r
469                         break;\r
470                 }\r
471                 \r
472                 case '<':\r
473                 case '>':\r
474                 case '!':\r
475                 \r
476                 if(line[0] == '!' && line[1] != ' ')\r
477                 {\r
478                         ERROR1("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'", filepos);\r
479                 \r
480                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
481 \r
482                         failure(unit);\r
483                         return;\r
484                 }\r
485 \r
486                 fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);    \r
487                 break;\r
488                 \r
489                 case 'p':\r
490                 \r
491                 {\r
492                         unsigned int j;\r
493                         int is_blank = 1;\r
494                         \r
495                         char* prompt = line2 + 2;\r
496 \r
497                         for(j = 0; j < strlen(prompt); j++) \r
498                                 if (prompt[j] != ' ' && prompt[j] != '\t')\r
499                                         is_blank = 0;\r
500 \r
501                         if(is_blank)\r
502                         {\r
503                                 ERROR1("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'", filepos);\r
504                                 \r
505                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
506 \r
507                                 failure(unit);\r
508                                 return;\r
509                         }\r
510 \r
511                         if(!dry_run_flag)\r
512                                 INFO2("[%s] %s",filepos,prompt);\r
513                 }\r
514 \r
515                 \r
516                 break;\r
517                 \r
518                 case 'P':\r
519                 \r
520                 {\r
521                         unsigned int j;\r
522                         int is_blank = 1;\r
523                                 \r
524                         char* prompt = line2 + 2;\r
525 \r
526                         for(j = 0; j < strlen(prompt); j++) \r
527                                 if (prompt[j] != ' ' && prompt[j] != '\t')\r
528                                         is_blank = 0;\r
529 \r
530                         if(is_blank)\r
531                         {\r
532                                 ERROR1("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'", filepos);\r
533                                 \r
534                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
535 \r
536                                 failure(unit);\r
537                                 return;\r
538                         }\r
539 \r
540                         if(!dry_run_flag)               \r
541                                 CRITICAL2("[%s] %s",filepos, prompt);\r
542                 }\r
543 \r
544                 break;\r
545                 \r
546                 case 'D':\r
547                         if(unit->description)\r
548                                 WARN2("[%s] Description already specified `%s'",filepos, line2 + 2); \r
549                         else\r
550                         {\r
551                                 unsigned int j;\r
552                                 int is_blank = 1;\r
553                                 \r
554                                 char* desc = line2 + 2;\r
555 \r
556                                 for(j = 0; j < strlen(desc); j++) \r
557                                         if (desc[j] != ' ' && desc[j] != '\t')\r
558                                                 is_blank = 0;\r
559 \r
560                                 if(is_blank)\r
561                                 {\r
562                                         ERROR1("[%s] Bad usage of the metacommand D `(usage : D <Description>)'", filepos);\r
563                                         \r
564                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
565 \r
566                                         failure(unit);\r
567                                         return;\r
568                                 }\r
569 \r
570                                 unit->description = strdup(desc);\r
571                         }\r
572                 break;\r
573                 \r
574                 default:\r
575                 ERROR2("[%s] Syntax error `%s'", filepos, line2);\r
576                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
577                 failure(unit);\r
578                 break;\r
579         }\r
580         \r
581         free(line2);\r
582 }\r
583 \r
584 void \r
585 fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* filepos, char token, char *line) \r
586 {\r
587         unit_t unit = fstream->unit;\r
588         \r
589         switch (token) \r
590         {\r
591                 case '$':\r
592                 case '&':\r
593                 \r
594                 if(context->command_line) \r
595                 {\r
596                         \r
597                         if(context->output->used || context->input->used) \r
598                         {\r
599                                 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
600 \r
601                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
602                                 failure(unit);\r
603                                 return;\r
604                         }\r
605                         \r
606                         if(fstream_launch_command(fstream, context, mutex) < 0)\r
607                                         return;\r
608                         \r
609                         VERB1("[%s] More than one command in this chunk of lines",filepos);\r
610                 }\r
611                 \r
612                 {\r
613                         size_t j,\r
614                         is_blank = 1;\r
615 \r
616                         for(j = 0; j < strlen(line); j++) \r
617                                 if (line[j] != ' ' && line[j] != '\t')\r
618                                         is_blank = 0;\r
619 \r
620                         if(is_blank)\r
621                         {\r
622                                 if(token == '$')\r
623                                 ERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'", filepos);\r
624                                 else\r
625                                 ERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'", filepos);\r
626 \r
627                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
628 \r
629                                 failure(unit);\r
630                                 return;\r
631                         }\r
632                 }\r
633                 \r
634                 context->command_line = strdup(line);\r
635                 context->line = /*strdup(filepos)*/ filepos;\r
636                 context->pos = strdup(filepos);\r
637                 break;\r
638                 \r
639                 case '<':\r
640                 xbt_strbuff_append(context->input,line);\r
641                 xbt_strbuff_append(context->input,"\n");\r
642                 break;\r
643                 \r
644                 case '>':\r
645                 xbt_strbuff_append(context->output,line);\r
646                 xbt_strbuff_append(context->output,"\n");\r
647                 break;\r
648                 \r
649                 case '!':\r
650                 \r
651                 if(context->command_line)\r
652                 {\r
653                         if(fstream_launch_command(fstream, context, mutex) < 0)\r
654                                         return;\r
655                 }\r
656                 \r
657                 if(!strncmp(line,"timeout no",strlen("timeout no"))) \r
658                 {\r
659                         VERB1("[%s] (disable timeout)", filepos);\r
660                         context->timeout = INDEFINITE;\r
661                 } \r
662                 else if(!strncmp(line,"timeout ",strlen("timeout "))) \r
663                 {\r
664                         int i = 0;\r
665                         unsigned int j;\r
666                         int is_blank = 1;\r
667                         char* p = line + strlen("timeout ");\r
668 \r
669 \r
670                         for(j = 0; j < strlen(p); j++) \r
671                                 if (p[j] != ' ' && p[j] != '\t')\r
672                                         is_blank = 0;\r
673 \r
674                         if(is_blank)\r
675                         {\r
676                                 ERROR1("[%s] Undefinite timeout value `(usage :timeout <seconds>)'", filepos);\r
677                                 \r
678                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
679 \r
680                                 failure(unit);\r
681                                 return;\r
682                         }\r
683         \r
684                         while(p[i] != '\0')\r
685                         {\r
686                                 if(!isdigit(p[i]))\r
687                                 {\r
688                                         ERROR2("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'", filepos, line + strlen("timeout "));\r
689 \r
690                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
691  \r
692                                         failure(unit);\r
693                                         return;\r
694                                 }\r
695 \r
696                                 i++;\r
697                         }\r
698                         \r
699                         context->timeout = atoi(line + strlen("timeout"));\r
700                         VERB2("[%s] (new timeout value: %d)",filepos,context->timeout);\r
701                 \r
702                 } \r
703                 else if (!strncmp(line,"expect signal ",strlen("expect signal "))) \r
704                 {\r
705                         unsigned int j;\r
706                         int is_blank = 1;\r
707 \r
708                         \r
709                         char* p = line + strlen("expect signal ");\r
710 \r
711 \r
712                         for(j = 0; j < strlen(p); j++) \r
713                                 if (p[j] != ' ' && p[j] != '\t')\r
714                                         is_blank = 0;\r
715 \r
716                         if(is_blank)\r
717                         {\r
718                                 ERROR1("[%s] Undefinite signal name `(usage :expect signal <signal name>)'", filepos);\r
719                                 \r
720                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
721 \r
722                                 failure(unit);\r
723                                 return;\r
724                         }\r
725 \r
726                         context->signal = strdup(line + strlen("expect signal "));\r
727                         \r
728                         xbt_str_trim(context->signal," \n");\r
729 \r
730                         #ifdef WIN32\r
731                         if(!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))\r
732                         {\r
733                                 ERROR2("[%s] Signal `%s' not supported by this platform", filepos, context->signal);\r
734 \r
735                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
736 \r
737 \r
738                                 failure(unit);\r
739                                 return;\r
740                         }\r
741                         #else\r
742                         if(!sig_exists(context->signal))\r
743                         {\r
744                                 ERROR2("[%s] Signal `%s' not supported by Tesh", filepos, context->signal);\r
745                                 \r
746                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
747 \r
748 \r
749                                 failure(unit);\r
750                                 return;\r
751                         }\r
752 \r
753                         #endif\r
754 \r
755                         \r
756                         VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);\r
757                 \r
758                 } \r
759                 else if (!strncmp(line,"expect return ",strlen("expect return "))) \r
760                 {\r
761 \r
762                         int i = 0;\r
763                         unsigned int j;\r
764                         int is_blank = 1;\r
765                         char* p = line + strlen("expect return ");\r
766 \r
767 \r
768                         for(j = 0; j < strlen(p); j++) \r
769                                 if (p[j] != ' ' && p[j] != '\t')\r
770                                         is_blank = 0;\r
771 \r
772                         if(is_blank)\r
773                         {\r
774                                 ERROR1("[%s] Undefinite return value `(usage :expect return <return value>)'", filepos);\r
775                                 \r
776                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
777 \r
778                                 failure(unit);\r
779                                 return;\r
780                         }\r
781                         \r
782                         while(p[i] != '\0')\r
783                         {\r
784                                 if(!isdigit(p[i]))\r
785                                 {\r
786                                         ERROR2("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255",  filepos, line + strlen("expect return "));\r
787 \r
788                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
789 \r
790                                         failure(unit);\r
791                                         return;\r
792                                 }\r
793 \r
794                                 i++;\r
795                         }\r
796 \r
797                         context->exit_code = atoi(line+strlen("expect return "));\r
798                         VERB2("[%s] (next command must return code %d)",filepos, context->exit_code);\r
799                 \r
800                 } \r
801                 else if (!strncmp(line,"output ignore",strlen("output ignore"))) \r
802                 {\r
803                         context->output_handling = oh_ignore;\r
804                         VERB1("[%s] (ignore output of next command)", filepos);\r
805                 \r
806                 } \r
807                 else if (!strncmp(line,"output display",strlen("output display"))) \r
808                 {\r
809                         context->output_handling = oh_display;\r
810                         VERB1("[%s] (ignore output of next command)", filepos);\r
811                 \r
812                 } \r
813                 else if(!strncmp(line,"include ", strlen("include ")))\r
814                 {\r
815                         char* p1;\r
816                         char* p2;\r
817                         \r
818                         p1 = line + strlen("include");\r
819                         \r
820                         while(*p1 == ' ' || *p1 == '\t')\r
821                                 p1++;\r
822                                 \r
823                         \r
824                         if(p1[0] == '\0')\r
825                         {\r
826                                 ERROR1("[%s] no file specified : `(usage : include <file> [<description>])'", filepos);\r
827 \r
828                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
829 \r
830                                 failure(unit);\r
831                                 return;\r
832                         }\r
833                         else\r
834                         {\r
835                                 char file_name[PATH_MAX + 1] = {0};\r
836                                 \r
837                                 p2 = p1;\r
838                                 \r
839                                 while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')\r
840                                         p2++;\r
841                                         \r
842                                 strncpy(file_name, p1, p2 - p1);\r
843                                 \r
844                                 \r
845                                 if(p2[0] != '\0')\r
846                                         while(*p2 == ' ' || *p2 == '\t')\r
847                                                 p2++;\r
848                                         \r
849                                 fstream_handle_include(fstream, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);\r
850                                 \r
851                         }\r
852                 }\r
853                 else if(!strncmp(line,"suite ", strlen("suite ")))\r
854                 {\r
855                         unsigned int j;\r
856                         int is_blank = 1;\r
857                         char* p = line + strlen("suite ");\r
858 \r
859 \r
860                         for(j = 0; j < strlen(p); j++) \r
861                                 if (p[j] != ' ' && p[j] != '\t')\r
862                                         is_blank = 0;\r
863                         \r
864                         if(is_blank)\r
865                         {\r
866                                 ERROR1("[%s] Undefinite suit description : `(usage : suite <description>)", filepos);\r
867 \r
868                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
869 \r
870                                 failure(unit);\r
871                                 return;\r
872                         }\r
873 \r
874                         if(unit->is_running_suite)\r
875                         {\r
876                                 ERROR1("[%s] Suite already in progress", filepos);\r
877 \r
878                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
879 \r
880                                 failure(unit);\r
881                                 return;\r
882                         }\r
883                         \r
884                         fstream_handle_suite(fstream, line + strlen("suite "), filepos);\r
885                 }\r
886                 else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))\r
887                 {\r
888                         unsigned int i, j;\r
889                         int exists = 0;\r
890                         int env = 0;\r
891                         int err = 0;\r
892                         variable_t variable;\r
893                         int is_blank;\r
894 \r
895                         char* name = line + strlen("unsetenv ");\r
896 \r
897                         is_blank = 1;\r
898 \r
899                         for(j = 0; j < strlen(name); j++) \r
900                                 if (name[j] != ' ' && name[j] != '\t')\r
901                                         is_blank = 0;\r
902 \r
903                         if(is_blank)\r
904                         {\r
905                                 ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
906                                 \r
907                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
908 \r
909                                 failure(unit);\r
910                                 return;\r
911                         }\r
912                         \r
913                         xbt_os_mutex_acquire(unit->mutex);\r
914                         \r
915 \r
916                         xbt_dynar_foreach(unit->runner->variables, i, variable)\r
917                         {\r
918                                 if(!strcmp(variable->name, name))\r
919                                 {\r
920                                         env = variable->env;\r
921                                         err = variable->err;\r
922                                         exists = 1;\r
923                                         break;\r
924                                 }\r
925                         }\r
926                                 \r
927                         if(env)\r
928                         {\r
929                                 if(exists)\r
930                                 {\r
931                                         #ifndef WIN32\r
932                                         unsetenv(name);\r
933                                         #else\r
934                                         SetEnvironmentVariable(name, NULL);\r
935                                         #endif\r
936                                         xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
937                                 }\r
938                                 else\r
939                                 {\r
940                                         ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);    \r
941                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
942                                         xbt_os_mutex_release(unit->mutex);\r
943                                         failure(unit);\r
944                                         return;\r
945                                 }\r
946                         }\r
947                         else\r
948                         {\r
949                                 if(exists)\r
950                                 {\r
951                                         if(!err)\r
952                                         {\r
953                                                 ERROR2("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",filepos, name);    \r
954                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
955                                                 failure(unit);\r
956                                                 xbt_os_mutex_release(unit->mutex);\r
957                                                 return;\r
958                                         }\r
959                                         else\r
960                                         {\r
961                                                 ERROR2("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",filepos, name);   \r
962                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
963                                                 xbt_os_mutex_release(unit->mutex);\r
964                                                 failure(unit);\r
965                                                 return;\r
966                                         }\r
967                                 }\r
968                                 else\r
969                                 {\r
970                                         ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);    \r
971                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
972                                         xbt_os_mutex_release(unit->mutex);\r
973                                         failure(unit);\r
974                                         return;\r
975                                 }\r
976                         }\r
977                         \r
978                         xbt_os_mutex_release(unit->mutex);      \r
979                         \r
980                                 \r
981                 }\r
982                 else if(!strncmp(line,"setenv ", strlen("setenv ")))\r
983                 {\r
984                         char* val;\r
985                         char name[PATH_MAX + 1] = {0};\r
986                         char* p;\r
987                         unsigned int i;\r
988                         int is_blank;\r
989                         unsigned int j;\r
990                         \r
991                         p = line + strlen("setenv ");\r
992                         \r
993                         val = strchr(p, '=');\r
994                         \r
995                         if(val)\r
996                         {\r
997                                 variable_t variable;\r
998                                 int exists = 0;\r
999                                 int env = 0;\r
1000                                 int err = 0;\r
1001                                 val++;\r
1002                                 \r
1003                                 /* syntax error */\r
1004                                 if(val[0] == '\0' || val[0] ==' ' || val[0] =='\t')\r
1005                                 {\r
1006                                         ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);  \r
1007 \r
1008                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1009 \r
1010                                         failure(unit);\r
1011                                         return;\r
1012                                 }\r
1013                                 \r
1014                                 \r
1015                                 \r
1016                                 strncpy(name, p, (val - p -1));\r
1017 \r
1018                                 is_blank = 1;\r
1019 \r
1020                                 for(j = 0; j < strlen(name); j++) \r
1021                                         if (name[j] != ' ' && name[j] != '\t')\r
1022                                                 is_blank = 0;\r
1023 \r
1024                                 if(is_blank)\r
1025                                 {\r
1026                                         \r
1027                                         ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
1028                                         \r
1029                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1030 \r
1031                                         failure(unit);\r
1032                                         return;\r
1033                                 }\r
1034                                 \r
1035                                 /* test if the variable is already registred */\r
1036                                 xbt_os_mutex_acquire(unit->mutex);\r
1037 \r
1038                                 xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1039                                 {\r
1040                                         if(!strcmp(variable->name, name))\r
1041                                         {\r
1042                                                 env = variable->env;\r
1043                                                 err = variable->err;\r
1044                                                 exists = 1;\r
1045                                                 break;\r
1046                                         }\r
1047                                 }\r
1048                                 \r
1049                                 /* if the variable is already registred, update its value;\r
1050                                  * otherwise register it.\r
1051                                  */\r
1052                                 if(exists)\r
1053                                 {\r
1054                                         if(env)\r
1055                                         {\r
1056                                                 if(!strcmp(val, variable->val))\r
1057                                                         WARN3("[%s] This environment variable `(%s)' is already set with the value `(%s)'", filepos, name, val);\r
1058 \r
1059                                                 free(variable->val);\r
1060                                                 variable->val = strdup(val);\r
1061 \r
1062                                                 #ifdef WIN32\r
1063                                                 SetEnvironmentVariable(variable->name, variable->val);\r
1064                                                 #else\r
1065                                                 setenv(variable->name, variable->val, 1);\r
1066                                                 #endif\r
1067                                         }\r
1068                                         else\r
1069                                         {\r
1070                                                 if(err)\r
1071                                                         ERROR2("[%s] Conflict : a system variable `(%s)' already exists", filepos, name);\r
1072                                                 else\r
1073                                                         ERROR2("[%s] Conflict : (none environment) variable `(%s)' already exists", filepos, name);     \r
1074 \r
1075                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1076                                                 xbt_os_mutex_release(unit->mutex);\r
1077                                                 failure(unit);\r
1078                                                 return;\r
1079                                         }\r
1080                                 }\r
1081                                 else\r
1082                                 {\r
1083                                         if(err)\r
1084                                         {\r
1085                                                 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
1086                                         \r
1087                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1088                                                 xbt_os_mutex_release(unit->mutex);\r
1089                                                 failure(unit);\r
1090                                                 return;\r
1091                                         }\r
1092                                         else\r
1093                                         {\r
1094                                                 variable = variable_new(name, val);\r
1095                                                 variable->env = 1;\r
1096                                                 \r
1097                                                 xbt_dynar_push(unit->runner->variables, &variable);\r
1098                                                 \r
1099                                                 #ifdef WIN32\r
1100                                                 SetEnvironmentVariable(variable->name, variable->val);\r
1101                                                 #else\r
1102                                                 setenv(variable->name, variable->val, 0);\r
1103                                                 #endif\r
1104                                         }\r
1105                                 }\r
1106                                 \r
1107                                 xbt_os_mutex_release(unit->mutex);\r
1108                                 \r
1109                         }\r
1110                         else\r
1111                         {\r
1112                                 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
1113                                         \r
1114                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1115                                 failure(unit);\r
1116                                 return;\r
1117                         }\r
1118                 }\r
1119                 else if(!strncmp(line,"unset ", strlen("unset ")))\r
1120                 {\r
1121                         unsigned int i, j;\r
1122                         int exists = 0;\r
1123                         int env = 0;\r
1124                         int err = 0;\r
1125                         variable_t variable;\r
1126                         int is_blank;\r
1127 \r
1128                         char* name = line + strlen("unset ");\r
1129 \r
1130                         is_blank = 1;\r
1131 \r
1132                         for(j = 0; j < strlen(name); j++) \r
1133                                 if (name[j] != ' ' && name[j] != '\t')\r
1134                                         is_blank = 0;\r
1135 \r
1136                         if(is_blank)\r
1137                         {\r
1138                                 \r
1139                                 ERROR1("[%s] Bad usage of the metacommand unset `(usage : unset variable)'", filepos);\r
1140                                 \r
1141                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1142 \r
1143                                 failure(unit);\r
1144                                 return;\r
1145                         }\r
1146 \r
1147                         \r
1148                         xbt_os_mutex_acquire(unit->mutex);\r
1149 \r
1150                         xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1151                         {\r
1152                                 if(!strcmp(variable->name, name))\r
1153                                 {\r
1154                                         env = variable->env;\r
1155                                         err = variable->err;\r
1156                                         exists = 1;\r
1157                                         break;\r
1158                                 }\r
1159                         }\r
1160                                 \r
1161                         if(!env && !err)\r
1162                         {\r
1163                                 if(exists)\r
1164                                         /*xbt_dynar_remove_at(unit->runner->variables, i, NULL);*/\r
1165                                         xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
1166                                 else\r
1167                                 {\r
1168                                         ERROR2("[%s] `(%s)' variable not found",filepos, name); \r
1169                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1170                                         xbt_os_mutex_release(unit->mutex);\r
1171                                         failure(unit);\r
1172                                         return;\r
1173                                 }\r
1174                         }\r
1175                         else if(env)\r
1176                         {\r
1177                                 ERROR2("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",filepos, name);  \r
1178                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1179                                 xbt_os_mutex_release(unit->mutex);\r
1180                                 failure(unit);\r
1181                                 return;\r
1182                         }\r
1183                         else if(err)\r
1184                         {\r
1185                                 ERROR2("[%s] `(%s)' is system variable : you can unset it",filepos, name);      \r
1186                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1187                                 xbt_os_mutex_release(unit->mutex);\r
1188                                 failure(unit);\r
1189                                 return;\r
1190                         }\r
1191                         \r
1192                         xbt_os_mutex_release(unit->mutex);\r
1193                                 \r
1194                 }\r
1195                 else if(!strncmp(line,"set ", strlen("set ")))\r
1196                 {\r
1197                         char* val;\r
1198                         char name[PATH_MAX + 1] = {0};\r
1199                         unsigned int j; \r
1200                         int is_blank;\r
1201                         \r
1202                         val = strchr(line + strlen("set "), '=');\r
1203                         \r
1204                         if(val)\r
1205                         {\r
1206                                 variable_t variable;\r
1207                                 int exists = 0;\r
1208                                 unsigned int i;\r
1209                                 int err;\r
1210                                 int env;\r
1211 \r
1212                                 val++;\r
1213                                 \r
1214                                 \r
1215                                 /* syntax error */\r
1216                                 if(val[0] == '\0')\r
1217                                 {\r
1218                                         ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
1219                                         \r
1220                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1221 \r
1222                                         failure(unit);\r
1223                                         return;\r
1224                                 }\r
1225                                 else if(val[0] ==' ' || val[0] =='\t')\r
1226                                 {\r
1227                                         strncpy(name, line + strlen("set "), (val - (line + strlen("set "))));\r
1228 \r
1229                                         ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
1230 \r
1231                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1232 \r
1233                                         failure(unit);\r
1234                                         return;\r
1235                                 }\r
1236                                 \r
1237                                 \r
1238                                 /* assume it's a varibale */\r
1239                                 \r
1240                                 strncpy(name, line + strlen("set "), (val - (line + strlen("set ")) -1));\r
1241                                 \r
1242                                 is_blank = 1;\r
1243 \r
1244                                 for(j = 0; j < strlen(name); j++) \r
1245                                         if (name[j] != ' ' && name[j] != '\t')\r
1246                                                 is_blank = 0;\r
1247 \r
1248                                 if(is_blank)\r
1249                                 {\r
1250                                         \r
1251                                         ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
1252                                         \r
1253                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1254 \r
1255                                         failure(unit);\r
1256                                         return;\r
1257                                 }\r
1258 \r
1259                                 xbt_os_mutex_acquire(unit->mutex);\r
1260                                 \r
1261                                 /* test if the variable is already registred */\r
1262                                 xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1263                                 {\r
1264                                         if(!strcmp(variable->name, name))\r
1265                                         {\r
1266                                                 exists = 1;\r
1267                                                 err = variable->err;\r
1268                                                 env = variable->env;\r
1269                                                 break;\r
1270                                         }\r
1271                                 }\r
1272                                 \r
1273                                 /* if the variable is already registred, update its value (if same value warns);\r
1274                                  * otherwise register it.\r
1275                                  */\r
1276                                 if(exists)\r
1277                                 {\r
1278                                         if(err)\r
1279                                         {\r
1280                                                 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
1281                                         \r
1282                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1283                                                 xbt_os_mutex_release(unit->mutex);\r
1284 \r
1285                                                 failure(unit);\r
1286                                                 return;\r
1287                                         }\r
1288                                         if(env)\r
1289                                         {\r
1290                                                 ERROR2("[%s] `(%s)' is an environment variable use `setenv' instead `set'", filepos, name);\r
1291                                         \r
1292                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1293                                                 xbt_os_mutex_release(unit->mutex);\r
1294 \r
1295                                                 failure(unit);\r
1296                                                 return;\r
1297                                         }\r
1298                                         else\r
1299                                         {\r
1300                                                 if(!strcmp(val, variable->val))\r
1301                                                         WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
1302 \r
1303                                                 free(variable->val);\r
1304                                                 variable->val = strdup(val);\r
1305                                         }\r
1306                                 }\r
1307                                 else\r
1308                                 {\r
1309                                         variable_t new_var = variable_new(name, val);\r
1310                                         xbt_dynar_push(unit->runner->variables, &new_var);\r
1311                                 }\r
1312 \r
1313                                         \r
1314                                 xbt_os_mutex_release(unit->mutex);\r
1315                         }\r
1316                         else\r
1317                         {\r
1318                                 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
1319                                         \r
1320                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1321                                 failure(unit);\r
1322                                 return;\r
1323                         }\r
1324                 }\r
1325                 else\r
1326                 {/* assume it's a variable */\r
1327                         char* val;\r
1328                         char name[PATH_MAX + 1] = {0};\r
1329                         unsigned int i, j; \r
1330                         int is_blank;\r
1331                         \r
1332                         val = strchr(line, '=');\r
1333 \r
1334                         if(val)\r
1335                         {\r
1336                                 variable_t variable;\r
1337                                 int exists = 0;\r
1338                                 int err;\r
1339                                 int env;\r
1340                                 val++;\r
1341                                 \r
1342                                 \r
1343                                 /* syntax error */\r
1344                                 if(val[0] == '\0')\r
1345                                 {\r
1346                                         strncpy(name, line, (val - line -1));\r
1347 \r
1348                                         is_blank = 1;\r
1349 \r
1350                                         for(j = 0; j < strlen(name); j++) \r
1351                                                 if (name[j] != ' ' && name[j] != '\t')\r
1352                                                         is_blank = 0;\r
1353 \r
1354                                         if(is_blank)\r
1355                                                 ERROR1("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'", filepos);\r
1356                                         else if(!strcmp("setenv", name))\r
1357                                                 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
1358                                         else if(!strcmp("set", name))\r
1359                                                 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
1360                                         else\r
1361                                                 ERROR2("[%s] Undefined variable `(%s)'", filepos, name);\r
1362 \r
1363                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1364 \r
1365                                         failure(unit);\r
1366                                         return;\r
1367                                 }\r
1368                                 else if(val[0] ==' ' || val[0] =='\t')\r
1369                                 {\r
1370                                         strncpy(name, line, (val - line));\r
1371 \r
1372                                         ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
1373 \r
1374                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1375 \r
1376                                         failure(unit);   \r
1377                                 }\r
1378                                 \r
1379                                 \r
1380                                 /* assume it's a varibale */\r
1381                                 \r
1382                                 strncpy(name, line, (val - line -1));\r
1383 \r
1384                                 is_blank = 1;\r
1385 \r
1386                                 for(j = 0; j < strlen(name); j++) \r
1387                                         if (name[j] != ' ' && name[j] != '\t')\r
1388                                                 is_blank = 0;\r
1389 \r
1390                                 if(is_blank)\r
1391                                 {\r
1392                                         \r
1393                                         ERROR1("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'", filepos);\r
1394 \r
1395                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1396 \r
1397                                         failure(unit);\r
1398                                         return;\r
1399                                 }\r
1400                                 \r
1401                                 if(!strcmp("set", name))\r
1402                                 {\r
1403                                         ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
1404                                         \r
1405                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1406                                         failure(unit);\r
1407                                         return;\r
1408                                 }\r
1409                                 else if(!strcmp("setenv", name))\r
1410                                 {\r
1411                                         ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
1412                                         \r
1413                                         unit_set_error(fstream->unit, ESYNTAX, 1);\r
1414                                         failure(unit);\r
1415                                         return;\r
1416                                 }\r
1417 \r
1418                                 xbt_os_mutex_acquire(unit->mutex);\r
1419                                 \r
1420                                 /* test if the variable is already registred */\r
1421                                 xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1422                                 {\r
1423                                         if(!strcmp(variable->name, name))\r
1424                                         {\r
1425                                                 exists = 1;\r
1426                                                 err = variable->err;\r
1427                                                 env = variable->env;\r
1428                                                 break;\r
1429                                         }\r
1430                                 }\r
1431                                 \r
1432                                 /* if the variable is already registred, update its value (if same value warns);\r
1433                                  * otherwise register it.\r
1434                                  */\r
1435                                 if(exists)\r
1436                                 {\r
1437                                         if(err)\r
1438                                         {\r
1439                                                 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
1440                                         \r
1441                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1442                                                 xbt_os_mutex_release(unit->mutex);\r
1443                                                 failure(unit);\r
1444                                                 return;\r
1445                                         }\r
1446                                         if(env)\r
1447                                         {\r
1448                                                 ERROR2("[%s] `(%s)' is an environment variable use `setenv' metacommand", filepos, name);\r
1449                                         \r
1450                                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1451                                                 xbt_os_mutex_release(unit->mutex);\r
1452 \r
1453                                                 failure(unit);\r
1454                                                 return;\r
1455                                         }\r
1456                                         else\r
1457                                         {\r
1458                                                 if(!strcmp(val, variable->val))\r
1459                                                         WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
1460 \r
1461                                                 free(variable->val);\r
1462                                                 variable->val = strdup(val);\r
1463                                         }\r
1464                                 }\r
1465                                 else\r
1466                                 {\r
1467                                         variable_t new_var = variable_new(name, val);\r
1468                                         xbt_dynar_push(unit->runner->variables, &new_var);\r
1469                                 }\r
1470 \r
1471                                         \r
1472                                 xbt_os_mutex_release(unit->mutex);\r
1473                                 \r
1474                         }\r
1475                         else \r
1476                         {\r
1477                                 if(!strncmp("setenv", line, strlen("setenv")))\r
1478                                         ERROR1("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'", filepos);\r
1479                                 else if(!strncmp("set", line, strlen("set")))\r
1480                                         ERROR1("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'", filepos);\r
1481                                 else if(!strncmp("unsetenv", line, strlen("unsetenv")))\r
1482                                         ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
1483                                 else if(!strncmp("unset", line, strlen("unset")))\r
1484                                         ERROR1("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'", filepos);\r
1485                                 else if(!strncmp("timeout", line, strlen("timeout")))\r
1486                                         ERROR1("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'", filepos);\r
1487                                 else if(!strncmp("expect signal", line, strlen("expect signal")))\r
1488                                         ERROR1("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'", filepos);\r
1489                                 else if(!strncmp("expect return", line, strlen("expect return")))\r
1490                                         ERROR1("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'", filepos);\r
1491                                 else if(!strncmp("include", line, strlen("include")))\r
1492                                         ERROR1("[%s] Bad usage of the metacommand include  :`(usage : include <file> [<description>])'", filepos);\r
1493                                 else if(!strncmp("suite", line, strlen("suite")))\r
1494                                         ERROR1("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'", filepos);\r
1495                                 else\r
1496                                         ERROR2("[%s] Unknown metacommand: `%s'",filepos,line);\r
1497 \r
1498                                 unit_set_error(fstream->unit, ESYNTAX, 1);\r
1499 \r
1500                                 failure(unit);\r
1501                                 return;\r
1502                         }\r
1503                 }\r
1504                 \r
1505                 break;\r
1506         }\r
1507 }\r
1508 \r
1509 void\r
1510 fstream_handle_include(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)\r
1511 {\r
1512         directory_t dir;\r
1513         char* prev_directory = NULL;\r
1514         fstream_t _fstream = NULL;\r
1515         struct stat buffer = {0};\r
1516         unit_t unit = fstream->unit;\r
1517         \r
1518         if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
1519         {\r
1520                 /* the file is in the current directory */\r
1521                 _fstream = fstream_new(getcwd(NULL, 0), file_name);\r
1522                 fstream_open(_fstream);\r
1523         }\r
1524         /* the file to include is not in the current directory, check if it is in a include directory */\r
1525         else\r
1526         {\r
1527                 unsigned int i;\r
1528                 prev_directory = getcwd(NULL, 0);\r
1529                 \r
1530                 xbt_dynar_foreach(include_dirs, i, dir)\r
1531                 {\r
1532                         chdir(dir->name);\r
1533                         \r
1534                         if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
1535                         {\r
1536                                 _fstream = fstream_new(dir->name, file_name);\r
1537                                 fstream_open(_fstream);\r
1538                                 break;\r
1539                         }\r
1540                 }\r
1541 \r
1542                 chdir(prev_directory);\r
1543                 free(prev_directory);\r
1544         }\r
1545         \r
1546         /* the file to include is not found handle the failure */\r
1547         if(!_fstream)\r
1548         {\r
1549                 if(file_name[0] == '$')\r
1550                 {\r
1551                         ERROR3("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",context->line, file_name, file_name + 1);\r
1552                 \r
1553                 }\r
1554                 else\r
1555                 {\r
1556 \r
1557                         /* may be a variable */\r
1558                         variable_t variable;\r
1559                         int exists = 0;\r
1560                         unsigned int i;\r
1561 \r
1562                         xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1563                         {\r
1564                                 if(!strcmp(variable->name, file_name))\r
1565                                 {\r
1566                                         exists = 1;\r
1567                                         break;\r
1568                                 }\r
1569                         }\r
1570 \r
1571                         if(exists)\r
1572                                 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
1573                         else\r
1574                                 ERROR2("[%s] Include file `(%s)' not found",context->line, file_name);\r
1575                 }\r
1576                 \r
1577                 unit_set_error(fstream->unit, EINCLUDENOTFOUND, 1);\r
1578 \r
1579                 failure(unit);\r
1580         }\r
1581         else\r
1582         {\r
1583                 if(!unit->is_running_suite)\r
1584                 {/* it's the unit of a suite */\r
1585                         unit_t include = unit_new(unit->runner, unit->root, unit, _fstream);\r
1586                         \r
1587                         include->mutex = unit->root->mutex;\r
1588                 \r
1589                         if(description)\r
1590                                 include->description = strdup(description);\r
1591                 \r
1592                         xbt_dynar_push(unit->includes, &include);\r
1593                  \r
1594                         if(!dry_run_flag)\r
1595                                 INFO1("Include from %s", _fstream->name);\r
1596                         else\r
1597                                 INFO1("Checking include %s...",_fstream->name);\r
1598                         \r
1599                         fstream_parse(_fstream, mutex);\r
1600                 }\r
1601                 else\r
1602                 {/* it's a include */\r
1603 \r
1604                         unit_t* owner;\r
1605                         unit_t include;\r
1606 \r
1607                         owner = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
1608                         \r
1609                         include = unit_new(unit->runner, unit->root, *owner, _fstream);\r
1610                         \r
1611                         include->mutex = unit->root->mutex;\r
1612                         \r
1613                         if(description)\r
1614                                 include->description = strdup(description);\r
1615                 \r
1616                         xbt_dynar_push((*owner)->includes, &include);\r
1617                         \r
1618                         if(!dry_run_flag)\r
1619                                 INFO1("Include from %s", _fstream->name);\r
1620                         else\r
1621                                 INFO1("Checking include %s...",_fstream->name);\r
1622                         \r
1623                         fstream_parse(_fstream, mutex);\r
1624                 }\r
1625         }\r
1626 }\r
1627 \r
1628 void\r
1629 fstream_handle_suite(fstream_t fstream, const char* description, const char* filepos)\r
1630 {\r
1631         unit_t unit = fstream->unit;\r
1632         unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);\r
1633         \r
1634         if(description)\r
1635                 suite->description = strdup(description);\r
1636 \r
1637         suite->filepos = strdup(filepos); \r
1638 \r
1639         xbt_dynar_push(unit->suites, &suite);\r
1640         unit->is_running_suite = 1;\r
1641         \r
1642         if(!dry_run_flag)\r
1643                 INFO1("Test suite %s", description);\r
1644         else\r
1645                 INFO1("Checking suite %s...",description);\r
1646         \r
1647 }\r
1648 \r
1649 int\r
1650 fstream_launch_command(fstream_t fstream, context_t context, xbt_os_mutex_t mutex)\r
1651 {\r
1652         unit_t unit = fstream->unit;\r
1653 \r
1654         if(!dry_run_flag)\r
1655         {\r
1656                 command_t command;\r
1657                 \r
1658                 if(!(command = command_new(unit, context, mutex)))\r
1659                 {\r
1660                         if(EINVAL == errno)\r
1661                         {\r
1662                                 ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);   \r
1663 \r
1664                                 unit_set_error(unit, errno, 0);\r
1665                                 failure(unit);\r
1666                                 return -1;\r
1667                         }\r
1668                         else if(ENOMEM == errno)\r
1669                         {\r
1670                                 ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);\r
1671 \r
1672                                 unit_set_error(unit, errno, 0);\r
1673 \r
1674                                 failure(unit);\r
1675                                 return -1;\r
1676                         }\r
1677                 }\r
1678                 \r
1679                 if(command_run(command) < 0)\r
1680                 {\r
1681                         ERROR3("[%s] Cannot run the command `%s' (%d)",context->pos, strerror(errno), errno);   \r
1682                         unit_set_error(unit, errno, 0);\r
1683                         failure(unit);\r
1684                         return -1;      \r
1685                 }\r
1686         }\r
1687         \r
1688         if(context_reset(context) < 0)\r
1689         {\r
1690                 ERROR3("[%s] Cannot reset the context of the command `%s' (%d)",context->pos, strerror(errno), errno);  \r
1691 \r
1692                 unit_set_error(fstream->unit, errno, 0);\r
1693 \r
1694                 failure(unit);\r
1695                 return -1;      \r
1696         }\r
1697         \r
1698         return 0;\r
1699 }\r
1700 \r
1701 \r
1702 \r
1703 \r