00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }