home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / VideoToolbox 95.04.18 / VideoToolboxSources / TranslateLinefeeds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-08  |  7.0 KB  |  198 lines  |  [TEXT/MMCC]

  1. /*
  2. TranslateLinefeeds.c helps to resolve an incompatibility between the MPW stdio
  3. library and code resources generated by the THINK C compiler. This is a problem
  4. if you need to link them together. The problem is that MPW and THINK C have
  5. adopted different solutions to the problem that Standard C specifies that
  6. linefeeds should be represented as '\n' (normally 10) inside programs, yet
  7. Apple, in their wisdom, decided that linefeeds should be represented by 13
  8. (normally '\r') in Macintosh ASCII text files. The problem is handled invisibly
  9. by both compilers. MPW redefines '\n' to mean 13. THINK C translates 13 to 10
  10. (and vice versa) when writing and reading text streams. Unfortunately, when you
  11. compile THINK C code resources that call the MPW stdio library both solutions
  12. are eliminated and the old problem raises its ugly head.
  13.  
  14. This file does NOT SUPPORT Metrowerks CodeWarrior C compiler.
  15.  
  16. TranslateLinefeeds.c intercepts the calls to the (MPW) stdio library and partially
  17. implements the THINK C stdio library convention of translating \n to \r and vice
  18. versa on input and output to text files. Let's call this "linefeed translation".
  19. (As in the THINK C stdio library, no translation is performed for binary files.)
  20. These routines should only be used by THINK C code resources that must use the
  21. MPW stdio library (because the MPW C stdio library doesn't do linefeed
  22. translation). Don't change your C programs; use the standard names for the stdio
  23. library routines and just #include the TranslateLinefeeds.h header (after stdio.h).
  24. The TranslateLinefeeds.h header uses preprocessor macros to redirect nearly all the
  25. stdio calls to this file, which interposes linefeed translation and calls the
  26. (MPW) stdio library.
  27.  
  28. I've implemented all the i/o routines in stdio.h except fscanf and scanf.
  29. They're difficult to handle, and I suspect that most uses of those routines
  30. wouldn't distinguish /n from /r anyway.
  31.  
  32. All the printf-related routines are funneled through vfprintfTL. The actual
  33. i/o is done by vfprintf(). If it's a "text" stream (as opposed to a "binary"
  34. stream), then we translate the format string before calling vfprintf(), and
  35. translate again afterwards, restoring the original string. This is a pretty good
  36. solution, translating most of the linefeeds, but it fails to translate linefeeds
  37. that appear in string and char arguments.
  38.  
  39. Our implementation of translation is incomplete for printf et al., and
  40. nonexistent for scanf and fscanf because scanning the variable argument list
  41. would require too much effort, requiring us to implement a large fraction of the
  42. printf/scanf code: parsing the format string into tokens, retrieving each
  43. argument, and passing them one at a time to fprintf/scanf.
  44.  
  45. The time overhead of these routines is negligible. All stdio functions that may
  46. be implemented as inline macros are redefined by TranslateLinefeeds.h as new inline
  47. macros that call the original routines.
  48.  
  49. Note that the getchar and putchar macros in TranslateLinefeeds.h assume that stdin
  50. and stdout are "text" streams, though I haven't checked whether this is
  51. guaranteed by Standard C.
  52.  
  53. For debugging, disabling the TRANSLATE flag results in the identity translation, 
  54. making all the code innocuous.
  55.  
  56. HISTORY:
  57. 7/31/93    dgp wrote it.
  58. 7/31/93    dgp Added support for MPW stdio library.
  59. 9/20/93    dgp Rewrote vfprintfTL to work with text strings of unlimited length.
  60.             Documented limitation of the new vfprintfTL. Implemented
  61.             getc, putc, getchar, and putchar as inline macros, in TranslateLinefeeds.h.
  62. */
  63. #if !defined(THINK_C)
  64.     #error "This file is intended solely for THINK C resources that will be called by MPW"
  65. #else
  66. #include "TranslateLinefeeds.h"
  67. #include <string.h>
  68. #undef fread
  69. #undef fwrite
  70. #undef fgetc
  71. #undef ungetc
  72. #undef fputc
  73. #undef gets
  74. #undef fgets
  75. #undef fputs
  76. #undef vfprintf
  77. #define TRANSLATE 1    /* set this to zero for identity translation, for debugging */
  78.  
  79. unsigned char translateLinefeed[256]={
  80.     #if TRANSLATE
  81.         0,1,2,3,4,5,6,7,8,9,13,11,12,10,14,15,16,17,18,19
  82.     #else
  83.         0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
  84.     #endif
  85.     ,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
  86.     ,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59
  87.     ,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79
  88.     ,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99
  89.     ,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119
  90.     ,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139
  91.     ,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  92.     ,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179
  93.     ,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199
  94.     ,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219
  95.     ,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  96.     ,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
  97. };
  98.  
  99. void TranslateLinefeeds(register char *s,register size_t n)
  100. {
  101.     if(s!=NULL)for(;n>0;n--)*s++=translateLinefeed[(unsigned char)*s];
  102. }
  103.  
  104. size_t freadTL(void *s,size_t size,size_t numitems,FILE *stream)
  105. {
  106.     numitems=fread(s,size,numitems,stream);
  107.     if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
  108.     return numitems;
  109. }
  110. size_t fwriteTL(void *s,size_t size,size_t numitems,FILE *stream)
  111. {
  112.     size_t n;
  113.     
  114.     if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
  115.     n=fwrite(s,size,numitems,stream);
  116.     if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
  117.     return n;
  118. }
  119. int fgetcTL(FILE *stream)
  120. {
  121.     char c;
  122.  
  123.     c=fgetc(stream);
  124.     if(IS_TEXT(stream))return translateLinefeed[(unsigned char)c];
  125.     else return c;
  126. }
  127. char *fgetsTL(char *string,int n,FILE *stream)
  128. {
  129.     char *s;
  130.     
  131.     s=fgets(string,n,stream);
  132.     if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
  133.     return s;
  134. }
  135. int fputcTL(int c,FILE *stream)
  136. {
  137.     int i;
  138.  
  139.     if(IS_TEXT(stream))c=translateLinefeed[(unsigned char)c];
  140.     return fputc(c,stream);
  141. }
  142. int fputsTL(char *s,FILE *stream)
  143. {
  144.     int error;
  145.     
  146.     if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
  147.     error=fputs(s,stream);
  148.     if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
  149.     return error;
  150. }
  151. int fprintfTL(FILE *stream,const char *format,...)
  152. {
  153.     va_list args;
  154.     int n;
  155.     
  156.     va_start(args,format);
  157.     n=vfprintfTL(stream,format,args);
  158.     va_end(args);
  159.     return n;
  160. }
  161. char *getsTL(char *string)
  162. {
  163.     char *s;
  164.     
  165.     s=gets(string);
  166.     if(IS_TEXT(stdin))TranslateLinefeeds(s,strlen(s));
  167.     return s;
  168. }
  169. int printfTL(char *format,...)
  170. {
  171.     va_list args;
  172.     int n;
  173.     
  174.     va_start(args,format);
  175.     n=vfprintfTL(stdout,format,args);
  176.     va_end(args);
  177.     return n;
  178. }
  179. /*
  180. In vfprintfTL we only translate the format string. We'll miss linefeeds that
  181. are hiding in char and string arguments in the variable argument list. Finding
  182. those would require a much more elaborate program, which would parse the format
  183. string.
  184. */
  185. int vfprintfTL(FILE *stream,const char *format,va_list args)
  186. {
  187.     int n;
  188.     
  189.     if(IS_TEXT(stream))TranslateLinefeeds((char *)format,strlen((char *)format));
  190.     n=vfprintf(stream,format,args);
  191.     if(IS_TEXT(stream))TranslateLinefeeds((char *)format,strlen((char *)format));
  192.     return n;
  193. }
  194. int vprintfTL(char *format,va_list args)
  195. {
  196.     return vfprintfTL(stdout,format,args);
  197. }
  198. #endif