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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f4f866c was 38aaacc2, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 207.

  • Property mode set to 100644
File size: 9.2 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 : int is\n"
74 "get is\n"
75 "return is_eof();\n"
76 "end\n"
77 "end\n"
78 "\n"
79 "fun is_eof() : int, 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
222/** Read one line from a text file.
223 *
224 * @param run Runner object
225 */
226static void bi_textfile_readline(run_t *run)
227{
228 FILE *file;
229 rdata_var_t *self_f_var;
230
231 rdata_string_t *str;
232 rdata_var_t *str_var;
233 rdata_value_t *str_val;
234 rdata_item_t *str_item;
235
236 run_proc_ar_t *proc_ar;
237 char *cp;
238
239 /* Extract pointer to file structure. */
240 self_f_var = builtin_get_self_mbr_var(run, "f");
241 assert(self_f_var->vc == vc_resource);
242 file = (FILE *) self_f_var->u.resource_v->data;
243
244 if (file == NULL) {
245 printf("Error: TextFile not valid for ReadLine.\n");
246 exit(1);
247 }
248
249 /* Check and read. */
250
251 if (feof(file)) {
252 printf("Error: Reading beyond end of file.\n");
253 exit(1);
254 }
255
256 if (fgets(line_buf, LINE_BUF_SIZE, file) == NULL)
257 line_buf[0] = '\0';
258
259 if (ferror(file)) {
260 printf("Error: I/O error while reading file.\n");
261 exit(1);
262 }
263
264 /* Remove trailing newline, if present. */
265
266 cp = line_buf;
267 while (*cp != '\0')
268 ++cp;
269
270 if (cp != line_buf && cp[-1] == '\n')
271 cp[-1] = '\0';
272
273#ifdef DEBUG_RUN_TRACE
274 printf("Read '%s' from file.\n", line_buf);
275#endif
276 /* Construct return value. */
277 str = rdata_string_new();
278 str->value = os_str_dup(line_buf);
279
280 str_var = rdata_var_new(vc_string);
281 str_var->u.string_v = str;
282 str_val = rdata_value_new();
283 str_val->var = str_var;
284
285 str_item = rdata_item_new(ic_value);
286 str_item->u.value = str_val;
287
288 proc_ar = run_get_current_proc_ar(run);
289 proc_ar->retval = str_item;
290}
291
292/** Write one line to a text file.
293 *
294 * @param run Runner object
295 */
296static void bi_textfile_writeline(run_t *run)
297{
298 FILE *file;
299 rdata_var_t *self_f_var;
300 rdata_var_t *line_var;
301 const char *line;
302
303 run_proc_ar_t *proc_ar;
304
305 /* Get 'line' argument. */
306 line_var = run_local_vars_lookup(run, strtab_get_sid("line"));
307 assert(line_var);
308 assert(line_var->vc == vc_string);
309 line = line_var->u.string_v->value;
310
311 /* Extract pointer to file structure. */
312 self_f_var = builtin_get_self_mbr_var(run, "f");
313 assert(self_f_var->vc == vc_resource);
314 file = (FILE *) self_f_var->u.resource_v->data;
315
316 if (file == NULL) {
317 printf("Error: TextFile not valid for WriteLine.\n");
318 exit(1);
319 }
320
321 /* Write and check. */
322
323#ifdef DEBUG_RUN_TRACE
324 printf("Write '%s' to file.\n", line);
325#endif
326 if (fprintf(file, "%s\n", line) < 0) {
327 printf("Error: I/O error while writing file.\n");
328 exit(1);
329 }
330
331 proc_ar = run_get_current_proc_ar(run);
332 proc_ar->retval = NULL;
333}
334
335/** Return value of EOF flag.
336 *
337 * @param run Runner object
338 */
339static void bi_textfile_is_eof(run_t *run)
340{
341 FILE *file;
342 rdata_var_t *self_f_var;
343
344 int eof_flag;
345 rdata_int_t *eof_int;
346 rdata_var_t *eof_var;
347 rdata_value_t *eof_val;
348 rdata_item_t *eof_item;
349
350 run_proc_ar_t *proc_ar;
351
352 /* Extract pointer to file structure. */
353 self_f_var = builtin_get_self_mbr_var(run, "f");
354 assert(self_f_var->vc == vc_resource);
355 file = (FILE *) self_f_var->u.resource_v->data;
356
357 if (file == NULL) {
358 printf("Error: TextFile not valid for EOF check.\n");
359 exit(1);
360 }
361
362 /* Get status of EOF flag. */
363
364 eof_flag = feof(file) ? 1 : 0;
365
366#ifdef DEBUG_RUN_TRACE
367 printf("Read EOF flag '%d'.\n", eof_flag);
368#endif
369 /* Construct return value. */
370 eof_int = rdata_int_new();
371 bigint_init(&eof_int->value, eof_flag);
372
373 eof_var = rdata_var_new(vc_int);
374 eof_var->u.int_v = eof_int;
375 eof_val = rdata_value_new();
376 eof_val->var = eof_var;
377
378 eof_item = rdata_item_new(ic_value);
379 eof_item->u.value = eof_val;
380
381 proc_ar = run_get_current_proc_ar(run);
382 proc_ar->retval = eof_item;
383}
Note: See TracBrowser for help on using the repository browser.