1    | /***************************************
2    |   $Header: /home/amb/cxref/RCS/comment.c 1.20 1998/12/22 14:26:26 amb Exp $
3    | 
4    |   C Cross Referencing & Documentation tool. Version 1.5.
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. If c==0 then it is a file (/ * * comment * * /) comment
52   |                             if c==1 then it is the other special comment (/ * + comment + * /).
53   |                             if c==2 then it is a normal comment (/ * comment * /).
54   |                             if c==3 then it is not a comment.
55   |   ++++++++++++++++++++++++++++++++++++++*/
56   | 
57   | void SeenComment(char* c)
58   | {
59   |  switch((int)c)
60   |    {
61   |    case 0:
62   | #if DEBUG
63   |     printf("#Comment.c# Seen comment /**\n%s\n**/\n",current_comment);
64   | #endif
65   |     TidyCommentString(&current_comment,0);
66   |     if(!CurFile->comment && !strcmp(CurFile->name,parse_file))
67   |        SeenFileComment(current_comment);
68   |     current_comment=NULL;
69   |     if(malloc_comment) *malloc_comment=0;
70   |     comment_ended=1;
71   |     break;
72   | 
73   |    case 1:
74   | #if DEBUG
75   |     printf("#Comment.c# Seen comment /*+\n%s\n+*/\n",current_comment);
76   | #endif
77   |     TidyCommentString(&current_comment,0);
78   |     if(SeenFuncIntComment(current_comment))
79   |       {
80   |        current_comment=NULL;
81   |        if(malloc_comment) *malloc_comment=0;
82   |       }
83   |     comment_ended=1;
84   |     break;
85   | 
86   |    case 2:
87   | #if DEBUG
88   |     printf("#Comment.c# Seen comment /*\n%s\n*/\n",current_comment);
89   | #endif
90   |     TidyCommentString(&current_comment,!option_verbatim_comments);
91   |     if(!CurFile->comment && !strcmp(CurFile->name,parse_file))
92   |       {
93   |        SeenFileComment(current_comment);
94   |        current_comment=NULL;
95   |        if(malloc_comment) *malloc_comment=0;
96   |       }
97   |     comment_ended=1;
98   |     break;
99   | 
100  |    default:
101  |     if(comment_ended)
102  |       {
103  |        comment_ended=0;
104  |        current_comment=NULL;
105  |        if(malloc_comment) *malloc_comment=0;
106  |       }
107  | 
108  |     if(malloc_comment==NULL)
109  |       {
110  |        malloc_comment=Malloc(strlen(c)+1);
111  |        strcpy(malloc_comment,c);
112  |       }
113  |     else
114  |       {
115  |        malloc_comment=Realloc(malloc_comment,strlen(c)+strlen(malloc_comment)+1);
116  |        strcat(malloc_comment,c);
117  |       }
118  | 
119  |     current_comment=malloc_comment;
120  |    }
121  | }
122  | 
123  | 
124  | /*++++++++++++++++++++++++++++++++++++++
125  |   Provide the current (latest) comment.
126  | 
127  |   char* GetCurrentComment Returns the current (latest) comment.
128  |   ++++++++++++++++++++++++++++++++++++++*/
129  | 
130  | char* GetCurrentComment(void)
131  | {
132  |  char* comment=current_comment;
133  | 
134  | #if DEBUG
135  |  printf("#Comment.c# GetCurrentComment returns <<<%s>>>\n",comment);
136  | #endif
137  | 
138  |  current_comment=NULL;
139  | 
140  |  return(comment);
141  | }
142  | 
143  | 
144  | /*++++++++++++++++++++++++++++++++++++++
145  |   Set the current (latest) comment.
146  | 
147  |   char* comment The comment.
148  |   ++++++++++++++++++++++++++++++++++++++*/
149  | 
150  | void SetCurrentComment(char* comment)
151  | {
152  | #if DEBUG
153  |  printf("#Comment.c# SetCurrentComment set to <<<%s>>>\n",comment);
154  | #endif
155  | 
156  |  if(comment)
157  |    {
158  |     malloc_comment=Realloc(malloc_comment,strlen(comment)+1);
159  |     strcpy(malloc_comment,comment);
160  |     current_comment=malloc_comment;
161  |    }
162  |  else
163  |    {
164  |     current_comment=NULL;
165  |     if(malloc_comment) *malloc_comment=0;
166  |    }
167  | }
168  | 
169  | 
170  | /*++++++++++++++++++++++++++++++++++++++
171  |   A function to split out the arguments etc from a comment,
172  |   for example the function argument comments are separated using this.
173  | 
174  |   char* SplitComment Returns the required comment.
175  | 
176  |   char** original A pointer to the original comment, this is altered in the process.
177  | 
178  |   char* name The name that is to be cut out from the comment.
179  | 
180  |   A most clever function that ignores spaces so that 'char* b' and 'char *b' match.
181  |   ++++++++++++++++++++++++++++++++++++++*/
182  | 
183  | char* SplitComment(char** original,char* name)
184  | {
185  |  char* c=NULL;
186  | 
187  |  if(*original)
188  |    {
189  |     int l=strlen(name);
190  |     c=*original;
191  | 
192  |     do{
193  |        int i,j,failed=0;
194  |        char* start=c;
195  | 
196  |        while(c[0]=='\n')
197  |           c++;
198  | 
199  |        for(i=j=0;i<l;i++,j++)
200  |          {
201  |           while(name[i]==' ') i++;
202  |           while(c[j]==' ') j++;
203  | 
204  |           if(!c[j] || name[i]!=c[j])
205  |             {failed=1;break;}
206  |          }
207  | 
208  |        if(!failed)
209  |          {
210  |           char* old=*original;
211  |           char* end=strstr(c,"\n\n");
212  |           *start=0;
213  |           if(end)
214  |              *original=MallocString(ConcatStrings(2,*original,end));
215  |           else
216  |              if(start==*original)
217  |                 *original=NULL;
218  |              else
219  |                 *original=MallocString(*original);
220  |           if(end)
221  |              *end=0;
222  | 
223  |           if(end && &c[j+1]>=end)
224  |              c=NULL;
225  |           else
226  |             {
227  |              c=CopyString(&c[j+1]);
228  |              TidyCommentString(&c,1);
229  |              if(!*c)
230  |                 c=NULL;
231  |             }
232  | 
233  |           Free(old);
234  |           break;
235  |          }
236  |       }
237  |     while((c=strstr(c,"\n\n")));
238  |    }
239  | 
240  |  return(c);
241  | }
242  | 
243  | 
244  | /*++++++++++++++++++++++++++++++++++++++
245  |   Tidy up the current comment string by snipping off trailing and leading junk.
246  | 
247  |   char **string The string that is to be tidied.
248  | 
249  |   int spaces Indicates that leading and trailing whitespace are to be removed as well.
250  |   ++++++++++++++++++++++++++++++++++++++*/
251  | 
252  | static void TidyCommentString(char **string,int spaces)
253  | {
254  |  int whitespace;
255  |  char *to=*string,*from=*string,*str;
256  | 
257  |  if(!*string)
258  |     return;
259  | 
260  |  /* Remove CR characters. */
261  | 
262  |  while(*from)
263  |    {
264  |     if(*from=='\r')
265  |        from++;
266  |     else
267  |        *to++=*from++;
268  |    }
269  |  *to=0;
270  | 
271  |  /* Remove leading blank lines. */
272  | 
273  |  whitespace=1;
274  |  str=*string;
275  |  do
276  |    {
277  |     if(*str!='\n')
278  |        do
279  |          {
280  |           if(*str!=' ' && *str!='\t')
281  |              whitespace=0;
282  |          }
283  |        while(whitespace && *str && *++str!='\n');
284  | 
285  |     if(whitespace)
286  |        *string=++str;
287  |     else if(spaces)
288  |        *string=str;
289  |    }
290  |  while(whitespace);
291  | 
292  |  /* Remove trailing blank lines. */
293  | 
294  |  whitespace=1;
295  |  str=*string+strlen(*string)-1;
296  |  do
297  |    {
298  |     if(*str!='\n')
299  |        do
300  |          {
301  |           if(*str!=' ' && *str!='\t')
302  |              whitespace=0;
303  |          }
304  |        while(whitespace && str>*string && *--str!='\n');
305  | 
306  |     if(whitespace)
307  |        *str--=0;
308  |     else if(spaces)
309  |        *(str+1)=0;
310  |    }
311  |  while(whitespace);
312  | 
313  |  /* Replace lines containing just whitespace with empty lines. */
314  | 
315  |  str=*string;
316  |  do
317  |    {
318  |     char *start;
319  | 
320  |     whitespace=1;
321  | 
322  |     while(*str=='\n')
323  |        str++;
324  | 
325  |     start=str;
326  | 
327  |     while(*str && *++str!='\n')
328  |        {
329  |         if(*str!=' ' && *str!='\t')
330  |            whitespace=0;
331  |        }
332  | 
333  |     if(whitespace)
334  |       {
335  |        char *copy=start;
336  | 
337  |        while((*start++=*str++));
338  | 
339  |        str=copy;
340  |       }
341  |    }
342  |  while(*str);
343  | }
344  | 
345  | 
346  | /*++++++++++++++++++++++++++++++++++++++
347  |   Delete the malloced string for the comment
348  |   ++++++++++++++++++++++++++++++++++++++*/
349  | 
350  | void DeleteComment(void)
351  | {
352  |  current_comment=NULL;
353  |  if(malloc_comment)
354  |     Free(malloc_comment);
355  |  malloc_comment=NULL;
356  |  comment_ended=0;
357  | }