Logo AND Algorithmique Numérique Distribuée

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