Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last version of tesh
[simgrid.git] / tools / tesh2 / src / fstream.c
1 #include <fstream.h>
2 #include <errno.h>
3 #include <context.h>
4 #include <command.h>
5 #include <unit.h>
6
7 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
8
9 fstream_t
10 fstream_new(const char* directory, const char* name)
11 {
12         fstream_t fstream;
13         
14         if(!name)
15         {
16                 errno = EINVAL;
17                 return NULL;
18         }
19         
20         if(!directory && !strcmp("stdin", name))
21         {
22                 fstream = xbt_new0(s_fstream_t, 1);
23                 fstream->name = strdup("stdin");
24                 return fstream;
25         }
26         else if(!directory)
27         {
28                 errno = EINVAL;
29                 return NULL;
30         }
31         
32         fstream = xbt_new0(s_fstream_t, 1);
33         
34         fstream->name = strdup(name);
35         
36         fstream->directory = strdup(directory);
37         fstream->stream = NULL;
38         
39         
40         return fstream;
41 }
42
43 int
44 fstream_open(fstream_t fstream)
45 {
46         char path[MAX_PATH] = {0};
47         
48         if(!fstream || fstream->stream)
49                 return EINVAL;
50                 
51         if(!strcmp(fstream->name, "stdin"))
52         {
53                 fstream->stream = stdin;
54                 return 0;
55         }
56         
57         sprintf(path,"%s/%s",fstream->directory, fstream->name);
58         
59         if(!(fstream->stream = fopen(path, "r")))
60                 return errno;
61         
62         return 0;
63 }
64
65 int
66 fstream_close(fstream_t fstream)
67 {
68         if(!fstream || !strcmp(fstream->name, "stdin"))
69                 return EINVAL;
70                 
71         if(!fstream->stream)
72                 return EBADF;   
73         
74         fclose(fstream->stream);
75         fstream->stream = NULL;
76         return errno;
77 }
78
79 int
80 fstream_free(void** fstreamptr)
81 {
82         if(!(*fstreamptr))
83                 return EINVAL;
84                 
85         if((*((fstream_t*)fstreamptr))->stream)
86                 fclose((*((fstream_t*)fstreamptr))->stream);
87         
88         free((*((fstream_t*)fstreamptr))->name);
89         
90         if((*((fstream_t*)fstreamptr))->directory)
91                 free((*((fstream_t*)fstreamptr))->directory);
92                 
93         free(*fstreamptr);
94         
95         *fstreamptr = NULL;
96         
97         return 0;
98                 
99 }
100
101 void
102 fstream_parse(fstream_t fstream, unit_t unit, xbt_os_mutex_t mutex)
103 {
104         size_t len;
105         char * line = NULL;
106         int line_num = 0;
107         char file_pos[256];
108         xbt_strbuff_t buff;
109         int buffbegin = 0; 
110         context_t context;
111         
112         /* Count the line length while checking wheather it's blank */
113         int blankline;
114         int linelen;    
115         /* Deal with \ at the end of the line, and call handle_line on result */
116         int to_be_continued;
117         
118         buff=xbt_strbuff_new();
119         context = context_new();
120         
121         while(!(unit->root->interrupted)  && getline(&line, &len, fstream->stream) != -1)
122         {
123                 
124                 blankline=1;
125                 linelen = 0;    
126                 to_be_continued = 0;
127
128                 line_num++;
129                 
130                 while(line[linelen] != '\0') 
131                 {
132                         if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')
133                                 blankline = 0;
134                         
135                         linelen++;
136                 }
137         
138                 if(blankline) 
139                 {
140                         if(!context->command_line && (context->input->used || context->output->used))
141                         {
142                                 ERROR1("[%d] Error: no command found in this chunk of lines.",buffbegin);
143                                 ERROR1("Unit `%s': NOK (syntax error)", fstream->name);
144                         
145                                 
146                                 exit_code = ESYNTAX;
147                                 unit_handle_failure(unit);
148                                 break;
149                         }
150                         else if(unit->running_suite)
151                                 unit->running_suite = 0;
152                                 
153                         
154                         if(context->command_line)
155                         {
156                                 if(!want_dry_run)
157                                 {
158                                         command_t command = command_new(unit, context, mutex);
159                                         command_run(command);
160                                         
161                                 }
162                                 
163                                 context_reset(context);
164                         }
165                 
166                         continue;
167                 }
168                 
169                 if(linelen>1 && line[linelen-2]=='\\') 
170                 {
171                         if(linelen>2 && line[linelen-3] == '\\') 
172                         {
173                                 /* Damn. Escaped \ */
174                                 line[linelen-2] = '\n';
175                                 line[linelen-1] = '\0';
176                         } 
177                         else 
178                         {
179                                 to_be_continued = 1;
180                                 line[linelen-2] = '\0';
181                                 linelen -= 2;  
182                                 
183                                 if (!buff->used)
184                                         buffbegin = line_num;
185                         }
186                 }
187         
188                 if(buff->used || to_be_continued) 
189                 { 
190                         xbt_strbuff_append(buff,line);
191         
192                         if (!to_be_continued) 
193                         {
194                                 snprintf(file_pos,256,"%s:%d",fstream->name, buffbegin);
195                                 unit_handle_line(unit, context, mutex, file_pos, buff->data);    
196                                 xbt_strbuff_empty(buff);
197                         }
198                 } 
199                 else 
200                 {
201                         snprintf(file_pos,256,"%s:%d",fstream->name, line_num);
202                         unit_handle_line(unit, context, mutex, file_pos, line);      
203                 }
204         }
205         
206         
207         
208         /* Check that last command of the file ran well */
209         if(context->command_line)
210         {
211                 if(!want_dry_run)
212                 {
213                         command_t command = command_new(unit, context, mutex);
214                         command_run(command);
215                 }
216                 
217                 context_reset(context);
218         }
219         
220         
221
222         /* Clear buffers */
223         if (line)
224                 free(line);
225                 
226         xbt_strbuff_free(buff); 
227         context_free(&context);
228 }
229
230