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

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

Update SBI to rev. 174.

  • Property mode set to 100644
File size: 8.9 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. */
56void bi_textfile_declare(builtin_t *bi)
57{
58 /* Declare class TextFile. */
59
60 builtin_code_snippet(bi,
61 "class TextFile is\n"
62 "var f : resource;\n"
63 "\n"
64 "fun OpenRead(fname : string), builtin;\n"
65 "fun OpenWrite(fname : string), builtin;\n"
66 "fun Close(), builtin;\n"
67 "fun ReadLine() : string, builtin;\n"
68 "fun WriteLine(line : string), builtin;\n"
69 "\n"
70 "prop EOF : int is\n"
71 "get is\n"
72 "return is_eof();\n"
73 "end\n"
74 "end\n"
75 "\n"
76 "fun is_eof() : int, builtin;\n"
77 "end\n");
78
79}
80
81/** Bind TextFile builtin. */
82void bi_textfile_bind(builtin_t *bi)
83{
84 builtin_fun_bind(bi, "TextFile", "OpenRead", bi_textfile_openread);
85 builtin_fun_bind(bi, "TextFile", "OpenWrite", bi_textfile_openwrite);
86 builtin_fun_bind(bi, "TextFile", "Close", bi_textfile_close);
87 builtin_fun_bind(bi, "TextFile", "ReadLine", bi_textfile_readline);
88 builtin_fun_bind(bi, "TextFile", "WriteLine", bi_textfile_writeline);
89 builtin_fun_bind(bi, "TextFile", "is_eof", bi_textfile_is_eof);
90}
91
92/** Open a text file for reading. */
93static void bi_textfile_openread(run_t *run)
94{
95 rdata_var_t *fname_var;
96 char *fname;
97 FILE *file;
98
99 rdata_resource_t *resource;
100 rdata_var_t *res_var;
101 rdata_value_t *res_val;
102 rdata_var_t *self_f_var;
103
104#ifdef DEBUG_RUN_TRACE
105 printf("Called TextFile.OpenRead()\n");
106#endif
107 fname_var = run_local_vars_lookup(run, strtab_get_sid("fname"));
108 assert(fname_var);
109 assert(fname_var->vc == vc_string);
110
111 fname = fname_var->u.string_v->value;
112 file = fopen(fname, "rt");
113 if (file == NULL) {
114 printf("Error: Failed opening file '%s' for reading.\n",
115 fname);
116 exit(1);
117 }
118
119 resource = rdata_resource_new();
120 resource->data = (void *) file;
121 res_var = rdata_var_new(vc_resource);
122 res_var->u.resource_v = resource;
123
124 res_val = rdata_value_new();
125 res_val->var = res_var;
126
127 /* Store resource handle into self.f */
128 self_f_var = builtin_get_self_mbr_var(run, "f");
129 rdata_var_write(self_f_var, res_val);
130}
131
132/** Open a text file for writing. */
133static void bi_textfile_openwrite(run_t *run)
134{
135 rdata_var_t *fname_var;
136 char *fname;
137 FILE *file;
138
139 rdata_resource_t *resource;
140 rdata_var_t *res_var;
141 rdata_value_t *res_val;
142 rdata_var_t *self_f_var;
143
144#ifdef DEBUG_RUN_TRACE
145 printf("Called TextFile.OpenWrite()\n");
146#endif
147 fname_var = run_local_vars_lookup(run, strtab_get_sid("fname"));
148 assert(fname_var);
149 assert(fname_var->vc == vc_string);
150
151 fname = fname_var->u.string_v->value;
152 file = fopen(fname, "wt");
153 if (file == NULL) {
154 printf("Error: Failed opening file '%s' for writing.\n",
155 fname);
156 exit(1);
157 }
158
159 resource = rdata_resource_new();
160 resource->data = (void *) file;
161 res_var = rdata_var_new(vc_resource);
162 res_var->u.resource_v = resource;
163
164 res_val = rdata_value_new();
165 res_val->var = res_var;
166
167 /* Store resource handle into self.f */
168 self_f_var = builtin_get_self_mbr_var(run, "f");
169 rdata_var_write(self_f_var, res_val);
170}
171
172/** Close a text file. */
173static void bi_textfile_close(run_t *run)
174{
175 FILE *file;
176 rdata_var_t *self_f_var;
177 run_proc_ar_t *proc_ar;
178
179 /* Extract pointer to file structure. */
180 self_f_var = builtin_get_self_mbr_var(run, "f");
181 assert(self_f_var->vc == vc_resource);
182 file = (FILE *) self_f_var->u.resource_v->data;
183
184 if (file == NULL) {
185 printf("Error: TextFile not valid for Close.\n");
186 exit(1);
187 }
188
189 /* Close the file. */
190
191#ifdef DEBUG_RUN_TRACE
192 printf("Close text file.\n");
193#endif
194 if (fclose(file) != 0) {
195 printf("Error: I/O error while closing file.\n");
196 exit(1);
197 }
198
199 /* Invalidate the resource handle. */
200 self_f_var->u.resource_v->data = NULL;
201
202 proc_ar = run_get_current_proc_ar(run);
203 proc_ar->retval = NULL;
204}
205
206
207/** Read one line from a text file. */
208static void bi_textfile_readline(run_t *run)
209{
210 FILE *file;
211 rdata_var_t *self_f_var;
212
213 rdata_string_t *str;
214 rdata_var_t *str_var;
215 rdata_value_t *str_val;
216 rdata_item_t *str_item;
217
218 run_proc_ar_t *proc_ar;
219 char *cp;
220
221 /* Extract pointer to file structure. */
222 self_f_var = builtin_get_self_mbr_var(run, "f");
223 assert(self_f_var->vc == vc_resource);
224 file = (FILE *) self_f_var->u.resource_v->data;
225
226 if (file == NULL) {
227 printf("Error: TextFile not valid for ReadLine.\n");
228 exit(1);
229 }
230
231 /* Check and read. */
232
233 if (feof(file)) {
234 printf("Error: Reading beyond end of file.\n");
235 exit(1);
236 }
237
238 if (fgets(line_buf, LINE_BUF_SIZE, file) == NULL)
239 line_buf[0] = '\0';
240
241 if (ferror(file)) {
242 printf("Error: I/O error while reading file.\n");
243 exit(1);
244 }
245
246 /* Remove trailing newline, if present. */
247
248 cp = line_buf;
249 while (*cp != '\0')
250 ++cp;
251
252 if (cp != line_buf && cp[-1] == '\n')
253 cp[-1] = '\0';
254
255#ifdef DEBUG_RUN_TRACE
256 printf("Read '%s' from file.\n", line_buf);
257#endif
258 /* Construct return value. */
259 str = rdata_string_new();
260 str->value = os_str_dup(line_buf);
261
262 str_var = rdata_var_new(vc_string);
263 str_var->u.string_v = str;
264 str_val = rdata_value_new();
265 str_val->var = str_var;
266
267 str_item = rdata_item_new(ic_value);
268 str_item->u.value = str_val;
269
270 proc_ar = run_get_current_proc_ar(run);
271 proc_ar->retval = str_item;
272}
273
274/** Write one line to a text file. */
275static void bi_textfile_writeline(run_t *run)
276{
277 FILE *file;
278 rdata_var_t *self_f_var;
279 rdata_var_t *line_var;
280 char *line;
281
282 run_proc_ar_t *proc_ar;
283
284 /* Get 'line' argument. */
285 line_var = run_local_vars_lookup(run, strtab_get_sid("line"));
286 assert(line_var);
287 assert(line_var->vc == vc_string);
288 line = line_var->u.string_v->value;
289
290 /* Extract pointer to file structure. */
291 self_f_var = builtin_get_self_mbr_var(run, "f");
292 assert(self_f_var->vc == vc_resource);
293 file = (FILE *) self_f_var->u.resource_v->data;
294
295 if (file == NULL) {
296 printf("Error: TextFile not valid for WriteLine.\n");
297 exit(1);
298 }
299
300 /* Write and check. */
301
302#ifdef DEBUG_RUN_TRACE
303 printf("Write '%s' to file.\n", line);
304#endif
305 if (fprintf(file, "%s\n", line) < 0) {
306 printf("Error: I/O error while writing file.\n");
307 exit(1);
308 }
309
310 proc_ar = run_get_current_proc_ar(run);
311 proc_ar->retval = NULL;
312}
313
314/** Return value of EOF flag. */
315static void bi_textfile_is_eof(run_t *run)
316{
317 FILE *file;
318 rdata_var_t *self_f_var;
319
320 int eof_flag;
321 rdata_int_t *eof_int;
322 rdata_var_t *eof_var;
323 rdata_value_t *eof_val;
324 rdata_item_t *eof_item;
325
326 run_proc_ar_t *proc_ar;
327
328 /* Extract pointer to file structure. */
329 self_f_var = builtin_get_self_mbr_var(run, "f");
330 assert(self_f_var->vc == vc_resource);
331 file = (FILE *) self_f_var->u.resource_v->data;
332
333 if (file == NULL) {
334 printf("Error: TextFile not valid for EOF check.\n");
335 exit(1);
336 }
337
338 /* Get status of EOF flag. */
339
340 eof_flag = feof(file) ? 1 : 0;
341
342#ifdef DEBUG_RUN_TRACE
343 printf("Read EOF flag '%d'.\n", eof_flag);
344#endif
345 /* Construct return value. */
346 eof_int = rdata_int_new();
347 bigint_init(&eof_int->value, eof_flag);
348
349 eof_var = rdata_var_new(vc_int);
350 eof_var->u.int_v = eof_int;
351 eof_val = rdata_value_new();
352 eof_val->var = eof_var;
353
354 eof_item = rdata_item_new(ic_value);
355 eof_item->u.value = eof_val;
356
357 proc_ar = run_get_current_proc_ar(run);
358 proc_ar->retval = eof_item;
359}
Note: See TracBrowser for help on using the repository browser.