1 /* makedoc.c -- Make doc.c and funs.h from input files.
2 $Id: makedoc.c,v 1.1.1.2 1998/03/22 20:42:43 law Exp $
4 This file is part of GNU Info, a program for reading online documentation
7 Copyright (C) 1993, 97 Free Software Foundation, Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Written by Brian Fox (bfox@ai.mit.edu). */
25 /* This program grovels the contents of the source files passed as arguments
26 and writes out a file of function pointers and documentation strings, and
27 a header file which describes the contents. This only does the functions
28 declared with DECLARE_INFO_COMMAND. */
32 static void fatal_file_error ();
34 /* Name of the header file which receives the declarations of functions. */
35 static char *funs_filename
= "funs.h";
37 /* Name of the documentation to function pointer file. */
38 static char *doc_filename
= "doc.c";
40 static char *doc_header
[] = {
41 "/* doc.c -- Generated structure containing function names and doc strings.",
43 " This file was automatically made from various source files with the",
44 " command \"%s\". DO NOT EDIT THIS FILE, only \"%s.c\".",
48 static char *doc_header_1
[] = {
49 " An entry in the array FUNCTION_DOC_ARRAY is made for each command",
50 " found in the above files; each entry consists of a function pointer,",
51 #if defined (NAMED_FUNCTIONS)
52 " a string which is the user-visible name of the function,",
53 #endif /* NAMED_FUNCTIONS */
54 " and a string which documents its purpose. */",
57 "#include \"funs.h\"",
59 "FUNCTION_DOC function_doc_array[] = {",
64 /* How to remember the locations of the functions found so that Emacs
65 can use the information in a tag table. */
67 char *name
; /* Name of the tag. */
68 int line
; /* Line number at which it appears. */
69 long char_offset
; /* Character offset at which it appears. */
73 char *filename
; /* Name of the file containing entries. */
74 long entrylen
; /* Total number of characters in tag block. */
75 EMACS_TAG
**entries
; /* Entries found in FILENAME. */
80 EMACS_TAG_BLOCK
**emacs_tags
= (EMACS_TAG_BLOCK
**)NULL
;
81 int emacs_tags_index
= 0;
82 int emacs_tags_slots
= 0;
84 #define DECLARATION_STRING "\nDECLARE_INFO_COMMAND"
86 static void process_one_file ();
87 static void maybe_dump_tags ();
88 static FILE *must_fopen ();
97 FILE *funs_stream
, *doc_stream
;
99 for (i
= 1; i
< argc
; i
++)
100 if (strcmp (argv
[i
], "-tags") == 0)
108 funs_filename
= "/dev/null";
109 doc_filename
= "/dev/null";
112 funs_stream
= must_fopen (funs_filename
, "w");
113 doc_stream
= must_fopen (doc_filename
, "w");
115 fprintf (funs_stream
,
116 "/* %s -- Generated declarations for Info commands. */\n",
119 for (i
= 0; doc_header
[i
]; i
++)
121 fprintf (doc_stream
, doc_header
[i
], argv
[0], argv
[0]);
122 fprintf (doc_stream
, "\n");
126 _(" Source files groveled to make this file include:\n\n"));
128 for (i
= 1; i
< argc
; i
++)
129 fprintf (doc_stream
, "\t%s\n", argv
[i
]);
131 fprintf (doc_stream
, "\n");
133 for (i
= 0; doc_header_1
[i
]; i
++)
134 fprintf (doc_stream
, "%s\n", doc_header_1
[i
]);
137 for (i
= 1; i
< argc
; i
++)
145 fprintf (doc_stream
, "/* Commands found in \"%s\". */\n", curfile
);
146 fprintf (funs_stream
, "\n/* Functions declared in \"%s\". */\n",
149 process_one_file (curfile
, doc_stream
, funs_stream
);
153 " { (VFunction *)NULL, (char *)NULL, (char *)NULL }\n};\n");
155 fclose (funs_stream
);
159 maybe_dump_tags (stdout
);
163 /* Dumping out the contents of an Emacs tags table. */
165 maybe_dump_tags (stream
)
170 /* Print out the information for each block. */
171 for (i
= 0; i
< emacs_tags_index
; i
++)
174 register EMACS_TAG_BLOCK
*block
;
175 register EMACS_TAG
*etag
;
179 block
= emacs_tags
[i
];
181 /* Calculate the length of the dumped block first. */
182 for (j
= 0; j
< block
->entries_index
; j
++)
185 etag
= block
->entries
[j
];
186 block_len
+= 3 + strlen (etag
->name
);
187 sprintf (digits
, "%d,%ld", etag
->line
, etag
->char_offset
);
188 block_len
+= strlen (digits
);
191 /* Print out the defining line. */
192 fprintf (stream
, "\f\n%s,%ld\n", block
->filename
, block_len
);
194 /* Print out the individual tags. */
195 for (j
= 0; j
< block
->entries_index
; j
++)
197 etag
= block
->entries
[j
];
199 fprintf (stream
, "%s,\177%d,%ld\n",
200 etag
->name
, etag
->line
, etag
->char_offset
);
205 /* Keeping track of names, line numbers and character offsets of functions
206 found in source files. */
207 static EMACS_TAG_BLOCK
*
208 make_emacs_tag_block (filename
)
211 EMACS_TAG_BLOCK
*block
;
213 block
= (EMACS_TAG_BLOCK
*)xmalloc (sizeof (EMACS_TAG_BLOCK
));
214 block
->filename
= xstrdup (filename
);
216 block
->entries
= (EMACS_TAG
**)NULL
;
217 block
->entries_index
= 0;
218 block
->entries_slots
= 0;
223 add_tag_to_block (block
, name
, line
, char_offset
)
224 EMACS_TAG_BLOCK
*block
;
231 tag
= (EMACS_TAG
*)xmalloc (sizeof (EMACS_TAG
));
234 tag
->char_offset
= char_offset
;
235 add_pointer_to_array (tag
, block
->entries_index
, block
->entries
,
236 block
->entries_slots
, 50, EMACS_TAG
*);
239 /* Read the file represented by FILENAME into core, and search it for Info
240 function declarations. Output the declarations in various forms to the
241 DOC_STREAM and FUNS_STREAM. */
243 process_one_file (filename
, doc_stream
, funs_stream
)
245 FILE *doc_stream
, *funs_stream
;
247 int descriptor
, decl_len
;
248 char *buffer
, *decl_str
;
252 EMACS_TAG_BLOCK
*block
;
254 if (stat (filename
, &finfo
) == -1)
255 fatal_file_error (filename
);
257 descriptor
= open (filename
, O_RDONLY
, 0666);
259 if (descriptor
== -1)
260 fatal_file_error (filename
);
262 file_size
= (long) finfo
.st_size
;
263 buffer
= (char *)xmalloc (1 + file_size
);
264 read (descriptor
, buffer
, file_size
);
268 decl_str
= DECLARATION_STRING
;
269 decl_len
= strlen (decl_str
);
271 block
= make_emacs_tag_block (filename
);
280 #if defined (NAMED_FUNCTIONS)
282 #endif /* NAMED_FUNCTIONS */
284 for (; offset
< (file_size
- decl_len
); offset
++)
286 if (buffer
[offset
] == '\n')
289 line_start
= offset
+ 1;
292 if (strncmp (buffer
+ offset
, decl_str
, decl_len
) == 0)
303 /* Skip forward until we find the open paren. */
304 while (point
< file_size
)
306 if (buffer
[point
] == '\n')
309 line_start
= point
+ 1;
311 else if (buffer
[point
] == '(')
317 while (point
++ < file_size
)
319 if (!whitespace_or_newline (buffer
[point
]))
321 else if (buffer
[point
] == '\n')
324 line_start
= point
+ 1;
328 if (point
>= file_size
)
331 /* Now looking at name of function. Get it. */
332 for (offset
= point
; buffer
[offset
] != ','; offset
++);
333 func
= (char *)xmalloc (1 + (offset
- point
));
334 strncpy (func
, buffer
+ point
, offset
- point
);
335 func
[offset
- point
] = '\0';
337 /* Remember this tag in the current block. */
341 tag_name
= (char *)xmalloc (1 + (offset
- line_start
));
342 strncpy (tag_name
, buffer
+ line_start
, offset
- line_start
);
343 tag_name
[offset
- line_start
] = '\0';
344 add_tag_to_block (block
, tag_name
, line_number
, point
);
347 #if defined (NAMED_FUNCTIONS)
348 /* Generate the user-visible function name from the function's name. */
355 if (strncmp (name_start
, "info_", 5) == 0)
358 func_name
= xstrdup (name_start
);
360 /* Fix up "ea" commands. */
361 if (strncmp (func_name
, "ea_", 3) == 0)
363 char *temp_func_name
;
365 temp_func_name
= (char *)xmalloc (10 + strlen (func_name
));
366 strcpy (temp_func_name
, "echo_area_");
367 strcat (temp_func_name
, func_name
+ 3);
369 func_name
= temp_func_name
;
372 for (i
= 0; func_name
[i
]; i
++)
373 if (func_name
[i
] == '_')
376 #endif /* NAMED_FUNCTIONS */
378 /* Find doc string. */
381 while (point
< file_size
)
383 if (buffer
[point
] == '\n')
386 line_start
= point
+ 1;
389 if (buffer
[point
] == '"')
397 while (offset
< file_size
)
399 if (buffer
[offset
] == '\n')
402 line_start
= offset
+ 1;
405 if (buffer
[offset
] == '\\')
407 else if (buffer
[offset
] == '"')
414 if (offset
>= file_size
)
417 doc
= (char *)xmalloc (1 + (offset
- point
));
418 strncpy (doc
, buffer
+ point
, offset
- point
);
419 doc
[offset
- point
] = '\0';
421 #if defined (NAMED_FUNCTIONS)
422 fprintf (doc_stream
, " { %s, \"%s\", %s },\n", func
, func_name
, doc
);
424 #else /* !NAMED_FUNCTIONS */
425 fprintf (doc_stream
, " { %s, %s },\n", func
, doc
);
426 #endif /* !NAMED_FUNCTIONS */
428 fprintf (funs_stream
, "extern void %s ();\n", func
);
434 /* If we created any tags, remember this file on our global list. Otherwise,
435 free the memory already allocated to it. */
437 add_pointer_to_array (block
, emacs_tags_index
, emacs_tags
,
438 emacs_tags_slots
, 10, EMACS_TAG_BLOCK
*);
441 free (block
->filename
);
447 fatal_file_error (filename
)
450 fprintf (stderr
, _("Couldn't manipulate the file %s.\n"), filename
);
455 must_fopen (filename
, mode
)
456 char *filename
, *mode
;
460 stream
= fopen (filename
, mode
);
462 fatal_file_error (filename
);