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 >
Wrap
Text File
|
1990-09-21
|
7KB
|
308 lines
/*
* File: P2S.L
*
* Program:
* P2S
*
* printf() to streams i/o converter
*
* Description:
*
* Converts printf() calls to << operators
* Uses Lex to find printf's, fprintf's and sprintf's in C source
* and then uses p2s() call to convert the printf arguments to C++ streams
* formatted I/O.
* Does handle things like %6.2f (width and precision flags)
* by generating the appropriate streams manipulators - setw()
* and setprecision().
* Does NOT handle things like %-6.2f (yet) since there are no manipulators
* for left and right justification (if you decide to enhance this to
* handle this or anything else please submit back to CUG or me)
*
* stdin reads inoriginal C source, converted source goes to stdout.
*
* Usage:
*
* P2S < {.c file with printfs} > {file with streams i/o}
* Options:
* f - don't convert fprintf()'s
* p - don't convert printf()'s
* s - don't convert sprintf()'s
* i - converts by doing
* #ifdef __cplusplus
* ... streams code ..
* #else
* ... old printf code ...
* #endif
* to maintain backward compatibility with C (if desired)
*
* Example:
*
* For example to only convert fprintf calls and maintain C compatibility
* the invocation is:
*
* p2s p s i < foo.c >foo.cpp
*
*
* Construction:
*
* Just flex (or lex) this file, and compile the resultant C source.
* MKP2S.BAT shows how to make program with Flex and Turbo C.
*
* Restrictions:
*
* You may use this program without restriction as a tool in your own
* development efforts.
* You MAY NOT redistribute either the source or executables, in modified
* or unmodified form, for any amount of money or along with any other
* commercial package. You must include this copyright in any program
* which uses this source and you may not distribute such programs
* commercially. No restrictions apply to any programs which you converted
* using this tool (using the tool is unrestricted, distributing it or using
* its source is).
*
* Copyright (c) 1990. Adam Blum, Retrieval Systems Corporation,(703)-524-4534
*/
%{
#include<stdio.h>
#include<ctype.h>
/* prototypes */
int p2s(char *s1,char *s2);
char *prs(char *p,char *s);
char *getfmt(char *p,int *prec,int *width);
void strrepl(char *s,char *srch,char *repl);
#define QUOTE 34
/* variables */
int ifdef=0,sprt=1,fprt=1,prt=1,i;
%}
%%
/* PATTERNS */
#define.*\n {ECHO;}
printf\([^\;]*\)\; {
if(prt)
p2sprt(yytext,yyleng,yytext+7);
else {
ECHO;
}
return 1;}
fprintf\([^\;]*\)\; {
if(fprt)
p2sprt(yytext,yyleng,yytext+8);
else{
ECHO;
}
return 1;}
sprintf\([^\;]*\)\; {
if(sprt)
p2sprt(yytext,yyleng,yytext+8);
else {
ECHO;
}
return 1;}
.|\n {ECHO;return 1;}
%%
/* FUNCTIONS */
main(int argc,char **argv)
{
for(i=0;i<argc;i++){
switch(toupper(argv[i][0])){
case 'I':ifdef=1;break;
case 'S':sprt=0;break;
case 'F':fprt=0;break;
case 'P':prt=0;break;
}
}
fprintf(stderr,
"printf to C++ streams converter, (c) 1990, Adam Blum, Retrieval Systems Corp.\n");
fprintf(stderr,
"Usage: p2s <{source with printf calls} >{output with streams operators}\n");
for(;;){
if(yylex()<1)break;
}
}
ctparens(char *s,int n)
{
int i,ct=0;
for(i=0;i<n;i++)
if(s[i]=='(')
ct++;
else if(s[i]==')')
ct--;
return ct;
}
/* P2SPRT
* Print the converted strings
*/
p2sprt(char *base,int n,char *s)
{
char s1[256],s2[1024];
strncpy(s1,s,n);
s1[n]=0;
p2s(s1,s2);
if(ifdef)
printf("\n#ifdef __cplusplus\n%s;\n#else\n%s\n#endif\n",s2,base);
else
printf("\n/* was %s*/\n%s;",base,s2);
}
/* P2S
* Convert printf arguments to formatted streams I/O
*/
p2s(char *s1,char *s2)
{
char srch[16],arg[256],*p=s1;
int replno=0,width,prec,i;
/* grab the filename first, and pass it through
untranslated. streams opening and closing of
file will have to be translated manually */
for(;isspace(*p);p++)
;
if(*p==QUOTE){
strcpy(s2,"cout\0");
}
else if(!strncmp(p,"stderr",6)){
strcpy(s2,"cerr\0");
/* read up to first quote mark for formatting string */
for(;*p!='"'&&*p;p++)
;
}
else{
p=prs(p,s2);
/* stream operator directed to file stream */
/* read up to first quote mark for formatting string */
for(;*p!='"'&&*p;p++)
;
}
if(!*p)return 0; /* not really a printf call */
p++; /* skip over quote otherwise*/
for(;;){
/* read up to a formatting code (starts with "%")
but skip any "%%"s and treat them as single "%" */
for( i=0;
(*p!='%'||*(p+1)=='%') &&
(*p!=QUOTE||*(p-1)=='\\');
p++,i++
)
{
arg[i]=*p;
if(*p=='%'&&*(p+1)=='%')
p++;
}
if(i){ /* if there is a literal */
arg[i]=0;
sprintf(s2+strlen(s2),"<<%c%s%c\0",QUOTE,arg,QUOTE);
}
if(*p=='%'){
p=getfmt(p,&width,&prec);
if(width>=0)
sprintf(s2+strlen(s2),
"<<setw(%d)",width);
if(prec>=0)
sprintf(s2+strlen(s2),
"<<setprecision(%d)",prec);
sprintf(s2+strlen(s2),"<<(_%d_)",replno++);
}
if(*p==QUOTE)break;
}
/* read up to and beyond first comma before printf arguments */
for(;*p!=',';p++)
;
p++; /* skip over comma */
replno=0; /* set number back to create search and replace strings */
for(;;){
p=prs(p,arg);
sprintf(srch,"_%d_",replno++);
strrepl(s2,srch,arg);
if(*p==')'||!*p)break;
}
return 1;
}
/* GETFMT
* extracts width and precision number from printf formatting code
*/
char *getfmt(char *p,int *width,int *prec)
{
char *period,*last;
if(*p++!='%')
return 0; /* wasnt even a formatting code */
/* find last char of fmt code (the alphabetic char) */
for(last=p;!isalpha(*last);last++)
;
if(last==p){ /* if its the next one after %, no width or prec */
*prec=-1;
*width=-1;
return last+1;
}
period=strchr(p,'.');
if(period==p) /* no width if . next to % */
*width=-1;
else
*width=atoi(p);
*prec=period?atoi(period+1):-1; /* no precision if didnt find period */
return last+1;
}
/*
* PRS
* Parse out field s from buffer pointed to by p, moving p to next field
* field ends on comma, null, or right paren that ends the first left paren
* scope in field, or is out of scope of any parens
*/
char *prs(char *p,char *s)
{
int i,parct=0;
for(i=0;*p!=','&&*p;p++,i++){
/* we are sensitive to paren nesting level:
* if we reach a right paren and we have seen as many or fewer
* left parens so far, we have reached end of field
*/
if(*p=='(')parct++;
if(*p==')'){
if(--parct<0)break;
}
s[i]=*p;
}
s[i]=0;
if(!*p||p==')')return p;
p++;
return p;
}
void strrepl(s,srch,repl)
char *s,*srch,*repl;
{
char near *found;
char temp[1024];int ofs;
for(;;){
found=(char near *)strstr(s,srch);
if(found){
ofs=(int)((char near *)found-(char near *)s);
strncpy(temp,s,ofs);
temp[ofs]=0;
strcat(temp,repl);
strcat(temp,s+ofs+strlen(srch));
strcpy(s,temp);
}
else
break;
}
}