#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define IN
#define OUT
#define MAX_COMMENT_SIZE 10000
#define isalpha(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
#define isnum(c) (c >= '0' && c <= '9')
#define ISWHITESPACE(c) (c == ' ' || c == '\t')
char *Header[] = {
"{\\rtf1\\pc {\\info{\\revtim\\mo07\\dy31\\yr1989}{\\creatim\\mo07\\dy31\\yr1989}",
"{\\nofchars9564}}\\deff0{\\fonttbl{\\f0\\fmodern pica;}",
"{\\f1\\fmodern Courier;}{\\f2\\fmodern elite;}{\\f3\\fmodern prestige;}",
"{\\f4\\fmodern lettergothic;}{\\f5\\fmodern gothicPS;}",
"{\\f6\\fmodern cubicPS;}{\\f7\\fmodern lineprinter;}",
"{\\f8\\fswiss Helvetica;}{\\f9\\fmodern avantegarde;}",
"{\\f10\\fmodern spartan;}{\\f11\\fmodern metro;}",
"{\\f12\\fmodern presentation;}{\\f13\\fmodern APL;}{\\f14\\fmodern OCRA;}",
"{\\f15\\fmodern OCRB;}{\\f16\\froman boldPS;}{\\f17\\froman emperorPS;}",
"{\\f18\\froman madaleine;}{\\f19\\froman zapf humanist;}",
"{\\f20\\froman classic;}{\\f21\\froman roman f;}{\\f22\\froman roman g;}",
"{\\f23\\froman roman h;}{\\f24\\froman timesroman;}{\\f25\\froman century;}",
"{\\f26\\froman palantino;}{\\f27\\froman souvenir;}{\\f28\\froman garamond;}",
"{\\f29\\froman caledonia;}{\\f30\\froman bodini;}{\\f31\\froman university;}",
"{\\f32\\fscript script;}{\\f33\\fscript scriptPS;}{\\f34\\fscript script c;}",
"{\\f35\\fscript script d;}{\\f36\\fscript commercial script;}",
"{\\f37\\fscript park avenue;}{\\f38\\fscript coronet;}",
"{\\f39\\fscript script h;}{\\f40\\fscript greek;}{\\f41\\froman kana;}",
"{\\f42\\froman hebrew;}{\\f43\\froman roman s;}{\\f44\\froman russian;}",
"{\\f45\\froman roman u;}{\\f46\\froman roman v;}{\\f47\\froman roman w;}",
"{\\f48\\fdecor narrator;}{\\f49\\fdecor emphasis;}",
"{\\f50\\fdecor zapf chancery;}{\\f51\\fdecor decor d;}",
"{\\f52\\fdecor old english;}{\\f53\\fdecor decor f;}{\\f54\\fdecor decor g;}",
"{\\f55\\fdecor cooper black;}{\\f56\\ftech Symbol;}{\\f57\\ftech linedraw;}",
"{\\f58\\ftech math7;}{\\f59\\ftech math8;}{\\f60\\ftech bar3of9;}",
"{\\f61\\ftech EAN;}{\\f62\\ftech pcline;}{\\f63\\ftech tech h;}}",
"{\\stylesheet {\\*\\cs1\\b\\f16 CT;}{\\*\\cs2\\b\\f16 CP;}{\\*\\cs3\\b\\f16 CD;}",
"{\\*\\cs4\\i\\f16 CI;}{\\*\\cs5\\f16\\ul CR;}{\\*\\s30\\sl-240\\sa240 \\f16",
"Normal;}{\\*\\s31\\li720\\fi-720\\sl-240\\sa240\\tqr\\tx432\\tx720 \\f16 L1;}",
"{\\*\\s32\\li1440\\fi-1440\\sl-240\\sa240\\tqr\\tx1152\\tx1440 \\f16 L2;}{\\*\\s33",
"\\li1152\\sl-240\\sa240 \\b\\f16\\ul P3;}{\\*\\s34\\li1728\\fi-576\\sl-240\\sa240",
"\\f16 P4;}{\\*\\s35\\li720\\sl-240\\sa240 \\f16 S1;}{\\*\\s36",
"\\li1440\\sl-240\\sa240 \\f16 S2;}{\\*\\s42\\ri576\\li576\\sl-240\\sa240 \\i\\f16",
"N1;}{\\*\\s43\\ri576\\li1296\\sl-240\\sa240 \\i\\f16 N2;}{\\*\\s44",
"\\li1152\\fi-576\\sl-240 \\f16 NL;}{\\*\\s52\\sl-240\\tx576\\tx1152\\tx1728",
"\\f16 PP;}{\\*\\s53\\li1152\\fi-576\\sl-240\\sa240 \\f16 PL;}{\\*\\s54",
"\\li1152\\sl-240\\sa240 \\f16 P2;}{\\*\\s62\\sl-240\\tqr\\tx9936 \\b\\f16 RH;}",
"{\\*\\s63\\qc\\sl-240 \\b\\f16 RF;}{\\*\\s64\\sl-240\\sa240 \\b\\f16 TN;}{\\*\\s65",
"\\sl-240\\sa240 \\i\\f16 TA;}{\\*\\s66\\sl-240 \\i\\f16 TR;}{\\*\\s72",
"\\li576\\fi-576\\sl-240\\sa240 \\f16 PT;}{\\*\\s73",
"\\li576\\sl-240\\tx1152\\tx1728\\tx2304\\tx2880\\tx3456\\tx4032\\tx4608\\tx5184\\tx5760\\tx6336\\tx6912",
"\\f7\\fs17 PC;}{\\*\\s74\\keep\\sl-240 \\f1 PD;}{\\*\\s88\\keepn\\sl-240\\sa240",
"\\b\\f16 heading 1;}{\\*\\s89\\keepn\\sl-240\\sa240 \\b\\f16 heading 2;}{\\*\\s90",
"\\keepn\\sl-240\\sa240 \\b\\f16 heading 3;}{\\*\\s91\\keepn\\sl-240\\sa240",
"\\b\\f16 heading 4;}{\\*\\s99",
"\\li288\\fi-288\\sl-240\\sb240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 1;}",
"{\\*\\s100\\li576\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 2;}",
"{\\*\\s101\\li864\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 3;}",
"{\\*\\s102\\li1152\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 4;}",
"{\\*\\ds105\\linex576\\endnhere\\pgnrestart standard division;}{\\*\\ds106",
"\\pgnlcrm\\linex576\\endnhere\\pgnrestart DT;}}",
"\0"
};
FILE *InputFile;
char FileName[50],Function[50];
char GetWord(char * word, char todo);
void DoFormat(),GlobalFormat();
int GetComment(),strpos();
char Comment[MAX_COMMENT_SIZE];
char *cp; /* pointer to current value in Comment */
int _cdecl
main(
int argc,
char **argv
)
{
int i,nummods;
char *modules[255];
nummods = 0;
if(argc != 3 && argc != 1) {
fprintf(stderr,"Usage: c2rtf [program function]\n");
exit(1);
}
i = 0;
while(*Header[i] != '\0') {
printf("%s\n",Header[i++]);
}
printf("\\ftnbj\\ftnrestart\\widowctrl \\sectd \\linex576\\endnhere");
printf(" \\pard \\sl-240\n");
if(argc == 3) {
InputFile = fopen(argv[1],"r");
if(InputFile == NULL) {
fprintf(stderr,"c2rtf: Error opening file %s.\n",argv[1]);
exit(2);
}
strcpy(Function,argv[2]);
strcpy(FileName,argv[1]);
DoFormat();
fclose(InputFile);
} else {
if(scanf("%s",FileName) == EOF) {
exit(1);
}
InputFile = fopen(FileName,"r");
if(InputFile == NULL) {
fprintf(stderr,"c2rtf: Error opening file %s.\n",FileName);
} else {
modules[nummods] = (char *)malloc((strlen(FileName) + 1) * sizeof(char));
strcpy(modules[nummods++],FileName);
GlobalFormat();
}
fclose(InputFile);
while(scanf("%s",Function) != EOF) {
if(!strncmp(strchr(Function,'\0')-2,".c",2) ||
!strncmp(strchr(Function,'\0')-2,".s",2) ||
!strncmp(strchr(Function,'\0')-2,".h",2)) {
strcpy(FileName,Function);
InputFile = fopen(FileName,"r");
if(InputFile == NULL) {
fprintf(stderr,"c2rtf: Error opening file %s.\n",FileName);
continue;
}
for(i = 0; i < nummods; i++) {
if(!strcmp(modules[i],FileName)) {
break;
}
}
if(i == nummods) {
modules[nummods] = (char *)malloc((strlen(FileName) + 1) * sizeof(char));
strcpy(modules[nummods++],FileName);
GlobalFormat();
}
fclose(InputFile);
if(scanf("%s",Function) == EOF) {
exit(0);
}
}
InputFile = fopen(FileName,"r");
if(InputFile == NULL) {
fprintf(stderr,"c2rtf: Error opening file %s for %s.\n",FileName,Function);
continue;
}
DoFormat();
fclose(InputFile);
}
}
printf("}\n");
return 0;
}
int
KillWhiteSpace(
char *killchars
)
/*++
Routine Description:
Removes white space from InputFile until non-whitespace character
is reached.
Arguments:
killchars - characters to be removed; generally some of ' ', '\t', '\n'.
Return Value:
Number of characters removed.
--*/
{
int i = 0;
char c;
c = getc(InputFile);
while(strpos(killchars,c) != -1) {
i++;
c = getc(InputFile);
}
ungetc(c,InputFile);
return(i);
}
char
GetWord(
OUT char *word,
IN char todo
)
/*++
Routine Description:
Finds the next string of alphabetic characters in InputFile.
Only letters are used.
Arguments:
word - pointer to space where the string is placed
todo - a character that determines whether to get the next word
from the input or the previous word (stored in the static last).
Return value:
EOF if the end of file is reached before a word is found, 0 otherwise.
--*/
{
char c;
char *w;
static char last[500];
/* if todo is 'l' then return the previous word instead of next */
if(todo == 'l') {
strcpy(word,last);
return(1);
}
strcpy(last,word);
w = word;
c = getc(InputFile);
while(c != EOF && !(isalpha(c) || c == '_' || c == '*')) {
c = getc(InputFile);
}
if(c != EOF) {
*w++ = c;
}
while((c = getc(InputFile)) != EOF && (isalpha(c) || c == '_' || c == '*' || isnum(c))) {
*w++ = c;
}
ungetc(c,InputFile);
*w = '\0';
if(strlen(word) == 0)
return(EOF);
else
return(0);
}
void
DoFormat(
)
/*++
Routine Description:
Performs actual parsing and output formating.
Arguments:
none
Return Value:
none
--*/
{
char word[500],c;
char prevline[500];
char *p;
int isfuncdef;
isfuncdef = 0;
*prevline = 0;
do {
if (GetWord(word, 'c') == EOF) {
fprintf(stderr,
"c2rtf: Function %s not found in %s.\n",
Function,
FileName);
return;
}
if (strcmp(word, Function)) {
// not the function; collect line
strcpy(prevline, word);
p = prevline + strlen(prevline);
while ((c = getc(InputFile)) != '\n' && c != EOF) {
*p++ = c;
}
*p = 0;
} else {
KillWhiteSpace("\n\t ");
if (getc(InputFile) == '(') {
KillWhiteSpace("\t /");
c = getc(InputFile);
if (c == '\n') {
isfuncdef = 1;
} else if (c == ')') {
KillWhiteSpace(" \t\n");
c = getc(InputFile);
if(c != ';') {
ungetc(c,InputFile);
isfuncdef = 2;
}
}
}
if (!isfuncdef) {
*prevline = 0;
}
}
}
while(!isfuncdef);
printf("\\s89\\keepn\\sl-240\\sa240 \\plain \\b\\f16 %s\\par\n",Function);
printf("\\pard \\s30\\sl-240\\sa0 \\plain \\b\\f16 %s\\par\n",prevline);
if(isfuncdef != 1) {
printf("%s()\\par\n",Function);
} else {
printf("%s(\\par\n",Function);
do {
int wstate = 0;
*word = 0;
printf("\\tab ");
KillWhiteSpace("\t\n ");
do {
KillWhiteSpace("\t ");
c = getc(InputFile);
if (c != '\n' && c != ',') {
if (*word) {
printf("%s ",word);
wstate = 1;
}
ungetc(c, InputFile);
GetWord(word, 'c');
} else {
if (*word) {
if (wstate == 0) {
printf(" %s",word);
} else {
printf("\\plain \\i\\f16 %s\\plain \\b\\f16 ",word);
}
}
if (c == '\n') {
printf("\\par\n\\tab )\\par");
} else if (c == ',') {
printf(",\\par\n");
}
}
}
while(c != '\n' && c != ',');
}
while(c != '\n');
}
if(GetComment()) {
printf("\\par \\pard\n");
return;
}
while(strncmp("Routine Description:",cp,20)) {
cp++;
if(*cp == '\0') {
fprintf(stderr,"c2rtf: Function %s in %s has no routine description.\n",Function,FileName);
printf("\\pard\n");
return;
}
}
printf("\\par\n");
printf("\\plain \\f16\\ul Routine Description:\\plain \\f16 \\par \\par\n");
printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 ");
for(cp += 22; strchr(" \t\n/",*cp) != NULL; cp++);
while(strncmp("Arguments:",cp,10)) {
if(*cp == '\n') {
if(*(cp + 1) == '\n' || !strncmp(cp + 1, "//\n",3)) {
printf("\\par\n");
for(cp++; strchr(" \t\n/",*cp) != NULL; cp++);
continue;
} else {
putchar(' ');
for(cp++; strchr(" \t/",*cp) != NULL; cp++);
continue;
}
}
putchar(*cp);
cp++;
if(*cp == '\0') {
fprintf(stderr,"c2rtf: Function %s in %s lacks 'Arguments:'.\n",Function,FileName);
printf("\\pard\n");
return;
}
}
printf("\\pard \\plain \\f16\\ul Parameters:\\plain \\f16 \\par \\par\n");
printf("\\pard \\s53\\li1152\\fi-576\\sl-240\\sa240 ");
for(cp += 11; strchr(" \t\n/",*cp) != NULL; cp++);
printf("\\plain \\i\\f16 ");
do {
putchar(*cp++);
}
while(isalpha(*cp));
printf("\\plain \\f16 ");
while(strncmp("Return Value",cp,12)) {
if(*cp == '\n') {
for(cp++; strchr(" \t/",*cp) != NULL; cp++);
if(*cp == '\n') {
while(strchr(" \t\n/",*cp) != NULL) {
cp++;
}
if(!strncmp("Return Value",cp,12)) {
continue;
}
printf("\\par\n");
printf("\\plain \\i\\f16 ");
do {
putchar(*cp++);
}
while(isalpha(*cp));
printf("\\plain \\f16 ");
continue;
} else {
while(strchr(" \t\n/",*cp) != NULL) {
cp++;
}
putchar(' ');
putchar(*cp);
}
} else {
putchar(*cp);
}
cp++;
if(*cp == '\0') {
fprintf(stderr,"c2rtf: Function %s in %s lacks 'Return Value'.\n",Function,FileName);
printf("\\pard\n");
return;
}
}
printf("\\par \\pard\n");
printf("\\plain \\f16\\ul Return Value:\\plain \\f16 \\par \\par\n");
printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 ");
for(cp += 14; strchr(" \t\n/",*cp) != NULL; cp++);
while(*cp != '\0' && strncmp(cp,"Environment",11)) {
if(*cp == '\n') {
for(cp++; strchr(" \t/",*cp) != NULL; cp++);
if(*cp == '\n') {
printf("\\par\n");
for(cp++; strchr(" \n\t/",*cp) != NULL && *cp != EOF; cp++) {
if(*cp == '\0') {
break;
}
}
continue;
} else {
putchar(' ');
continue;
}
}
putchar(*cp);
cp++;
}
if(*cp == '\0') {
printf("\\pard \\plain\n");
return;
}
printf("\\pard\n");
printf("\\plain \\f16\\ul Environment:\\plain \\f16 \\par \\par\n");
printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 ");
for(cp += 14; strchr(" \t\n/",*cp) != NULL; cp++);
while(*cp != '\0') {
if(*cp == '\n') {
for(cp++; strchr(" \t/",*cp) != NULL; cp++);
if(*cp == '\n') {
printf("\\par\n");
for(cp++; strchr(" \n\t/",*cp) != NULL && *cp != EOF; cp++) {
if(*cp == '\0') {
break;
}
}
continue;
} else {
putchar(' ');
continue;
}
}
putchar(*cp);
cp++;
}
printf("\\pard \\plain\n");
}
int
GetComment(
)
/*++
Routine Description:
This routine loads the next comment in the input, defined in the normal C
manner with / *++ and --* / (no spaces in there) into the Comment[]
array.
Arguments:
none
Return Value:
0 if successful
1 if { precedes the next comment
2 if the comment is not ended
3 if comment size is larger than MAX_COMMENT_SIZE
--*/
{
int index,i;
char temp[5];
for(i = 0; i<4; i++) {
if((temp[i] = getc(InputFile)) == EOF) {
fprintf(stderr,"No comment found.\n");
return(1);
}
}
temp[4] = '\0';
while(strcmp(temp,"/*++") && strcmp(temp + 2,"//")) {
temp[0] = temp[1];
temp[1] = temp[2];
temp[2] = temp[3];
temp[3] = getc(InputFile);
if(temp[3] == EOF || temp[3] == '{') {
fprintf(stderr,"c2rtf: No comment found in %s of %s.\n",Function,FileName);
return(1);
}
}
for(i = 0; i<4; i++) {
if((temp[i] = getc(InputFile)) == EOF) {
fprintf(stderr,"c2rtf: Comment not ended in %s of %s.\n",Function,FileName);
return(1);
}
}
temp[4] = '\0';
index = 0;
while(strcmp(temp,"--*/") && strcmp(temp,"//--")) {
if(temp[0] == '\t') {
for(i=0; i<8; i++) {
Comment[index++] = ' ';
}
} else {
Comment[index++] = temp[0];
}
temp[0] = temp[1];
temp[1] = temp[2];
temp[2] = temp[3];
temp[3] = getc(InputFile);
if(temp[3] == EOF) {
fprintf(stderr,"c2rtf: Comment not ended in %s of %s.\n",Function,FileName);
return(2);
}
if(index >= MAX_COMMENT_SIZE) {
fprintf(stderr,"c2rtf: Comment too large in %s of %s.\n",Function,FileName);
return(3);
}
}
Comment[index] = '\0';
cp = Comment;
return(0);
}
int
strpos(
char *s,
char c
)
/*++
Routine Description:
Finds the location of the character c in the string s. See section
15.5 of _C: A Reference Manual_, page 300, for complete description.
Parameters:
s - "haystack" of characters to search for.
c - character to search for.
Return Value:
The position of c in s or -1 if c is not in s.
--*/
{
int i;
for(i = 0; *s != '\0'; s++,i++) {
if(c == *s) {
return(i);
}
}
return(-1);
}
void GlobalFormat(
)
/*++
Routine Description:
Formats the abstract of a module into RTF format.
Arguments:
None.
Return Value:
None.
--*/
{
char c,word[50],basename[75],*s;
int i;
do {
if(GetWord(word,'c') == EOF) {
fprintf(stderr,"Module %s lacks an abstract.\n");
return;
}
}
while(strcmp("Abstract",word));
while((c = getchar()) == ' ' || c == '\t' || c == '\n') {
i++;
}
i = 0;
if(c == '\"') {
while((c = getchar()) != '\"') {
basename[i++] = c;
}
basename[i] = '\0';
} else {
ungetc(c,stdin);
for(s = FileName; *s != '\0'; s++) {
if(*s == '\\') {
i = 0;
} else {
basename[i++] = *s;
}
}
basename[i] = '\0';
}
if(!strcmp("continue",basename)) {
return;
}
printf("\\page\n");
printf("\\pard \\s88\\keepn\\sl-240\\sa240 \\plain \\b\\f16 %s\\par",basename);
printf("\\pard \\li576\\sl-240\\sa240 \\plain \\f16\n");
strcpy(word,"\0");
KillWhiteSpace(" \t\n/:");
do {
c = getc(InputFile);
if(c == '\n') {
putchar(' ');
KillWhiteSpace(" \t/");
c = getc(InputFile);
if(c == '\n') {
printf("\\par\n");
KillWhiteSpace(" \t\n/");
GetWord(word,'c');
if(strcmp(word,"Author")) {
printf("%s",word);
}
} else {
putchar(c);
}
} else {
putchar(c);
}
}
while(strcmp(word,"Author"));
printf("\\pard\n");
return;
}