Article View: vmsnet.misc
Article #30XV(v2.11) for VMS: new GIFMAPF.C => DECNET access
From: Rick Dyson
Date: Wed, 15 Apr 1992 20:15
Date: Wed, 15 Apr 1992 20:15
329 lines
11620 bytes
11620 bytes
/*
* I've modified gifmapf.c (included below) to fallback to reading the file
* via RMS if the search operation does not return a device, which is required
* for mapping the file via $CRMPSC.
*
* With this change,
* XV node::disk:[dir]*.gif
* will now work.
*
* >>Dave
*
* Comments follow that were made by several people concerning DECNET
* access of a GIF with XV. There is a minor mod of VMS.C that is
* mentioned a couple paragraphs down that you might consider making.
* Use your own discretion... (or indiscretion....;)
*
* BTW, mapping the file to memory is faster than reading the file record by
* record, but it doesn't seem any faster than reading the whole file at once
* with a single fread() call. The mapping method does save you the trouble
* of fighting with VAXCRTL/RMS to get it to handle files with certain record
* attributes, however.
*
* >I've defined DEVICE_LIST_ROOT to allow selecting different disks, and this
* >works well, where each directory name in this directory is the name of
* >a concealed logical name pointing to another device.
* >
* >However, this won't work when the logical name includes a node name.
*
* To put remote node disk/directories into DEVICE_LIST_ROOT, you make for
* that directory name a logical of the form "node::disk:", where disk may
* be a device name or concealed logical defined on the remote node. Note
* that the directory name logical does not have the concealed attribute in
* this case.
*
* This should be all you need to do, but it turns out that stat() calls
* won't recognize directories over DECnet links, so you can't get past the
* root level. You need to comment out the following line in VMS.C to make
* it work:
*
* else return (stat ( f, st ));
*
*
* This change makes XV slightly less robust, but it is a small price to pay
* for the increased functionality. Once you've gone to the new directory,
* the "/" entry in the directory list is replaced by "/node", but you can
* still navigate back to device_list_root.
*
*
* David L. Jones | Phone: (614) 292-6929
* Ohio State Unviversity | Internet:
* 1971 Neil Ave. Rm. 406 | jonesd@kcgl1.eng.ohio-state.edu
* Columbus, OH 43210 | jones-d@eng.ohio-state.edu
*
*/
/*
*
* Define substitute routines for the fopen/fclose/fread/fgetc calls done by
* the gif decoder. Map the gif file to memory and access via page faults.
*/
#include stdio
#include atrdef
#include fab
#include fibdef
#include nam
#include iodef
#include secdef
typedef struct {
unsigned char *pos; /* points to next char to read */
unsigned char *start;
unsigned char *end;
int chan, size;
} map_block;
static int map_block_in_use = 0;
static int max_mapped = 0; /* largest address region used */
static unsigned char *max_region = NULL;
static map_block giffile;
map_block *gif_fopen_fallback();
/*
* Open file for access. A returned size of -1 indicates error.
*/
map_block *gif_fopen ( Filestring )
char *Filestring;
{
unsigned char *address, *inadr[2], *retadr[2];
int size, status, channel, func_code;
int sys$assign(), sys$qiow(), sys$crmpsc(), sys$expreg();
short int iosb[4];
struct { long length; char *adr; } desc, fib_desc;
struct {
unsigned char rtype, rattrib;
unsigned short int rsize, hiblk[2], efblk[2], ffbyte;
unsigned char bktsize, vfcsize;
unsigned short int maxrec, defext, gbc, fill[4], versions;
} fat; /* File attributes block (RMS) */
struct FAB fab; /* File access block (RMS) */
struct NAM nam; /* Name block (RMS) */
struct fibdef fib; /* File information block (XQP) */
struct atrdef atr[2]; /* Read attributes descriptor list */
char esa[256], rsa[256]; /* aux storage for nam block */
/*
* Close currently open file and init block to error status (size = -1).
*/
if ( map_block_in_use ) (void) gif_fclose();
giffile.start = giffile.end = giffile.pos = "";
giffile.size = -1;
/* Use RMS services to lookup fspec, initialize FAB and NAM blocks */
fab = cc$rms_fab;
fab.fab$l_fna = Filestring; fab.fab$b_fns = strlen ( Filestring );
fab.fab$l_dna = ".GIF"; fab.fab$b_dns = strlen ( fab.fab$l_dna );
fab.fab$l_fop = FAB$M_NAM; /* file options */
fab.fab$l_nam = &nam;
nam = cc$rms_nam;
nam.nam$b_ess = 255;
nam.nam$l_esa = &esa;
nam.nam$b_rss = 255;
nam.nam$l_rsa = &rsa;
/* use $parse and $search for find file, device and FID will end up in
nam block */
status = sys$parse ( &fab ); if ((status&3) != 1) return &giffile;
status = sys$search ( &fab ); if ((status&3) != 1) return &giffile;
/* Define descriptor to assign and load FID in FIB */
desc.length = nam.nam$t_dvi[0]; /* length */
desc.adr = &nam.nam$t_dvi[1];
func_code = IO$_ACCESS + IO$M_ACCESS; /* actually open the file */
fib.fib$r_fid_overlay.fib$w_fid[0] = nam.nam$w_fid[0];
fib.fib$r_fid_overlay.fib$w_fid[1] = nam.nam$w_fid[1];
fib.fib$r_fid_overlay.fib$w_fid[2] = nam.nam$w_fid[2];
/* If no device name, try it with real open (DECnet operation) */
if ( desc.length == 0 ) return gif_fopen_fallback ( Filestring );
/* build atrribute descriptor list for returning record attributes */
atr[0].atr$w_size = sizeof(fat);
atr[0].atr$w_type = ATR$C_RECATTR;
atr[0].atr$l_addr = &fat;
atr[1].atr$w_size = 0; atr[1].atr$w_type = 0;
/* assign channel to disk specified in NAM block. */
channel = 0;
status = sys$assign ( &desc, &channel, 0, 0 );
if ((status&3) != 1) return &giffile;
/* build FIB and access (open file) */
fib_desc.length = 10; fib_desc.adr = (char *) &fib;
fib.fib$r_acctl_overlay.fib$l_acctl = 0;
status = sys$qiow
( 0, channel, func_code, &iosb, 0, 0, &fib_desc, 0, 0, 0, &atr, 0 );
if ( (status&1) == 1 ) status = iosb[0];
if ( (status&1) != 1 ) return &giffile;
/* Determine size of file and create section */
size = fat.efblk[0];
size = (size<<16) | fat.efblk[1]; /* invert word order */
size = (size-1)*512 + fat.ffbyte;
/*
* Make a large region of P0 space to hold contents of file plus
* 500 blocks spare.
*/
if ( max_mapped <= size ) {
int pages;
pages = ((size+511)/512) + 500;
status = sys$expreg ( pages, &retadr, 0, 0 );
if ( (status&1) != 1 ) return &giffile;
max_region = retadr[0];
max_mapped = (pages*512) - 1;
}
/* Map file into address space. */
inadr[0] = max_region;
inadr[1] = &max_region[size-1];
status = sys$crmpsc ( &inadr, &retadr, 0, 0, 0, 0, 0,
channel, (size+511)/512, 0, 0, 64 );
if ( (status&1) != 1 ) return &giffile;
address = retadr[0];
map_block_in_use = 1;
/*
* Allocate structure to store file state and initialize it.
*/
giffile.start = address;
giffile.end = &address[size];
giffile.pos = address;
giffile.chan = channel;
giffile.size = size;
return &giffile;
}
int gif_fclose ( )
{
void sys$dassgn();
if ( map_block_in_use && (giffile.size > 0) ) sys$purgws ( &giffile.start );
map_block_in_use = 0;
sys$dassgn ( giffile.chan );
return 0;
}
int gif_fgetc ( )
{
int result;
if ( giffile.pos >= giffile.end ) return -1;
result = *giffile.pos++;
return result;
}
int gif_fread ( buffer, unit, count )
unsigned char *buffer;
unsigned int unit, count; /* max count is 65535 */
{
unsigned char *next_pos;
/* determin number of charaters to move */
count *= unit;
if ( giffile.pos >= giffile.end ) return 0;
next_pos = &giffile.pos[count];
while ( next_pos >= giffile.end ) next_pos = &giffile.pos[--count];
LIB$MOVC3 ( &count, giffile.pos, buffer );
giffile.pos = next_pos;
return count;
}
unsigned char *gif_freadm ( unit, count )
unsigned int unit, count; /* max count is 65535 */
{
unsigned char *cur_pos, *next_pos;
/* determin number of charaters to move */
count *= unit;
if ( giffile.pos >= giffile.end ) return NULL;
cur_pos = giffile.pos;
next_pos = &cur_pos[count];
while ( next_pos >= giffile.end ) --next_pos;
giffile.pos = next_pos;
return cur_pos;
}
int gif_fget_counted ( map, desc )
map_block *map;
struct { int len; char *addr; } *desc;
{
int length;
if ( map->pos < map->end ) {
/* Get length of record and truncate to EOF if needed */
for ( length = *map->pos++; &map->pos[length] > map->end; --length);
/* fill out descriptor and update position pointer */
desc->len = length;
desc->addr = map->pos;
map->pos = &map->pos[length];
return 1;
}
return 2160;
}
/*
* Fallback to reading file into memory with C RTL functions.
*/
map_block *gif_fopen_fallback ( Filestring )
char *Filestring;
{
unsigned char *address;
int size, status, channel, func_code;
int sys$assign();
struct { long length; char *adr; } desc;
FILE *fp;
/* printf("Loading network file..."); */
fp = fopen ( Filestring, "rb" );
if ( fp == (FILE *) NULL )
{ /* printf(" could not open.\n"); */ return &giffile; }
/* find the size of the file by positioning to end. */
fseek(fp, 0L, 2);
size = ftell(fp);
/* printf(" size is %d bytes.\n", size ); */
fseek(fp, 0L, 0);
/* determine if we must allocat new block or can reuse existing one */
if ( max_mapped <= size ) {
/*
* Make a large region of P0 space to hold contents of file plus
* 500 blocks spare.
*/
int pages, retadr[2], sys$expreg();
pages = ((size+511)/512) + 500;
status = sys$expreg ( pages, &retadr, 0, 0 );
if ( (status&1) != 1 ) return &giffile;
max_region = retadr[0];
max_mapped = (pages*512) - 1;
}
address = max_region;
/* read data into memory and close file */
status = fread(address, size, 1, fp );
fclose ( fp );
if ( status != 1 ) return &giffile; /* error in read */
map_block_in_use = 1;
desc.length = 3; desc.adr = "NL:"; channel = 0;
status = sys$assign ( &desc, &channel, 0, 0 );
/*
* Allocate structure to store file state and initialize it.
*/
giffile.start = address;
giffile.end = &address[size];
giffile.pos = address;
giffile.chan = channel;
giffile.size = size;
return &giffile;
}
--
Richard L. Dyson INTERNET: Dyson@IowaSP.Physics.UIowa.EDU
Graduate Research Assistant NSI/DECnet: IOWASP::DYSON or 7231::DYSON
Department of Physics & Astronomy H: (319) 338--6117
The University of Iowa O: (319) 335--1879
Iowa City, IA 52242-1479
Technical Details
Message-ID:
<1992Apr15.151502.1@iowasp.physics.uiowa.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!usc!zaphod.mps.ohio-state.edu!hobbes.physics.uiowa.edu!iowasp.physics.uiowa.edu!dysonShow Full Headers
Complete Article Headers
Newsgroups: vmsnet.misc Path: arc1-ca.pugleaf.net!sparky!uunet!usc!zaphod.mps.ohio-state.edu!hobbes.physics.uiowa.edu!iowasp.physics.uiowa.edu!dyson From: dyson@iowasp.physics.uiowa.edu (Rick Dyson) Subject: XV(v2.11) for VMS: new GIFMAPF.C => DECNET access Message-ID: <1992Apr15.151502.1@iowasp.physics.uiowa.edu> Lines: 331 Sender: news@space.physics.uiowa.edu Nntp-Posting-Host: lafvax.physics.uiowa.edu Organization: Department of Physics and Astronomy, University of Iowa Date: Wed, 15 Apr 1992 20:15:02 GMT