This is parseobjc.c in view mode; [Download] [Up]
/*
docgen Objective C Document Generator
Copyright (C) 1995 Bill Bereza.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Email:
berezaw@river.it.gvsu.edu
S-mail:
Bill Bereza
9526 Judson Rd.
Ravenna, MI 49451-9427
*/
/* docgen Objective C Document Generator
* Copyright (c) 1994 Bill Bereza
*
* $Log: parseobjc.c,v $
* Revision 1.23 96/01/07 01:30:15 berezaw
* additions for 0.3.2
*
* Revision 1.22 95/07/26 22:28:40 berezaw
* *** empty log message ***
*
* Revision 1.21 95/07/26 21:46:22 berezaw
*
*
* Revision 1.20 95/07/26 19:51:03 berezaw
* *** empty log message ***
*
* Revision 1.19 95/07/26 17:50:25 berezaw
* *** empty log message ***
*
* Revision 1.18 95/07/26 16:17:31 berezaw
* 0.3.1
*
* Revision 1.17 95/07/21 22:56:33 berezaw
* *** empty log message ***
*
* Revision 1.16 95/07/21 21:40:15 berezaw
* *** empty log message ***
*
* Revision 1.15 95/07/16 19:19:05 berezaw
*
* bug fix found by pburka
*
* Revision ???? 95/04/26 14:16:15 pburka
* added check to see if the interface declares
* an empty block of ivars ('{ }'). Previously,
* this resulted in an unexpected eof; now it just
* gives a friendly message, just as if the braces
* hadn't been there at all
*
* Revision 1.14 95/03/02 03:44:46 berezaw
* using GNU regex library
* rewrote recmp() as docgen_recmp()
* added GPL stuff to each file
* increase rev. to 0.1.9
*
* Revision 1.13 95/02/02 18:32:13 berezaw
* 0.1.7, fixed problems with skipping lines
* in odd classes
*
* Revision 1.12 95/02/02 17:57:20 berezaw
* fixed class description printing
*
* Revision 1.11 95/02/02 15:21:58 berezaw
* 0.1.6
*
* Revision 1.10 95/02/01 16:41:28 berezaw
* fixed protocol parsing
*
* Revision 1.9 95/01/31 18:28:40 berezaw
*
* added 0.1.5 stuff
*
* Revision 1.8 95/01/30 14:11:19 berezaw
* fixed fancy text
*
* Revision 1.7 95/01/29 01:51:26 berezaw
* reused code from parsemethods to create general
* comment printing function to handle italicizing
* variable names, and to eventually handle fancy
* text
*
* Revision 1.6 95/01/28 23:21:53 berezaw
* nicer copyright check.
*
* Revision 1.5 95/01/26 15:27:29 berezaw
* added rtfproth for protocols
*
* Revision 1.4 95/01/26 05:35:10 berezaw
* handles copyrights better
*
* Revision 1.3 94/11/28 12:08:34 berezaw
* *** empty log message ***
*
*
* @(#)1.2
* $Id: parseobjc.c,v 1.23 96/01/07 01:30:15 berezaw Exp $
*/
#include "parsers.h"
#define CLOSEALL \
if(fflush(RTFf) == EOF) if(V_BADERR) perror("Something wouldn't flush : Try using a plunger");\
if(fclose(Hf) == EOF) if(V_BADERR) perror("I couldn't close the header file. Pray.");\
if(fclose(Mf) == EOF) if(V_BADERR) perror("I couldn't close the .m file. Pray.");\
if(fclose(RTFf) == EOF) if(V_BADERR) perror("I couldn't close the RTF file. Pray.");\
if(fFQh) free(fFQh);\
freedstr(GLOB_istring)
int parseobjc(char *FQm, char *FQh, char *FQrtf, char *hdir)
{
FILE *Hf, *Mf, *RTFf;
char errmess[1024];
char *hline, *mline, *stringptr;
ofiletype fty;
char *hpath, *honepath, *fFQh=NULL, *fhname;
fpos_t currPos;
char pathsep[]=":";
DSTRING *dhname;
#ifndef NODEBUG
if(V_USELESS)
printf("parseobjc(%s, %s, %s, %s)\n", FQm, FQh, FQrtf, hdir);
#endif
/* Open all files, return on error */
Hf=fopen(FQh,"r");
if(!Hf) {
dhname=dstrarr(hdir);
hpath=arrdstr(dhname);
freedstr(dhname);
if(!hpath) {
sprintf(errmess, "%.1023s", FQh);
if(V_STAT)
perror(errmess);
return -1;
}
strcpy(hpath, hdir);
fhname=strrchr(FQh,'/');
if(!fhname)
fhname=FQh;
else
fhname++;
honepath=strtok(hpath, pathsep);
if(GLOB_recurs) {
while(honepath && !fFQh) {
fFQh=findfile(fhname, honepath);
honepath=strtok(NULL, pathsep);
}
if(fFQh) {
Hf=fopen(fFQh, "r");
}
}
else
while(honepath && !Hf) {
fFQh=dirfile(honepath, fhname);
if(fFQh) {
Hf=fopen(fFQh, "r");
if(!Hf) {
free(fFQh);
fFQh=NULL;
}
}
honepath=strtok(NULL, pathsep);
}
free(hpath);
if(fFQh)
FQh=fFQh;
}
if(Hf == NULL) {
sprintf(errmess, "%.1023s", FQh);
if(V_STAT)
perror(errmess);
return -1;
}
if((Mf=fopen(FQm, "r")) == NULL) {
sprintf(errmess, "%.1023s", FQm);
perror(errmess);
if(fclose(Hf) == EOF)
if(V_BADERR)
perror("I couldn't close the header file. Pray.");
return -1;
}
if((RTFf=fopen(FQrtf, "w")) == NULL) {
sprintf(errmess, "%.1023s", FQrtf);
perror(errmess);
if(fclose(Hf) == EOF)
if(V_BADERR)
perror("I couldn't close the header file. Pray.");
if(fclose(Mf) == EOF)
if(V_BADERR)
perror("I couldn't close the .m file. Pray.");
return -1;
}
#ifndef NODEBUG
if(V_STAT)
fprintf(stderr,"All files opened : Begin parsing\n.m\t:%s\n.h\t:%s\n.rtf\t:%s\n", FQm, FQh, FQrtf);
#endif
[myForm setOfile:RTFf];
GLOB_istring=initdstr();
dstrarrcat(GLOB_istring, DEFITAL);
#ifdef OBJC
[myForm putHead];
#else
fputhead(RTFf);
#endif
mline=fgetdline(Mf);
/* go to @implementation line in the .m */
while(docgen_recmp(IMPLEM, mline) && !feof(Mf)) {
free(mline);
mline=fgetdline(Mf);
/* if the first non-blank line in .m matches the copyright
* pattern, then get it
*/
if(!docgen_recmp(CPEXP, mline) || !docgen_recmp(CPEXPII, mline)) {
#ifdef OBJC
[myForm putCPHead];
#else
fputcphead(RTFf);
#endif
if(docgen_recmp(CPEXPII, mline)) {
free(mline);
mline=fgetdline(Mf);
#ifdef OBJC
[myForm putLine:mline];
#else
fputline(RTFf, mline);
#endif
}
else {
#ifdef OBJC
[myForm putLine:strstr(mline, "Copy")];
#else
fputline(RTFf, strstr(mline, "Copy"));
#endif
}
while(docgen_recmp(WHITEXP, mline) && !feof(Mf)) {
free(mline);
mline=fgetdline(Mf);
if(!docgen_recmp("^ *\\*", mline)) {
#ifdef OBJC
[myForm putLine:strstr(mline, "*")+1];
#else
fputline(RTFf, strstr(mline,"*")+1);
#endif
}
else {
#ifdef OBJC
[myForm putLine:mline];
#else
fputline(RTFf, mline);
#endif
}
}
}
} /* while(docgen_recmp */
/* read to the @interface line in the .h file */
hline=fgetdline(Hf);
while(!feof(Hf) && docgen_recmp(INTERFACE, hline)) {
free(hline);
hline=fgetdline(Hf);
}
if(feof(Hf)) {
/* since all these eof error blocks are so
* similar I was thinking of having another
* function, but I don't like closing
* files outside of the function they were
* opened in. And a goto or macro wouldn't
* handle all the different cases
*/
free(hline);
free(mline);
if(V_ERR)
fprintf(stderr,"Unexpected end of file in %s\n", FQh);
CLOSEALL;
return -1;
}
#ifdef OBJC
[myForm putStart];
#else
fputstart(RTFf);
#endif
/* check for wether we're dealing with a Class or
* Category
*/
if(strstr(hline, CLASSCHK) != NULL)
fty=class;
else if(strstr(hline, CATCHK) != NULL)
fty=category;
else {
fty=none;
#ifndef NODEBUG
if(V_STAT)
fprintf(stderr,"%s is neither a Class or a Category\n",FQh);
#endif
}
/* If strtok fails on this first pass
* then exit with an error.
*/
if(fty!=none) {
if((stringptr=strtok(hline, INTTOK)) == NULL) {
free(hline);
free(mline);
if(V_ERR)
fprintf(stderr, "Improper @interface description in\n%s\n", FQh);
CLOSEALL;
return -1;
}
else
stringptr=strtok(NULL, INTTOK);
/* Output the Inherits From: , Category Of: messages */
if(fty==class) {
#ifdef OBJC
[myForm putLine:stringptr];
#else
fputline(RTFf, stringptr);
#endif
stringptr=strtok(NULL, INTTOK);
#ifdef OBJC
[myForm putInheritHeader];
#else
fputinherith(RTFf);
#endif
if(stringptr != NULL) {
char *pro, *as;
pro=strtok(NULL, "<");
fprintf(RTFf, "%s", stringptr);
traceinheritance(RTFf, hdir, stringptr);
#ifdef OBJC
[myForm putLine:" "];
#else
fputline(RTFf," ");
#endif
if(pro) {
as=strchr(pro, '>');
if(as)
*as='\0';
#ifdef OBJC
[myForm putConformHeader:pro];
#else
fputconformh(RTFf, pro);
#endif
}
}
else
#ifdef OBJC
[myForm putLine:"No Inheritance"];
#else
fputline(RTFf, "No Inheritance");
#endif
if(!GLOB_decdir) {
char *z=strstr(FQm, "./");
if(!z)
z=FQm;
else
z+=2;
#ifdef OBJC
[myForm putInheritTail:z];
#else
fputinheritt(RTFf, z);
#endif
}
else
{
char buff[strlen(GLOB_decdir) + strlen(FQm) + 2];
sprintf (buff, "%s/%s", GLOB_decdir, strrchr(FQm, '/') + 1);
#ifdef OBJC
[myForm putInheritTail:buff];
#else
fputinheritt(RTFf, buff);
#endif
}
}
else {
char *as, *cof;
cof=stringptr;
stringptr=strtok(NULL, INTTOK);
if(stringptr!=NULL) {
as=strchr(stringptr,')');
*as='\0';
}
#ifdef OBJC
[myForm putLine:stringptr];
[myForm putCategoryHeader];
#else
fputline(RTFf, stringptr);
fputcath(RTFf);
#endif
if(stringptr != NULL) {
char *pro;
pro=strtok(NULL, "< ");
fprintf(RTFf,"%s", cof);
traceinheritance(RTFf, hdir, cof);
#ifdef OBJC
[myForm putLine:" "];
#else
fputline(RTFf, " ");
#endif
if(pro) {
as=strchr(pro, '>');
if(as)
*as='\0';
#ifdef OBJC
[myForm putConformHeader:pro];
#else
fputconformh(RTFf, pro);
#endif
}
}
else
#ifdef OBJC
[myForm putLine:"No Category"];
#else
fputline(RTFf, "No Category");
#endif
if(!GLOB_decdir) {
char *z=strstr(FQm, "./");
if(!z)
z=FQm;
else
z+=2;
#ifdef OBJC
[myForm putCategoryTail:z];
#else
fputcatt(RTFf, z);
#endif
}
else {
char buff[strlen(GLOB_decdir) + strlen(FQm) + 2];
sprintf (buff, "%s/%s", GLOB_decdir, strrchr(FQm, '/') + 1);
#ifdef OBJC
[myForm putCategoryTail:buff];
#else
fputcatt(RTFf, buff);
#endif
}
}
}
if(feof(Mf)) {
free(hline);
free(mline);
if(V_ERR)
fprintf(stderr,"Unexpected end of file in %s\n", FQm);
CLOSEALL;
return -1;
}
free(mline);
/* go to the next non-blank line in the .m */
fgetpos(Mf, &currPos);
mline=fgetdline(Mf);
while(!docgen_recmp(WHITEXP, mline) && !feof(Mf)) {
fgetpos(Mf, &currPos);
free(mline);
mline=fgetdline(Mf);
}
/* print out the description text, if any */
if(!docgen_recmp(STARTEXP, mline)) {
if(GLOB_firstcomm)
parsecomments(RTFf, mline+2, NULL);
if(docgen_recmp(STOPEXP, mline)) {
free(mline);
fgetpos(Mf, &currPos);
mline=fgetdline(Mf);
while(docgen_recmp(STOPEXP, mline) && !feof(Mf)) {
parsecomments(RTFf, mline, NULL);
free(mline);
fgetpos(Mf, &currPos);
mline=fgetdline(Mf);
}
}
}
if(feof(Mf)) {
free(hline);
free(mline);
if(V_ERR)
fprintf(stderr,"Unexpected end of file in %s\n", FQm);
CLOSEALL;
return -1;
}
/* If this is a class, print out I-Var info */
if(fty==class) {
free(hline);
hline=fgetdline(Hf);
while(docgen_recmp(IVARBEG, hline) && !feof(Hf) && docgen_recmp(METHEXP, hline)) {
free(hline);
hline=fgetdline(Hf);
}
if(!feof(Hf)) {
if(docgen_recmp(IVARBEG, hline) || !docgen_recmp(IVARNONE, hline)) {
if(V_ERR)
fprintf(stderr,"%s is a Class file with no i-vars!\n", FQh);
}
else
if(parseivars(RTFf, Hf, FQh)<0) {
free(hline);
free(mline);
if(V_ERR)
fprintf(stderr,"Problem while parsing i-vars\n");
CLOSEALL;
return -1;
}
#ifdef OBJC
[myForm putMethodType];
#else
fputmethodtype(RTFf);
#endif
parsemethodtype(Hf, RTFf, hline);
}
else {
if(V_ERR)
fprintf(stderr,"No methods or i-vars in %s\n", FQh);
}
} /* done with class file */
/* Methods */
parsemethods(Mf, RTFf, mline, currPos);
/* Flush and close all files */
#ifdef OBJC
[myForm putLine:" "];
[myForm putEof];
#else
fputline(RTFf, " ");
fputeof(RTFf);
#endif
CLOSEALL;
#ifndef NODEBUG
if(V_STAT)
printf("parseobjc: returning success\n");
#endif
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.