Added SILC Thread Queue API
[silc.git] / util / robodoc / Source / links.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include "robodoc.h"
6 #include "headers.h"
7 #include "util.h"
8 #include "links.h"
9 #include "folds.h"
10
11
12 FILE *xreffiles_file = NULL;
13 FILE *xref_file = NULL;
14 int link_index_size = 0;
15 struct RB_link **link_index = NULL;
16
17 /****f* ROBODoc/RB_Analyse_Xrefs [3.0b]
18  * NAME
19  *   RB_Analyse_Xrefs -- scan the xref files.
20  * SYNOPSIS
21  *   RB_Analyse_Xrefs (xreffiles_file)
22  *   RB_Analyse_Xrefs (FILE *)
23  * FUNCTION
24  *   Scan the file xreffiles_file. This file contains the
25  *   names of one or more xref files. All the references in the
26  *   files are scaned and stored in a link list of the type
27  *   RB_link. These xref files can be generated with robodoc.
28  * INPUTS
29  *   xreffiles_file - a file pointer to the file with xref file
30  *   names.
31  * RESULT
32  *   none
33  * BUGS
34  *   Might fail if there are syntax errors in one of the xref
35  *   files.
36  *   Bad use of feof() and fgets().
37  * SEE ALSO
38  *   RB_Generate_xrefs, RB_Add_Link
39  * SOURCE
40  */
41
42 void
43 RB_Analyse_Xrefs (FILE * xreffiles_file)
44 {
45   while (!feof (xreffiles_file))
46     {
47       fgets (line_buffer, MAX_LINE_LEN, xreffiles_file);
48       if (!feof (xreffiles_file))
49         {
50           char *cur_char;
51
52           cur_char = line_buffer;
53           find_eol;
54           if (*cur_char == '\n')
55             *cur_char = '\0';
56           if (strlen (line_buffer) > 1)
57             {
58               for (cur_char--;
59                    (cur_char != line_buffer) && isspace (*cur_char);
60                    cur_char--)
61                 *cur_char = '\0';
62               if ((xref_file = fopen (line_buffer, "r")) != NULL)
63                 {
64                   int xrefs_found = FALSE;
65                   int end_of_xrefs = FALSE;
66
67                   while (!feof (xref_file) && !xrefs_found)
68                     {
69                       fgets (line_buffer, MAX_LINE_LEN, xref_file);
70                       if (!feof (xref_file) && !strncmp ("XREF:",
71                                                          line_buffer, 5))
72                         xrefs_found = TRUE;
73                     }
74
75                   while (!feof (xref_file) && !end_of_xrefs)
76                     {
77                       fgets (line_buffer, MAX_LINE_LEN, xref_file);
78                       if (!feof (xref_file))
79                         {
80                           cur_char = line_buffer;
81                           find_quote;
82                           if (*cur_char == '\"')
83                             RB_Add_Link ();
84                           else
85                             end_of_xrefs = TRUE;
86                         }
87                     }
88                   fclose (xref_file);
89                   xref_file = NULL;
90                 }
91               else
92                 RB_Panic ("could not open xref file \"%s\"\n", line_buffer);
93             }
94         }
95     }
96 }
97
98 /*************/
99
100
101 /****f* ROBODoc/RB_Slow_Sort_Links
102  * NAME
103  *   RB_Slow_Sort_Links -- sort all links according to label name.
104  ******
105  */
106
107 void
108 RB_Slow_Sort_Links (void)
109 {
110   struct RB_link *cur_link, *unsorted_links, *bigger_link;
111
112   if ((unsorted_links = first_link) != NULL)
113     {                           /* additional check koessi */
114       for (first_link = NULL;
115            unsorted_links->next_link;)
116         {
117           for (bigger_link = unsorted_links,
118                cur_link = bigger_link->next_link;
119                cur_link;
120                cur_link = cur_link->next_link)
121             {
122               if (strcmp (cur_link->label_name, bigger_link->label_name) > 0)
123                 bigger_link = cur_link;
124             }
125           RB_Remove_From_List ((struct RB_header **) &unsorted_links,
126                                (struct RB_header *) bigger_link);
127           RB_Insert_In_List ((struct RB_header **) &first_link,
128                              (struct RB_header *) bigger_link);
129         }
130       RB_Insert_In_List ((struct RB_header **) &first_link,
131                          (struct RB_header *) unsorted_links);
132     }
133 }
134
135
136 /****f* ROBODoc/RB_Add_Link [3.0b]
137  * NAME
138  *   RB_Add_Link -- add a reference link to the list
139  * SYNOPSIS
140  *   void RB_Add_Link ()
141  * FUNCTION
142  *   Adds a reference from a xref file to the linked list
143  *   with references.
144  * INPUTS
145  *   Uses the global variable line_buffer and first_link.
146  * NOTES
147  *   Makes sneaky use of the function RB_Insert_In_List.
148  * SEE ALSO
149  *   RB_Analyse_Xrefs, RB_link.
150  * SOURCE
151  */
152
153 void
154 RB_Add_Link ()
155 {
156   char *label_name, *file_name;
157   struct RB_link *new_link;
158   char *cur_char = line_buffer;
159
160   find_quote;
161   label_name = ++cur_char;
162   find_quote;
163   *cur_char++ = '\0';
164   find_quote;
165   file_name = ++cur_char;
166   find_quote;
167   *cur_char = '\0';
168   ++cur_char;
169
170   RB_Say ("adding xref link \"%s\"->\"%s\"\n", label_name, file_name);
171
172   new_link = RB_Alloc_Link (label_name, file_name);
173   new_link->type = atoi (cur_char);
174   RB_Insert_In_List ((struct RB_header **) &first_link,
175                      (struct RB_header *) new_link);
176 }
177
178 /*** RB_Add_Link ***/
179
180
181
182 /****f* ROBODoc/RB_Generate_xrefs [2.0]
183  * NAME
184  *   RB_Generate_xrefs
185  * SYNOPSIS
186  *   RB_Generate_xrefs (dest_doc, source_name, dest_name)
187  *
188  *   RB_Generate_xrefs (FILE *, char *, char *)
189  * FUNCTION
190  *   Generates a xref file for the document that has been
191  *   analysed by ROBODoc.
192  * INPUTS
193  *   dest_doc    - pointer to the file to which the xrefs will be
194  *                 written.
195  *   source_name - pointer to the name of the document that has
196  *                 been analysed by robodoc
197  *   dest_name   - pointer to the name of the document robodoc will
198  *                 write the documentation to.
199  *   first_header - global variable, the list with function
200  *                 headers.
201  * SOURCE
202  */
203
204 void
205 RB_Generate_xrefs (FILE * dest_doc, char *source_name, char *dest_name)
206 {
207   struct RB_header *cur_header;
208
209   fprintf (dest_doc, "/* XREF-File generated by ROBODoc v" VERSION
210            " */\n");
211   fprintf (dest_doc, "\nXREF:\n");
212   fprintf (dest_doc, " \"%s\" \"%s\" 0\n", source_name, dest_name);
213   for (cur_header = first_header;
214        cur_header;
215        cur_header = cur_header->next_header
216     )
217     {
218       if (cur_header->function_name)
219         fprintf (dest_doc, " \"%s\" \"%s\" %d\n",
220                  cur_header->function_name, dest_name, cur_header->type);
221     }
222   fprintf (dest_doc, "\n/* End of XREF-File */\n");
223 }
224
225 /*** RB_Generate_xrefs ***/
226
227
228
229 /****f* ROBODoc/RB_Find_Link [3.0h]
230  * NAME
231  *   RB_Find_Link -- try to match word with a link
232  * SYNOPSIS
233  *   result = RB_Find_Link (word_begin, label_name, file_name)
234  *   int      RB_Find_Link (char *,     char **,    char **)
235  * FUNCTION
236  *   Searches for the given word in the list of links and
237  *   headers.  There are three passes (or four, when the C option
238  *   is selected). Each pass uses a different definition of "word".
239  *   In the first pass it is any thing that ends with a 'space', a '.' 
240  *   or a ','.
241  *   In the second pass it is any string that consists of alpha
242  *   numerics, '_', ':', '.', or '-'.  
243  *   In the third pass (for C) it is any string that consists 
244  *   of alpha numerics or '_'.
245  *   In the last pass it is any string that consists of alpha
246  *   numerics.
247  * INPUTS
248  *   word_begin  - pointer to a word (a string).
249  *   label_name  - pointer to a pointer to a string
250  *   file_name   - pointer to a pointer to a string
251  * SIDE EFFECTS
252  *   label_name & file_name are modified
253  * RESULT
254  *   label_name    -- points to the label if a match was found,
255  *                    NULL otherwise.
256  *   file_name     -- points to the file name if a match was found,
257  *                    NULL otherwise.
258  *   TRUE          -- a match was found.
259  *   FALSE         -- no match was found.
260  * NOTES
261  *   This is a rather sensitive algorithm.
262  * BUGS
263  ******
264  */
265
266 int
267 RB_Find_Link (char *word_begin, char **label_name, char **file_name)
268 {
269   char *cur_char, old_char;
270   int low_index, high_index, cur_index, state, pass;
271
272
273   for (pass = 0; pass < 4; pass++)
274     {
275
276       switch (pass)
277         {
278         case 0:
279           {
280             for (cur_char = word_begin;
281                  isalnum (*cur_char) || ispunct (*cur_char);
282                  cur_char++);
283             if (((*(cur_char-1)) == ',') || ((*(cur_char-1)) == '.')) 
284               cur_char--;
285             break;
286           }
287         case 1:
288           {
289             for (cur_char = word_begin;
290                  isalnum (*cur_char) || (*cur_char == '_') ||
291                  (*cur_char == '-') || (*cur_char == '.') ||
292                  (*cur_char == ':');
293                  cur_char++);
294             break;
295           }
296         case 2:
297           {
298             if (extra_flags & C_MODE) {
299           for (cur_char = word_begin;
300                    isalnum(*cur_char) || (*cur_char  == '_');
301                    cur_char++);
302               break;
303                 }
304             else continue;
305           }
306         case 3:
307           {
308             for (cur_char = word_begin;
309                  isalnum (*cur_char);
310                  cur_char++);
311             break;
312           }
313         }
314
315       old_char = *cur_char;
316       *cur_char = '\0';         /* End the word with a '\0' */
317 /*      RB_Say ("Testing \"%s\"\n", word_begin); */
318
319       /* Search in header table */
320       for (cur_index = 0, low_index = 0, high_index = header_index_size - 1;
321            high_index >= low_index;)
322         {
323           cur_index = (high_index - low_index) / 2 + low_index;
324           state = strcmp (word_begin, header_index[cur_index]->function_name);
325           if (state < 0)
326             high_index = cur_index - 1;
327           else if (state > 0)
328             low_index = cur_index + 1;
329           else
330             {
331               *label_name = header_index[cur_index]->function_name;
332               *file_name = NULL;
333               RB_Say ("linking \"%s\"->\"%s\"\n", word_begin, *label_name);
334               *cur_char = old_char;
335               return (TRUE);
336             }
337         }
338
339       /* Search in the link table */
340       for (cur_index = 0, low_index = 0, high_index = link_index_size - 1;
341            high_index >= low_index;)
342         {
343           cur_index = (high_index - low_index) / 2 + low_index;
344           state = strcmp (word_begin, link_index[cur_index]->label_name);
345           if (state < 0)
346             {
347               high_index = cur_index - 1;
348             }
349           else if (state == 0)
350             {
351               *label_name = link_index[cur_index]->label_name;
352               *file_name = link_index[cur_index]->file_name;
353               RB_Say ("linking \"%s\"->\"%s\" form \"%s\"\n",
354                               word_begin, *label_name, *file_name);
355               *cur_char = old_char;
356               return (TRUE);
357             }
358           else if (state > 0)
359             {
360               low_index = cur_index + 1;
361             }
362         }
363       *cur_char = old_char;
364       *file_name = NULL;
365       *label_name = NULL;
366     }
367
368   return (FALSE);
369 }
370
371
372
373
374
375 /****f* ROBODoc/RB_Alloc_Link [2.01]
376  * NAME
377  *   RB_Alloc_Link              -- oop
378  * SYNOPSIS
379  *   struct RB_link *RB_Alloc_Link( char *label_name, char *file_name )
380  * FUNCTION
381  *   allocate struct + strings
382  * INPUTS
383  *   char *label_name -- strings to copy into the link
384  *   char *file_name
385  * RESULT
386  *   struct RB_link *  -- ready-to-use
387  * AUTHOR
388  *   Koessi
389  * SEE ALSO
390  *   RB_StrDup(), RB_Free_Link()
391  *******
392  */
393
394 struct RB_link *
395 RB_Alloc_Link (char *label_name, char *file_name)
396 {
397   struct RB_link *new_link;
398   if ((new_link = malloc (sizeof (struct RB_link))) != NULL)
399     {
400       memset (new_link, 0, sizeof (struct RB_link));
401
402       if (file_name)
403         new_link->file_name = RB_StrDup (file_name);
404       if (label_name)
405         new_link->label_name = RB_StrDup (label_name);
406     }
407   else
408     RB_Panic ("out of memory! [Alloc Link]\n");
409
410   return (new_link);
411 }
412
413
414 /****f* ROBODoc/RB_Free_Link [2.01]
415  * NAME
416  *   RB_Free_Link               -- oop
417  * SYNOPSIS
418  *   void RB_Free_Link( struct RB_link *link )
419  * FUNCTION
420  *   free struct + strings
421  * INPUTS
422  *   struct RB_link *link
423  * AUTHOR
424  *   Koessi
425  * SEE ALSO
426  *   RB_Alloc_Link(), RB_Close_The_Shop()
427  * SOURCE
428  ******
429  */
430
431 void
432 RB_Free_Link (struct RB_link *link)
433 {
434   if (link)
435     {
436       if (link->label_name)
437         free (link->label_name);
438       if (link->file_name)
439         free (link->file_name);
440       free (link);
441     }
442 }