This is parsers.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: parsers.c,v $ * Revision 1.39 96/01/07 01:30:27 berezaw * additions for 0.3.2 * * Revision 1.38 95/07/26 18:56:08 berezaw * *** empty log message *** * * Revision 1.37 95/07/26 17:50:28 berezaw * got before and after comments parsing to work * * added findrealchr() function * * Revision 1.36 95/07/26 16:17:32 berezaw * 0.3.1 * * Revision 1.35 95/07/21 21:40:17 berezaw * *** empty log message *** * * Revision 1.34 95/07/16 19:19:55 berezaw * * bug fix found by pburka * * * Revision 1.33.1 95/04/26 13:34:00 pburka * added an input check to make sure there's something * in the file. * * * Revision 1.33 95/03/02 18:20:50 berezaw * added gathermethod() to get each method as a block * create COMMINTERN macro to do the check and printing * of comments for a method * created GETNEWLINE macro for getting a new line * of text from the queue * * Revision 1.32 95/03/02 03:44:47 berezaw * using GNU regex library * rewrote recmp() as docgen_recmp() * added GPL stuff to each file * increase rev. to 0.1.9 * * Revision 1.31 95/02/14 12:36:44 berezaw * * fixed new line getting in parsemethods * * Revision 1.30 95/02/13 19:05:34 berezaw * * will now skip to next line on end of comments * * Revision 1.29 95/02/02 18:32:14 berezaw * 0.1.7, fixed problems with skipping lines * in odd classes * * Revision 1.28 95/02/02 17:57:38 berezaw * didn't skip spaces often enough * * Revision 1.27 95/02/02 15:21:59 berezaw * 0.1.6 * * Revision 1.26 95/02/01 18:49:59 berezaw * * 0.1.6 * * Revision 1.25 95/02/01 16:41:36 berezaw * better parsing for i-vars in parseivars * * Revision 1.24 95/01/31 18:28:40 berezaw * * added 0.1.5 stuff * * Revision 1.23 95/01/30 14:11:20 berezaw * fixed fancy text * * Revision 1.22 95/01/30 13:39:47 berezaw * *** empty log message *** * * Revision 1.21 95/01/30 13:32:23 berezaw * added loop to check for nested fancy text * * Revision 1.20 95/01/29 02:52:44 berezaw * (parsecomments) started support for word decorations * * Revision 1.19 95/01/29 01:52:52 berezaw * reused code from parsemethods to create general * comment printing function to handle italicizing * variable names, and to eventually handle fancy * text * * Revision 1.18 95/01/27 00:59:35 berezaw * *** empty log message *** * * Revision 1.17 95/01/27 00:31:46 berezaw * added '-x' option to hide methods beginning with '_' * * Revision 1.16 95/01/26 15:32:56 berezaw * added BSD, SYSV and HPUX checks * * Revision 1.15 95/01/26 15:27:35 berezaw * now checks for comments for method types * * Revision 1.14 95/01/26 05:35:22 berezaw * major fixing in parseivars and parsemethodtypes * added dcmp() * changed parsemethods to handle multiple classes, * to use a list that can be sorted, * and to handle method declarations better * * Revision 1.13 94/11/28 12:08:35 berezaw * *** empty log message *** * * * $Id: parsers.c,v 1.39 96/01/07 01:30:27 berezaw Exp $ */ #include "parsers.h" int docgen_recmp(char *expr, char *line) { static struct re_pattern_buffer expbuf; static bool set=no; int matret; if(!set) { set=yes; re_syntax_options=0; re_syntax_options=DOCGEN_SYNTAX; expbuf.buffer=(char *)malloc(DOCGEN_REBUF); expbuf.allocated=DOCGEN_REBUF; expbuf.translate=NULL; } if(re_compile_pattern(expr, strlen(expr), &expbuf)) { fprintf(stderr, "docgen_recmp:error compiling expression\n"); return -1; } switch((matret=re_match(&expbuf, line, strlen(line), 0, 0))) { case -1: return 1; default: return 0; } } #define DYNLINESEP "||--||" int parseivars(FILE *RTFf, FILE *Hf, char *FQh) { char *hline, *stringptr, *idescstr, *as; DSTRING *dynstring; #ifndef NODEBUG if(V_USELESS) fprintf(stderr,"parseivars(FILE, FILE, %s)\n", FQh); #endif #ifdef OBJC [myForm putIHeader]; #else fputihead(RTFf); /* Setup margins, font and header for I-Vars */ #endif hline=fgetdline(Hf); /* initialize it now, so that we know we can safely free it later */ dynstring=initdstr(); /* parse through each ivar line */ while(docgen_recmp(IVAREND, hline) && !feof(Hf)) { if(!strchr(hline, ';')) { free(hline); hline=fgetdline(Hf); continue; } idescstr=strstr(hline,"//"); if(!idescstr) idescstr=strstr(hline,"/*"); if(idescstr) idescstr++; stringptr=strtok(hline, IVTOK); /* split line up into tokens * seperated by IVTOK */ #ifndef NODEBUG if(V_USELESS) fprintf(stderr,"%s\n\n",stringptr); #endif /* parse through each ivar on a line */ while((stringptr!=NULL) && docgen_recmp(WHITEXP, stringptr)) { char *varp=&stringptr[strlen(stringptr)-1]; char *stopper=stringptr; SKIPSPACE(stringptr); if(*stringptr == IDESCCHAR) break; while(isspace(*varp) && (varp!=stopper)) varp--; if((*varp!='{') && (*varp!='}')) { while(*varp) { while(isspace(*varp) && (varp!=stopper)) varp--; while(!isspace(*varp) && (varp!=stopper)) varp--; while(isspace(*varp) && (varp!=stopper)) varp--; if(((*varp==',') || (*varp==':')) && (varp!=stopper)) varp--; else { varp++; *varp='\0'; } } varp++; } else if(*varp!='}') { *(varp+1)='\0'; varp=stringptr; } if(!strchr(stringptr,'{') && !strchr(stringptr,'}')) { while(*stringptr) { fputc(*stringptr++, RTFf); } fputc('\t', RTFf); } stringptr=varp; varp=&stringptr[strlen(stringptr)-1]; SKIPSPACE(stringptr); if((*varp!='{') && (*varp!='}')) { #ifdef OBJC [myForm makeBold]; fprintf(RTFf, "%s", stringptr); [myForm unBold]; [myForm putLine:";"]; #else fputbold(RTFf, stringptr); fputline(RTFf, ";"); #endif } else #ifdef OBJC [myForm putLine:" "]; #else fputline(RTFf, " "); #endif if(*stringptr=='*') stringptr++; if((*varp!='{') && (*varp!='}')) { // daddchar(dynstring, IFEOL); // daddchar(dynstring, '\n'); // dstrarrcat(dynstring, IFSIZE); dstrarrcat(dynstring, stringptr); daddchar(dynstring, '\t'); if(idescstr != NULL) { ++idescstr; SKIPSPACE(idescstr); as=strstr(idescstr,"*/"); if(as) *as='\0'; dstrarrcat(dynstring, idescstr); } else dstrarrcat(dynstring, "No Description"); dstrarrcat(dynstring,DYNLINESEP); // daddchar(dynstring, IFEOL); // daddchar(dynstring, '\n'); while(*stringptr) { SKIPSPACE(stringptr); daddchar(GLOB_istring, '#'); while(!isspace(*stringptr) && (*stringptr != ',') && *stringptr) { daddchar(GLOB_istring, *stringptr++); } daddchar(GLOB_istring, '#'); if(*stringptr) stringptr++; } } stringptr=strtok(NULL, IVTOK); } free(hline); hline=fgetdline(Hf); } /* print out the ivar description lines */ #ifdef OBJC [myForm putIVarDescription]; [myForm putLine:" "]; [myForm changeFontSize:28]; #else fputivardesc(RTFf); fputline(" "); fchfontsize(RTFf,28); #endif stringptr=arrdstr(dynstring); { char *zptr=strtok(stringptr, DYNLINESEP); while(zptr) { #ifdef OBJC [myForm putLine:" "]; [myForm putLine:zptr]; #else fputline(RTFf," "); fputline(RTFf, zptr); #endif zptr=strtok(NULL,DYNLINESEP); } } // fprintf(RTFf,"%s",stringptr); if(!strlen(stringptr)) #ifdef OBJC [myForm putLine:"No additional instance variables declared."]; #else fputline(RTFf, "No additional instance variables declared."); #endif freedstr(dynstring); free(stringptr); if(feof(Hf)) { free(hline); if(V_ERR) fprintf(stderr,"Unexpected end of file in %s\n", FQh); return -1; } free(hline); #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "parseivars: returning\n"); #endif return 0; } void parsemethodtype(FILE *Hf, FILE *RTFf, char *hline) { char *stringptr, *descstr, *as; #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "parsemethodtype(FILE *, FILE *)\n"); #endif descstr=NULL; as=NULL; /* parse method types until we get to a line * matching DONINT expression */ while(docgen_recmp(DONEINT, hline) && !feof(Hf)) { #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "%s\n", hline); #endif if((!strncmp(hline,"/*",2)) || (!strncmp(hline, "//",2))) { descstr=hline+2; as=strstr(descstr,"*/"); if(as) *as='\0'; #ifdef OBJC [myForm putLine:" "]; [myForm putLine:descstr]; #else fputline(RTFf,"\n"); fputline(RTFf,descstr); #endif fprintf(RTFf,"\t"); } if(!docgen_recmp(METHEXP, hline) && (GLOB_undoc ? docgen_recmp(UNDOC, hline) : 1)) { /* If this is a method expression */ stringptr=hline; SKIPSPACE(stringptr); if(*stringptr) { #ifdef OBJC [myForm putFont:1 Char:stringptr[0]]; #else fputfchar(RTFf, 1, stringptr[0]); /* put the + or - char */ #endif stringptr++; } SKIPSPACE(stringptr); if(*stringptr =='(') { /* Skip past the type */ SKIPPARENS(stringptr); } #ifdef OBJC [myForm changeFont:0]; #else fchangefont(RTFf, 0); #endif SKIPSPACE(stringptr); while(*stringptr != ':' && !isspace(*stringptr) && *stringptr != ';' && *stringptr) fputc(*stringptr++, RTFf); if(*stringptr && *stringptr!=';') { fputc(*stringptr++, RTFf); } while(*stringptr != ';' && *stringptr) { SKIPSPACE(stringptr); if(*stringptr=='(') { /* And not all argyments have a type */ /* And we don't need the * type for the list of * arguments */ SKIPPARENS(stringptr); } SKIPSPACE(stringptr); while(!isspace(*stringptr) && *stringptr && *stringptr!=';' && (*stringptr!=':')) stringptr++; SKIPSPACE(stringptr); while(*stringptr != ':' && *stringptr && *stringptr != ';') fputc(*stringptr++, RTFf); if(*stringptr && *stringptr != ';') fputc(*stringptr++, RTFf); /* fputc(' ', RTFf); */ } #ifdef OBJC [myForm putLine:" "]; #else fputline(RTFf," "); #endif fprintf(RTFf, "\t"); } /* if */ free(hline); hline=fgetdline(Hf); } /* while */ free(hline); #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "parsemethodtype: returning\n"); #endif } int dcmp(void *a, void *b) { char *ca=(*(char **)a); char *cb=(*(char **)b); SKIPSPACE(ca); SKIPSPACE(cb); if(*ca!=*cb) return *ca-*cb; if(*ca) ca++; if(*cb) cb++; SKIPSPACE(ca); SKIPSPACE(cb); if(*ca=='(') { SKIPPARENS(ca); } if(*cb=='(') { SKIPPARENS(cb); } SKIPSPACE(ca); SKIPSPACE(cb); return strcmp(ca, cb); } void parsecomments(FILE *RTFf, char *mline, DSTRING *dynstr) { char blank[]="#"; char punchar[3], tline[255]; char *hline, *stringptr, *opstrptr=NULL; stringptr=arrdstr(GLOB_istring); if(dynstr) opstrptr=arrdstr(dynstr); else opstrptr=blank; #ifndef NODEBUG if(V_USELESS) fprintf(stderr,"\n\n%s\n\n", stringptr); #endif { char *z=strstr(mline, "*/"); if(z) { z[0]=' '; z[1]=' '; } if(!docgen_recmp("^ *\\* *", mline)) { z=strstr(mline, "*"); if(z) { z[0]=' '; } } } hline=strtok(mline, DESCRIPTOK); while(hline!=NULL) { if(strrchr(PUNCS,hline[strlen(hline)-1]) != NULL) { punchar[0]=hline[strlen(hline)-1]; punchar[1]=' '; punchar[2]='\0'; hline[strlen(hline)-1]='\0'; #ifndef NODEBUG if(V_USELESS) fprintf(stderr,"%s\n", hline); #endif } else { punchar[0]=' '; punchar[1]='\0'; } strcpy(tline, "#"); strcat(tline, hline); strcat(tline, "#"); if(!strstr(stringptr, tline) && !strstr(opstrptr, tline)) { bool bolded=no; bool italicized=no; bool underlined=no; bool fancyd=no; if(GLOB_fancy) { while(!fancyd) { #ifndef NODEBUG if(V_USELESS) printf("%s\n", hline); #endif switch(*hline) { case '*': if((hline[strlen(hline)-1]=='*') && (strlen(hline)>1)) { #ifdef OBJC [myForm makeBold]; #else fmakebold(RTFf); #endif hline++; hline[strlen(hline)-1]='\0'; bolded=yes; } else fancyd=yes; break; case '%': if((hline[strlen(hline)-1]=='%') && (strlen(hline)>1)) { #ifdef OBJC [myForm makeItalic]; #else fmakeitalic(RTFf); #endif hline++; hline[strlen(hline)-1]='\0'; italicized=yes; } else fancyd=yes; break; case '_': if((hline[strlen(hline)-1]=='_') && (strlen(hline)>1)) { #ifdef OBJC [myForm makeUnderline]; #else fmakeul(RTFf); #endif hline++; hline[strlen(hline)-1]='\0'; underlined=yes; } else fancyd=yes; break; default: fancyd=yes; break; } } } fprintf(RTFf, "%s%s", hline, punchar); if(bolded) #ifdef OBJC [myForm unBold]; #else funbold(RTFf); #endif if(italicized) #ifdef OBJC [myForm unItalic]; #else funitalic(RTFf); #endif if(underlined) #ifdef OBJC [myForm unUnderline]; #else funul(RTFf); #endif } else { #ifdef OBJC [myForm makeItalic]; #else fmakeitalic(RTFf); #endif fprintf(RTFf, "%s%s", hline, punchar); #ifdef OBJC [myForm unItalic]; #else funitalic(RTFf); #endif } hline=strtok(NULL, DESCRIPTOK); } #ifdef OBJC [myForm putLine:" "]; #else fputline(RTFf, " "); #endif free(stringptr); if(dynstr) free(opstrptr); } static char *findrealchr(char *line, int find) { char *ret=line; bool inComm=no; while(*ret) { if(!strncmp(ret,"//", 2)) /* The rest is all comments */ return NULL; if(!strncmp(ret,"/*",2)) inComm=yes; if(!strncmp(ret,"*/",2)) inComm=no; if(*ret==find && !inComm) return ret; ret++; } return NULL; } static char *parseoneliner(DSTRING *methstring, char *ivarstr, char *mline) { char *stringptr; /* All this just to handle one-line methods */ stringptr=findrealchr(mline,'{'); if(!docgen_recmp(METHEXP, mline) && (GLOB_autodoc || stringptr)) { if(stringptr) { *stringptr='\0'; stringptr++; } else stringptr=strchr(mline,'\n'); if(stringptr) { *stringptr='\0'; stringptr++; } else stringptr=&mline[strlen(mline)]; dstrarrcat(methstring, mline); daddchar(methstring, '\n'); dstrarrcat(methstring, "/*\n"); if(!docgen_recmp(SETEXP, mline)) { char autostr[strlen(mline)]; char *endcol, *endto; char *setstr=autostr; strcpy(setstr, mline); setstr=strstr(mline,"set"); setstr+=3; endcol=strchr(setstr,':'); *endcol='\0'; endcol++; SKIPSPACE(endcol); if(*endcol=='(') { SKIPPARENS(endcol); } SKIPSPACE(endcol); endto=endcol; while(!isspace(*endto) && *endto) endto++; *endto='\0'; /* if(strstr(ivarstr, setstr)) { */ dstrarrcat(methstring, "Sets "); if(isupper(*setstr)) *setstr=tolower(*setstr); dstrarrcat(methstring, setstr); dstrarrcat(methstring, " to "); dstrarrcat(methstring, endcol); /* } */ } else { char autostr[strlen(mline)]; char *endto; char *getstr=autostr; strcpy(getstr, mline); SKIPSPACE(getstr); if(*getstr) getstr++; SKIPSPACE(getstr); if(*getstr=='(') { SKIPPARENS(getstr); } endto=getstr; while(!isspace(*endto) && *endto) endto++; *endto='\0'; if(strstr(ivarstr, getstr)) { dstrarrcat(methstring, "Returns "); dstrarrcat(methstring, getstr); } } dstrarrcat(methstring, "\n*/\n"); mline=stringptr; } return mline; } #define NULLPOS ((fpos_t)0) static char *gathermethod(char *mline, FILE *Mf, fpos_t lastComment) { bool first=yes; DSTRING *methstring; char *sline; char *ivarstr=arrdstr(GLOB_istring); fpos_t currPos; sline=mline; methstring=initdstr(); while(!feof(Mf)) { while(*sline!='/' && *sline!='{' && *sline) { daddchar(methstring, *sline); sline++; } if(GLOB_before && first && lastComment) { char *tline; char *zline=sline; fgetpos(Mf, &currPos); if(fsetpos(Mf, &lastComment)<0) { perror("docgen:gathermethod():fsetpos->lastComment"); exit(2); } tline=fgetdline(Mf); sline=tline; while(*sline!='/' && *sline) { sline++; } if(*sline == '/') { if(!strncmp(sline, "//", 2)) { dstrarrcat(methstring, "\n/*\n"); dstrarrcat(methstring, sline+2); dstrarrcat(methstring, "\n*/\n"); } else if(!strncmp(sline, "/*", 2)) { daddchar(methstring,'\n'); while(!feof(Mf) && docgen_recmp(STOPEXP, sline)) { dstrarrcat(methstring, sline); daddchar(methstring,'\n'); free(tline); tline=fgetdline(Mf); sline=tline; } if(feof(Mf)) { fprintf(stderr, "Unexpected eof\n"); exit(3); } sline=strstr(tline, "*/"); dstrarrcat(methstring, tline); // daddchar(methstring,'\n'); sline+=2; } } free(tline); sline=zline; if(fsetpos(Mf, &currPos)<0) { perror("docgen:gathermethod():fsetpos->currPos"); exit(2); } } if((*sline == '/')) { if(!strncmp(sline, "//", 2) && GLOB_after) { dstrarrcat(methstring, "\n/*\n"); dstrarrcat(methstring, sline+2); dstrarrcat(methstring, "\n*/\n"); } else if(!strncmp(sline, "/*", 2)) { if(GLOB_after) daddchar(methstring,'\n'); while(!feof(Mf) && docgen_recmp(STOPEXP, sline)) { if(GLOB_after) { dstrarrcat(methstring, sline); daddchar(methstring,'\n'); } free(mline); mline=fgetdline(Mf); sline=mline; } if(feof(Mf)) { fprintf(stderr, "Unexpected eof\n"); exit(3); } sline=strstr(mline, "*/"); if(GLOB_after) { dstrarrcat(methstring, mline); // daddchar(methstring,'\n'); } sline+=2; continue; } } else if(*sline=='{') { if(first) daddchar(methstring, '{'); dstrarrcat(methstring, "\n}\n"); sline=arrdstr(methstring); freedstr(methstring); methstring=initdstr(); mline=parseoneliner(methstring, ivarstr, sline); dstrarrcat(methstring, mline); dstrarrcat(methstring, "\n\n"); sline=arrdstr(methstring); freedstr(methstring); free(ivarstr); return sline; } first=no; daddchar(methstring,' '); free(mline); mline=fgetdline(Mf); sline=mline; } return NULL; } #define GETNEWLINE \ { mline=nextline;\ if(!mline) {\ free(qline);\ qline=dqueuesize(methlist) ? *(char **)dsdequeue(methlist) : NULL;\ \ if(!qline)\ return;\ \ mline=qline;\ }\ \ nextline=strchr(mline,'\n');\ if(nextline) {\ *nextline='\0';\ nextline++;\ } }\ /* Print description * text as long as this * isn't a line with a * comment ender. * * But some comments * might have text on * the same line as the * comment ender. * * Should be no problem * since we only want * useful comments and * they shouldn't be on * the same line as a * comment ender. * * But this could be * changed to a * do-while loop to * handle that case. */ #ifdef OBJC #define PUTMETHDESC [myForm putMethodDescription] #define PUTLINE [myForm putLine:mline] #else #define PUTMETHDESC fputmethdesc(RTFf) #define PUTLINE fputline(RTFf, mline) #endif #define COMMINTERN \ { mline+=2;\ \ if(GLOB_firstcomm)\ parsecomments(RTFf, mline, dynstring);\ \ GETNEWLINE;\ \ while(mline && docgen_recmp(STOPEXP, mline)) {\ if(docgen_recmp(SEEALSO, mline)) {\ /* Any line that matches the See Also\ * expression is handled differently\ * So do this only if it isn't\ * a See Also line.\ */\ /* void parsecomments(FILE *RTFf, char *mline, DSTRING *dynstr) */\ parsecomments(RTFf, mline, dynstring);\ }\ else { /* This IS a See Also Line. */\ PUTMETHDESC; \ /* If this isn't the last line\ * of comments, then the\ * font style is gonna be\ * goofed up\ */\ PUTLINE; \ }\ \ GETNEWLINE;\ \ } /* while(docgen_recmp(STOPEXP, mline) && !feof(Mf)); */ \ if(GLOB_firstcomm && mline) \ parsecomments(RTFf, mline, dynstring); \ } /* do until * this matches * a comment ender */ #define COMMIES 5 void parsemethods(FILE *Mf, FILE *RTFf, char *mline, fpos_t currPos) { char *hline, *stringptr; DSTRING *dynstring; DLSTQUEUE *methlist; DSTRING *methstring; int descrip=0; int aclass=0; char *qline, *nextline; int parencount; char *ivarstr; int commieloop; bool inComments=no; fpos_t prePos=NULLPOS, lastComment=NULLPOS; #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "parsemethods(FILE *, FILE *, char *\"%s\")\n", mline); #endif methlist=initdqueue(sizeof(char *)); prePos=currPos; /* go to the first _uncommented_ method */ while((docgen_recmp(METHEXP, mline) || inComments) && !feof(Mf)) { if(!docgen_recmp(STARTEXP, mline)) { inComments=yes; lastComment=prePos; } if(!inComments && strstr(mline,"//")) lastComment=prePos; if(!docgen_recmp(STOPEXP, mline)) inComments=no; free(mline); fgetpos(Mf, &prePos); mline=fgetdline(Mf); } if(feof(Mf)) return; ivarstr=arrdstr(GLOB_istring); methstring=initdstr(); qline=gathermethod(mline, Mf, lastComment); if(qline) dsenqueue(methlist, &qline); #ifndef NODEBUG if(V_USELESS) fprintf(stderr,mline); #endif lastComment=NULLPOS; fgetpos(Mf, &prePos); mline=fgetdline(Mf); inComments=no; while(!feof(Mf) && docgen_recmp(DONEINT ,mline)) { while((docgen_recmp(METHEXP, mline) || inComments) && !feof(Mf)) { if(!docgen_recmp(STARTEXP, mline)) { inComments=yes; lastComment=prePos; } if(!inComments && strstr(mline,"//")) lastComment=prePos; if(!docgen_recmp(STOPEXP, mline)) inComments=no; free(mline); fgetpos(Mf, &prePos); mline=fgetdline(Mf); } if(feof(Mf) && docgen_recmp(DONEINT, mline)) break; qline=gathermethod(mline, Mf, lastComment); #ifndef NODEBUG if(V_USELESS) fprintf(stderr,qline); #endif if(qline) dsenqueue(methlist, &qline); lastComment=NULLPOS; fgetpos(Mf, &prePos); mline=fgetdline(Mf); } if(mline) free(mline); dynstring=initdstr(); dstrarrcat(dynstring, DEFITAL); if(GLOB_sort) dlstsort(methlist, dcmp); qline=*(char **)dsdequeue(methlist); if(!qline) return; nextline=strchr(qline, '\n'); if(!nextline) return; *nextline='\0'; nextline++; mline=qline; if(!mline) return; if(!docgen_recmp(CLASSMETH, mline)) { #ifdef OBJC [myForm putMethodHeader:"Class"]; #else fputmethodh(RTFf, "Class"); /* Set up for Class Methods */ #endif aclass=1; } else #ifdef OBJC [myForm putMethodHeader:"Instance"]; #else fputmethodh(RTFf, "Instance"); #endif /* keep parsing until we hit a line matching DONEINT */ while(mline && docgen_recmp(DONEINT, mline)) { while(mline && docgen_recmp(DONEINT, mline) && docgen_recmp(METHEXP, mline)) { GETNEWLINE; } if(GLOB_undoc ? !docgen_recmp(UNDOC, mline) : 0) { free(qline); qline=dqueuesize(methlist) ? *(char **)dsdequeue(methlist) : NULL; if(!qline) break; nextline=strchr(qline, '\n'); if(nextline) { *nextline='\0'; nextline++; } mline=qline; continue; } if(!docgen_recmp(METHEXP, mline)) { /* this line, or any line found in the .m file * matches the METHEXP pattern. */ if(aclass && docgen_recmp(CLASSMETH, mline)) { #ifdef OBJC [myForm putMethodHeader:"Instance"]; #else fputmethodh(RTFf, "Instance"); #endif aclass=0; } descrip=0; freedchars(dynstring); /* These variables are used with * the comments, but should be reset * for every new method. */ /* Everything between here and the comment beginning * with DONE is just for printing the name of the method * and find the arguments to the method */ hline=mline; /* We need to free mline * so we must have another pointer * that will be stepped through the string * * stringptr and hline are just pointers * used for stepping * * It may seem pointless to use hline here * because we just assign it to stringptr, * but we want to reset stringptr back to * hline's position later */ SKIPSPACE(hline); stringptr=hline; while(isspace(*stringptr) || *stringptr == '-' || *stringptr == '+') stringptr++; if(*stringptr == '(') { /* Right now we just want the name * so skip the type */ SKIPPARENS(stringptr); } SKIPSPACE(stringptr); #ifdef OBJC [myForm putLine:" "]; [myForm putMethodL1]; #else fputline(RTFf," "); /* Start a new line */ fputmethodl1(RTFf); /* Set up for method name */ #endif while(*stringptr != ':' && *stringptr) fputc(*stringptr++, RTFf); if(*stringptr) fputc(*stringptr++, RTFf); while(*stringptr) { /* This while statement goes through * the rest of the line and puts * the name of each argument in * the dynamic string, dynstring */ SKIPSPACE(stringptr); if(*stringptr=='(') { /* And not all argyments have a type */ /* And we don't need the * type for the list of * arguments */ SKIPPARENS(stringptr); } SKIPSPACE(stringptr); daddchar(dynstring, '#'); while(!isspace(*stringptr) && (*stringptr!=':') && *stringptr) daddchar(dynstring, *stringptr++); daddchar(dynstring, '#'); /* The '#' seperates each argument in the big * list of names */ SKIPSPACE(stringptr); while(*stringptr != ':' && *stringptr) fputc(*stringptr++, RTFf); if(*stringptr) fputc(*stringptr++, RTFf); } /* while(*stringptr) */ #ifdef OBJC [myForm putLine:" "]; #else fputline(RTFf, " "); #endif /* DONE parsing for arguments to method */ stringptr=hline; /* re-set stringptr back to hline * which is the first non-space character * in the line */ #ifdef OBJC [myForm putMethodL2]; #else fputmethodl2(RTFf); /* Set up for full method line */ #endif fprintf(RTFf,"%c",stringptr[0]); /* That first character * should be a + or - * so print it specially */ #ifdef OBJC [myForm changeFont:0]; #else fchangefont(RTFf, 0); #endif stringptr++; SKIPSPACE(stringptr); if(*stringptr == '(') { /* Not all methods have a type */ parencount=1; while(parencount && *stringptr) { fputc(*stringptr++, RTFf); if(*stringptr=='(') parencount++; else if(*stringptr==')') parencount--; } if(*stringptr) fputc(*stringptr++, RTFf); } #ifdef OBJC [myForm makeBold]; #else fmakebold(RTFf); /* The method name will be bold */ #endif SKIPSPACE(stringptr); while(*stringptr != ':' && *stringptr) fputc(*stringptr++, RTFf); if(*stringptr) fputc(*stringptr++, RTFf); /* Put the ':' as bold also */ #ifdef OBJC [myForm unBold]; #else funbold(RTFf); #endif while(*stringptr) { /* Eveything else after the first ':' * should be an argument. */ SKIPSPACE(stringptr); if(*stringptr=='(') { /* If there is a type, print it unspecially */ /* Until you hit a * closing ')' */ parencount=1; while(parencount && *stringptr) { fputc(*stringptr++, RTFf); if(*stringptr=='(') parencount++; else if(*stringptr==')') parencount--; } if(*stringptr) fputc(*stringptr++, RTFf); } SKIPSPACE(stringptr); #ifdef OBJC [myForm makeItalic]; #else fmakeitalic(RTFf); /* The argument itself is italicized */ #endif while(!isspace(*stringptr) && (*stringptr!=':') && *stringptr) fputc(*stringptr++, RTFf); #ifdef OBJC [myForm unItalic]; #else funitalic(RTFf); /* Note: This is not a fun italic */ #endif SKIPSPACE(stringptr); fputc(' ', RTFf); #ifdef OBJC [myForm makeBold]; #else fmakebold(RTFf); #endif while(*stringptr != ':' && *stringptr) fputc(*stringptr++, RTFf); if(*stringptr) fputc(*stringptr++, RTFf); #ifdef OBJC [myForm unBold]; #else funbold(RTFf); #endif } /* while(*stringptr) */ #ifdef OBJC [myForm putLine:" "]; #else fputline(RTFf, " "); #endif } /* if(!docgen_recmp(METHEXP, mline)) */ /* Handle up to COMMIES comments in a method */ for(commieloop=0;commieloop<COMMIES;commieloop++) { GETNEWLINE; if(!docgen_recmp(STARTEXP, mline)) { /* else this or any line that matches * a comment beginning line will * have it's comments printed. * That's why this program will * print out any comments in a * method, even after it's already * printed a No Description line */ COMMINTERN; descrip=1; } else break; /* get away from these commies! */ } } /* while(docgen_recmp(DONEINT, mline) && !feof(Mf)) */ freedstr(dynstring); free(ivarstr); free(qline); freedlist(methlist); #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "parsemethods: returning\n"); #endif } void traceinheritance(FILE *RTFf, char *hdir, char *hname) { char pathsep[]=":"; FILE *Hf; char *hline, *stringptr, *FQh; ofiletype fty; DSTRING *dhname; char *hpath, *honepath, *fhname; static unsigned long of_counter=MAX_INHERIT_SEARCHES; #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "traceinheritance(FILE *, %s, %s)\n", hdir, hname); #endif dstrarrcat(GLOB_istring, hname); daddchar(GLOB_istring, '#'); dhname=dstrarr(hdir); hpath=arrdstr(dhname); free(dhname); dhname=dstrarr(hname); dstrarrcat(dhname, ".h"); fhname=arrdstr(dhname); free(dhname); honepath=strtok(hpath, pathsep); Hf=NULL; FQh=NULL; if(GLOB_recurs) { /* We want to recursively search for * the file in every directory in directories * of the search path. */ while(honepath!=NULL && FQh==NULL) { /* Keep looping until either * we find a file or run out * of directories. */ FQh=findfile(fhname, honepath); honepath=strtok(NULL, pathsep); } if(FQh!=NULL) { Hf=fopen(FQh,"r"); free(FQh); } } else while(honepath!=NULL && Hf==NULL) { FQh=dirfile(honepath, fhname); if(FQh) { Hf=fopen(FQh, "r"); free(FQh); } honepath=strtok(NULL, pathsep); } free(fhname); free(hpath); if(Hf == NULL) { if(V_STAT) fprintf(stderr, "traceinheritance: %.200s not found in %.800s\n", hname, hdir); return; } if(!--of_counter) { /* If this is true, the we must be tracing too many */ if(V_BADERR) fprintf(stderr,"traceinheritance: We seem to have hit an infinite loop in\n%s\n",hname); return; } #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "of_counter = %ld\n", of_counter); #endif /* 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); if(V_BADERR) fprintf(stderr,"Unexpected end of file %s\n", hname); if(fclose(Hf) == EOF) if(V_BADERR) perror("I couldn't close the header file. Pray."); of_counter++; return; } /* 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 { free(hline); if(fclose(Hf) == EOF) if(V_BADERR) perror("I couldn't close the header file. Pray."); if(V_STAT) fprintf(stderr,"traceinheritance: %s is neither a Class or a Category\n", hname); of_counter++; return; } /* If strtok fails on this first pass * then exit with an error. */ if((stringptr=strtok(hline, INTTOK)) == NULL) { free(hline); if(V_ERR) fprintf(stderr, "Improper @interface description in\n%s\n", hname); if(fclose(Hf) == EOF) if(V_BADERR) perror("I couldn't close the header file. Pray."); of_counter++; return; } else stringptr=strtok(NULL, INTTOK); if(fty==class) { stringptr=strtok(NULL, INTTOK); if(stringptr != NULL) { fprintf(RTFf, " %s %s",GLOB_sep, stringptr); traceinheritance(RTFf, hdir, stringptr); } } else { stringptr=strtok(NULL, INTTOK); if(stringptr!=NULL) stringptr[strlen(stringptr)-1]='\0'; if(stringptr != NULL) { fprintf(RTFf, " %s %s",GLOB_sep, stringptr); traceinheritance(RTFf, hdir, stringptr); } } of_counter++; #ifndef NODEBUG if(V_USELESS) fprintf(stderr, "of_counter++ = %ld\n", of_counter); #endif if(fclose(Hf) == EOF) if(V_BADERR) perror("I couldn't close the header file. Pray."); return; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.