home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 344_01 / p2s.l < prev    next >
Text File  |  1990-09-21  |  7KB  |  308 lines

  1. /*
  2. * File: P2S.L
  3. *
  4. * Program: 
  5. *                 P2S
  6. *
  7. *         printf() to streams i/o converter
  8. *
  9. * Description:
  10. *
  11. * Converts printf() calls to << operators
  12. * Uses Lex to find printf's, fprintf's and sprintf's in C source
  13. * and then uses p2s() call to convert the printf arguments to C++ streams
  14. * formatted I/O.
  15. * Does handle things like %6.2f (width and precision flags)
  16. * by generating the appropriate streams manipulators - setw()
  17. * and setprecision().
  18. * Does NOT handle things like %-6.2f (yet) since there are no manipulators
  19. * for left and right justification (if you decide to enhance this to
  20. * handle this or anything else please submit back to CUG or me)
  21. *
  22. * stdin reads inoriginal C source, converted source goes to stdout.
  23. *
  24. * Usage: 
  25. *
  26. * P2S < {.c file with printfs} > {file with streams i/o}
  27. * Options:
  28. *    f - don't convert fprintf()'s
  29. *    p - don't convert printf()'s
  30. *    s - don't convert sprintf()'s
  31. *    i - converts by doing 
  32. *        #ifdef __cplusplus
  33. *          ... streams code ..
  34. *        #else
  35. *          ... old printf code ...
  36. *        #endif
  37. *        to maintain backward compatibility with C (if desired)
  38. *
  39. * Example:
  40. *
  41. * For example to only convert fprintf calls and maintain C compatibility
  42. * the invocation is:
  43. *
  44. *     p2s p s i < foo.c >foo.cpp
  45. *         
  46. *    
  47. * Construction:
  48. *
  49. * Just flex (or lex) this file, and compile the resultant C source. 
  50. * MKP2S.BAT shows how to make program with Flex and Turbo C.
  51. *
  52. * Restrictions:
  53. * You may use this program without restriction as a tool in your own 
  54. * development efforts. 
  55. * You MAY NOT redistribute either the source or executables, in modified
  56. * or unmodified form, for any amount of money or along with any other 
  57. * commercial package. You must include this copyright in any program
  58. * which uses this source and you may not distribute such programs 
  59. * commercially. No restrictions apply to any programs which you converted
  60. * using this tool (using the tool is unrestricted, distributing it or using
  61. * its source is).
  62. * Copyright (c) 1990. Adam Blum, Retrieval Systems Corporation,(703)-524-4534
  63. */
  64.  
  65. %{
  66. #include<stdio.h>
  67. #include<ctype.h>
  68. /* prototypes */
  69. int p2s(char *s1,char *s2);
  70. char *prs(char *p,char *s);
  71. char *getfmt(char *p,int *prec,int *width);
  72. void strrepl(char *s,char *srch,char *repl);
  73.  
  74. #define QUOTE 34
  75.  
  76. /* variables */
  77. int ifdef=0,sprt=1,fprt=1,prt=1,i;
  78.  
  79. %}
  80.  
  81. %%
  82. /*        PATTERNS            */
  83.  
  84. #define.*\n    {ECHO;}
  85. printf\([^\;]*\)\; {
  86.         if(prt)
  87.             p2sprt(yytext,yyleng,yytext+7);
  88.         else {
  89.             ECHO;
  90.         }
  91.         return 1;}
  92. fprintf\([^\;]*\)\; {
  93.         if(fprt)
  94.             p2sprt(yytext,yyleng,yytext+8);
  95.         else{
  96.             ECHO;
  97.         }
  98.         return 1;}
  99.  
  100. sprintf\([^\;]*\)\; {
  101.         if(sprt)
  102.             p2sprt(yytext,yyleng,yytext+8);
  103.         else {
  104.             ECHO;
  105.         }
  106.         return 1;}
  107. .|\n    {ECHO;return 1;}
  108. %%
  109. /*        FUNCTIONS            */
  110. main(int argc,char **argv)
  111. {
  112.     for(i=0;i<argc;i++){
  113.         switch(toupper(argv[i][0])){
  114.         case 'I':ifdef=1;break;
  115.         case 'S':sprt=0;break;
  116.         case 'F':fprt=0;break;
  117.         case 'P':prt=0;break;
  118.         }
  119.     }        
  120.     fprintf(stderr,           
  121. "printf to C++ streams converter, (c) 1990, Adam Blum, Retrieval Systems Corp.\n");
  122.     fprintf(stderr,
  123. "Usage: p2s <{source with printf calls} >{output with streams operators}\n");
  124.     for(;;){
  125.         if(yylex()<1)break;
  126.     }
  127. }
  128.  
  129. ctparens(char *s,int n)
  130. {
  131.     int i,ct=0;
  132.     for(i=0;i<n;i++)    
  133.         if(s[i]=='(')
  134.             ct++;
  135.         else if(s[i]==')')
  136.             ct--;
  137.     return ct;
  138. }
  139.  
  140. /* P2SPRT
  141. * Print the converted strings
  142. */
  143. p2sprt(char *base,int n,char *s)
  144. {
  145.     char s1[256],s2[1024];
  146.     strncpy(s1,s,n);
  147.     s1[n]=0;
  148.     p2s(s1,s2);    
  149.     if(ifdef)
  150.         printf("\n#ifdef __cplusplus\n%s;\n#else\n%s\n#endif\n",s2,base);
  151.     else
  152.          printf("\n/* was %s*/\n%s;",base,s2);
  153. }
  154.  
  155.  
  156. /* P2S
  157. * Convert printf arguments to formatted streams I/O
  158. */
  159. p2s(char *s1,char *s2)
  160. {
  161.     char srch[16],arg[256],*p=s1;
  162.     int replno=0,width,prec,i;
  163.     /* grab the filename first, and pass it through
  164.      untranslated. streams opening and closing of
  165.      file will have to be translated manually */
  166.     for(;isspace(*p);p++)
  167.         ;
  168.     if(*p==QUOTE){
  169.         strcpy(s2,"cout\0");
  170.     }
  171.     else if(!strncmp(p,"stderr",6)){
  172.         strcpy(s2,"cerr\0");
  173.         /* read up to first quote mark for formatting string */
  174.         for(;*p!='"'&&*p;p++)
  175.             ;
  176.  
  177.     }
  178.     else{
  179.         p=prs(p,s2);
  180.         /* stream operator directed to file stream */
  181.         /* read up to first quote mark for formatting string */
  182.         for(;*p!='"'&&*p;p++)
  183.             ;
  184.     }
  185.     if(!*p)return 0; /* not really a printf call */
  186.     p++; /* skip over quote otherwise*/
  187.  
  188.  
  189.     for(;;){
  190.         /* read up to a formatting code (starts with "%")
  191.         but skip any "%%"s and treat them as single "%" */
  192.         for(    i=0;
  193.             (*p!='%'||*(p+1)=='%')    &&
  194.             (*p!=QUOTE||*(p-1)=='\\');
  195.             p++,i++
  196.         )
  197.         {
  198.             arg[i]=*p;
  199.             if(*p=='%'&&*(p+1)=='%')
  200.                 p++;
  201.         }
  202.         if(i){ /* if there is a literal */
  203.             arg[i]=0;
  204.             sprintf(s2+strlen(s2),"<<%c%s%c\0",QUOTE,arg,QUOTE);
  205.         }
  206.         if(*p=='%'){
  207.             p=getfmt(p,&width,&prec);
  208.             if(width>=0)
  209.                 sprintf(s2+strlen(s2),
  210.                     "<<setw(%d)",width);
  211.             if(prec>=0)
  212.                 sprintf(s2+strlen(s2),
  213.                     "<<setprecision(%d)",prec);
  214.             sprintf(s2+strlen(s2),"<<(_%d_)",replno++);
  215.         }
  216.         if(*p==QUOTE)break;
  217.     }
  218.  
  219.     /* read up to and beyond first comma before printf arguments */
  220.     for(;*p!=',';p++)
  221.         ;
  222.     p++;  /* skip over comma */
  223.  
  224.     replno=0;  /* set number back to create search and replace strings */
  225.     for(;;){
  226.         p=prs(p,arg);
  227.         sprintf(srch,"_%d_",replno++);
  228.         strrepl(s2,srch,arg);
  229.         if(*p==')'||!*p)break;
  230.     }
  231.     return 1;
  232. }
  233.  
  234.  
  235. /* GETFMT
  236. * extracts width and precision number from printf formatting code
  237. */
  238. char *getfmt(char *p,int *width,int *prec)
  239. {
  240.     char *period,*last;
  241.     if(*p++!='%')
  242.         return 0; /* wasnt even a formatting code */
  243.     /* find last char of fmt code (the alphabetic char) */
  244.     for(last=p;!isalpha(*last);last++)
  245.         ;
  246.     if(last==p){ /* if its the next one after %, no width or prec */
  247.         *prec=-1;
  248.         *width=-1;
  249.         return last+1; 
  250.     }
  251.     period=strchr(p,'.'); 
  252.     if(period==p) /* no width if . next to % */
  253.         *width=-1;
  254.     else          
  255.         *width=atoi(p);
  256.     *prec=period?atoi(period+1):-1; /* no precision if didnt find period */
  257.     return last+1;
  258. }
  259.  
  260. /*
  261. * PRS
  262. * Parse out field s from buffer pointed to by p, moving p to next field
  263. * field ends on comma, null, or right paren that ends the first left paren
  264. * scope in field, or is out of scope of any parens
  265. */
  266. char *prs(char *p,char *s)
  267. {
  268.     int i,parct=0;
  269.     for(i=0;*p!=','&&*p;p++,i++){
  270.         /* we are sensitive to paren nesting level:
  271.          * if we reach a right paren and we have seen as many or fewer
  272.                  * left parens so far, we have reached end of field 
  273.          */
  274.         if(*p=='(')parct++;
  275.         if(*p==')'){
  276.             if(--parct<0)break;
  277.         }
  278.         s[i]=*p;
  279.     }
  280.     s[i]=0;
  281.     if(!*p||p==')')return p;
  282.     p++;
  283.     return p;
  284. }
  285.  
  286. void strrepl(s,srch,repl)
  287. char *s,*srch,*repl;
  288. {
  289.     char near *found;
  290.     char temp[1024];int ofs;
  291.     for(;;){
  292.         found=(char near *)strstr(s,srch);
  293.         if(found){
  294.             ofs=(int)((char near *)found-(char near *)s);
  295.             strncpy(temp,s,ofs);
  296.             temp[ofs]=0;
  297.             strcat(temp,repl);
  298.             strcat(temp,s+ofs+strlen(srch));
  299.             strcpy(s,temp);
  300.         }
  301.         else
  302.             break;
  303.     }
  304. }
  305.  
  306.