Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Delete unused -fprofile-arcs flags.
[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 #include <getpath.h>\r
27 \r
28 #ifndef WIN32\r
29 #include <xsignal.h>\r
30 #endif\r
31 \r
32 #ifdef WIN32\r
33 static int\r
34 is_w32_cmd(char* cmd, char** path)\r
35 {\r
36         size_t i = 0;\r
37         struct stat stat_buff = {0};\r
38         char buff[PATH_MAX + 1] = {0};\r
39         \r
40 \r
41 \r
42         if(!cmd)\r
43         {\r
44                 errno = EINVAL;\r
45                 return 0;\r
46         }\r
47         \r
48         if(stat(cmd, &stat_buff) || !S_ISREG(stat_buff.st_mode))\r
49         {\r
50                 if(path)\r
51                 {\r
52                         for (i = 0; path[i] != NULL; i++)\r
53                         {\r
54                                 /* use Cat.exe on Windows */\r
55                                 if(!strcmp(cmd, "cat"))\r
56                                         cmd[0] = 'C';\r
57                                 \r
58                                 sprintf(buff,"%s\\%s",path[i], cmd);\r
59                                 \r
60                                 if(!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))\r
61                                         return 1;\r
62                         }\r
63                 }\r
64         }\r
65         else\r
66                 return 1;\r
67                 \r
68 \r
69         return 0;\r
70 }\r
71 #endif\r
72 \r
73 \r
74 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
75 \r
76 \r
77 long fstream_getline(fstream_t fstream, char **buf, size_t *n) {\r
78 \r
79         return readline(fstream->stream, buf, n);\r
80         \r
81 }\r
82 \r
83 static void\r
84 failure(unit_t unit)\r
85 {\r
86         if(!keep_going_unit_flag)\r
87         {\r
88                 unit_t root = unit->root ? unit->root : unit;\r
89                         \r
90                 if(!root->interrupted)\r
91                 {\r
92                         /* the unit interrupted (exit for the loop) */\r
93                         root->interrupted = 1;\r
94 \r
95                         /* release the unit */\r
96                         xbt_os_sem_release(root->sem);\r
97                 }\r
98 \r
99                 /* if the --keep-going option is not specified */\r
100                 if(!keep_going_flag)\r
101                 {\r
102                         if(!interrupted)\r
103                         {\r
104                                 /* request an global interruption by the runner */\r
105                                 interrupted = 1;\r
106 \r
107                                 /* release the runner */\r
108                                 xbt_os_sem_release(units_sem);\r
109                         }\r
110                 }\r
111         }\r
112 }\r
113 \r
114 fstream_t\r
115 fstream_new(const char* directory, const char* name)\r
116 {\r
117         fstream_t fstream;\r
118         \r
119         if(!name)\r
120         {\r
121                 errno = EINVAL;\r
122                 return NULL;\r
123         }\r
124         \r
125         if(!directory && !strcmp("stdin", name))\r
126         {\r
127                 fstream = xbt_new0(s_fstream_t, 1);\r
128                 fstream->name = strdup("stdin");\r
129                 return fstream;\r
130         }\r
131         else if(!directory)\r
132         {\r
133                 errno = EINVAL;\r
134                 return NULL;\r
135         }\r
136         \r
137         fstream = xbt_new0(s_fstream_t, 1);\r
138         \r
139         if(!(fstream->name = strdup(name)))\r
140         {\r
141                 free(fstream);\r
142                 return NULL;\r
143         }\r
144         \r
145         if(!(fstream->directory = strdup(directory)))\r
146         {\r
147                 free(fstream->name);\r
148                 free(fstream);\r
149                 return NULL;\r
150         }\r
151         \r
152         fstream->stream = NULL;\r
153         fstream->unit = NULL;\r
154         fstream->parsed = 0;\r
155         \r
156         \r
157         return fstream;\r
158 }\r
159 \r
160 int\r
161 fstream_open(fstream_t fstream)\r
162 {\r
163         char path[PATH_MAX + 1] = {0};\r
164         \r
165         /* check the parameter */\r
166         if(!(fstream))\r
167     {\r
168         errno = EINVAL;\r
169         return -1;\r
170     }\r
171         \r
172         if(!fstream || fstream->stream)\r
173         {\r
174                 errno = EALREADY;\r
175                 return -1;\r
176         }\r
177                 \r
178         if(!strcmp(fstream->name, "stdin"))\r
179         {\r
180                 fstream->stream = stdin;\r
181                 return 0;\r
182         }\r
183         \r
184         #ifndef WIN32\r
185         sprintf(path,"%s/%s",fstream->directory, fstream->name);\r
186         #else\r
187         sprintf(path,"%s\\%s",fstream->directory, fstream->name);\r
188     #endif\r
189 \r
190         if(!(fstream->stream = fopen(path, "r")))\r
191         {\r
192                 return -1;\r
193         }\r
194         \r
195         return 0;\r
196 }\r
197 \r
198 int\r
199 fstream_close(fstream_t fstream)\r
200 {\r
201         /* check the parameter */\r
202         if(!(fstream) || !strcmp(fstream->name, "stdin") )\r
203     {\r
204         errno = EINVAL;\r
205         return -1;\r
206     }\r
207                 \r
208         if(!fstream->stream)\r
209                 return EBADF;   \r
210         \r
211         if(EOF == fclose(fstream->stream))\r
212                 return -1;\r
213                 \r
214         fstream->stream = NULL;\r
215         \r
216         return 0;\r
217 }\r
218 \r
219 int\r
220 fstream_free(fstream_t* ptr)\r
221 {\r
222         \r
223         /* check the parameter */\r
224         if(!(*ptr))\r
225     {\r
226         errno = EINVAL;\r
227         return -1;\r
228     }\r
229     \r
230         if(!(*ptr))\r
231                 return EINVAL;\r
232                 \r
233         if((*ptr)->stream)\r
234                 fclose((*ptr)->stream);\r
235         \r
236         if((*ptr)->name)\r
237                 free((*ptr)->name);\r
238         \r
239         if((*ptr)->directory)\r
240                 free((*ptr)->directory);\r
241                 \r
242         free(*ptr);\r
243 \r
244         *ptr = NULL;\r
245         \r
246         return 0;\r
247                 \r
248 }\r
249 \r
250 int\r
251 fstream_parse(fstream_t fstream, xbt_os_mutex_t mutex)\r
252 {\r
253         size_t len;\r
254         char * line = NULL;\r
255         int line_num = 0;\r
256         char file_pos[256];\r
257         xbt_strbuff_t buff;\r
258         int buffbegin = 0; \r
259         context_t context;\r
260         unit_t unit;\r
261         \r
262         /* Count the line length while checking wheather it's blank */\r
263         int blankline;\r
264         int linelen;    \r
265         /* Deal with \ at the end of the line, and call handle_line on result */\r
266         int to_be_continued;\r
267         \r
268         /* check the parameter */\r
269         if(!(fstream) || !mutex)\r
270     {\r
271         errno = EINVAL;\r
272         return -1;\r
273     }\r
274     \r
275         buff = xbt_strbuff_new();\r
276         \r
277         if(!(context = context_new()))\r
278                 return -1;\r
279                 \r
280         unit = fstream->unit;\r
281         \r
282         /*while(!(unit->root->interrupted)  && getline(&line, &len, fstream->stream) != -1)*/\r
283         while(!(unit->root->interrupted)  && fstream_getline(fstream, &line, &len) != -1)\r
284         {\r
285                 \r
286                 blankline=1;\r
287                 linelen = 0;    \r
288                 to_be_continued = 0;\r
289 \r
290                 line_num++;\r
291                 \r
292                 while(line[linelen] != '\0') \r
293                 {\r
294                         if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')\r
295                                 blankline = 0;\r
296                         \r
297                         linelen++;\r
298                 }\r
299         \r
300                 if(blankline) \r
301                 {\r
302                         if(!context->command_line && (context->input->used || context->output->used))\r
303                         {\r
304                                 snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
305                                 ERROR1("[%s] Error : no command found in the last chunk of lines", file_pos);\r
306                                 \r
307                                 unit_set_error(fstream->unit, ESYNTAX, 1, file_pos);\r
308 \r
309                                 failure(unit);\r
310                                 break;\r
311                         }\r
312                         else if(unit->is_running_suite)\r
313                         {/* it's the end of a suite */\r
314                                 \r
315                                 unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
316 \r
317                                 if(!xbt_dynar_length((*current_suite)->includes))\r
318                                 {\r
319                                         ERROR2("[%s] Malformated suite `(%s)' : include missing", file_pos, (*current_suite)->description);\r
320                                 \r
321                                         unit_set_error(*current_suite, ESYNTAX, 1, file_pos);\r
322 \r
323                                         failure(unit);\r
324                                         \r
325                                 }\r
326                         \r
327                                 unit->is_running_suite = 0;\r
328                         }\r
329                                 \r
330                         if(context->command_line)\r
331                         {\r
332                                 #ifdef WIN32\r
333                                 if(!context->is_not_found)\r
334                                 {\r
335                                 #endif\r
336                                 if(fstream_launch_command(fstream, context, mutex) < 0)\r
337                                                 break;\r
338 \r
339                                 #ifdef WIN32\r
340                                 }\r
341                                 #endif\r
342                         }\r
343                 \r
344                         continue;\r
345                 }\r
346                 \r
347                 if(linelen>1 && line[linelen-2]=='\\') \r
348                 {\r
349                         if(linelen>2 && line[linelen-3] == '\\') \r
350                         {\r
351                                 /* Damn. Escaped \ */\r
352                                 line[linelen-2] = '\n';\r
353                                 line[linelen-1] = '\0';\r
354                         } \r
355                         else \r
356                         {\r
357                                 to_be_continued = 1;\r
358                                 line[linelen-2] = '\0';\r
359                                 linelen -= 2;  \r
360                                 \r
361                                 if (!buff->used)\r
362                                         buffbegin = line_num;\r
363                         }\r
364                 }\r
365         \r
366                 if(buff->used || to_be_continued) \r
367                 { \r
368                         xbt_strbuff_append(buff,line);\r
369         \r
370                         if (!to_be_continued) \r
371                         {\r
372                                 snprintf(file_pos,256,"%s:%d",fstream->name, buffbegin);\r
373                                 fstream_lex_line(fstream, context, mutex, file_pos, buff->data);    \r
374                                 xbt_strbuff_empty(buff);\r
375                         }\r
376                 } \r
377                 else \r
378                 {\r
379                         snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
380                         fstream_lex_line(fstream, context, mutex, file_pos, line);      \r
381                 }\r
382         }\r
383         \r
384         /* Check that last command of the file ran well */\r
385         if(context->command_line)\r
386         {\r
387                 #ifdef WIN32\r
388                 if(!context->is_not_found)\r
389                 {\r
390                 #endif\r
391 \r
392                 if(fstream_launch_command(fstream, context, mutex) < 0)\r
393                         return -1;\r
394 \r
395                 #ifdef WIN32\r
396                 }\r
397                 #endif\r
398         }\r
399         \r
400         /* clear buffers */\r
401         if(line)\r
402                 free(line);\r
403                 \r
404         xbt_strbuff_free(buff); \r
405         \r
406         if(context_free(&context) < 0)\r
407                 return -1;\r
408         \r
409         return (exit_code || errno) ? -1 : 0;\r
410 }\r
411 \r
412 \r
413 void \r
414 fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line) \r
415 {\r
416         char* line2;\r
417         variable_t variable;\r
418         unsigned int i;\r
419         char exp[PATH_MAX + 1] = {0};\r
420         unit_t unit = fstream->unit;\r
421         xbt_dynar_t variables = unit->runner->variables;\r
422         char* p= NULL;\r
423         char* end = NULL;\r
424         char* val = NULL;\r
425         char buff[PATH_MAX + 1] = {0}; \r
426         size_t len;\r
427         char delimiters[4] = {' ', '\t', '\n', '\0'}; \r
428         \r
429         int j;\r
430         \r
431         if(line[0] == '#')\r
432                 return;\r
433 \r
434         if(unit->is_running_suite && strncmp(line, "! include", strlen("! include")))\r
435         {/* it's the end of a suite */\r
436                 \r
437                 unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
438 \r
439                 if(!xbt_dynar_length((*current_suite)->includes))\r
440                         ERROR2("[%s] Malformated suite `(%s)': include missing", filepos, (*current_suite)->description);\r
441                 else\r
442                         ERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos, (*current_suite)->description);\r
443                 \r
444                 unit_set_error(*current_suite, ESYNTAX, 1, filepos);\r
445 \r
446                 failure(fstream->unit);\r
447         }\r
448         \r
449         context->line = strdup(filepos);\r
450         \r
451         /* search end */\r
452         xbt_str_rtrim(line + 2,"\n");\r
453         \r
454         line2 = strdup(line);\r
455 \r
456         len = strlen(line2 + 2) + 1;\r
457 \r
458         /* replace each variable by its value */\r
459         xbt_os_mutex_acquire(unit->mutex);\r
460         \r
461 \r
462         /* replace all existing\r
463            ${var}\r
464            ${var:=val}\r
465            ${var:+val}\r
466            ${var:-val}\r
467            ${var:?val}\r
468            ${#var}\r
469    */\r
470         \r
471         xbt_dynar_foreach(variables, i, variable)\r
472         {\r
473                 if(!(p = strstr(line2 + 2, "${")))\r
474                         break;\r
475 \r
476                 memset(buff, 0, len);\r
477 \r
478                 sprintf(buff,"${%s",variable->name);\r
479                 \r
480                 /* FALSE */\r
481                 if((p = strstr(line2 + 2, buff)))\r
482                 {\r
483                         memset(buff, 0, len);\r
484                         p--;\r
485                         j = 0;\r
486 \r
487                         while(*(p++) != '\0')\r
488                         {\r
489                                 buff[j++] = *p;\r
490 \r
491                                 if(*p == '}')\r
492                                         break;\r
493                         }\r
494 \r
495                         if(buff[j - 1] != '}')\r
496                         {\r
497                                 xbt_os_mutex_release(unit->mutex);      \r
498                                 \r
499                                 \r
500                                 ERROR2("[%s] Syntax error : `%s'.",filepos, p - j);\r
501                                 \r
502                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
503                                 failure(fstream->unit);\r
504                                 return;\r
505                         }\r
506 \r
507                         if((p = strstr(buff , ":=")))\r
508                         {\r
509                                 /* ${var:=val} */\r
510                                 \r
511                                 /* if the value of the variable is empty, update its value by the value*/\r
512                                 p += 2;\r
513                                 \r
514                                 end = strchr(p, '}');\r
515 \r
516                                 if(!end || (end == p))\r
517                                 {\r
518                                         xbt_os_mutex_release(unit->mutex);      \r
519                                 \r
520                                 \r
521                                         ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(buff, "${"));\r
522                                 \r
523                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
524                                         failure(fstream->unit);\r
525                                         return;\r
526                                 }\r
527 \r
528                                 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
529 \r
530                                 strncpy(val, p,(end - p));\r
531                                 \r
532                                 \r
533                                 /* replace the expression by the expression of the value of the variable*/\r
534                                 sprintf(exp, "${%s:=%s}", variable->name, val);\r
535 \r
536                                 if(variable->val)\r
537                                         str_replace_all(&line2, exp, variable->val, NULL);\r
538                                 else\r
539                                 {\r
540                                         str_replace_all(&line2, exp, val, NULL);\r
541 \r
542                                         variable->val = strdup(val);\r
543                                 }\r
544 \r
545                                 memset(exp, 0, VAR_NAME_MAX + 1);\r
546 \r
547                                 if(val)\r
548                                 {\r
549                                         free(val);\r
550                                         val = NULL;\r
551                                 }\r
552 \r
553                         }\r
554                         else if((p = strstr(buff, ":-")))\r
555                         {\r
556                                 /* ${var:-val} */\r
557                                 \r
558                                 /* if the value of the variable is empty, replace the expression by the value */\r
559                                 p += 2;\r
560                                 end = strchr(p, '}');\r
561 \r
562                                 if(!end || (end == p))\r
563                                 {\r
564                                         xbt_os_mutex_release(unit->mutex);      \r
565                                 \r
566                                         ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
567                                 \r
568                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
569                                         failure(fstream->unit);\r
570                                         return;\r
571                                 }\r
572 \r
573                                 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
574 \r
575                                 strncpy(val, p,(end - p)); \r
576 \r
577                                 sprintf(exp, "${%s:-%s}", variable->name, val);\r
578                                 \r
579                                 str_replace_all(&line2, exp, variable->val ? variable->val : val, NULL);\r
580                                 \r
581 \r
582                                 memset(exp, 0, VAR_NAME_MAX + 1);\r
583                                 \r
584                                 if(val)\r
585                                 {\r
586                                         free(val);\r
587                                         val = NULL;\r
588                                 }\r
589 \r
590                         }\r
591                         else if((p = strstr(buff, ":+")))\r
592                         {\r
593                                 /* ${var:+val} */\r
594         \r
595                                 /* if the value of the variable is not empty, replace the expression by the value */\r
596                                 p += 2;\r
597 \r
598                                 end = strchr(p, '}');\r
599 \r
600                                 if(!end || (end == p))\r
601                                 {\r
602                                         xbt_os_mutex_release(unit->mutex);      \r
603                                 \r
604                                 \r
605                                         ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
606                                 \r
607                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
608                                         failure(fstream->unit);\r
609                                         return;\r
610                                 }\r
611 \r
612                                 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
613 \r
614                                 strncpy(val, p,(end - p));\r
615 \r
616                                 sprintf(exp, "${%s:+%s}", variable->name, val);\r
617 \r
618                                 if(variable->val)\r
619                                 {\r
620                                         str_replace_all(&line2, exp, val, NULL);\r
621                                 }\r
622                                 else\r
623                                 {\r
624                                         str_replace_all(&line2, exp, NULL , NULL);\r
625                                         variable->val = strdup(val);\r
626                                 }\r
627                                 \r
628                                 memset(exp, 0, VAR_NAME_MAX + 1);\r
629                                 \r
630                                 if(val)\r
631                                 {\r
632                                         free(val);\r
633                                         val = NULL;\r
634                                 }\r
635                         }\r
636                         else if((p = strstr(buff, ":?")))\r
637                         {\r
638                                 /*  ${var:?val} */\r
639         \r
640                                 /* if the value of the variable is not empty, replace the expression by the value */\r
641                                 p += 2;\r
642                                 end = strchr(p, '}');\r
643 \r
644                                 if(!end || (end == p))\r
645                                 {\r
646                                         xbt_os_mutex_release(unit->mutex);      \r
647                                 \r
648                                         ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
649                                 \r
650                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
651                                         failure(fstream->unit);\r
652                                         return;\r
653                                 }\r
654 \r
655                                 val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
656 \r
657                                 strncpy(val, p,(end - p));\r
658 \r
659                                 sprintf(exp, "${%s:?%s}", variable->name, val);\r
660                                 \r
661                                 if(variable->val)\r
662                                         str_replace_all(&line2, exp, variable->val, NULL);\r
663                                 else\r
664                                 {\r
665 \r
666                                         xbt_os_mutex_release(unit->mutex);      \r
667 \r
668                                         ERROR2("[%s] %s.",filepos, val);\r
669 \r
670                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
671                                         failure(fstream->unit);\r
672                                         return;\r
673                                 }\r
674                                 \r
675                                 memset(exp, 0, VAR_NAME_MAX + 1);\r
676                                 \r
677                                 if(val)\r
678                                 {\r
679                                         free(val);\r
680                                         val = NULL;\r
681                                 }\r
682                         }\r
683                 }\r
684         }\r
685 \r
686         /* replace all existing $var */\r
687         xbt_dynar_foreach(variables, i, variable)\r
688         {\r
689                 if(!strchr(line2 + 2, '$'))\r
690                         break;\r
691 \r
692                 if(strstr(line2 + 2, variable->name))\r
693                 {\r
694 \r
695                         sprintf(exp, "${#%s}", variable->name);\r
696                         \r
697                         if(strstr(line2 + 2, exp))\r
698                         {\r
699 \r
700                                 if(variable->val)\r
701                                 {\r
702                                         char slen[4] = {0};\r
703                                         sprintf(slen,"%d", (int)strlen(variable->val));\r
704                                         str_replace_all(&line2, exp, slen, NULL);\r
705                                 }\r
706                                 else\r
707                                         str_replace_all(&line2, exp, "0", NULL);\r
708                         }\r
709 \r
710                         memset(exp, 0, VAR_NAME_MAX + 1);\r
711 \r
712                         sprintf(exp, "${%s}", variable->name);\r
713 \r
714                         if(strstr(line2 + 2, exp))\r
715                         {\r
716                                 if(variable->val)\r
717                                         str_replace_all(&line2, exp, variable->val, NULL);\r
718                                 else\r
719                                         str_replace_all(&line2, exp, NULL, NULL);\r
720                         }\r
721 \r
722                         memset(exp, 0, VAR_NAME_MAX + 1);\r
723 \r
724                         sprintf(exp, "$%s", variable->name);\r
725                         \r
726                         if((p = strstr(line2 + 2, exp)))\r
727                         {\r
728                                 if((p + strlen(variable->name) + 1)[0] != '\0' && !(isalpha((p + strlen(variable->name) + 1)[0])))\r
729                                         delimiters[0] = (p + strlen(variable->name) + 1)[0];\r
730 \r
731                                 if(variable->val)\r
732                                         str_replace_all(&line2, exp, variable->val,  delimiters);\r
733                                 else\r
734                                         str_replace_all(&line2, exp, NULL, delimiters);\r
735                         }\r
736 \r
737                         memset(exp, 0, VAR_NAME_MAX + 1);\r
738 \r
739                 }\r
740         }\r
741 \r
742         while((p = strstr(line2 + 2, "${")))\r
743         {\r
744                 /*if(*(p+1) != '{')\r
745                 {\r
746                         j = 0;\r
747                         p --;\r
748 \r
749                         while(*(p++) != '\0')\r
750                         {\r
751                                 if(*p != ' ' && *p !='\t')\r
752                                         exp[j++] = *p;\r
753                                 else\r
754                                         break;\r
755 \r
756                         }\r
757                         \r
758                         str_replace_all(&line2, exp, NULL, " \t\n\r");\r
759                         memset(exp, 0, VAR_NAME_MAX + 1);\r
760                 }.\r
761                 else\r
762                 */\r
763                 {\r
764                         char* begin = NULL;\r
765                         \r
766                         j = 0;\r
767                         p --;\r
768 \r
769                         while(*(p++) != '\0')\r
770                         {\r
771                                 if((!begin && *p != ' ' && *p !='\t') || begin)\r
772                                 {\r
773                                         /* `:' must be before this caracter, bad substitution : exit loop \r
774                                             ||\r
775                                                 the current character is already present, bad substitution : exit loop\r
776                                                 */\r
777                                         if(\r
778                                                         (\r
779                                                                 *(p - 1) != ':' && (\r
780                                                                                                                 (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')\r
781                                                                                                         )\r
782                                                         )\r
783                                                 || \r
784                                                         (\r
785                                                                 begin &&        (\r
786                                                                                                 (*p == ':') || (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')\r
787                                                                                         )\r
788                                                         )\r
789                                                 )\r
790                                                 break;\r
791                                         else\r
792                                                 exp[j++] = *p;\r
793 \r
794                                         if(*p == ':')\r
795                                         {\r
796                                                 /* save the begining of the value */\r
797                                                 if((*(p+1) == '=') || (*(p+1) == '-') || (*(p+1) == '+') || (*(p+1) == '?'))\r
798                                                 {\r
799                                                         begin = p + 2;\r
800                                                         exp[j++] = *(p+1);\r
801                                                         p++;\r
802                                                         continue;\r
803 \r
804                                                 }\r
805                                                 else\r
806                                                 /* the current char is `:' but the next is invalid, bad substitution : exit loop */\r
807                                                         break;\r
808                                         }\r
809                                         /* end of the substitution : exit loop */\r
810                                         else if(*p == '}')\r
811                                                 break;\r
812                                 }\r
813                                 else\r
814                                         break;\r
815                         }\r
816                         \r
817                         if(exp[j - 1] == '}')\r
818                         {\r
819                                 if(exp[2] == '#')\r
820                                 {\r
821                                         /* ${#var} */\r
822 \r
823 \r
824                                         if(4 == strlen(exp))\r
825                                         {\r
826                                                 xbt_os_mutex_release(unit->mutex);      \r
827                                         \r
828                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
829                                         \r
830                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
831                                                 failure(fstream->unit);\r
832                                                 return;\r
833                                         }\r
834                                         \r
835                                         str_replace_all(&line2, exp, "0", NULL);        \r
836                                 }\r
837                                 else if(strstr(exp,":="))\r
838                                 {\r
839                                         /* ${var:=value} */     \r
840                                         \r
841                                         end = strchr(p, '}');\r
842 \r
843                                         if(!end || (end == begin))\r
844                                         {\r
845                                                 xbt_os_mutex_release(unit->mutex);      \r
846                                         \r
847                                         \r
848                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
849                                         \r
850                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
851                                                 failure(fstream->unit);\r
852                                                 return;\r
853                                         }\r
854 \r
855                                         variable = xbt_new0(s_variable_t, 1);\r
856 \r
857                                         variable->val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
858 \r
859                                         strncpy(variable->val, begin ,(end - begin));\r
860 \r
861                                         begin = exp + 2;\r
862                                         end = strchr(exp, ':');\r
863 \r
864                                         if(!end || (end == begin))\r
865                                         {\r
866                                                 xbt_os_mutex_release(unit->mutex);      \r
867                                         \r
868                                         \r
869                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
870                                         \r
871                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
872                                                 failure(fstream->unit);\r
873                                                 return;\r
874                                         }\r
875 \r
876                                         variable->name = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
877 \r
878                                         strncpy(variable->name, exp + 2 ,(end - begin));\r
879 \r
880                                         str_replace_all(&line2, exp, variable->val, NULL);\r
881 \r
882                                         xbt_dynar_push(variables, &variable);\r
883 \r
884                                 }\r
885                                 else if(strstr(exp,":-"))\r
886                                 {\r
887                                         /* ${var:-value} */     \r
888 \r
889                                         \r
890                                         end = strchr(p, '}');\r
891 \r
892                                         if(!end || (end == begin))\r
893                                         {\r
894                                                 xbt_os_mutex_release(unit->mutex);      \r
895                                         \r
896                                         \r
897                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
898                                         \r
899                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
900                                                 failure(fstream->unit);\r
901                                                 return;\r
902                                         }\r
903 \r
904                                         val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
905 \r
906                                         strncpy(val, begin ,(end - begin));\r
907 \r
908                                         str_replace_all(&line2, exp, val, NULL);\r
909 \r
910                                         if(val)\r
911                                                 free(val);\r
912 \r
913                                 }\r
914                                 else if(strstr(exp,":+"))\r
915                                 {\r
916                                         /* ${var:+value} */     \r
917 \r
918                                         end = strchr(p, '}');\r
919 \r
920                                         if(!end || (end == begin))\r
921                                         {\r
922                                                 xbt_os_mutex_release(unit->mutex);      \r
923                                         \r
924                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
925                                         \r
926                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
927                                                 failure(fstream->unit);\r
928                                                 return;\r
929                                         }\r
930 \r
931                                         str_replace_all(&line2, exp, NULL, NULL);\r
932                                 }\r
933                                 else if(strstr(exp,":?"))\r
934                                 {\r
935                                         /* ${var:?value} */\r
936                                         \r
937                                         end = strchr(p, '}');\r
938 \r
939                                         if(!end || (end == begin))\r
940                                         {\r
941                                                 xbt_os_mutex_release(unit->mutex);      \r
942                                         \r
943                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
944                                         \r
945                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
946                                                 failure(fstream->unit);\r
947                                                 return;\r
948                                         }\r
949 \r
950                                         val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
951 \r
952                                         strncpy(val, begin ,(end - begin));\r
953 \r
954                                         xbt_os_mutex_release(unit->mutex);      \r
955                                         \r
956                                         ERROR2("[%s] : `%s'.",filepos, val);\r
957 \r
958                                         if(val)\r
959                                                 free(val);\r
960                                         \r
961                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
962                                         failure(fstream->unit);\r
963 \r
964                                         return;\r
965                                         \r
966                                 }\r
967                                 else\r
968                                 {\r
969                                         /* ${var} */\r
970 \r
971                                         if(3 == strlen(exp))\r
972                                         {\r
973                                                 xbt_os_mutex_release(unit->mutex);      \r
974                                         \r
975                                                 ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
976                                         \r
977                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
978                                                 failure(fstream->unit);\r
979                                                 return;\r
980                                         }\r
981 \r
982                                         str_replace_all(&line2, exp, NULL, NULL);\r
983                                         \r
984                                 }\r
985 \r
986                                 memset(exp, 0, VAR_NAME_MAX + 1);\r
987                         }\r
988                         else\r
989                         {\r
990                                 xbt_os_mutex_release(unit->mutex);      \r
991                                 \r
992                                 if(strstr(line2 + 2, "${"))\r
993                                         ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
994                                 else\r
995                                         ERROR2("[%s] Syntax error : `%s'.",filepos, strstr(line2, "${"));\r
996 \r
997                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
998                                 failure(fstream->unit);\r
999                                 return;\r
1000                         }\r
1001 \r
1002                 }\r
1003                 \r
1004         }\r
1005         \r
1006         while(1)\r
1007         {\r
1008                 p = line2 + (line2[0] =='<' ? 4 : 2);\r
1009                 \r
1010                 if((p = strchr(p, '$')))\r
1011                 {\r
1012                         if(*(p+1) != ' ')\r
1013                         {\r
1014                                 j = 0;\r
1015                                 p --;\r
1016 \r
1017                                 while(*(p++) != '\0')\r
1018                                 {\r
1019                                         if(*p != ' ' && *p !='\t')\r
1020                                                 exp[j++] = *p;\r
1021                                         else\r
1022                                                 break;\r
1023 \r
1024                                 }\r
1025                                 \r
1026                                 str_replace_all(&line2, exp, NULL, " \t\n\r");\r
1027                                 memset(exp, 0, VAR_NAME_MAX + 1);\r
1028                         }\r
1029                         else\r
1030                         {\r
1031                                 /* maybe < $ cmd */\r
1032                                 p++;\r
1033                         }\r
1034                 }\r
1035                 else\r
1036                         break;\r
1037         }\r
1038 \r
1039         xbt_os_mutex_release(unit->mutex);      \r
1040         \r
1041         switch(line2[0]) \r
1042         {\r
1043                 /*case '#': \r
1044                 break;\r
1045                 */\r
1046                 \r
1047                 case '$':\r
1048                 case '&':\r
1049 \r
1050                 if(line[1] != ' ')\r
1051                 {\r
1052                         \r
1053                         if(line2[0] == '$')\r
1054                                 ERROR1("[%s] Missing space after `$' `(usage : $ <command>)'", filepos);\r
1055                         else\r
1056                                 ERROR1("[%s] Missing space after & `(usage : & <command>)'", filepos);\r
1057                 \r
1058                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1059 \r
1060                         failure(unit);\r
1061                         return;\r
1062                 }\r
1063                         \r
1064                 context->async = (line2[0] == '&');\r
1065 \r
1066                 \r
1067                 /* further trim useless chars which are significant for in/output */\r
1068                 xbt_str_rtrim(line2 + 2," \t");\r
1069                 \r
1070                 /* deal with CD commands here, not in context */\r
1071                 if(!strncmp("cd ",line2 + 2, 3)) \r
1072                 {\r
1073                         char* dir = strdup(line2 + 4);\r
1074                         \r
1075                         if(context->command_line)\r
1076                         {\r
1077                                 if(fstream_launch_command(fstream, context, mutex) < 0)\r
1078                                         return;\r
1079                         }\r
1080                 \r
1081                         /* search begining */\r
1082                         while(*(dir++) == ' ');\r
1083                         \r
1084                         dir--;\r
1085                         \r
1086                         if(!dry_run_flag)\r
1087                         {\r
1088                                 if(!silent_flag)\r
1089                                         INFO2("[%s] cd %s", filepos, dir);\r
1090                                 \r
1091                                 if(!just_print_flag)\r
1092                                 {\r
1093                                         if(chdir(dir))\r
1094                                         {\r
1095                                                 ERROR3("[%s] Chdir to %s failed: %s",filepos, dir,error_to_string(errno, 0));\r
1096                                                 unit_set_error(fstream->unit, errno, 0, filepos);\r
1097 \r
1098                                                 failure(unit);\r
1099                                         }\r
1100                                 }\r
1101                         }\r
1102                         \r
1103                         break;\r
1104                 }\r
1105                 else\r
1106                 {\r
1107                         fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);\r
1108                         break;\r
1109                 }\r
1110                 \r
1111                 case '<':\r
1112                 case '>':\r
1113                 case '!':\r
1114                 \r
1115                 if(line[0] == '!' && line[1] != ' ')\r
1116                 {\r
1117                         ERROR1("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'", filepos);\r
1118                 \r
1119                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1120 \r
1121                         failure(unit);\r
1122                         return;\r
1123                 }\r
1124 \r
1125                 fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);    \r
1126                 break;\r
1127                 \r
1128                 case 'p':\r
1129                 \r
1130                 {\r
1131                         unsigned int j;\r
1132                         int is_blank = 1;\r
1133                         \r
1134                         char* prompt = line2 + 2;\r
1135 \r
1136                         for(j = 0; j < strlen(prompt); j++)\r
1137                         {\r
1138                                 if (prompt[j] != ' ' && prompt[j] != '\t')\r
1139                                 {\r
1140                                         is_blank = 0;\r
1141                                         break;\r
1142                                 }\r
1143                         }\r
1144 \r
1145                         if(is_blank)\r
1146                         {\r
1147                                 ERROR1("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'", filepos);\r
1148                                 \r
1149                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1150 \r
1151                                 failure(unit);\r
1152                                 return;\r
1153                         }\r
1154 \r
1155                         if(!dry_run_flag)\r
1156                                 INFO2("[%s] %s",filepos,prompt);\r
1157                 }\r
1158 \r
1159                 \r
1160                 break;\r
1161                 \r
1162                 case 'P':\r
1163                 \r
1164                 {\r
1165                         unsigned int j;\r
1166                         int is_blank = 1;\r
1167                                 \r
1168                         char* prompt = line2 + 2;\r
1169 \r
1170                         for(j = 0; j < strlen(prompt); j++) \r
1171                                 if (prompt[j] != ' ' && prompt[j] != '\t')\r
1172                                         is_blank = 0;\r
1173 \r
1174                         if(is_blank)\r
1175                         {\r
1176                                 ERROR1("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'", filepos);\r
1177                                 \r
1178                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1179 \r
1180                                 failure(unit);\r
1181                                 return;\r
1182                         }\r
1183 \r
1184                         if(!dry_run_flag)               \r
1185                                 CRITICAL2("[%s] %s",filepos, prompt);\r
1186                 }\r
1187 \r
1188                 break;\r
1189                 \r
1190                 case 'D':\r
1191                         if(unit->description)\r
1192                                 WARN2("[%s] Description already specified `%s'",filepos, line2 + 2); \r
1193                         else\r
1194                         {\r
1195                                 unsigned int j;\r
1196                                 int is_blank = 1;\r
1197                                 \r
1198                                 char* desc = line2 + 2;\r
1199 \r
1200                                 for(j = 0; j < strlen(desc); j++) \r
1201                                         if (desc[j] != ' ' && desc[j] != '\t')\r
1202                                                 is_blank = 0;\r
1203 \r
1204                                 if(is_blank)\r
1205                                 {\r
1206                                         ERROR1("[%s] Bad usage of the metacommand D `(usage : D <Description>)'", filepos);\r
1207                                         \r
1208                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1209 \r
1210                                         failure(unit);\r
1211                                         return;\r
1212                                 }\r
1213 \r
1214                                 unit->description = strdup(desc);\r
1215                         }\r
1216                 break;\r
1217                 \r
1218                 default:\r
1219                 ERROR2("[%s] Syntax error `%s'", filepos, line2);\r
1220                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1221                 failure(unit);\r
1222                 break;\r
1223         }\r
1224         \r
1225         free(line2);\r
1226 }\r
1227 \r
1228 void \r
1229 fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* filepos, char token, char *line) \r
1230 {\r
1231         unit_t unit = fstream->unit;\r
1232         \r
1233         switch (token) \r
1234         {\r
1235                 case '$':\r
1236                 case '&':\r
1237                 \r
1238                 if(context->command_line) \r
1239                 {\r
1240                         \r
1241                         if(context->output->used || context->input->used) \r
1242                         {\r
1243                                 ERROR2("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",filepos, context->command_line);\r
1244 \r
1245                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1246                                 failure(unit);\r
1247                                 return;\r
1248                         }\r
1249                         \r
1250                         if(fstream_launch_command(fstream, context, mutex) < 0)\r
1251                                         return;\r
1252                         \r
1253                         VERB1("[%s] More than one command in this chunk of lines",filepos);\r
1254                 }\r
1255                 \r
1256                 {\r
1257                         size_t j,\r
1258                         is_blank = 1;\r
1259 \r
1260                         for(j = 0; j < strlen(line); j++) \r
1261                                 if (line[j] != ' ' && line[j] != '\t')\r
1262                                         is_blank = 0;\r
1263 \r
1264                         if(is_blank)\r
1265                         {\r
1266                                 if(token == '$')\r
1267                                 ERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'", filepos);\r
1268                                 else\r
1269                                 ERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'", filepos);\r
1270 \r
1271                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1272 \r
1273                                 failure(unit);\r
1274                                 return;\r
1275                         }\r
1276                 }\r
1277                 \r
1278                 context->command_line = strdup(line);\r
1279 \r
1280                 xbt_str_ltrim(context->command_line," ");\r
1281                 \r
1282                 context->line = /*strdup(filepos)*/ filepos;\r
1283                 context->pos = strdup(filepos);\r
1284                 \r
1285                 #ifdef WIN32\r
1286                 {\r
1287 \r
1288                 /* translate the command line */\r
1289 \r
1290                 char* path = NULL;\r
1291                 char* delimiter;\r
1292                 char command_line[PATH_MAX + 1] = {0};\r
1293                 size_t i = 0;\r
1294                 char* args = NULL;\r
1295 \r
1296                 \r
1297 \r
1298                 /*if(strstr(context->command_line,".exe"))\r
1299                         strcpy(command_line,context->command_line);*/\r
1300                 \r
1301                 {\r
1302                         size_t len;\r
1303                         \r
1304                         size_t j = 0;\r
1305         \r
1306                         len = strlen(context->command_line);\r
1307                         \r
1308                         while(i < len)\r
1309                         {\r
1310                                 if(context->command_line[i] != ' ' && context->command_line[i] != '\t' && context->command_line[i] != '>')\r
1311                                         command_line[j++] = context->command_line[i];\r
1312                                 else\r
1313                                         break;\r
1314                                         \r
1315                                 i++;\r
1316                         }\r
1317                         \r
1318                         if(!strstr(context->command_line,".exe"))\r
1319                                 strcat(command_line,".exe");\r
1320 \r
1321                         args = strdup(context->command_line + i);\r
1322                 }\r
1323                 \r
1324                 if(!is_w32_cmd(command_line, fstream->unit->runner->path) && getpath(command_line, &path) < 0)\r
1325                 {\r
1326                         command_t command;\r
1327 \r
1328                         ERROR3("[%s] `%s' : NOK (%s)", filepos, command_line, error_to_string(ECMDNOTFOUND, 1));\r
1329                         unit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);\r
1330 \r
1331                         context->is_not_found = 1;\r
1332                         \r
1333                         command = command_new(fstream->unit, context, mutex);\r
1334 \r
1335                         command->status = cs_failed;\r
1336                         command->reason = csr_command_not_found;\r
1337 \r
1338                         failure(unit);\r
1339                         \r
1340                         \r
1341                         return;\r
1342                 }\r
1343                 \r
1344                 delimiter = strrchr(command_line,'/');\r
1345 \r
1346                 if(!delimiter)\r
1347                         delimiter = strrchr(command_line,'\\');\r
1348                 \r
1349                 /*free(context->command_line);*/\r
1350                 \r
1351                 \r
1352                 if(path)\r
1353                 {\r
1354                         if(args)\r
1355                         {\r
1356                                 context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + strlen(args) + 2, sizeof(char));\r
1357                                 sprintf(context->t_command_line,"%s\\%s%s",path,delimiter ? delimiter + 1 : command_line, args);\r
1358 \r
1359                                 free(args);\r
1360 \r
1361                         }\r
1362                         else\r
1363                         {\r
1364                                 context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + 2, sizeof(char));\r
1365                                 sprintf(context->t_command_line,"%s\\%s",path,delimiter ? delimiter + 1 : command_line);\r
1366                         }\r
1367                 \r
1368                         free(path);\r
1369                 }\r
1370                 else\r
1371                 {\r
1372                         if(args)\r
1373                         {\r
1374 \r
1375                                 context->t_command_line = (char*)calloc(strlen(command_line) + strlen(args) + 1, sizeof(char));\r
1376                                 sprintf(context->t_command_line,"%s%s",command_line, args);\r
1377 \r
1378                         \r
1379                                 free(args);\r
1380 \r
1381                         }\r
1382                         else\r
1383                         {\r
1384                                 context->t_command_line = (char*)calloc(strlen(command_line) + 1, sizeof(char));\r
1385                                 strcpy(context->t_command_line,command_line);\r
1386                         }\r
1387                 }\r
1388 \r
1389 \r
1390                 }\r
1391                 #endif\r
1392 \r
1393 \r
1394                 break;\r
1395                 \r
1396                 case '<':\r
1397                 xbt_strbuff_append(context->input,line);\r
1398                 xbt_strbuff_append(context->input,"\n");\r
1399                 break;\r
1400                 \r
1401                 case '>':\r
1402                 xbt_strbuff_append(context->output,line);\r
1403                 xbt_strbuff_append(context->output,"\n");\r
1404                 break;\r
1405                 \r
1406                 case '!':\r
1407                 \r
1408                 if(context->command_line)\r
1409                 {\r
1410                         if(fstream_launch_command(fstream, context, mutex) < 0)\r
1411                                         return;\r
1412                 }\r
1413                 \r
1414                 if(!strncmp(line,"timeout no",strlen("timeout no"))) \r
1415                 {\r
1416                         VERB1("[%s] (disable timeout)", filepos);\r
1417                         context->timeout = INDEFINITE;\r
1418                 } \r
1419                 else if(!strncmp(line,"timeout ",strlen("timeout "))) \r
1420                 {\r
1421                         int i = 0;\r
1422                         unsigned int j;\r
1423                         int is_blank = 1;\r
1424                         char* p = line + strlen("timeout ");\r
1425 \r
1426 \r
1427                         for(j = 0; j < strlen(p); j++) \r
1428                                 if (p[j] != ' ' && p[j] != '\t')\r
1429                                         is_blank = 0;\r
1430 \r
1431                         if(is_blank)\r
1432                         {\r
1433                                 ERROR1("[%s] Undefinite timeout value `(usage :timeout <seconds>)'", filepos);\r
1434                                 \r
1435                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1436 \r
1437                                 failure(unit);\r
1438                                 return;\r
1439                         }\r
1440         \r
1441                         while(p[i] != '\0')\r
1442                         {\r
1443                                 if(!isdigit(p[i]))\r
1444                                 {\r
1445                                         ERROR2("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'", filepos, line + strlen("timeout "));\r
1446 \r
1447                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1448  \r
1449                                         failure(unit);\r
1450                                         return;\r
1451                                 }\r
1452 \r
1453                                 i++;\r
1454                         }\r
1455                         \r
1456                         context->timeout = atoi(line + strlen("timeout"));\r
1457                         VERB2("[%s] (new timeout value: %d)",filepos,context->timeout);\r
1458                 \r
1459                 } \r
1460                 else if (!strncmp(line,"expect signal ",strlen("expect signal "))) \r
1461                 {\r
1462                         unsigned int j;\r
1463                         int is_blank = 1;\r
1464 \r
1465                         \r
1466                         char* p = line + strlen("expect signal ");\r
1467 \r
1468 \r
1469                         for(j = 0; j < strlen(p); j++) \r
1470                                 if (p[j] != ' ' && p[j] != '\t')\r
1471                                         is_blank = 0;\r
1472 \r
1473                         if(is_blank)\r
1474                         {\r
1475                                 ERROR1("[%s] Undefinite signal name `(usage :expect signal <signal name>)'", filepos);\r
1476                                 \r
1477                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1478 \r
1479                                 failure(unit);\r
1480                                 return;\r
1481                         }\r
1482 \r
1483                         context->signal = strdup(line + strlen("expect signal "));\r
1484                         \r
1485                         xbt_str_trim(context->signal," \n");\r
1486 \r
1487                         #ifdef WIN32\r
1488                         if(!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))\r
1489                         {\r
1490                                 ERROR2("[%s] Signal `%s' not supported by this platform", filepos, context->signal);\r
1491 \r
1492                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1493 \r
1494 \r
1495                                 failure(unit);\r
1496                                 return;\r
1497                         }\r
1498                         #else\r
1499                         if(!sig_exists(context->signal))\r
1500                         {\r
1501                                 ERROR2("[%s] Signal `%s' not supported by Tesh", filepos, context->signal);\r
1502                                 \r
1503                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1504 \r
1505 \r
1506                                 failure(unit);\r
1507                                 return;\r
1508                         }\r
1509 \r
1510                         #endif\r
1511 \r
1512                         \r
1513                         VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);\r
1514                 \r
1515                 } \r
1516                 else if (!strncmp(line,"expect return ",strlen("expect return "))) \r
1517                 {\r
1518 \r
1519                         int i = 0;\r
1520                         unsigned int j;\r
1521                         int is_blank = 1;\r
1522                         char* p = line + strlen("expect return ");\r
1523 \r
1524 \r
1525                         for(j = 0; j < strlen(p); j++) \r
1526                                 if (p[j] != ' ' && p[j] != '\t')\r
1527                                         is_blank = 0;\r
1528 \r
1529                         if(is_blank)\r
1530                         {\r
1531                                 ERROR1("[%s] Undefinite return value `(usage :expect return <return value>)'", filepos);\r
1532                                 \r
1533                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1534 \r
1535                                 failure(unit);\r
1536                                 return;\r
1537                         }\r
1538                         \r
1539                         while(p[i] != '\0')\r
1540                         {\r
1541                                 if(!isdigit(p[i]))\r
1542                                 {\r
1543                                         ERROR2("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255",  filepos, line + strlen("expect return "));\r
1544 \r
1545                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1546 \r
1547                                         failure(unit);\r
1548                                         return;\r
1549                                 }\r
1550 \r
1551                                 i++;\r
1552                         }\r
1553 \r
1554                         context->exit_code = atoi(line+strlen("expect return "));\r
1555                         VERB2("[%s] (next command must return code %d)",filepos, context->exit_code);\r
1556                 \r
1557                 } \r
1558                 else if (!strncmp(line,"output ignore",strlen("output ignore"))) \r
1559                 {\r
1560                         context->output_handling = oh_ignore;\r
1561                         VERB1("[%s] (ignore output of next command)", filepos);\r
1562                 \r
1563                 } \r
1564                 else if (!strncmp(line,"output display",strlen("output display"))) \r
1565                 {\r
1566                         context->output_handling = oh_display;\r
1567                         VERB1("[%s] (ignore output of next command)", filepos);\r
1568                 \r
1569                 } \r
1570                 else if(!strncmp(line,"include ", strlen("include ")))\r
1571                 {\r
1572                         char* p1;\r
1573                         char* p2;\r
1574                         \r
1575                         p1 = line + strlen("include");\r
1576                         \r
1577                         while(*p1 == ' ' || *p1 == '\t')\r
1578                                 p1++;\r
1579                                 \r
1580                         \r
1581                         if(p1[0] == '\0')\r
1582                         {\r
1583                                 ERROR1("[%s] no file specified : `(usage : include <file> [<description>])'", filepos);\r
1584 \r
1585                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1586 \r
1587                                 failure(unit);\r
1588                                 return;\r
1589                         }\r
1590                         else\r
1591                         {\r
1592                                 char file_name[PATH_MAX + 1] = {0};\r
1593                                 \r
1594                                 p2 = p1;\r
1595                                 \r
1596                                 while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')\r
1597                                         p2++;\r
1598                                         \r
1599                                 strncpy(file_name, p1, p2 - p1);\r
1600                                 \r
1601                                 \r
1602                                 if(p2[0] != '\0')\r
1603                                         while(*p2 == ' ' || *p2 == '\t')\r
1604                                                 p2++;\r
1605                                         \r
1606                                 fstream_handle_include(fstream, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);\r
1607                                 \r
1608                         }\r
1609                 }\r
1610                 else if(!strncmp(line,"suite ", strlen("suite ")))\r
1611                 {\r
1612                         unsigned int j;\r
1613                         int is_blank = 1;\r
1614                         char* p = line + strlen("suite ");\r
1615 \r
1616 \r
1617                         for(j = 0; j < strlen(p); j++) \r
1618                                 if (p[j] != ' ' && p[j] != '\t')\r
1619                                         is_blank = 0;\r
1620                         \r
1621                         if(is_blank)\r
1622                         {\r
1623                                 ERROR1("[%s] Undefinite suit description : `(usage : suite <description>)", filepos);\r
1624 \r
1625                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1626 \r
1627                                 failure(unit);\r
1628                                 return;\r
1629                         }\r
1630 \r
1631                         if(unit->is_running_suite)\r
1632                         {\r
1633                                 ERROR1("[%s] Suite already in progress", filepos);\r
1634 \r
1635                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1636 \r
1637                                 failure(unit);\r
1638                                 return;\r
1639                         }\r
1640                         \r
1641                         fstream_handle_suite(fstream, line + strlen("suite "), filepos);\r
1642                 }\r
1643                 else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))\r
1644                 {\r
1645                         unsigned int i, j;\r
1646                         int exists = 0;\r
1647                         int env = 0;\r
1648                         int err = 0;\r
1649                         variable_t variable;\r
1650                         int is_blank;\r
1651 \r
1652                         char* name = line + strlen("unsetenv ");\r
1653 \r
1654                         is_blank = 1;\r
1655 \r
1656                         for(j = 0; j < strlen(name); j++) \r
1657                                 if (name[j] != ' ' && name[j] != '\t')\r
1658                                         is_blank = 0;\r
1659 \r
1660                         if(is_blank)\r
1661                         {\r
1662                                 ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
1663                                 \r
1664                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1665 \r
1666                                 failure(unit);\r
1667                                 return;\r
1668                         }\r
1669                         \r
1670                         xbt_os_mutex_acquire(unit->mutex);\r
1671                         \r
1672 \r
1673                         xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1674                         {\r
1675                                 if(!strcmp(variable->name, name))\r
1676                                 {\r
1677                                         env = variable->env;\r
1678                                         err = variable->err;\r
1679                                         exists = 1;\r
1680                                         break;\r
1681                                 }\r
1682                         }\r
1683                                 \r
1684                         if(env)\r
1685                         {\r
1686                                 if(exists)\r
1687                                 {\r
1688                                         #ifndef WIN32\r
1689                                         unsetenv(name);\r
1690                                         #else\r
1691                                         SetEnvironmentVariable(name, NULL);\r
1692                                         #endif\r
1693                                         xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
1694                                 }\r
1695                                 else\r
1696                                 {\r
1697                                         ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);    \r
1698                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1699                                         xbt_os_mutex_release(unit->mutex);\r
1700                                         failure(unit);\r
1701                                         return;\r
1702                                 }\r
1703                         }\r
1704                         else\r
1705                         {\r
1706                                 if(exists)\r
1707                                 {\r
1708                                         if(!err)\r
1709                                         {\r
1710                                                 ERROR2("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",filepos, name);    \r
1711                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1712                                                 failure(unit);\r
1713                                                 xbt_os_mutex_release(unit->mutex);\r
1714                                                 return;\r
1715                                         }\r
1716                                         else\r
1717                                         {\r
1718                                                 ERROR2("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",filepos, name);   \r
1719                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1720                                                 xbt_os_mutex_release(unit->mutex);\r
1721                                                 failure(unit);\r
1722                                                 return;\r
1723                                         }\r
1724                                 }\r
1725                                 else\r
1726                                 {\r
1727                                         ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);    \r
1728                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1729                                         xbt_os_mutex_release(unit->mutex);\r
1730                                         failure(unit);\r
1731                                         return;\r
1732                                 }\r
1733                         }\r
1734                         \r
1735                         xbt_os_mutex_release(unit->mutex);      \r
1736                         \r
1737                                 \r
1738                 }\r
1739                 else if(!strncmp(line,"setenv ", strlen("setenv ")))\r
1740                 {\r
1741                         char* val;\r
1742                         char name[PATH_MAX + 1] = {0};\r
1743                         char* p;\r
1744                         unsigned int i;\r
1745                         int is_blank;\r
1746                         unsigned int j;\r
1747                         \r
1748                         p = line + strlen("setenv ");\r
1749                         \r
1750                         val = strchr(p, '=');\r
1751                         \r
1752                         if(val)\r
1753                         {\r
1754                                 variable_t variable;\r
1755                                 int exists = 0;\r
1756                                 int env = 0;\r
1757                                 int err = 0;\r
1758                                 val++;\r
1759                                 \r
1760                                 /* syntax error */\r
1761                                 if(val[0] == '\0' || val[0] ==' ' || val[0] =='\t')\r
1762                                 {\r
1763                                         ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);  \r
1764 \r
1765                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1766 \r
1767                                         failure(unit);\r
1768                                         return;\r
1769                                 }\r
1770                                 \r
1771                                 \r
1772                                 \r
1773                                 strncpy(name, p, (val - p -1));\r
1774 \r
1775                                 is_blank = 1;\r
1776 \r
1777                                 for(j = 0; j < strlen(name); j++) \r
1778                                         if (name[j] != ' ' && name[j] != '\t')\r
1779                                                 is_blank = 0;\r
1780 \r
1781                                 if(is_blank)\r
1782                                 {\r
1783                                         \r
1784                                         ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
1785                                         \r
1786                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1787 \r
1788                                         failure(unit);\r
1789                                         return;\r
1790                                 }\r
1791                                 \r
1792                                 /* test if the variable is already registred */\r
1793                                 xbt_os_mutex_acquire(unit->mutex);\r
1794 \r
1795                                 xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1796                                 {\r
1797                                         if(!strcmp(variable->name, name))\r
1798                                         {\r
1799                                                 env = variable->env;\r
1800                                                 err = variable->err;\r
1801                                                 exists = 1;\r
1802                                                 break;\r
1803                                         }\r
1804                                 }\r
1805                                 \r
1806                                 /* if the variable is already registred, update its value;\r
1807                                  * otherwise register it.\r
1808                                  */\r
1809                                 if(exists)\r
1810                                 {\r
1811                                         if(env)\r
1812                                         {\r
1813                                                 if(!strcmp(val, variable->val))\r
1814                                                         WARN3("[%s] This environment variable `(%s)' is already set with the value `(%s)'", filepos, name, val);\r
1815 \r
1816                                                 free(variable->val);\r
1817                                                 variable->val = strdup(val);\r
1818 \r
1819                                                 #ifdef WIN32\r
1820                                                 SetEnvironmentVariable(variable->name, variable->val);\r
1821                                                 #else\r
1822                                                 setenv(variable->name, variable->val, 1);\r
1823                                                 #endif\r
1824                                         }\r
1825                                         else\r
1826                                         {\r
1827                                                 if(err)\r
1828                                                         ERROR2("[%s] Conflict : a system variable `(%s)' already exists", filepos, name);\r
1829                                                 else\r
1830                                                         ERROR2("[%s] Conflict : (none environment) variable `(%s)' already exists", filepos, name);     \r
1831 \r
1832                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1833                                                 xbt_os_mutex_release(unit->mutex);\r
1834                                                 failure(unit);\r
1835                                                 return;\r
1836                                         }\r
1837                                 }\r
1838                                 else\r
1839                                 {\r
1840                                         if(err)\r
1841                                         {\r
1842                                                 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
1843                                         \r
1844                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1845                                                 xbt_os_mutex_release(unit->mutex);\r
1846                                                 failure(unit);\r
1847                                                 return;\r
1848                                         }\r
1849                                         else\r
1850                                         {\r
1851                                                 variable = variable_new(name, val);\r
1852                                                 variable->env = 1;\r
1853                                                 \r
1854                                                 xbt_dynar_push(unit->runner->variables, &variable);\r
1855                                                 \r
1856                                                 #ifdef WIN32\r
1857                                                 SetEnvironmentVariable(variable->name, variable->val);\r
1858                                                 #else\r
1859                                                 setenv(variable->name, variable->val, 0);\r
1860                                                 #endif\r
1861                                         }\r
1862                                 }\r
1863                                 \r
1864                                 xbt_os_mutex_release(unit->mutex);\r
1865                                 \r
1866                         }\r
1867                         else\r
1868                         {\r
1869                                 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
1870                                         \r
1871                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1872                                 failure(unit);\r
1873                                 return;\r
1874                         }\r
1875                 }\r
1876                 else if(!strncmp(line,"unset ", strlen("unset ")))\r
1877                 {\r
1878                         unsigned int i, j;\r
1879                         int exists = 0;\r
1880                         int env = 0;\r
1881                         int err = 0;\r
1882                         variable_t variable;\r
1883                         int is_blank;\r
1884 \r
1885                         char* name = line + strlen("unset ");\r
1886 \r
1887                         is_blank = 1;\r
1888 \r
1889                         for(j = 0; j < strlen(name); j++) \r
1890                                 if (name[j] != ' ' && name[j] != '\t')\r
1891                                         is_blank = 0;\r
1892 \r
1893                         if(is_blank)\r
1894                         {\r
1895                                 \r
1896                                 ERROR1("[%s] Bad usage of the metacommand unset `(usage : unset variable)'", filepos);\r
1897                                 \r
1898                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1899 \r
1900                                 failure(unit);\r
1901                                 return;\r
1902                         }\r
1903 \r
1904                         \r
1905                         xbt_os_mutex_acquire(unit->mutex);\r
1906 \r
1907                         xbt_dynar_foreach(unit->runner->variables, i, variable)\r
1908                         {\r
1909                                 if(!strcmp(variable->name, name))\r
1910                                 {\r
1911                                         env = variable->env;\r
1912                                         err = variable->err;\r
1913                                         exists = 1;\r
1914                                         break;\r
1915                                 }\r
1916                         }\r
1917                                 \r
1918                         if(!env && !err)\r
1919                         {\r
1920                                 if(exists)\r
1921                                 {\r
1922                                         /*xbt_dynar_remove_at(unit->runner->variables, i, NULL);*/\r
1923                                         /*xbt_dynar_cursor_rm(unit->runner->variables, &i);*/\r
1924                                         if(variable->val)\r
1925                                         {\r
1926                                                 free(variable->val);\r
1927                                                 variable->val = NULL;\r
1928                                         }\r
1929                                         else\r
1930                                         {\r
1931                                                 WARN2("[%s] Variable `(%s)' already unseted",filepos, variable->name);\r
1932                                         }\r
1933                                 }       \r
1934                                 else\r
1935                                 {\r
1936                                         ERROR2("[%s] `(%s)' variable not found",filepos, name); \r
1937                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1938                                         xbt_os_mutex_release(unit->mutex);\r
1939                                         failure(unit);\r
1940                                         return;\r
1941                                 }\r
1942                         }\r
1943                         else if(env)\r
1944                         {\r
1945                                 ERROR2("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",filepos, name);  \r
1946                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1947                                 xbt_os_mutex_release(unit->mutex);\r
1948                                 failure(unit);\r
1949                                 return;\r
1950                         }\r
1951                         else if(err)\r
1952                         {\r
1953                                 ERROR2("[%s] `(%s)' is system variable : you can unset it",filepos, name);      \r
1954                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1955                                 xbt_os_mutex_release(unit->mutex);\r
1956                                 failure(unit);\r
1957                                 return;\r
1958                         }\r
1959                         \r
1960                         xbt_os_mutex_release(unit->mutex);\r
1961                                 \r
1962                 }\r
1963                 else if(!strncmp(line,"set ", strlen("set ")))\r
1964                 {\r
1965                         char* val;\r
1966                         char name[PATH_MAX + 1] = {0};\r
1967                         unsigned int j; \r
1968                         int is_blank;\r
1969                         \r
1970                         val = strchr(line + strlen("set "), '=');\r
1971                         \r
1972                         if(val)\r
1973                         {\r
1974                                 variable_t variable;\r
1975                                 int exists = 0;\r
1976                                 unsigned int i;\r
1977                                 int err;\r
1978                                 int env;\r
1979 \r
1980                                 val++;\r
1981                                 \r
1982                                 \r
1983                                 /* syntax error */\r
1984                                 if(val[0] == '\0')\r
1985                                 {\r
1986                                         ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
1987                                         \r
1988                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
1989 \r
1990                                         failure(unit);\r
1991                                         return;\r
1992                                 }\r
1993                                 else if(val[0] ==' ' || val[0] =='\t')\r
1994                                 {\r
1995                                         strncpy(name, line + strlen("set "), (val - (line + strlen("set "))));\r
1996 \r
1997                                         ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
1998 \r
1999                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2000 \r
2001                                         failure(unit);\r
2002                                         return;\r
2003                                 }\r
2004                                 \r
2005                                 \r
2006                                 /* assume it's a varibale */\r
2007                                 \r
2008                                 strncpy(name, line + strlen("set "), (val - (line + strlen("set ")) -1));\r
2009                                 \r
2010                                 is_blank = 1;\r
2011 \r
2012                                 for(j = 0; j < strlen(name); j++) \r
2013                                         if (name[j] != ' ' && name[j] != '\t')\r
2014                                                 is_blank = 0;\r
2015 \r
2016                                 if(is_blank)\r
2017                                 {\r
2018                                         \r
2019                                         ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
2020                                         \r
2021                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2022 \r
2023                                         failure(unit);\r
2024                                         return;\r
2025                                 }\r
2026 \r
2027                                 xbt_os_mutex_acquire(unit->mutex);\r
2028                                 \r
2029                                 /* test if the variable is already registred */\r
2030                                 xbt_dynar_foreach(unit->runner->variables, i, variable)\r
2031                                 {\r
2032                                         if(!strcmp(variable->name, name))\r
2033                                         {\r
2034                                                 exists = 1;\r
2035                                                 err = variable->err;\r
2036                                                 env = variable->env;\r
2037                                                 break;\r
2038                                         }\r
2039                                 }\r
2040                                 \r
2041                                 /* if the variable is already registred, update its value (if same value warns);\r
2042                                  * otherwise register it.\r
2043                                  */\r
2044                                 if(exists)\r
2045                                 {\r
2046                                         if(err)\r
2047                                         {\r
2048                                                 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
2049                                         \r
2050                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2051                                                 xbt_os_mutex_release(unit->mutex);\r
2052 \r
2053                                                 failure(unit);\r
2054                                                 return;\r
2055                                         }\r
2056                                         if(env)\r
2057                                         {\r
2058                                                 ERROR2("[%s] `(%s)' is an environment variable use `setenv' instead `set'", filepos, name);\r
2059                                         \r
2060                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2061                                                 xbt_os_mutex_release(unit->mutex);\r
2062 \r
2063                                                 failure(unit);\r
2064                                                 return;\r
2065                                         }\r
2066                                         else\r
2067                                         {\r
2068                                                 if(!strcmp(val, variable->val))\r
2069                                                         WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
2070 \r
2071                                                 free(variable->val);\r
2072                                                 variable->val = strdup(val);\r
2073                                         }\r
2074                                 }\r
2075                                 else\r
2076                                 {\r
2077                                         variable_t new_var = variable_new(name, val);\r
2078                                         xbt_dynar_push(unit->runner->variables, &new_var);\r
2079                                 }\r
2080 \r
2081                                         \r
2082                                 xbt_os_mutex_release(unit->mutex);\r
2083                         }\r
2084                         else\r
2085                         {\r
2086                                 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
2087                                         \r
2088                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2089                                 failure(unit);\r
2090                                 return;\r
2091                         }\r
2092                 }\r
2093                 else\r
2094                 {/* assume it's a variable */\r
2095                         char* val;\r
2096                         char name[PATH_MAX + 1] = {0};\r
2097                         unsigned int i, j; \r
2098                         int is_blank;\r
2099                         \r
2100                         val = strchr(line, '=');\r
2101 \r
2102                         if(val)\r
2103                         {\r
2104                                 variable_t variable;\r
2105                                 int exists = 0;\r
2106                                 int err;\r
2107                                 int env;\r
2108                                 val++;\r
2109                                 \r
2110                                 \r
2111                                 /* syntax error */\r
2112                                 if(val[0] == '\0')\r
2113                                 {\r
2114                                         strncpy(name, line, (val - line -1));\r
2115 \r
2116                                         is_blank = 1;\r
2117 \r
2118                                         for(j = 0; j < strlen(name); j++) \r
2119                                                 if (name[j] != ' ' && name[j] != '\t')\r
2120                                                         is_blank = 0;\r
2121 \r
2122                                         if(is_blank)\r
2123                                                 ERROR1("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'", filepos);\r
2124                                         else if(!strcmp("setenv", name))\r
2125                                                 ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
2126                                         else if(!strcmp("set", name))\r
2127                                                 ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
2128                                         else\r
2129                                                 ERROR2("[%s] Undefined variable `(%s)'", filepos, name);\r
2130 \r
2131                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2132 \r
2133                                         failure(unit);\r
2134                                         return;\r
2135                                 }\r
2136                                 else if(val[0] ==' ' || val[0] =='\t')\r
2137                                 {\r
2138                                         strncpy(name, line, (val - line));\r
2139 \r
2140                                         ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
2141 \r
2142                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2143 \r
2144                                         failure(unit);   \r
2145                                 }\r
2146                                 \r
2147                                 \r
2148                                 /* assume it's a varibale */\r
2149                                 \r
2150                                 strncpy(name, line, (val - line -1));\r
2151 \r
2152                                 is_blank = 1;\r
2153 \r
2154                                 for(j = 0; j < strlen(name); j++) \r
2155                                         if (name[j] != ' ' && name[j] != '\t')\r
2156                                                 is_blank = 0;\r
2157 \r
2158                                 if(is_blank)\r
2159                                 {\r
2160                                         \r
2161                                         ERROR1("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'", filepos);\r
2162 \r
2163                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2164 \r
2165                                         failure(unit);\r
2166                                         return;\r
2167                                 }\r
2168                                 \r
2169                                 if(!strcmp("set", name))\r
2170                                 {\r
2171                                         ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
2172                                         \r
2173                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2174                                         failure(unit);\r
2175                                         return;\r
2176                                 }\r
2177                                 else if(!strcmp("setenv", name))\r
2178                                 {\r
2179                                         ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
2180                                         \r
2181                                         unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2182                                         failure(unit);\r
2183                                         return;\r
2184                                 }\r
2185 \r
2186                                 xbt_os_mutex_acquire(unit->mutex);\r
2187                                 \r
2188                                 /* test if the variable is already registred */\r
2189                                 xbt_dynar_foreach(unit->runner->variables, i, variable)\r
2190                                 {\r
2191                                         if(!strcmp(variable->name, name))\r
2192                                         {\r
2193                                                 exists = 1;\r
2194                                                 err = variable->err;\r
2195                                                 env = variable->env;\r
2196                                                 break;\r
2197                                         }\r
2198                                 }\r
2199                                 \r
2200                                 /* if the variable is already registred, update its value (if same value warns);\r
2201                                  * otherwise register it.\r
2202                                  */\r
2203                                 if(exists)\r
2204                                 {\r
2205                                         if(err)\r
2206                                         {\r
2207                                                 ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
2208                                         \r
2209                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2210                                                 xbt_os_mutex_release(unit->mutex);\r
2211                                                 failure(unit);\r
2212                                                 return;\r
2213                                         }\r
2214                                         if(env)\r
2215                                         {\r
2216                                                 ERROR2("[%s] `(%s)' is an environment variable use `setenv' metacommand", filepos, name);\r
2217                                         \r
2218                                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2219                                                 xbt_os_mutex_release(unit->mutex);\r
2220 \r
2221                                                 failure(unit);\r
2222                                                 return;\r
2223                                         }\r
2224                                         else\r
2225                                         {\r
2226                                                 if(!strcmp(val, variable->val))\r
2227                                                         WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
2228 \r
2229                                                 free(variable->val);\r
2230                                                 variable->val = strdup(val);\r
2231                                         }\r
2232                                 }\r
2233                                 else\r
2234                                 {\r
2235                                         variable_t new_var = variable_new(name, val);\r
2236                                         xbt_dynar_push(unit->runner->variables, &new_var);\r
2237                                 }\r
2238 \r
2239                                         \r
2240                                 xbt_os_mutex_release(unit->mutex);\r
2241                                 \r
2242                         }\r
2243                         else \r
2244                         {\r
2245                                 if(!strncmp("setenv", line, strlen("setenv")))\r
2246                                         ERROR1("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'", filepos);\r
2247                                 else if(!strncmp("set", line, strlen("set")))\r
2248                                         ERROR1("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'", filepos);\r
2249                                 else if(!strncmp("unsetenv", line, strlen("unsetenv")))\r
2250                                         ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
2251                                 else if(!strncmp("unset", line, strlen("unset")))\r
2252                                         ERROR1("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'", filepos);\r
2253                                 else if(!strncmp("timeout", line, strlen("timeout")))\r
2254                                         ERROR1("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'", filepos);\r
2255                                 else if(!strncmp("expect signal", line, strlen("expect signal")))\r
2256                                         ERROR1("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'", filepos);\r
2257                                 else if(!strncmp("expect return", line, strlen("expect return")))\r
2258                                         ERROR1("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'", filepos);\r
2259                                 else if(!strncmp("include", line, strlen("include")))\r
2260                                         ERROR1("[%s] Bad usage of the metacommand include  :`(usage : include <file> [<description>])'", filepos);\r
2261                                 else if(!strncmp("suite", line, strlen("suite")))\r
2262                                         ERROR1("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'", filepos);\r
2263                                 else\r
2264                                         ERROR2("[%s] Unknown metacommand: `%s'",filepos,line);\r
2265 \r
2266                                 unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
2267 \r
2268                                 failure(unit);\r
2269                                 return;\r
2270                         }\r
2271                 }\r
2272                 \r
2273                 break;\r
2274         }\r
2275 }\r
2276 \r
2277 void\r
2278 fstream_handle_include(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)\r
2279 {\r
2280         directory_t dir;\r
2281         char* prev_directory = NULL;\r
2282         fstream_t _fstream = NULL;\r
2283         struct stat buffer = {0};\r
2284         unit_t unit = fstream->unit;\r
2285         \r
2286         if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
2287         {\r
2288                 /* the file is in the current directory */\r
2289                 _fstream = fstream_new(getcwd(NULL, 0), file_name);\r
2290                 fstream_open(_fstream);\r
2291         }\r
2292         /* the file to include is not in the current directory, check if it is in a include directory */\r
2293         else\r
2294         {\r
2295                 unsigned int i;\r
2296                 prev_directory = getcwd(NULL, 0);\r
2297                 \r
2298                 xbt_dynar_foreach(include_dirs, i, dir)\r
2299                 {\r
2300                         chdir(dir->name);\r
2301                         \r
2302                         if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
2303                         {\r
2304                                 _fstream = fstream_new(dir->name, file_name);\r
2305                                 fstream_open(_fstream);\r
2306                                 break;\r
2307                         }\r
2308                 }\r
2309 \r
2310                 chdir(prev_directory);\r
2311                 free(prev_directory);\r
2312         }\r
2313         \r
2314         /* the file to include is not found handle the failure */\r
2315         if(!_fstream)\r
2316         {\r
2317                 if(file_name[0] == '$')\r
2318                 {\r
2319                         ERROR3("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",context->line, file_name, file_name + 1);\r
2320                 \r
2321                 }\r
2322                 else\r
2323                 {\r
2324                         /* may be a variable */\r
2325                         variable_t variable;\r
2326                         int exists = 0;\r
2327                         unsigned int i;\r
2328 \r
2329                         xbt_dynar_foreach(unit->runner->variables, i, variable)\r
2330                         {\r
2331                                 if(!strcmp(variable->name, file_name))\r
2332                                 {\r
2333                                         exists = 1;\r
2334                                         break;\r
2335                                 }\r
2336                         }\r
2337 \r
2338                         if(exists)\r
2339                                 ERROR3("[%s] Include file `(%s)' not found (if you want to use the variable <%s> add the prefix `$')",context->line, file_name, file_name);\r
2340                         else\r
2341                                 ERROR2("[%s] Include file `(%s)' not found",context->line, file_name);\r
2342                 }\r
2343                 \r
2344                 unit_set_error(fstream->unit, EINCLUDENOTFOUND, 1, context->line);\r
2345 \r
2346                 failure(fstream->unit);\r
2347 \r
2348                 return;\r
2349         }\r
2350         else\r
2351         {\r
2352                 if(!unit->is_running_suite)\r
2353                 {/* it's the unit of a suite */\r
2354                         unit_t include = unit_new(unit->runner, unit->root, unit, _fstream);\r
2355                         \r
2356                         include->mutex = unit->root->mutex;\r
2357                 \r
2358                         if(description)\r
2359                                 include->description = strdup(description);\r
2360                 \r
2361                         xbt_dynar_push(unit->includes, &include);\r
2362                  \r
2363                         if(!dry_run_flag)\r
2364                         {\r
2365                                 if(description)\r
2366                                         INFO2("Include from %s (%s)", _fstream->name, description);\r
2367                                 else\r
2368                                         INFO1("Include from %s", _fstream->name);\r
2369 \r
2370                         }\r
2371                         else\r
2372                                 INFO1("Checking include %s...",_fstream->name);\r
2373                         \r
2374                         fstream_parse(_fstream, mutex);\r
2375                 }\r
2376                 else\r
2377                 {/* it's a include */\r
2378 \r
2379                         unit_t* owner;\r
2380                         unit_t include;\r
2381 \r
2382                         owner = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
2383                         \r
2384                         include = unit_new(unit->runner, unit->root, *owner, _fstream);\r
2385                         \r
2386                         include->mutex = unit->root->mutex;\r
2387                         \r
2388                         if(description)\r
2389                                 include->description = strdup(description);\r
2390                 \r
2391                         xbt_dynar_push((*owner)->includes, &include);\r
2392                         \r
2393                         if(!dry_run_flag)\r
2394                         {\r
2395                                 if(description)\r
2396                                         INFO2("Include from %s (%s)", _fstream->name, description);\r
2397                                 else\r
2398                                         INFO1("Include from %s", _fstream->name);\r
2399                         }\r
2400                         else\r
2401                                 INFO1("Checking include %s...",_fstream->name);\r
2402                         \r
2403                         fstream_parse(_fstream, mutex);\r
2404                 }\r
2405         }\r
2406 }\r
2407 \r
2408 void\r
2409 fstream_handle_suite(fstream_t fstream, const char* description, const char* filepos)\r
2410 {\r
2411         unit_t unit = fstream->unit;\r
2412         unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);\r
2413         \r
2414         if(description)\r
2415                 suite->description = strdup(description);\r
2416 \r
2417         suite->filepos = strdup(filepos); \r
2418 \r
2419         xbt_dynar_push(unit->suites, &suite);\r
2420         unit->is_running_suite = 1;\r
2421         \r
2422         if(!dry_run_flag)\r
2423                 INFO1("Test suite %s", description);\r
2424         else\r
2425                 INFO1("Checking suite %s...",description);\r
2426         \r
2427 }\r
2428 \r
2429 int\r
2430 fstream_launch_command(fstream_t fstream, context_t context, xbt_os_mutex_t mutex)\r
2431 {\r
2432         unit_t unit = fstream->unit;\r
2433 \r
2434         if(!dry_run_flag)\r
2435         {\r
2436                 command_t command;\r
2437                 \r
2438                 if(!(command = command_new(unit, context, mutex)))\r
2439                 {\r
2440                         if(EINVAL == errno)\r
2441                         {\r
2442                                 ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);   \r
2443 \r
2444                                 unit_set_error(unit, errno, 0, context->pos);\r
2445                                 failure(unit);\r
2446                                 return -1;\r
2447                         }\r
2448                         else if(ENOMEM == errno)\r
2449                         {\r
2450                                 ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);\r
2451 \r
2452                                 unit_set_error(unit, errno, 0, context->pos);\r
2453 \r
2454                                 failure(unit);\r
2455                                 return -1;\r
2456                         }\r
2457                 }\r
2458                 \r
2459                 if(command_run(command) < 0)\r
2460                 {\r
2461                         ERROR3("[%s] Cannot run the command `%s' (%d)",context->pos, strerror(errno), errno);   \r
2462                         unit_set_error(unit, errno, 0, context->pos);\r
2463                         failure(unit);\r
2464                         return -1;      \r
2465                 }\r
2466         }\r
2467         \r
2468         if(context_reset(context) < 0)\r
2469         {\r
2470                 ERROR3("[%s] Cannot reset the context of the command `%s' (%d)",context->pos, strerror(errno), errno);  \r
2471 \r
2472                 unit_set_error(fstream->unit, errno, 0, context->pos);\r
2473 \r
2474                 failure(unit);\r
2475                 return -1;      \r
2476         }\r
2477         \r
2478         return 0;\r
2479 }\r
2480 \r
2481 \r
2482 \r
2483 \r