1    | /***************************************
2    |   $Header: /home/amb/cxref/RCS/comment.c 1.21 1999/11/16 18:58:13 amb Exp $
3    | 
4    |   C Cross Referencing & Documentation tool. Version 1.5c.
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   | 
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  | 
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  | 
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  |     malloc_comment=Realloc(malloc_comment,strlen(comment)+1);
162  |     strcpy(malloc_comment,comment);
163  |     current_comment=malloc_comment;
164  |    }
165  |  else
166  |    {
167  |     current_comment=NULL;
168  |     if(malloc_comment) *malloc_comment=0;
169  |    }
170  | }
171  | 
172  | 
173  | /*++++++++++++++++++++++++++++++++++++++
174  |   A function to split out the arguments etc from a comment,
175  |   for example the function argument comments are separated using this.
176  | 
177  |   char* SplitComment Returns the required comment.
178  | 
179  |   char** original A pointer to the original comment, this is altered in the process.
180  | 
181  |   char* name The name that is to be cut out from the comment.
182  | 
183  |   A most clever function that ignores spaces so that 'char* b' and 'char *b' match.
184  |   ++++++++++++++++++++++++++++++++++++++*/
185  | 
186  | char* SplitComment(char** original,char* name)
187  | {
188  |  char* c=NULL;
189  | 
190  |  if(*original)
191  |    {
192  |     int l=strlen(name);
193  |     c=*original;
194  | 
195  |     do{
196  |        int i,j,failed=0;
197  |        char* start=c;
198  | 
199  |        while(c[0]=='\n')
200  |           c++;
201  | 
202  |        for(i=j=0;i<l;i++,j++)
203  |          {
204  |           while(name[i]==' ') i++;
205  |           while(c[j]==' ') j++;
206  | 
207  |           if(!c[j] || name[i]!=c[j])
208  |             {failed=1;break;}
209  |          }
210  | 
211  |        if(!failed)
212  |          {
213  |           char* old=*original;
214  |           char* end=strstr(c,"\n\n");
215  |           *start=0;
216  |           if(end)
217  |              *original=MallocString(ConcatStrings(2,*original,end));
218  |           else
219  |              if(start==*original)
220  |                 *original=NULL;
221  |              else
222  |                 *original=MallocString(*original);
223  |           if(end)
224  |              *end=0;
225  | 
226  |           if(end && &c[j+1]>=end)
227  |              c=NULL;
228  |           else
229  |             {
230  |              c=CopyString(&c[j+1]);
231  |              TidyCommentString(&c,1);
232  |              if(!*c)
233  |                 c=NULL;
234  |             }
235  | 
236  |           Free(old);
237  |           break;
238  |          }
239  |       }
240  |     while((c=strstr(c,"\n\n")));
241  |    }
242  | 
243  |  return(c);
244  | }
245  | 
246  | 
247  | /*++++++++++++++++++++++++++++++++++++++
248  |   Tidy up the current comment string by snipping off trailing and leading junk.
249  | 
250  |   char **string The string that is to be tidied.
251  | 
252  |   int spaces Indicates that leading and trailing whitespace are to be removed as well.
253  |   ++++++++++++++++++++++++++++++++++++++*/
254  | 
255  | static void TidyCommentString(char **string,int spaces)
256  | {
257  |  int whitespace;
258  |  char *to=*string,*from=*string,*str;
259  | 
260  |  if(!*string)
261  |     return;
262  | 
263  |  /* Remove CR characters. */
264  | 
265  |  while(*from)
266  |    {
267  |     if(*from=='\r')
268  |        from++;
269  |     else
270  |        *to++=*from++;
271  |    }
272  |  *to=0;
273  | 
274  |  /* Remove leading blank lines. */
275  | 
276  |  whitespace=1;
277  |  str=*string;
278  |  do
279  |    {
280  |     if(*str!='\n')
281  |        do
282  |          {
283  |           if(*str!=' ' && *str!='\t')
284  |              whitespace=0;
285  |          }
286  |        while(whitespace && *str && *++str!='\n');
287  | 
288  |     if(whitespace)
289  |        *string=++str;
290  |     else if(spaces)
291  |        *string=str;
292  |    }
293  |  while(whitespace);
294  | 
295  |  /* Remove trailing blank lines. */
296  | 
297  |  whitespace=1;
298  |  str=*string+strlen(*string)-1;
299  |  do
300  |    {
301  |     if(*str!='\n')
302  |        do
303  |          {
304  |           if(*str!=' ' && *str!='\t')
305  |              whitespace=0;
306  |          }
307  |        while(whitespace && str>*string && *--str!='\n');
308  | 
309  |     if(whitespace)
310  |        *str--=0;
311  |     else if(spaces)
312  |        *(str+1)=0;
313  |    }
314  |  while(whitespace);
315  | 
316  |  /* Replace lines containing just whitespace with empty lines. */
317  | 
318  |  str=*string;
319  |  do
320  |    {
321  |     char *start;
322  | 
323  |     whitespace=1;
324  | 
325  |     while(*str=='\n')
326  |        str++;
327  | 
328  |     start=str;
329  | 
330  |     while(*str && *++str!='\n')
331  |        {
332  |         if(*str!=' ' && *str!='\t')
333  |            whitespace=0;
334  |        }
335  | 
336  |     if(whitespace)
337  |       {
338  |        char *copy=start;
339  | 
340  |        while((*start++=*str++));
341  | 
342  |        str=copy;
343  |       }
344  |    }
345  |  while(*str);
346  | }
347  | 
348  | 
349  | /*++++++++++++++++++++++++++++++++++++++
350  |   Delete the malloced string for the comment
351  |   ++++++++++++++++++++++++++++++++++++++*/
352  | 
353  | void DeleteComment(void)
354  | {
355  |  current_comment=NULL;
356  |  if(malloc_comment)
357  |     Free(malloc_comment);
358  |  malloc_comment=NULL;
359  |  comment_ended=0;
360  | }