/* yorick functions to read and write FORTRAN binary files contributed by David Syer Dave, Here's my seqio.i with functions for FORTRAN sequential IO. To mimic ftell, and keep track of the file position I cheat and use get_addrs. Files pretty much have to be strictly sequential, but I've provided _len_rec to take a peek ahead without altering the value of _ftell. I suppose other functions could be written which take a peek at non-integer values in the next read-position. Writing structs works best with my new get_vars(struct) function (see _struct_write), but will only fail if the file to be written has different primitives than the native format. I haven't implemented your suggestion of a _setup_rec function, but I've added some low level routines _{read,write}_bare which could be used to write C-style sequential files, or records with different kinds of padding. (I didn't call them _fread,_fwrite because their syntax is a bit different.) I used them already to write records which correspond to some weird fortran output statements. Dave. */ func _ftell(f) // like ftell { local addr; addr= *(get_addrs(f)(1)); if(is_void(addr)) addr= 0; else addr= addr(0) + sizeof(get_member(f,(*get_vars(f)(1))(0))); return addr; } func _write_rec(f,..) /* DOCUMENT _write_rec, f, var1, var2 write record to fortran file from var1, var2, .. return number of bytes written (excluding padding) SEE ALSO: _read_rec */ { local addr, pn0, pn1; addr= _ftell(f); pn0= swrite(format="pad%d",addr); add_variable,f,-1,pn0,int; addr+= sizeof(get_member(f,pn0)); local size, arg; size=0; while(more_args()>0) { local len; arg= next_arg(); len= _write_bare(f,arg); size+= len; addr+= len; } pn1= swrite(format="pad%d",addr); add_variable,f,-1,pn1,int; get_member(f,pn0)= get_member(f,pn1)= size; return size; } func _read_rec(f,..) /* DOCUMENT _read_rec, f, &var1, &var2, .. read record from fortran file into var1, var2, .. return number of bytes written (excluding padding) SEE ALSO: _write_rec */ { local addr, pn0, pn1; addr= _ftell(f); pn0= swrite(format="pad%d",addr); add_variable,f,-1,pn0,int; addr+= sizeof(get_member(f,pn0)); local size0, size, arg; size0=get_member(f,pn0); size=0; while(more_args()>0) { local len; arg= next_arg(); len= _read_bare(f,arg); size+= len; addr+= len; } pn1= swrite(format="pad%d",addr); add_variable,f,-1,pn1,int; if(size!=size0) error,"Wrong record length"; return size; } func _len_rec(f) /* DOCUMENT _len_rec,f return length of next record in sequential fortran file */ { local addr, len; addr= _ftell(f); len= 0; _read,f,addr,len; return len; } func _write_bare(f,arg,size) /* DOCUMENT _write_bare, f, arg, size write var to file f in a record of size bytes if size is omitted just use sizeof(f.arg) return numberof bytes written */ { local addr, name, len; addr= _ftell(f); name= swrite(format="%s%d",typeof(arg),addr); add_variable,f,-1,name,structof(arg),dimsof(arg); if(typeof(arg)=="struct_instance") { _struct_write,f,arg,name; } else { get_member(f,name)= arg; } len= sizeof(get_member(f,name)); if(is_void(size)) size= len; addr+= len; if(len