home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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;
- /*
- * 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];
-
- /* 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;
- }
-