ftp.nice.ch/pub/next/unix/developer/docgen.0.3.2.s.tar.gz#/docgen-0.3.2/parseobjc.c

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.