home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / program / sprtools / c / io < prev    next >
Encoding:
Text File  |  1994-07-18  |  12.6 KB  |  462 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * io.c                                                                     *
  4.  * ====                                                                     *
  5.  *                                                                          *
  6.  * I/O routines for image format conversion programs                        *
  7.  *                                                                          *
  8.  * Version 1.00 (13-Aug-1993)                                               *
  9.  *         1.10 (20-Aug-1993) read_struct & write_struct added              *
  10.  *         1.20 (22-Aug-1993) new endian routines added                     *
  11.  *         1.30 (23-Aug-1993) progess function added                        *
  12.  *         1.41 (13-Oct-1993) progess start & finish functions added        *
  13.  *                                                                          *
  14.  * (C) 1993 DEEJ Technology PLC                                             *
  15.  *                                                                          *
  16.  ****************************************************************************/
  17.  
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include "io.h"
  22.  
  23. #ifndef ENDIAN_MACROS
  24.  
  25. /*
  26.  * little-endian to big-endian
  27.  */
  28.  
  29. uint swap_endian(uint dword)
  30. {
  31.         return( ((dword & 0xff000000)>>24) |
  32.                 ((dword & 0x00ff0000)>>8)  |
  33.                 ((dword & 0x0000ff00)<<8)  |
  34.                 ((dword & 0x000000ff)<<24) );
  35. }
  36.  
  37. /*
  38.  * little-endian to big-endian for 16 bit words
  39.  */
  40.  
  41. ushort swap_endian_word(ushort word)
  42. {
  43.         return( ((ushort)(word & 0xff00)>>8) |
  44.                 ((ushort)(word & 0x00ff)<<8) );
  45. }
  46.  
  47. /*
  48.  * swaps endian of DWORD/WORD if type doesnot match machine type
  49.  * type is LITTLE_ENDIAN (LE) or BIG_ENDIAN (BE)
  50.  */
  51.  
  52. uint endian(int type, uint dword)
  53. {
  54.         if(type != ENDIAN_TYPE)
  55.                 return(swap_endian(dword));
  56.         else
  57.                 return(dword);
  58. }
  59.  
  60. ushort endian_w(int type, ushort word)
  61. {
  62.         if(type != ENDIAN_TYPE)
  63.                 return(swap_endian_word(word));
  64.         else
  65.                 return(word);
  66. }
  67.  
  68. /*
  69.  * reverses bit fields in byte
  70.  */
  71.  
  72. uint bit_swap(uint byte)
  73. {
  74.         return( ((byte & 0x80)>>7) |
  75.                 ((byte & 0x40)>>5) |
  76.                 ((byte & 0x20)>>3) |
  77.                 ((byte & 0x10)>>1) |
  78.                 ((byte & 0x08)<<1) |
  79.                 ((byte & 0x04)<<3) |
  80.                 ((byte & 0x02)<<5) |
  81.                 ((byte & 0x01)<<7) );
  82. }
  83.  
  84. uint bit2_swap(uint byte)
  85. {
  86.         return( ((byte & 0xC0)>>6) |
  87.                 ((byte & 0x30)>>2) |
  88.                 ((byte & 0x0C)<<2) |
  89.                 ((byte & 0x03)<<6) );
  90. }
  91.  
  92. uint bit4_swap(uint byte)
  93. {
  94.         return( ((byte & 0xF0)>>4) |
  95.                 ((byte & 0x0F)<<4) );
  96. }
  97.  
  98. #endif
  99.  
  100. /* put/get word little endian */
  101.  
  102. void fputwLE(ushort word, FILE *file)
  103. {
  104.         word = endian_w(LE,word);
  105.         fwrite((char*)&word, sizeof(ushort), 1, file);
  106. }
  107.  
  108. ushort fgetwLE(FILE *file)
  109. {
  110.         ushort word;
  111.  
  112.         word = endian_w(LE,word);
  113.         fread((char*)&word, sizeof(ushort), 1, file);
  114.  
  115.         return(word);
  116. }
  117.  
  118. /* put/get word big endian */
  119.  
  120. void fputwBE(ushort word, FILE *file)
  121. {
  122.         word = endian_w(BE,word);
  123.         fwrite((char*)&word, sizeof(ushort), 1, file);
  124. }
  125.  
  126. ushort fgetwBE(FILE *file)
  127. {
  128.         ushort word;
  129.  
  130.         word = endian_w(BE,word);
  131.         fread((char*)&word, sizeof(ushort), 1, file);
  132.  
  133.         return(word);
  134. }
  135.  
  136. /* put/get double word little endian */
  137.  
  138. void fputdLE(uint dword, FILE *file)
  139. {
  140.         dword = endian(LE,dword);
  141.         fwrite((char*)&dword, sizeof(dword), 1, file);
  142. }
  143.  
  144. uint fgetdLE(FILE *file)
  145. {
  146.         uint dword;
  147.  
  148.         dword = endian(LE,dword);
  149.         fread((char*)&dword, sizeof(dword), 1, file);
  150.  
  151.         return(dword);
  152. }
  153.  
  154. /* put/get word big endian */
  155.  
  156. void fputdBE(uint dword, FILE *file)
  157. {
  158.         dword = endian(BE,dword);
  159.         fwrite((char*)&dword, sizeof(uint), 1, file);
  160. }
  161.  
  162. uint fgetdBE(FILE *file)
  163. {
  164.         uint dword;
  165.  
  166.         dword = endian(BE,dword);
  167.         fread((char*)&dword, sizeof(uint), 1, file);
  168.  
  169.         return(dword);
  170. }
  171.  
  172. /*
  173.  * reads input, output & progress filenames from argv
  174.  * and opens streams in, out & err. If names are not
  175.  * given the streams default to stdin, stdout & stderr 
  176.  *
  177.  * Can be used before arg processing if syntax is
  178.  * [-in <file>] [-out <file>] [-err <file>]. If so any parts
  179.  * found are removed from parameter list. If syntax is
  180.  * [<flags>...] [<infile> [<outfile> [<errfile]]], must be
  181.  * called after flags have been processed, and argc & argv
  182.  * ajusted to after the last flag.
  183.  */
  184.  
  185. void file_args(int argc, char **argv, FILE **in, FILE **out, FILE **err)
  186. {
  187.         char *infile, *outfile, *errfile;
  188.         int    o_argc = argc;
  189.         char **o_argv = argv;
  190.  
  191.         infile = outfile = errfile = 0;
  192.  
  193.         argc--; argv++;         /* skip program name */
  194.  
  195.         /* look for -in, -out, -err <file> */
  196.  
  197.         while(argc>0)
  198.         {
  199.             if(**argv=='-')
  200.             {
  201.                 switch( (*argv)[1] )
  202.                 {
  203.                 case 'i':
  204.                         if(strcmp(*argv, "-in")==0)
  205.                         {
  206.                                 **argv = 0;     /* clear flag from parameters */
  207.                                 argc--; argv++;
  208.                                 infile = *argv;
  209.                         }
  210.                         break;
  211.  
  212.                 case 'o':
  213.                         if(strcmp(*argv, "-out")==0)
  214.                         {
  215.                                 **argv = 0;
  216.                                 argc--; argv++;
  217.                                 outfile = *argv;
  218.                         }
  219.                         break;
  220.  
  221.                 case 'e':
  222.                         if(strcmp(*argv, "-err")==0)
  223.                         {
  224.                                 **argv = 0;
  225.                                 argc--; argv++;
  226.                                 errfile = *argv;
  227.                         }
  228.                         break;
  229.  
  230.                 default:
  231.                         break;
  232.                 }
  233.             }
  234.             /* next parameter */
  235.             argc--; argv++;
  236.         }
  237.  
  238.         /* if no filenames found try alternate syntax */
  239.  
  240.         if(infile==0 && outfile==0 && errfile==0)
  241.         {
  242.                 if(o_argc>=2 && o_argv[1][0]!='-')
  243.                 {
  244.                         infile  = o_argv[1];
  245.                         if(o_argc>=3 && o_argv[2][0]!='-')
  246.                         {
  247.                                 outfile = o_argv[2];
  248.                                 if(o_argc>=4 && o_argv[3][0]!='-')
  249.                                         errfile = o_argv[3];
  250.                         }
  251.                 }
  252.         }
  253.  
  254.         if(infile == 0)
  255.         {
  256.                 *in = stdin;
  257.         }
  258.         else
  259.         {
  260.                 if((*in = fopen(infile,"r")) == NULL)
  261.                 {
  262.                         fprintf(stderr, "Unable to open input file %s\n",
  263.                                         infile);
  264.                         exit(1);        
  265.                 }
  266.                 *infile = 0; /* remove from parameter list */
  267.         }
  268.         if(outfile == 0)
  269.         {
  270.                 *out = stdout;
  271.         }
  272.         else
  273.         {
  274.                 if((*out = fopen(outfile,"w")) == NULL)
  275.                 {
  276.                         fprintf(stderr, "Unable to open output file %s\n",
  277.                                         outfile);
  278.                         exit(2);        
  279.                 }
  280.                 *outfile = 0; /* remove from parameter list */
  281.         }
  282.         if(errfile == 0)
  283.         {
  284.                 *err = stderr;
  285.         }
  286.         else
  287.         {
  288.                 /*
  289.                  * open err file and ensure stderr from 
  290.                  * libraries uses it as well
  291.                  */
  292.  
  293.                 if((*err = freopen(errfile,"w",stderr)) == NULL)
  294.                 {
  295.                         /* dont use stderr as it will be closed */
  296.                         fprintf(stdout, "Unable to open error file %s\n",
  297.                                         errfile);
  298.                         exit(3);        
  299.                 }
  300.                 /* set no buffering of stderr file */
  301.                 setvbuf(*err, NULL, _IONBF, BUFSIZ);
  302.                 *errfile = 0; /* remove from parameter list */
  303.         }
  304. }
  305.  
  306. /*
  307.  * reads in a structure from a file
  308.  * correcting for endian'ness and arbitary alignment
  309.  *
  310.  * type    : LITTLE_ENDIAN or BIG_ENDIAN
  311.  * buffer  : structure cast to uchar*
  312.  * descrip : array of structure field sizes
  313.  *           (1=byte, 2=word, 4=dword, >4=string, -1=end of table)
  314.  * file    : file stream descriptor
  315.  */
  316.  
  317. void read_struct(int type, BYTE *buffer, int *descrip, FILE *file)
  318. {
  319.         WORD  word;
  320.         DWORD dword;
  321.  
  322.         while(*descrip != -1)
  323.         {
  324.                 switch(*descrip)
  325.                 {
  326.                 case 1:         /* byte */
  327.                         *buffer++ = fgetc(file);
  328.                         break;
  329.  
  330.                 case 2:         /* word */
  331.                         fread(&word, sizeof(WORD), 1, file);
  332.                         word = endian_w(type,word);
  333.  
  334.                         buffer = (BYTE*)
  335.                               (((int)buffer+ALIGN_WORD-1) & ~(ALIGN_WORD-1));
  336.                         memcpy(buffer, (char*)&word, sizeof(WORD));
  337.                         buffer += sizeof(WORD);
  338.                         break;
  339.  
  340.                 case 4:         /* double word */
  341.                         fread(&dword, sizeof(DWORD), 1, file);
  342.                         dword = endian(type,dword);
  343.  
  344.                         buffer = (BYTE*)
  345.                               (((int)buffer+ALIGN_DWORD-1) & ~(ALIGN_DWORD-1));
  346.                         memcpy(buffer, (char*)&dword, sizeof(DWORD));
  347.                         buffer += sizeof(DWORD);
  348.                         break;
  349.  
  350.                 default:
  351.                         if(*descrip > 0)
  352.                         {
  353.                                 fread(buffer, *descrip, 1, file);
  354.                                 buffer += *descrip;
  355.                         }
  356.                         break;
  357.                 }
  358.  
  359.                 /* description pointer */
  360.  
  361.                 descrip++;
  362.         }
  363. }
  364.  
  365. /*
  366.  * writes a structure to a file
  367.  * correcting for endian'ness and arbitary alignment
  368.  */
  369.  
  370. void write_struct(int type, BYTE *buffer, int *descrip, FILE *file)
  371. {
  372.         WORD  word;
  373.         DWORD dword;
  374.  
  375.         while(*descrip != -1)
  376.         {
  377.                 switch(*descrip)
  378.                 {
  379.                 case 1:         /* byte */
  380.                         fputc(*buffer++,file);
  381.                         break;
  382.  
  383.                 case 2:         /* word */
  384.                         buffer = (BYTE*)
  385.                               (((int)buffer+ALIGN_WORD-1) & ~(ALIGN_WORD-1));
  386.                         memcpy((char*)&word, buffer, sizeof(WORD));
  387.                         buffer += sizeof(WORD);
  388.  
  389.                         word = endian_w(type,word);
  390.                         fwrite(&word, sizeof(WORD), 1, file);
  391.                         break;
  392.  
  393.                 case 4:         /* double word */
  394.                         buffer = (BYTE*)
  395.                               (((int)buffer+ALIGN_DWORD-1) & ~(ALIGN_DWORD-1));
  396.                         memcpy((char*)&dword, buffer, sizeof(DWORD));
  397.                         buffer += sizeof(DWORD);
  398.  
  399.                         dword = endian(type,dword);
  400.                         fwrite(&dword, sizeof(DWORD), 1, file);
  401.                         break;
  402.  
  403.                 default:
  404.                         if(*descrip > 0)
  405.                         {
  406.                                 fwrite(buffer, *descrip, 1, file);
  407.                                 buffer += *descrip;
  408.                         }
  409.                         break;
  410.                 }
  411.  
  412.                 /* advance description pointer */
  413.  
  414.                 descrip++;
  415.         }
  416. }
  417.  
  418. /*
  419.  * prints banner before calls to progress()
  420.  * string should not contain newline
  421.  */
  422.  
  423. void progress_start(char *string)
  424. {
  425.         fprintf(stderr, string);
  426.     progress(0,100);
  427. }
  428.  
  429. /*
  430.  * displays progress of operation on stderr
  431.  * by printing dots every 2% of completion
  432.  * determined by value of current and max
  433.  */
  434.  
  435. void progress(int current, int max)
  436. {
  437.         static old_percent = 0;
  438.         int    percent     = (current*100)/max;
  439.         int    i;
  440.  
  441.     /* reset on for new progress indication */
  442.  
  443.     if(percent < old_percent) old_percent = 0;
  444.  
  445.         if(percent-old_percent>=2)
  446.         {
  447.                 for(i=old_percent; i<percent; i+=2)
  448.                         fputc('.', stderr);
  449.                 old_percent = percent;
  450.         }
  451. }
  452.  
  453. /*
  454.  * ensure display is correct after calls to progress()
  455.  */
  456.  
  457. void progress_finish(void)
  458. {
  459.     progress(100,100);
  460.         fprintf(stderr,"\n");
  461. }
  462.