Logo AND Algorithmique Numérique Distribuée

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