1 /***************************************
2   $Header: /home/amb/CVS/cxref/src/comment.c,v 1.22 2003-01-17 19:07:56 amb Exp $
3 
4   C Cross Referencing & Documentation tool. Version 1.5e.
5 
6   Collects the comments from the parser.
7   ******************/ /******************
8   Written by Andrew M. Bishop
9 
10   This file Copyright 1995,96,97,98 Andrew M. Bishop
11   It may be distributed under the GNU Public License, version 2, or
12   any higher version.  See section COPYING of the GNU Public license
13   for conditions under which this file may be redistributed.
14   ***************************************/
15 
16 /*+ Turn on the debugging in this file. +*/
17 #define DEBUG 0
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "memory.h"
24 #include "datatype.h"
25 #include "cxref.h"
26 
27 static void TidyCommentString(char **string,int spaces);
28 
29 /*+ The option to insert the comments verbatim into the output. +*/
30 extern int option_verbatim_comments;
31 
32 /*+ The file that is currently being processed. +*/
33 extern File CurFile;
34 
35 /*+ The name of the current file. +*/
36 extern char* parse_file;
37 
38 /*+ The current (latest) comment. +*/
39 static char* current_comment=NULL;
40 
41 /*+ The malloced string for the current comment. +*/
42 static char* malloc_comment=NULL;
43 
44 /*+ The status of the current comment. +*/
45 static int comment_ended=0;
46 
47 
48 /*++++++++++++++++++++++++++++++++++++++
49   Function that is called when a comment or part of one is seen. The comment is built up until an end of comment is signaled.
50 
51   char* c The comment text.
52 
53   int flag A flag to indicate the type of comment that it is.
54            if flag==0 then it is a comment of some sort.
55            If flag==1 then it is the end of a file (/ * * comment * * /) comment
56            if flag==2 then it is the end of the other special comment (/ * + comment + * /).
57            if flag==3 then it is the end of a normal comment (/ * comment * /).
58   ++++++++++++++++++++++++++++++++++++++*/
59 
SeenComment(char * c,int flag)60 void SeenComment(char* c,int flag)
61 {
62  switch(flag)
63    {
64    case 1:
65 #if DEBUG
66     printf("#Comment.c# Seen comment /**\n%s\n**/\n",current_comment);
67 #endif
68     TidyCommentString(&current_comment,0);
69     if(!CurFile->comment && !strcmp(CurFile->name,parse_file))
70        SeenFileComment(current_comment);
71     current_comment=NULL;
72     if(malloc_comment) *malloc_comment=0;
73     comment_ended=1;
74     break;
75 
76    case 2:
77 #if DEBUG
78     printf("#Comment.c# Seen comment /*+\n%s\n+*/\n",current_comment);
79 #endif
80     TidyCommentString(&current_comment,0);
81     if(SeenFuncIntComment(current_comment))
82       {
83        current_comment=NULL;
84        if(malloc_comment) *malloc_comment=0;
85       }
86     comment_ended=1;
87     break;
88 
89    case 3:
90 #if DEBUG
91     printf("#Comment.c# Seen comment /*\n%s\n*/\n",current_comment);
92 #endif
93     TidyCommentString(&current_comment,!option_verbatim_comments);
94     if(!CurFile->comment && !strcmp(CurFile->name,parse_file))
95       {
96        SeenFileComment(current_comment);
97        current_comment=NULL;
98        if(malloc_comment) *malloc_comment=0;
99       }
100     comment_ended=1;
101     break;
102 
103    default:
104     if(comment_ended)
105       {
106        comment_ended=0;
107        current_comment=NULL;
108        if(malloc_comment) *malloc_comment=0;
109       }
110 
111     if(malloc_comment==NULL)
112       {
113        malloc_comment=Malloc(strlen(c)+1);
114        strcpy(malloc_comment,c);
115       }
116     else
117       {
118        malloc_comment=Realloc(malloc_comment,strlen(c)+strlen(malloc_comment)+1);
119        strcat(malloc_comment,c);
120       }
121 
122     current_comment=malloc_comment;
123    }
124 }
125 
126 
127 /*++++++++++++++++++++++++++++++++++++++
128   Provide the current (latest) comment.
129 
130   char* GetCurrentComment Returns the current (latest) comment.
131   ++++++++++++++++++++++++++++++++++++++*/
132 
GetCurrentComment(void)133 char* GetCurrentComment(void)
134 {
135  char* comment=current_comment;
136 
137 #if DEBUG
138  printf("#Comment.c# GetCurrentComment returns <<<%s>>>\n",comment);
139 #endif
140 
141  current_comment=NULL;
142 
143  return(comment);
144 }
145 
146 
147 /*++++++++++++++++++++++++++++++++++++++
148   Set the current (latest) comment.
149 
150   char* comment The comment.
151   ++++++++++++++++++++++++++++++++++++++*/
152 
SetCurrentComment(char * comment)153 void SetCurrentComment(char* comment)
154 {
155 #if DEBUG
156  printf("#Comment.c# SetCurrentComment set to <<<%s>>>\n",comment);
157 #endif
158 
159  if(comment)
160    {
161     if(malloc_comment!=comment)
162       {
163        malloc_comment=Realloc(malloc_comment,strlen(comment)+1);
164        strcpy(malloc_comment,comment);
165       }
166     current_comment=malloc_comment;
167    }
168  else
169    {
170     current_comment=NULL;
171     if(malloc_comment) *malloc_comment=0;
172    }
173 }
174 
175 
176 /*++++++++++++++++++++++++++++++++++++++
177   A function to split out the arguments etc from a comment,
178   for example the function argument comments are separated using this.
179 
180   char* SplitComment Returns the required comment.
181 
182   char** original A pointer to the original comment, this is altered in the process.
183 
184   char* name The name that is to be cut out from the comment.
185 
186   A most clever function that ignores spaces so that 'char* b' and 'char *b' match.
187   ++++++++++++++++++++++++++++++++++++++*/
188 
SplitComment(char ** original,char * name)189 char* SplitComment(char** original,char* name)
190 {
191  char* c=NULL;
192 
193  if(*original)
194    {
195     int l=strlen(name);
196     c=*original;
197 
198     do{
199        int i,j,failed=0;
200        char* start=c;
201 
202        while(c[0]=='\n')
203           c++;
204 
205        for(i=j=0;i<l;i++,j++)
206          {
207           while(name[i]==' ') i++;
208           while(c[j]==' ') j++;
209 
210           if(!c[j] || name[i]!=c[j])
211             {failed=1;break;}
212          }
213 
214        if(!failed)
215          {
216           char* old=*original;
217           char* end=strstr(c,"\n\n");
218           *start=0;
219           if(end)
220              *original=MallocString(ConcatStrings(2,*original,end));
221           else
222              if(start==*original)
223                 *original=NULL;
224              else
225                 *original=MallocString(*original);
226           if(end)
227              *end=0;
228 
229           if(end && &c[j+1]>=end)
230              c=NULL;
231           else
232             {
233              c=CopyString(&c[j+1]);
234              TidyCommentString(&c,1);
235              if(!*c)
236                 c=NULL;
237             }
238 
239           Free(old);
240           break;
241          }
242       }
243     while((c=strstr(c,"\n\n")));
244    }
245 
246  return(c);
247 }
248 
249 
250 /*++++++++++++++++++++++++++++++++++++++
251   Tidy up the current comment string by snipping off trailing and leading junk.
252 
253   char **string The string that is to be tidied.
254 
255   int spaces Indicates that leading and trailing whitespace are to be removed as well.
256   ++++++++++++++++++++++++++++++++++++++*/
257 
TidyCommentString(char ** string,int spaces)258 static void TidyCommentString(char **string,int spaces)
259 {
260  int whitespace;
261  char *to=*string,*from=*string,*str;
262 
263  if(!*string)
264     return;
265 
266  /* Remove CR characters. */
267 
268  while(*from)
269    {
270     if(*from=='\r')
271        from++;
272     else
273        *to++=*from++;
274    }
275  *to=0;
276 
277  /* Remove leading blank lines. */
278 
279  whitespace=1;
280  str=*string;
281  do
282    {
283     if(*str!='\n')
284        do
285          {
286           if(*str!=' ' && *str!='\t')
287              whitespace=0;
288          }
289        while(whitespace && *str && *++str!='\n');
290 
291     if(whitespace)
292        *string=++str;
293     else if(spaces)
294        *string=str;
295    }
296  while(whitespace);
297 
298  /* Remove trailing blank lines. */
299 
300  whitespace=1;
301  str=*string+strlen(*string)-1;
302  do
303    {
304     if(*str!='\n')
305        do
306          {
307           if(*str!=' ' && *str!='\t')
308              whitespace=0;
309          }
310        while(whitespace && str>*string && *--str!='\n');
311 
312     if(whitespace)
313        *str--=0;
314     else if(spaces)
315        *(str+1)=0;
316    }
317  while(whitespace);
318 
319  /* Replace lines containing just whitespace with empty lines. */
320 
321  str=*string;
322  do
323    {
324     char *start;
325 
326     whitespace=1;
327 
328     while(*str=='\n')
329        str++;
330 
331     start=str;
332 
333     while(*str && *++str!='\n')
334        {
335         if(*str!=' ' && *str!='\t')
336            whitespace=0;
337        }
338 
339     if(whitespace)
340       {
341        char *copy=start;
342 
343        while((*start++=*str++));
344 
345        str=copy;
346       }
347    }
348  while(*str);
349 }
350 
351 
352 /*++++++++++++++++++++++++++++++++++++++
353   Delete the malloced string for the comment
354   ++++++++++++++++++++++++++++++++++++++*/
355 
DeleteComment(void)356 void DeleteComment(void)
357 {
358  current_comment=NULL;
359  if(malloc_comment)
360     Free(malloc_comment);
361  malloc_comment=NULL;
362  comment_ended=0;
363 }
364