From help-octave-request at che dot utexas dot edu Tue Jan 10 02:22:25 1995 Subject: MATLAB like fread/fwrite available! From: Superuser AIA To: help-octave at che dot utexas dot edu Cc: bug-octave at che dot utexas dot edu Date: Tue, 10 Jan 95 09:21:54 +0100 -------- Hello OCTAVE users, For further use of our old MATLAB programs and datas we needed a procedure for a raw file i/o like in the new MATLAB fread and fwrite. Therefore we implemented these functions and added a mode 'b' to fopen. The help informations for the added functions is implemented, too. Due to the use of different ENDIAN models in our institute there is a new builtin-var called 'io_swap_bytes' which makes you able to swap the bytes while reading and writing to files. Further floating-point conversions are not implemented yet. We'll hope you can use these additions. Some requested informations for bug reporting: * octave, version 1.0 * machines: hppa1.1-hp-hpux9.01 / m68k-hp-hpux9.00 / i486-linux The first diff in the file is a very small bug in the pager procedures, but it caused trouble at the m68k-hp-hpux9.00 (leaving the page with a SIGSEV). Fromon the second diff to the end you'll find the necessary differences for the raw file i/o. diff -c octave.old/src/pager.cc octave.new/src/pager.cc *** octave.old/src/pager.cc Tue Jan 10 08:49:31 1995 --- octave.new/src/pager.cc Tue Jan 10 08:50:26 1995 *************** *** 109,117 **** char *message = pager_buf->str (); ! if (message == (char *) NULL || *message == '\0') { delete [] message; initialize_pager (); return; } --- 109,121 ---- char *message = pager_buf->str (); ! if (message == (char *) NULL) ! goto initonly; ! ! if (*message == '\0') { delete [] message; + initonly: initialize_pager (); return; } diff -c octave.old/src/builtins.cc octave.new/src/builtins.cc *** octave.old/src/builtins.cc Tue Jan 10 08:49:28 1995 --- octave.new/src/builtins.cc Tue Jan 10 08:49:51 1995 *************** *** 316,321 **** --- 316,338 ---- { "fgets",3, 2, builtin_fgets, "[string, length] = fgets (\"filename\" or filenum, length): read a string from a file", }, + { "fread",4, 2, builtin_fread, + "[A, count] = fread (\"filename\" or filenum, size, 'precision'): binary read from a file\n\n\ + Valid values for 'precision' include:\n\n\ + 'char', 'char*1'; 'schar', 'signed char', 'int8';\n\ + 'uchar', 'unsigned char', 'uint8':\n\ + Character, 8 bits\n\ + 'short', 'int16'; 'ushort', 'unsigned short', 'uint16':\n\ + Integer, 16 bits\n\ + 'int'; 'uint', 'unsigned int':\n\ + Integer, 16 or 32 bits\n\ + 'long', 'int32'; 'ulong', 'unsigned long', 'uint32':\n\ + Integer, 32 bits\n\ + 'float32', 'real*4':\n\ + Floating point value, 32 bits\n\ + 'double', 'float64', 'real*8':\n\ + Floating point value, 64 bits\n", }, + { "find", -1, 1, builtin_find, "find (x): return vector of indices of nonzero elements", }, *************** *** 390,395 **** --- 407,429 ---- { "ftell", 2, 1, builtin_ftell, "position = ftell (\"filename\" or filenum): returns the current file position", }, + { "fwrite",4, 1, builtin_fwrite, + "count = fwrite (\"filename\" or filenum, X, 'precision'): binary write to a file\n\n\ + Valid values for 'precision' include:\n\n\ + 'char', 'char*1'; 'schar', 'signed char', 'int8';\n\ + 'uchar', 'unsigned char', 'uint8':\n\ + Character, 8 bits\n\ + 'short', 'int16'; 'ushort', 'unsigned short', 'uint16':\n\ + Integer, 16 bits\n\ + 'int'; 'uint', 'unsigned int':\n\ + Integer, 16 or 32 bits\n\ + 'long', 'int32'; 'ulong', 'unsigned long', 'uint32':\n\ + Integer, 32 bits\n\ + 'float32', 'real*4':\n\ + Floating point value, 32 bits\n\ + 'double', 'float64', 'real*8':\n\ + Floating point value, 64 bits\n", }, + { "getenv", 2, 1, builtin_getenv, "getenv (\"string\"): get environment variable values", }, *************** *** 711,716 **** --- 745,753 ---- { "inf", "??", NULL, "infinity", }, + { "io_swap_bytes", "false", io_swap_bytes, + "swap bytes while low-level file i/o", }, + { "j", "??", NULL, "sqrt (-1)", }, diff -c octave.old/src/file-io.cc octave.new/src/file-io.cc *** octave.old/src/file-io.cc Tue Jan 10 08:49:28 1995 --- octave.new/src/file-io.cc Tue Jan 10 08:50:02 1995 *************** *** 38,44 **** --- 38,46 ---- #include "statdefs.h" #include "file-io.h" #include "input.h" + #include "mappers.h" #include "octave-hist.h" + #include "user-prefs.h" #include "tree-const.h" #include "error.h" #include "utils.h" *************** *** 342,349 **** char m = mode[0]; if (m == 'r' || m == 'w' || m == 'a') { ! m = mode[1]; ! return (m == '\0' || (m == '+' && mode[2] == '\0')); } } return 0; --- 344,362 ---- char m = mode[0]; if (m == 'r' || m == 'w' || m == 'a') { ! for(;;) ! { ! switch (*++mode) ! { ! case '+': case 'b': ! continue; ! case '\0': ! return 1; ! default: ! break; ! } ! break; ! } } } return 0; *************** *** 392,397 **** --- 405,736 ---- retval[0] = tree_constant (string); + return retval; + } + + struct elminfo{ unsigned realv:1; unsigned signedv:1; }; + + static size_t + decode_precision (const char *prec, struct elminfo *elminf) + { const struct { const char *name; unsigned realv:1; unsigned signedv:1; + size_t size; } *p, + ref [] = + { {"char", 0, 1, sizeof(char)}, + {"char*1", 0, 1, sizeof(char)}, + {"schar", 0, 1, sizeof(signed char)}, + {"signed char", 0, 1, sizeof(signed char)}, + {"uchar", 0, 0, sizeof(unsigned char)}, + {"unsigned char", 0, 0, sizeof(unsigned char)}, + {"short", 0, 1, sizeof(short)}, + {"ushort", 0, 0, sizeof(unsigned short)}, + {"unsigned short", 0, 0, sizeof(unsigned short)}, + {"int", 0, 1, sizeof(int)}, + {"uint", 0, 0, sizeof(unsigned)}, + {"unsigned", 0, 0, sizeof(unsigned)}, + {"long", 0, 1, sizeof(long)}, + {"ulong", 0, 0, sizeof(unsigned long)}, + {"unsigned long", 0, 0, sizeof(unsigned long)}, + {"float", 1, 1, sizeof(float)}, + {"float32", 1, 1, 4}, + {"float*4", 1, 1, 4}, + {"float64", 1, 1, 8}, + {"double", 1, 1, sizeof(double)}, + {"real*8", 1, 1, 8}, + {"int8", 0, 1, 1}, + {"int16", 0, 1, 2}, + {"int32", 0, 1, 4}, + {"uint8", 0, 0, 1}, + {"uint16", 0, 0, 2}, + {"uint32", 0, 0, 4}, + {0, 0, 0, 0}, + }; + for (p=ref; p->name; p++) + if(!strcmp(p->name, prec)) + { + elminf->realv = p->realv; + elminf->signedv = p->signedv; + return p->size; + } + + error ("not a valid precision"); + return 0; + } + + /*srb*/ + tree_constant * + fwrite_internal (const tree_constant *args, int nargin, int nargout) { + tree_constant *retval = NULL_TREE_CONST; + + Pix p = file_io_get_file (args[1], "wb", "fwrite"); + + if (p == (Pix) NULL) + return retval; + + size_t elmsize = 1; + elminfo elminf = {0, 0}; + long sizer = 1, sizec = 1; + union {Matrix*matrix; char*string;} src; + enum {matrix,string,scalar} type; + + if (args[2].is_matrix_type ()) { + sizer = (long) args[2].rows (); + sizec = (long) args[2].columns (); + type = matrix; src.matrix = &args[2].matrix_value (); + } + else if (args[2].is_string_type ()) { + sizer = (long) strlen(args[2].string_value ()); + type = string; src.string = args[2].string_value (); + } + else if (args[2].is_scalar_type ()) { + type = scalar; + } + else + goto fwrite_usage; + + if (args[3].is_string_type ()) + elmsize = decode_precision (args[3].string_value (), &elminf); + else + { + fwrite_usage: + error ("fwrite: usage error"); + return retval; + } + + file_info file = file_list (p); + + size_t count = 0, ir, ic; + union {char c[sizeof(double)*2];long l;double d;} buf; + + #define WRITEbuf(type) \ + if(elmsize==sizeof(type)) \ + *(type*)(void*)&buf = (type)result + + for (ic = 0; ic < sizec; ic++) + for (ir = 0; ir < sizer ; ir++) + { + double result; + + switch (type) + { + case matrix: + result = src.matrix->xelem(ir,ic); + break; + case string: + result = src.string[ir]; + break; + case scalar: + result = args[2].double_value (); + break; + } + + if (elminf.realv) + { + WRITEbuf(float); + else WRITEbuf(double); + else goto unk_prec; + } + else if (elminf.signedv) + { + WRITEbuf(char); + else WRITEbuf(short); + else WRITEbuf(int); + else WRITEbuf(long); + else goto unk_prec; + } + else + { + WRITEbuf(unsigned char); + else WRITEbuf(unsigned short); + else WRITEbuf(unsigned int); + else WRITEbuf(unsigned long); + else + { + unk_prec: error ("fwrite: unknown precision"); + return retval; + } + } + + if (user_pref.io_swap_bytes) + { + unsigned char *bufb=NULL, *bufe=NULL; + unsigned bufbuf; + + for (bufb=(unsigned char *)(void *)&buf, bufe=bufb+elmsize-1; + bufb= 3) { + if (args[2].is_scalar_type ()) + { + d = args[2].double_value (); + if (((variablesize = (xisinf(d) != 0)) && (d < 0)) || + !variablesize && + (sizer = (long) d) && + (double) NINT (d) != (unsigned long) sizer) + { + error ("fread: size not a positive integer value"); + return retval; + } + } + else if (args[2].is_matrix_type ()) + { + sizer = (long) args[2].rows (); + sizec = (long) args[2].columns (); + variablesize = 0; + + if (sizer * sizec != 2) + { + error ("fread: size not a two-valued vector"); + return retval; + } + + sizec = sizer == 1 ? + (long) args[2].matrix_value ().xelem(0,1) : + (long) args[2].matrix_value ().xelem(1,0) ; + + sizer = (long) args[2].matrix_value ().xelem(0,0) ; + + if ( sizer <= 0 || sizec <= 0 ) + { + error ("fread: size not of positive integer values"); + return retval; + } + } + else if (nargin == 3) + { if(args[2].is_string_type ()) + goto fread_readprec; + goto fread_usage; + } + } + + if (nargin == 4 && args[3].is_string_type ()) + { + fread_readprec: + elmsize = decode_precision (args[nargin-1].string_value (), &elminf); + } + else if (nargin >= 4) + { + fread_usage: + error ("fread: usage error"); + return retval; + } + + file_info file = file_list (p); + + Matrix tmp (sizer, sizec, 0.0); + size_t count = 0, ir, ic; + union {char c[sizeof(double)*2];long l;double d;} buf; + #define READ_BUF_SIZE 2048 + #define READbuf(type) \ + if(elmsize==sizeof(type)) \ + result = *(type*)(void*)&buf + + for (ic = 0; ic < sizec; ic++) + for (ir = 0; ir < sizer ; ir++) + { + double result; + + if (fread(&buf, elmsize, 1, file.fptr()) != 1) + goto eof; + + if (variablesize) { + if (count % READ_BUF_SIZE == 0) + tmp.resize(sizer+READ_BUF_SIZE-1,1); + sizer++; + } + + if (user_pref.io_swap_bytes) + { + unsigned char *bufb=NULL, *bufe=NULL; + unsigned bufbuf; + + for (bufb=(unsigned char *)(void *)&buf, bufe=bufb+elmsize-1; + bufb 4 || nargout > 2) + print_usage ("fread"); + else + retval = fread_internal (args, nargin, nargout); + + return retval; + } + + /* * Find nonzero elements. This should probably only work if * do_fortran_indexing is true... */ *************** *** 856,861 **** --- 872,893 ---- else retval = ftell_internal (args); + return retval; + } + + /* + * binary write to a file + */ + tree_constant * + builtin_fwrite (const tree_constant *args, int nargin, int nargout) + { + tree_constant *retval = NULL_TREE_CONST; + + if (nargin != 4 || nargout > 1) + print_usage ("fwrite"); + else + retval = fwrite_internal (args, nargin, nargout); + return retval; } diff -c octave.old/src/g-builtins.h octave.new/src/g-builtins.h *** octave.old/src/g-builtins.h Tue Jan 10 08:49:30 1995 --- octave.new/src/g-builtins.h Tue Jan 10 08:50:14 1995 *************** *** 62,67 **** --- 62,68 ---- extern tree_constant *builtin_fflush (const tree_constant *, int, int); extern tree_constant *builtin_fft (const tree_constant *, int, int); extern tree_constant *builtin_fgets (const tree_constant *, int, int); + extern tree_constant *builtin_fread (const tree_constant *, int, int); extern tree_constant *builtin_find (const tree_constant *, int, int); extern tree_constant *builtin_flops (const tree_constant *, int, int); extern tree_constant *builtin_fopen (const tree_constant *, int, int); *************** *** 75,80 **** --- 76,82 ---- extern tree_constant *builtin_fsqp (const tree_constant *, int, int); extern tree_constant *builtin_fsqp_options (const tree_constant *, int, int); extern tree_constant *builtin_ftell (const tree_constant *, int, int); + extern tree_constant *builtin_fwrite (const tree_constant *, int, int); extern tree_constant *builtin_getenv (const tree_constant *, int, int); extern tree_constant *builtin_givens (const tree_constant *, int, int); extern tree_constant *builtin_hess (const tree_constant *, int, int); diff -c octave.old/src/t-builtins.cc octave.new/src/t-builtins.cc *** octave.old/src/t-builtins.cc Tue Jan 10 08:49:32 1995 --- octave.new/src/t-builtins.cc Tue Jan 10 08:50:33 1995 *************** *** 798,808 **** return retval; } ! static istream stream; ! static ifstream file; if (strcmp (*argv, "-") == 0) { ! stream = cin; } else { --- 798,808 ---- return retval; } ! istream *stream; ! ifstream file; if (strcmp (*argv, "-") == 0) { ! stream = &cin; } else { *************** *** 813,819 **** error ("load: couldn't open input file `%s'", *argv); return retval; } ! stream = file; } int count = 0; --- 813,819 ---- error ("load: couldn't open input file `%s'", *argv); return retval; } ! stream = &file; } int count = 0; *************** *** 822,828 **** { // Read name for this entry or break on EOF. delete [] nm; ! nm = extract_keyword (stream, "name"); if (nm == (char *) NULL) { if (count == 0) --- 822,828 ---- { // Read name for this entry or break on EOF. delete [] nm; ! nm = extract_keyword (*stream, "name"); if (nm == (char *) NULL) { if (count == 0) *************** *** 844,850 **** continue; } ! load_variable (nm, force, stream); if (error_state) { --- 844,850 ---- continue; } ! load_variable (nm, force, *stream); if (error_state) { *************** *** 853,861 **** } } - if (file); - file.close (); - return retval; } --- 853,858 ---- *************** *** 960,972 **** argc--; argv++; ! static ostream stream; ! static ofstream file; if (strcmp (*argv, "-") == 0) { // XXX FIXME XXX -- should things intended for the screen end up in a // tree_constant (string)? ! stream = cout; } else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things { // like `save a*', --- 957,969 ---- argc--; argv++; ! ostream *stream; ! ofstream file; if (strcmp (*argv, "-") == 0) { // XXX FIXME XXX -- should things intended for the screen end up in a // tree_constant (string)? ! stream = &cout; } else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things { // like `save a*', *************** *** 982,988 **** error ("save: couldn't open output file `%s'", *argv); return retval; } ! stream = file; } --- 979,985 ---- error ("save: couldn't open output file `%s'", *argv); return retval; } ! stream = &file; } *************** *** 996,1002 **** SYMTAB_ALL_SCOPES); for (int i = 0; i < count; i++) ! curr_sym_tab->save (stream, vars[i], is_globally_visible (vars[i]), prec); delete [] vars; --- 993,999 ---- SYMTAB_ALL_SCOPES); for (int i = 0; i < count; i++) ! curr_sym_tab->save (*stream, vars[i], is_globally_visible (vars[i]), prec); delete [] vars; *************** *** 1016,1022 **** for (i = 0; i < count; i++) { if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0 ! && curr_sym_tab->save (stream, lvars[i], is_globally_visible (lvars[i]), prec) != 0) saved_or_error++; --- 1013,1019 ---- for (i = 0; i < count; i++) { if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0 ! && curr_sym_tab->save (*stream, lvars[i], is_globally_visible (lvars[i]), prec) != 0) saved_or_error++; *************** *** 1028,1034 **** for (i = 0; i < count; i++) { if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0 ! && global_sym_tab->save (stream, bvars[i], 0, prec) != 0) saved_or_error++; } --- 1025,1031 ---- for (i = 0; i < count; i++) { if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0 ! && global_sym_tab->save (*stream, bvars[i], 0, prec) != 0) saved_or_error++; } *************** *** 1040,1048 **** } } - if (file); - file.close (); - return retval; } --- 1037,1042 ---- diff -c octave.old/src/user-prefs.cc octave.new/src/user-prefs.cc *** octave.old/src/user-prefs.cc Tue Jan 10 08:49:32 1995 --- octave.new/src/user-prefs.cc Tue Jan 10 08:50:44 1995 *************** *** 110,115 **** --- 110,125 ---- } /* + * Should we swap the bytes while low-level file i/o in order + * to get around the machine dependency? + */ + int + io_swap_bytes (void) + { + user_pref.io_swap_bytes = check_str_pref ("io_swap_bytes"); + } + + /* * Should we allow silent conversion of complex to real when a real * type is what we\'re really looking for? */ diff -c octave.old/src/user-prefs.h octave.new/src/user-prefs.h *** octave.old/src/user-prefs.h Tue Jan 10 08:49:32 1995 --- octave.new/src/user-prefs.h Tue Jan 10 08:50:44 1995 *************** *** 28,33 **** --- 28,34 ---- { int do_fortran_indexing; int empty_list_elements_ok; + int io_swap_bytes; int implicit_str_to_num_ok; int ok_to_lose_imaginary_part; int prefer_column_vectors; *************** *** 63,68 **** --- 64,70 ---- extern int do_fortran_indexing (void); extern int empty_list_elements_ok (void); + extern int io_swap_bytes (void); extern int implicit_str_to_num_ok (void); extern int ok_to_lose_imaginary_part (void); extern int prefer_column_vectors (void);