Logo AND Algorithmique Numérique Distribuée

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