source: mainline/uspace/app/sbi/src/builtin/bi_textfile.c

Last change on this file was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 9.3 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file TextFile builtin binding. */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <assert.h>
34#include "../bigint.h"
35#include "../builtin.h"
36#include "../debug.h"
37#include "../mytypes.h"
38#include "../os/os.h"
39#include "../rdata.h"
40#include "../run.h"
41#include "../strtab.h"
42
43#include "bi_textfile.h"
44
45#define LINE_BUF_SIZE 256
46static char line_buf[LINE_BUF_SIZE];
47
48static void bi_textfile_openread(run_t *run);
49static void bi_textfile_openwrite(run_t *run);
50static void bi_textfile_close(run_t *run);
51static void bi_textfile_readline(run_t *run);
52static void bi_textfile_writeline(run_t *run);
53static void bi_textfile_is_eof(run_t *run);
54
55/** Declare TextFile builtin.
56 *
57 * @param bi Builtin object
58 */
59void bi_textfile_declare(builtin_t *bi)
60{
61 /* Declare class TextFile. */
62
63 builtin_code_snippet(bi,
64 "class TextFile is\n"
65 " var f : resource;\n"
66 "\n"
67 " fun OpenRead(fname : string), builtin;\n"
68 " fun OpenWrite(fname : string), builtin;\n"
69 " fun Close(), builtin;\n"
70 " fun ReadLine() : string, builtin;\n"
71 " fun WriteLine(line : string), builtin;\n"
72 "\n"
73 " prop EOF : bool is\n"
74 " get is\n"
75 " return is_eof();\n"
76 " end\n"
77 " end\n"
78 "\n"
79 " fun is_eof() : bool, builtin;\n"
80 "end\n");
81
82}
83
84/** Bind TextFile builtin.
85 *
86 * @param bi Builtin object
87 */
88void bi_textfile_bind(builtin_t *bi)
89{
90 builtin_fun_bind(bi, "TextFile", "OpenRead", bi_textfile_openread);
91 builtin_fun_bind(bi, "TextFile", "OpenWrite", bi_textfile_openwrite);
92 builtin_fun_bind(bi, "TextFile", "Close", bi_textfile_close);
93 builtin_fun_bind(bi, "TextFile", "ReadLine", bi_textfile_readline);
94 builtin_fun_bind(bi, "TextFile", "WriteLine", bi_textfile_writeline);
95 builtin_fun_bind(bi, "TextFile", "is_eof", bi_textfile_is_eof);
96}
97
98/** Open a text file for reading.
99 *
100 * @param run Runner object
101 */
102static void bi_textfile_openread(run_t *run)
103{
104 rdata_var_t *fname_var;
105 const char *fname;
106 FILE *file;
107
108 rdata_resource_t *resource;
109 rdata_var_t *res_var;
110 rdata_value_t *res_val;
111 rdata_var_t *self_f_var;
112
113#ifdef DEBUG_RUN_TRACE
114 printf("Called TextFile.OpenRead()\n");
115#endif
116 fname_var = run_local_vars_lookup(run, strtab_get_sid("fname"));
117 assert(fname_var);
118 assert(fname_var->vc == vc_string);
119
120 fname = fname_var->u.string_v->value;
121 file = fopen(fname, "rt");
122 if (file == NULL) {
123 printf("Error: Failed opening file '%s' for reading.\n",
124 fname);
125 exit(1);
126 }
127
128 resource = rdata_resource_new();
129 resource->data = (void *) file;
130 res_var = rdata_var_new(vc_resource);
131 res_var->u.resource_v = resource;
132
133 res_val = rdata_value_new();
134 res_val->var = res_var;
135
136 /* Store resource handle into self.f */
137 self_f_var = builtin_get_self_mbr_var(run, "f");
138 rdata_var_write(self_f_var, res_val);
139}
140
141/** Open a text file for writing.
142 *
143 * @param run Runner object
144 */
145static void bi_textfile_openwrite(run_t *run)
146{
147 rdata_var_t *fname_var;
148 const char *fname;
149 FILE *file;
150
151 rdata_resource_t *resource;
152 rdata_var_t *res_var;
153 rdata_value_t *res_val;
154 rdata_var_t *self_f_var;
155
156#ifdef DEBUG_RUN_TRACE
157 printf("Called TextFile.OpenWrite()\n");
158#endif
159 fname_var = run_local_vars_lookup(run, strtab_get_sid("fname"));
160 assert(fname_var);
161 assert(fname_var->vc == vc_string);
162
163 fname = fname_var->u.string_v->value;
164 file = fopen(fname, "wt");
165 if (file == NULL) {
166 printf("Error: Failed opening file '%s' for writing.\n",
167 fname);
168 exit(1);
169 }
170
171 resource = rdata_resource_new();
172 resource->data = (void *) file;
173 res_var = rdata_var_new(vc_resource);
174 res_var->u.resource_v = resource;
175
176 res_val = rdata_value_new();
177 res_val->var = res_var;
178
179 /* Store resource handle into self.f */
180 self_f_var = builtin_get_self_mbr_var(run, "f");
181 rdata_var_write(self_f_var, res_val);
182}
183
184/** Close a text file.
185 *
186 * @param run Runner object
187 */
188static void bi_textfile_close(run_t *run)
189{
190 FILE *file;
191 rdata_var_t *self_f_var;
192 run_proc_ar_t *proc_ar;
193
194 /* Extract pointer to file structure. */
195 self_f_var = builtin_get_self_mbr_var(run, "f");
196 assert(self_f_var->vc == vc_resource);
197 file = (FILE *) self_f_var->u.resource_v->data;
198
199 if (file == NULL) {
200 printf("Error: TextFile not valid for Close.\n");
201 exit(1);
202 }
203
204 /* Close the file. */
205
206#ifdef DEBUG_RUN_TRACE
207 printf("Close text file.\n");
208#endif
209 if (fclose(file) != 0) {
210 printf("Error: I/O error while closing file.\n");
211 exit(1);
212 }
213
214 /* Invalidate the resource handle. */
215 self_f_var->u.resource_v->data = NULL;
216
217 proc_ar = run_get_current_proc_ar(run);
218 proc_ar->retval = NULL;
219}
220
221/** Read one line from a text file.
222 *
223 * @param run Runner object
224 */
225static void bi_textfile_readline(run_t *run)
226{
227 FILE *file;
228 rdata_var_t *self_f_var;
229
230 rdata_string_t *str;
231 rdata_var_t *str_var;
232 rdata_value_t *str_val;
233 rdata_item_t *str_item;
234
235 run_proc_ar_t *proc_ar;
236 char *cp;
237
238 /* Extract pointer to file structure. */
239 self_f_var = builtin_get_self_mbr_var(run, "f");
240 assert(self_f_var->vc == vc_resource);
241 file = (FILE *) self_f_var->u.resource_v->data;
242
243 if (file == NULL) {
244 printf("Error: TextFile not valid for ReadLine.\n");
245 exit(1);
246 }
247
248 /* Check and read. */
249
250 if (feof(file)) {
251 printf("Error: Reading beyond end of file.\n");
252 exit(1);
253 }
254
255 if (fgets(line_buf, LINE_BUF_SIZE, file) == NULL)
256 line_buf[0] = '\0';
257
258 if (ferror(file)) {
259 printf("Error: I/O error while reading file.\n");
260 exit(1);
261 }
262
263 /* Remove trailing newline, if present. */
264
265 cp = line_buf;
266 while (*cp != '\0')
267 ++cp;
268
269 if (cp != line_buf && cp[-1] == '\n')
270 cp[-1] = '\0';
271
272#ifdef DEBUG_RUN_TRACE
273 printf("Read '%s' from file.\n", line_buf);
274#endif
275 /* Construct return value. */
276 str = rdata_string_new();
277 str->value = os_str_dup(line_buf);
278
279 str_var = rdata_var_new(vc_string);
280 str_var->u.string_v = str;
281 str_val = rdata_value_new();
282 str_val->var = str_var;
283
284 str_item = rdata_item_new(ic_value);
285 str_item->u.value = str_val;
286
287 proc_ar = run_get_current_proc_ar(run);
288 proc_ar->retval = str_item;
289}
290
291/** Write one line to a text file.
292 *
293 * @param run Runner object
294 */
295static void bi_textfile_writeline(run_t *run)
296{
297 FILE *file;
298 rdata_var_t *self_f_var;
299 rdata_var_t *line_var;
300 const char *line;
301
302 run_proc_ar_t *proc_ar;
303
304 /* Get 'line' argument. */
305 line_var = run_local_vars_lookup(run, strtab_get_sid("line"));
306 assert(line_var);
307 assert(line_var->vc == vc_string);
308 line = line_var->u.string_v->value;
309
310 /* Extract pointer to file structure. */
311 self_f_var = builtin_get_self_mbr_var(run, "f");
312 assert(self_f_var->vc == vc_resource);
313 file = (FILE *) self_f_var->u.resource_v->data;
314
315 if (file == NULL) {
316 printf("Error: TextFile not valid for WriteLine.\n");
317 exit(1);
318 }
319
320 /* Write and check. */
321
322#ifdef DEBUG_RUN_TRACE
323 printf("Write '%s' to file.\n", line);
324#endif
325 if (fprintf(file, "%s\n", line) < 0) {
326 printf("Error: I/O error while writing file.\n");
327 exit(1);
328 }
329
330 proc_ar = run_get_current_proc_ar(run);
331 proc_ar->retval = NULL;
332}
333
334/** Return value of EOF flag.
335 *
336 * @param run Runner object
337 */
338static void bi_textfile_is_eof(run_t *run)
339{
340 FILE *file;
341 rdata_var_t *self_f_var;
342
343 bool_t eof_flag;
344 rdata_bool_t *eof_bool;
345 rdata_var_t *eof_var;
346 rdata_value_t *eof_val;
347 rdata_item_t *eof_item;
348
349 run_proc_ar_t *proc_ar;
350
351 /* Extract pointer to file structure. */
352 self_f_var = builtin_get_self_mbr_var(run, "f");
353 assert(self_f_var->vc == vc_resource);
354 file = (FILE *) self_f_var->u.resource_v->data;
355
356 if (file == NULL) {
357 printf("Error: TextFile not valid for EOF check.\n");
358 exit(1);
359 }
360
361 /* Get status of EOF flag. */
362
363 eof_flag = feof(file) ? b_true : b_false;
364
365#ifdef DEBUG_RUN_TRACE
366 printf("Read EOF flag '%s'.\n", eof_flag ? "true" : "false");
367#endif
368 /* Construct return value. */
369 eof_bool = rdata_bool_new();
370 eof_bool->value = eof_flag;
371
372 eof_var = rdata_var_new(vc_bool);
373 eof_var->u.bool_v = eof_bool;
374 eof_val = rdata_value_new();
375 eof_val->var = eof_var;
376
377 eof_item = rdata_item_new(ic_value);
378 eof_item->u.value = eof_val;
379
380 proc_ar = run_get_current_proc_ar(run);
381 proc_ar->retval = eof_item;
382}
Note: See TracBrowser for help on using the repository browser.