bi_textfile.c

00001 /*
00002  * Copyright (c) 2010 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <assert.h>
00034 #include "../bigint.h"
00035 #include "../builtin.h"
00036 #include "../debug.h"
00037 #include "../mytypes.h"
00038 #include "../os/os.h"
00039 #include "../rdata.h"
00040 #include "../run.h"
00041 #include "../strtab.h"
00042 
00043 #include "bi_textfile.h"
00044 
00045 #define LINE_BUF_SIZE 256
00046 static char line_buf[LINE_BUF_SIZE];
00047 
00048 static void bi_textfile_openread(run_t *run);
00049 static void bi_textfile_openwrite(run_t *run);
00050 static void bi_textfile_close(run_t *run);
00051 static void bi_textfile_readline(run_t *run);
00052 static void bi_textfile_writeline(run_t *run);
00053 static void bi_textfile_is_eof(run_t *run);
00054 
00059 void bi_textfile_declare(builtin_t *bi)
00060 {
00061         /* Declare class TextFile. */
00062 
00063         builtin_code_snippet(bi,
00064                 "class TextFile is\n"
00065                         "var f : resource;\n"
00066                         "\n"
00067                         "fun OpenRead(fname : string), builtin;\n"
00068                         "fun OpenWrite(fname : string), builtin;\n"
00069                         "fun Close(), builtin;\n"
00070                         "fun ReadLine() : string, builtin;\n"
00071                         "fun WriteLine(line : string), builtin;\n"
00072                         "\n"
00073                         "prop EOF : bool is\n"
00074                                 "get is\n"
00075                                         "return is_eof();\n"
00076                                 "end\n"
00077                         "end\n"
00078                         "\n"
00079                         "fun is_eof() : bool, builtin;\n"
00080                 "end\n");
00081 
00082 }
00083 
00088 void bi_textfile_bind(builtin_t *bi)
00089 {
00090         builtin_fun_bind(bi, "TextFile", "OpenRead", bi_textfile_openread);
00091         builtin_fun_bind(bi, "TextFile", "OpenWrite", bi_textfile_openwrite);
00092         builtin_fun_bind(bi, "TextFile", "Close", bi_textfile_close);
00093         builtin_fun_bind(bi, "TextFile", "ReadLine", bi_textfile_readline);
00094         builtin_fun_bind(bi, "TextFile", "WriteLine", bi_textfile_writeline);
00095         builtin_fun_bind(bi, "TextFile", "is_eof", bi_textfile_is_eof);
00096 }
00097 
00102 static void bi_textfile_openread(run_t *run)
00103 {
00104         rdata_var_t *fname_var;
00105         const char *fname;
00106         FILE *file;
00107 
00108         rdata_resource_t *resource;
00109         rdata_var_t *res_var;
00110         rdata_value_t *res_val;
00111         rdata_var_t *self_f_var;
00112 
00113 #ifdef DEBUG_RUN_TRACE
00114         printf("Called TextFile.OpenRead()\n");
00115 #endif
00116         fname_var = run_local_vars_lookup(run, strtab_get_sid("fname"));
00117         assert(fname_var);
00118         assert(fname_var->vc == vc_string);
00119 
00120         fname = fname_var->u.string_v->value;
00121         file = fopen(fname, "rt");
00122         if (file == NULL) {
00123                 printf("Error: Failed opening file '%s' for reading.\n",
00124                     fname);
00125                 exit(1);
00126         }
00127 
00128         resource = rdata_resource_new();
00129         resource->data = (void *) file;
00130         res_var = rdata_var_new(vc_resource);
00131         res_var->u.resource_v = resource;
00132 
00133         res_val = rdata_value_new();
00134         res_val->var = res_var;
00135 
00136         /* Store resource handle into self.f */
00137         self_f_var = builtin_get_self_mbr_var(run, "f");
00138         rdata_var_write(self_f_var, res_val);
00139 }
00140 
00145 static void bi_textfile_openwrite(run_t *run)
00146 {
00147         rdata_var_t *fname_var;
00148         const char *fname;
00149         FILE *file;
00150 
00151         rdata_resource_t *resource;
00152         rdata_var_t *res_var;
00153         rdata_value_t *res_val;
00154         rdata_var_t *self_f_var;
00155 
00156 #ifdef DEBUG_RUN_TRACE
00157         printf("Called TextFile.OpenWrite()\n");
00158 #endif
00159         fname_var = run_local_vars_lookup(run, strtab_get_sid("fname"));
00160         assert(fname_var);
00161         assert(fname_var->vc == vc_string);
00162 
00163         fname = fname_var->u.string_v->value;
00164         file = fopen(fname, "wt");
00165         if (file == NULL) {
00166                 printf("Error: Failed opening file '%s' for writing.\n",
00167                     fname);
00168                 exit(1);
00169         }
00170 
00171         resource = rdata_resource_new();
00172         resource->data = (void *) file;
00173         res_var = rdata_var_new(vc_resource);
00174         res_var->u.resource_v = resource;
00175 
00176         res_val = rdata_value_new();
00177         res_val->var = res_var;
00178 
00179         /* Store resource handle into self.f */
00180         self_f_var = builtin_get_self_mbr_var(run, "f");
00181         rdata_var_write(self_f_var, res_val);
00182 }
00183 
00188 static void bi_textfile_close(run_t *run)
00189 {
00190         FILE *file;
00191         rdata_var_t *self_f_var;
00192         run_proc_ar_t *proc_ar;
00193 
00194         /* Extract pointer to file structure. */
00195         self_f_var = builtin_get_self_mbr_var(run, "f");
00196         assert(self_f_var->vc == vc_resource);
00197         file = (FILE *) self_f_var->u.resource_v->data;
00198 
00199         if (file == NULL) {
00200                 printf("Error: TextFile not valid for Close.\n");
00201                 exit(1);
00202         }
00203 
00204         /* Close the file. */
00205 
00206 #ifdef DEBUG_RUN_TRACE
00207         printf("Close text file.\n");
00208 #endif
00209         if (fclose(file) != 0) {
00210                 printf("Error: I/O error while closing file.\n");
00211                 exit(1);
00212         }
00213 
00214         /* Invalidate the resource handle. */
00215         self_f_var->u.resource_v->data = NULL;
00216 
00217         proc_ar = run_get_current_proc_ar(run);
00218         proc_ar->retval = NULL;
00219 }
00220 
00221 
00226 static void bi_textfile_readline(run_t *run)
00227 {
00228         FILE *file;
00229         rdata_var_t *self_f_var;
00230 
00231         rdata_string_t *str;
00232         rdata_var_t *str_var;
00233         rdata_value_t *str_val;
00234         rdata_item_t *str_item;
00235 
00236         run_proc_ar_t *proc_ar;
00237         char *cp;
00238 
00239         /* Extract pointer to file structure. */
00240         self_f_var = builtin_get_self_mbr_var(run, "f");
00241         assert(self_f_var->vc == vc_resource);
00242         file = (FILE *) self_f_var->u.resource_v->data;
00243 
00244         if (file == NULL) {
00245                 printf("Error: TextFile not valid for ReadLine.\n");
00246                 exit(1);
00247         }
00248 
00249         /* Check and read. */
00250 
00251         if (feof(file)) {
00252                 printf("Error: Reading beyond end of file.\n");
00253                 exit(1);
00254         }
00255 
00256         if (fgets(line_buf, LINE_BUF_SIZE, file) == NULL)
00257                 line_buf[0] = '\0';
00258 
00259         if (ferror(file)) {
00260                 printf("Error: I/O error while reading file.\n");
00261                 exit(1);
00262         }
00263 
00264         /* Remove trailing newline, if present. */
00265 
00266         cp = line_buf;
00267         while (*cp != '\0')
00268                 ++cp;
00269 
00270         if (cp != line_buf && cp[-1] == '\n')
00271                 cp[-1] = '\0';
00272 
00273 #ifdef DEBUG_RUN_TRACE
00274         printf("Read '%s' from file.\n", line_buf);
00275 #endif
00276         /* Construct return value. */
00277         str = rdata_string_new();
00278         str->value = os_str_dup(line_buf);
00279 
00280         str_var = rdata_var_new(vc_string);
00281         str_var->u.string_v = str;
00282         str_val = rdata_value_new();
00283         str_val->var = str_var;
00284 
00285         str_item = rdata_item_new(ic_value);
00286         str_item->u.value = str_val;
00287 
00288         proc_ar = run_get_current_proc_ar(run);
00289         proc_ar->retval = str_item;
00290 }
00291 
00296 static void bi_textfile_writeline(run_t *run)
00297 {
00298         FILE *file;
00299         rdata_var_t *self_f_var;
00300         rdata_var_t *line_var;
00301         const char *line;
00302 
00303         run_proc_ar_t *proc_ar;
00304 
00305         /* Get 'line' argument. */
00306         line_var = run_local_vars_lookup(run, strtab_get_sid("line"));
00307         assert(line_var);
00308         assert(line_var->vc == vc_string);
00309         line = line_var->u.string_v->value;
00310 
00311         /* Extract pointer to file structure. */
00312         self_f_var = builtin_get_self_mbr_var(run, "f");
00313         assert(self_f_var->vc == vc_resource);
00314         file = (FILE *) self_f_var->u.resource_v->data;
00315 
00316         if (file == NULL) {
00317                 printf("Error: TextFile not valid for WriteLine.\n");
00318                 exit(1);
00319         }
00320 
00321         /* Write and check. */
00322 
00323 #ifdef DEBUG_RUN_TRACE
00324         printf("Write '%s' to file.\n", line);
00325 #endif
00326         if (fprintf(file, "%s\n", line) < 0) {
00327                 printf("Error: I/O error while writing file.\n");
00328                 exit(1);
00329         }
00330 
00331         proc_ar = run_get_current_proc_ar(run);
00332         proc_ar->retval = NULL;
00333 }
00334 
00339 static void bi_textfile_is_eof(run_t *run)
00340 {
00341         FILE *file;
00342         rdata_var_t *self_f_var;
00343 
00344         bool_t eof_flag;
00345         rdata_bool_t *eof_bool;
00346         rdata_var_t *eof_var;
00347         rdata_value_t *eof_val;
00348         rdata_item_t *eof_item;
00349 
00350         run_proc_ar_t *proc_ar;
00351 
00352         /* Extract pointer to file structure. */
00353         self_f_var = builtin_get_self_mbr_var(run, "f");
00354         assert(self_f_var->vc == vc_resource);
00355         file = (FILE *) self_f_var->u.resource_v->data;
00356 
00357         if (file == NULL) {
00358                 printf("Error: TextFile not valid for EOF check.\n");
00359                 exit(1);
00360         }
00361 
00362         /* Get status of EOF flag. */
00363 
00364         eof_flag = feof(file) ? b_true : b_false;
00365 
00366 #ifdef DEBUG_RUN_TRACE
00367         printf("Read EOF flag '%s'.\n", eof_flag ? "true" : "false");
00368 #endif
00369         /* Construct return value. */
00370         eof_bool = rdata_bool_new();
00371         eof_bool->value = eof_flag;
00372 
00373         eof_var = rdata_var_new(vc_bool);
00374         eof_var->u.bool_v = eof_bool;
00375         eof_val = rdata_value_new();
00376         eof_val->var = eof_var;
00377 
00378         eof_item = rdata_item_new(ic_value);
00379         eof_item->u.value = eof_val;
00380 
00381         proc_ar = run_get_current_proc_ar(run);
00382         proc_ar->retval = eof_item;
00383 }

Generated on Thu Jun 2 07:45:42 2011 for HelenOS/USB by  doxygen 1.4.7