home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / xv221src / unsupt / vms / gifmapf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-26  |  6.3 KB  |  204 lines

  1. /*
  2.  * Define substitute routines for the fopen/fclose/fread/fgetc calls done by
  3.  * the gif decoder.  Map the gif file to memory and access via page faults.
  4.  */
  5. #include stdio
  6. #include atrdef
  7. #include fab
  8. #include fibdef
  9. #include nam
  10. #include iodef
  11. #include secdef
  12. typedef struct {
  13.     unsigned char *pos;        /* points to next char to read */
  14.     unsigned char *start;
  15.     unsigned char *end;
  16.     int chan, size;
  17. } map_block;
  18.  
  19. static int map_block_in_use = 0;
  20. static int max_mapped = 0;    /* largest address region used */
  21. static unsigned char *max_region = NULL;
  22. static map_block giffile;
  23. /*
  24.  * Open file for access.  A returned size of -1 indicates error.
  25.  */
  26. map_block *gif_fopen ( Filestring )
  27.     char *Filestring;
  28. {
  29.     unsigned char *address, *inadr[2], *retadr[2];
  30.     int size, status, channel, func_code;
  31.     int sys$assign(), sys$qiow(), sys$crmpsc(), sys$expreg();
  32.     short int iosb[4];
  33.     struct { long length; char *adr; } desc, fib_desc;
  34.     struct {
  35.     unsigned char rtype, rattrib;
  36.     unsigned short int  rsize, hiblk[2], efblk[2], ffbyte;
  37.     unsigned char bktsize, vfcsize;
  38.     unsigned short int maxrec, defext, gbc, fill[4], versions;
  39.     } fat;            /* File attributes block (RMS) */
  40.    struct FAB fab;        /* File access block (RMS) */
  41.    struct NAM nam;        /* Name block (RMS) */
  42.    struct fibdef fib;        /* File information block (XQP) */
  43.    struct atrdef atr[2];    /* Read attributes descriptor list */
  44.    char esa[256], rsa[256];    /* aux storage for nam block */
  45.  
  46.    /*
  47.     * Close currently open file and init block to error status (size = -1).
  48.     */
  49.    if ( map_block_in_use ) (void) gif_fclose();
  50.    giffile.start = giffile.end = giffile.pos = "";
  51.    giffile.size = -1;
  52.  
  53.       /* Use RMS services to lookup fspec, initialize FAB and NAM blocks */
  54.  
  55.       fab = cc$rms_fab;
  56.       fab.fab$l_fna = Filestring; fab.fab$b_fns = strlen ( Filestring );
  57.       fab.fab$l_dna = ".GIF"; fab.fab$b_dns = strlen ( fab.fab$l_dna );
  58.       fab.fab$l_fop = FAB$M_NAM;    /* file options */
  59.       fab.fab$l_nam = &nam;
  60.       nam = cc$rms_nam;
  61.       nam.nam$b_ess = 255;
  62.       nam.nam$l_esa = &esa;
  63.       nam.nam$b_rss = 255;
  64.       nam.nam$l_rsa = &rsa;
  65.  
  66.       /* use $parse and $search for find file, device and FID will end up in 
  67.          nam  block */
  68.  
  69.       status = sys$parse ( &fab );  if ((status&3) != 1) return &giffile;
  70.       status = sys$search ( &fab ); if ((status&3) != 1) return &giffile;
  71.  
  72.       /* Define descriptor to assign and load FID in FIB */
  73.  
  74.       desc.length = nam.nam$t_dvi[0];        /* length */
  75.       desc.adr = &nam.nam$t_dvi[1];
  76.       func_code = IO$_ACCESS + IO$M_ACCESS; /* actually open the file */
  77.       fib.fib$r_fid_overlay.fib$w_fid[0] = nam.nam$w_fid[0];
  78.       fib.fib$r_fid_overlay.fib$w_fid[1] = nam.nam$w_fid[1];
  79.       fib.fib$r_fid_overlay.fib$w_fid[2] = nam.nam$w_fid[2];
  80.  
  81.    /* build atrribute descriptor list for returning record attributes */
  82.  
  83.    atr[0].atr$w_size = sizeof(fat);
  84.    atr[0].atr$w_type = ATR$C_RECATTR;
  85.    atr[0].atr$l_addr = &fat;
  86.    atr[1].atr$w_size = 0; atr[1].atr$w_type = 0;
  87.  
  88.    /* assign channel to disk specified in NAM block. */
  89.  
  90.    channel = 0;
  91.    status = sys$assign ( &desc, &channel, 0, 0 );
  92.    if ((status&3) != 1) return &giffile;
  93.     
  94.     /* build FIB and access (open file) */
  95.    fib_desc.length = 10; fib_desc.adr = (char *) &fib;
  96.     fib.fib$r_acctl_overlay.fib$l_acctl = 0;
  97.     status = sys$qiow 
  98.     ( 0, channel, func_code, &iosb, 0, 0, &fib_desc, 0, 0, 0, &atr, 0 );
  99.     if ( (status&1) == 1 ) status = iosb[0];
  100.     if ( (status&1) != 1 ) return &giffile;
  101.  
  102.     /* Determine size of file and create section */
  103.     size = fat.efblk[0];
  104.     size = (size<<16) | fat.efblk[1];    /* invert word order */
  105.     size = (size-1)*512 + fat.ffbyte;
  106.  
  107.     /*
  108.      * Make a large region of P0 space to hold contents of file plus
  109.      * 500 blocks spare.
  110.      */
  111.     if ( max_mapped <= size ) {
  112.     int pages;
  113.     pages = ((size+511)/512) + 500;
  114.         status = sys$expreg ( pages, &retadr, 0, 0 );
  115.         if ( (status&1) != 1 ) return &giffile;
  116.         max_region = retadr[0];
  117.         max_mapped = (pages*512) - 1;
  118.     }
  119.  
  120.     /* Map file into address space. */
  121.     inadr[0] = max_region;
  122.     inadr[1] = &max_region[size-1];
  123.     status = sys$crmpsc ( &inadr, &retadr, 0, 0, 0, 0, 0,
  124.         channel, (size+511)/512, 0, 0, 64 );
  125.     if ( (status&1) != 1 ) return &giffile;
  126.     address = retadr[0];
  127.     map_block_in_use = 1;
  128.  
  129.     /*
  130.      * Allocate structure to store file state and initialize it.
  131.      */
  132.     giffile.start = address;
  133.     giffile.end = &address[size];
  134.     giffile.pos = address;
  135.     giffile.chan = channel;
  136.     giffile.size = size;
  137.     return &giffile;
  138. }
  139.  
  140. int gif_fclose ( )
  141. {
  142.     void sys$dassgn();
  143.     if ( map_block_in_use && (giffile.size > 0) ) sys$purgws ( &giffile.start );
  144.     map_block_in_use = 0;
  145.     sys$dassgn ( giffile.chan );
  146.     return 0; 
  147. }
  148.  
  149. int gif_fgetc ( )
  150. {
  151.     int result;
  152.     if ( giffile.pos >= giffile.end ) return -1;
  153.     result = *giffile.pos++;
  154.     return result;
  155. }
  156.  
  157. int gif_fread ( buffer, unit, count )
  158.     unsigned char *buffer;
  159.     unsigned int unit, count;    /* max count is 65535 */
  160. {
  161.     unsigned char *next_pos;
  162.     /* determin number of charaters to move */
  163.     count *= unit;
  164.     if ( giffile.pos >= giffile.end ) return 0;
  165.     next_pos = &giffile.pos[count];
  166.     while ( next_pos >= giffile.end ) next_pos = &giffile.pos[--count];
  167.  
  168.     LIB$MOVC3 ( &count, giffile.pos, buffer );
  169.     giffile.pos = next_pos;
  170.     return count;
  171. }
  172.  
  173. unsigned char *gif_freadm ( unit, count )
  174.     unsigned int unit, count;    /* max count is 65535 */
  175. {
  176.     unsigned char *cur_pos, *next_pos;
  177.     /* determin number of charaters to move */
  178.     count *= unit;
  179.     if ( giffile.pos >= giffile.end ) return NULL;
  180.     cur_pos = giffile.pos;
  181.     next_pos = &cur_pos[count];
  182.     while ( next_pos >= giffile.end ) --next_pos;
  183.     giffile.pos = next_pos;
  184.     return cur_pos;
  185. }
  186.  
  187. int gif_fget_counted ( map, desc )
  188.     map_block *map;
  189.     struct { int len; char *addr; } *desc;
  190. {
  191.     int length;
  192.     if ( map->pos < map->end ) {
  193.     /* Get length of record and truncate to EOF if needed */
  194.     for ( length = *map->pos++; &map->pos[length] > map->end; --length);
  195.  
  196.     /* fill out descriptor and update position pointer */
  197.     desc->len = length;
  198.     desc->addr = map->pos;
  199.     map->pos = &map->pos[length];
  200.     return 1;
  201.     }
  202.     return 2160;
  203. }
  204.