home *** CD-ROM | disk | FTP | other *** search
- /* cinfo.c -- A C library information tool.
- Copyright (C) 1995 Sandro Sigala - <sansig@freenet.hut.fi> */
-
- /* $Id: cinfo.c,v 1.29 1995/08/12 16:59:21 sandro Exp $ */
-
- /* This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- /*
- * To do:
- * - add a description to all symbols
- * - add an example program to all symbols
- */
-
- #ifndef DEFAULT_SEARCH_PATH
- #define DEFAULT_SEARCH_PATH "/usr/lib/cinfo"
- #endif
-
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <getopt.h>
-
- #include "misc.h"
- #include "cinfolib.h"
-
- #include "version.h"
-
- static FILE *output_file;
-
- #define MAX_INCLUDE_DEEP 128
-
- static int debug = 0;
-
- static struct library_entry *library_head = NULL;
- static char current_library[128];
- static char current_header[128];
- static int library_ok = 0, header_ok = 0;
-
- enum { LIBRARY, HEADER, SYMBOL, STRING, INCLUDE };
-
- static struct
- { char *file_name; int lineno; FILE *file; } include_stack[MAX_INCLUDE_DEEP];
-
- static int include_stack_idx = 0;
-
- static FILE *current_file;
- static char current_file_name[128];
- static int lineno = 1;
-
- void
- include_enter (void)
- {
- if (debug)
- fprintf (stderr, "debug: entering include level %d\n",
- include_stack_idx + 1);
-
- include_stack[include_stack_idx].file = current_file;
- include_stack[include_stack_idx].file_name =
- xmalloc (strlen (current_file_name) + 1);
- strcpy (include_stack[include_stack_idx].file_name, current_file_name);
- include_stack[include_stack_idx++].lineno = lineno;
- }
-
- void
- include_leave (void)
- {
- if (debug)
- fprintf (stderr, "debug: leaving include level %d (%s %d)\n",
- include_stack_idx, current_file_name, lineno);
-
- current_file = include_stack[--include_stack_idx].file;
- strcpy (current_file_name, include_stack[include_stack_idx].file_name);
- free (include_stack[include_stack_idx].file_name);
- lineno = include_stack[include_stack_idx].lineno;
- }
-
- static char charbuffer[36];
- static int buffindex = 0;
-
- #define xgetc() \
- (buffindex ? charbuffer[--buffindex] : getc (current_file))
-
- #define xungetc(c) \
- charbuffer[buffindex++] = c
-
- static char *token_buffer;
-
- static int maxtoken;
-
- static void
- init_lex (void)
- {
- maxtoken = 40;
- token_buffer = (char *) xmalloc (maxtoken + 1);
- }
-
- static void
- done_lex (void)
- {
- free (token_buffer);
- }
-
- static char *
- extend_token_buffer (char *p)
- {
- int offset = p - token_buffer;
-
- maxtoken = maxtoken * 2 + 10;
- token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
-
- return token_buffer + offset;
- }
-
-
- static void
- error (char *s)
- {
- fprintf (stderr, "%s:%d: %s\n", current_file_name, lineno, s);
- exit (1);
- }
-
- static int
- gettoken (void)
- {
- int c, c1, err = 0;
- while ((c = xgetc ()) == ' ' ||
- c == '\011' || c == '\013' || c == '\014' || c == '\015')
- ;
-
- if (c == EOF)
- return c;
- else if (c == '\n')
- {
- lineno++;
- return (gettoken ());
- }
- else if (c == '#')
- {
- while ((c = xgetc ()) != EOF && c != '\n')
- ;
- lineno++;
- return (gettoken ());
- }
- else if (c == ';')
- return ';';
- else if (c == '"')
- {
- char *p = token_buffer;
-
- while ((c = xgetc ()) != EOF)
- {
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
-
- if (c == '"')
- break;
- else if (c == '\n')
- {
- lineno++;
- *p++ = c;
- }
- else if (c == '\\')
- {
- if ((c1 = xgetc ()) == '\n')
- lineno++;
- else
- *p++ = c1;
- }
- else
- *p++ = c;
- }
-
- *p = '\0';
-
- return STRING;
- }
- else if (c == '.')
- {
- int i = 0;
- char buf[128];
-
- c = xgetc ();
-
- if (c == 'l')
- {
- buf[i++] = 'l';
- if ((buf[i++] = xgetc ()) == 'i' &&
- (buf[i++] = xgetc ()) == 'b' &&
- (buf[i++] = xgetc ()) == 'r' &&
- (buf[i++] = xgetc ()) == 'a' &&
- (buf[i++] = xgetc ()) == 'r' &&
- (buf[i++] = xgetc ()) == 'y')
- return LIBRARY;
- else err = 1;
- }
- else if (c == 'h')
- {
- buf[i++] = 'i';
- if ((buf[i++] = xgetc ()) == 'e' &&
- (buf[i++] = xgetc ()) == 'a' &&
- (buf[i++] = xgetc ()) == 'd' &&
- (buf[i++] = xgetc ()) == 'e' &&
- (buf[i++] = xgetc ()) == 'r')
- return HEADER;
- else err = 1;
- }
- else if (c == 's')
- {
- buf[i++] = 's';
- if ((buf[i++] = xgetc ()) == 'y' &&
- (buf[i++] = xgetc ()) == 'm' &&
- (buf[i++] = xgetc ()) == 'b' &&
- (buf[i++] = xgetc ()) == 'o' &&
- (buf[i++] = xgetc ()) == 'l')
- return SYMBOL;
- else err = 1;
- }
- else if (c == 'i')
- {
- buf[i++] = 'i';
- if ((buf[i++] = xgetc ()) == 'n' &&
- (buf[i++] = xgetc ()) == 'c' &&
- (buf[i++] = xgetc ()) == 'l' &&
- (buf[i++] = xgetc ()) == 'u' &&
- (buf[i++] = xgetc ()) == 'd' &&
- (buf[i++] = xgetc ()) == 'e')
- return INCLUDE;
- else err = 1;
- }
-
- if (err)
- {
- char buf1[64];
- if (buf[i-1] == '\n')
- i--;
- buf[i] = '\0';
- sprintf (buf1, "invalid `.%s' directive", buf);
- error (buf1);
- }
- error ("invalid directive");
- }
- error ("unexpected character");
- return 0;
- }
-
- static int opt_lib = 0;
-
- static void
- parse (void)
- {
- int tk;
- while (1)
- {
- if ((tk = gettoken ()) == EOF)
- {
- fclose (current_file);
- if (include_stack_idx < 1)
- return;
-
- include_leave ();
-
- continue;
- }
-
- switch (tk)
- {
- case LIBRARY:
- {
- struct library_entry *lp;
- char buf[128];
-
- if ((tk = gettoken ()) != STRING)
- error ("expected name");
- if (strlen (token_buffer) == 0)
- error ("bad name");
-
- strcpy (current_library, token_buffer);
-
- if ((tk = gettoken ()) == STRING)
- {
- if (strlen (token_buffer) == 0)
- error ("bad description");
- }
- else if (tk != ';')
- error ("expected ';' or description after directive");
-
- if (tk == STRING)
- cinfo_compact_info (buf, current_library, token_buffer, 0, 0);
- else
- cinfo_compact_info (buf, current_library, 0, 0, 0);
-
- lp = cinfo_build_library_entry (buf);
-
- if (library_head == NULL)
- library_head = lp;
- else
- cinfo_add_library_to_list (library_head, lp);
-
- library_ok = 1;
-
- break;
- }
-
- case HEADER:
- {
- struct library_entry *lp;
- struct header_entry *hp;
- char buf[128];
-
- if ((tk = gettoken ()) != STRING)
- error ("expected name");
- if (strlen (token_buffer) == 0)
- error ("bad name");
-
- strcpy (current_header, token_buffer);
-
- if ((tk = gettoken ()) == STRING)
- {
- if (strlen (token_buffer) == 0)
- error ("bad description");
- }
- else if (tk != ';')
- error ("expected ';' or description after directive");
-
- if (library_ok == 0)
- error ("unset library name");
-
- if ((lp = cinfo_search_library (library_head,
- current_library)) == NULL)
- error ("internal fault (1)");
-
- if (tk == STRING)
- cinfo_compact_info (buf, current_header, token_buffer, 0, 0);
- else
- cinfo_compact_info (buf, current_header, 0, 0, 0);
-
- hp = cinfo_build_header_entry (buf);
-
- if (lp->head == NULL)
- lp->head = hp;
- else
- cinfo_add_header_to_list (lp->head, hp);
-
- header_ok = 1;
-
- break;
- }
-
- case SYMBOL:
- {
- struct library_entry *lp;
- struct header_entry *hp;
- struct symbol_entry *sp;
- char *symbol_name, *symbol_type, *symbol_proto, *name;
-
- if ((tk = gettoken ()) != STRING)
- error ("expected name after directive");
- if (strlen (token_buffer) == 0)
- error ("bad name");
- symbol_name = (char *) xmalloc (strlen (token_buffer) + 1);
- strcpy (symbol_name, token_buffer);
-
- if ((tk = gettoken ()) != STRING)
- error ("expected type string after symbol name");
- if (strlen (token_buffer) == 0 ||
- (strcmp (token_buffer, "func") != 0 &&
- strcmp (token_buffer, "macro") != 0 &&
- strcmp (token_buffer, "struct") != 0 &&
- strcmp (token_buffer, "union") != 0 &&
- strcmp (token_buffer, "type") != 0))
- error ("bad type");
-
- symbol_type = (char *) xmalloc (strlen (token_buffer) + 1);
- strcpy (symbol_type, token_buffer);
-
- if ((tk = gettoken ()) != STRING)
- error ("expected prototype or definition after type");
- if (strlen (token_buffer) == 0)
- error ("bad prototype or definition");
-
- symbol_proto = (char *) xmalloc (strlen (token_buffer) + 1);
- strcpy (symbol_proto, token_buffer);
-
- if ((tk = gettoken ()) != ';')
- error ("expected ';' after directive");
-
- name = (char *) xmalloc (strlen (symbol_name) +
- strlen (symbol_type) +
- strlen (symbol_proto) + 20);
-
- cinfo_compact_info (name, symbol_name,
- symbol_type, symbol_proto, 0);
-
- free (symbol_name);
- free (symbol_type);
- free (symbol_proto);
-
- if (library_ok == 0)
- error ("unset library name");
-
- if (header_ok == 0)
- error ("unset header name");
-
- lp = cinfo_search_library (library_head, current_library);
-
- if (lp == NULL)
- error ("internal fault (2)");
-
- hp = cinfo_search_header (lp->head, current_header);
-
- if (hp == NULL)
- error ("internal fault (3)");
-
- sp = cinfo_build_symbol_entry (name);
-
- free (name);
-
- if (hp->head == NULL)
- hp->head = sp;
- else
- cinfo_add_symbol_to_list (hp->head, sp);
-
- break;
- }
-
- case INCLUDE:
- {
- char buf[128];
-
- if ((tk = gettoken ()) != STRING)
- error ("expected string");
- if (strlen (token_buffer) == 0)
- error ("bad string");
-
- strcpy (buf, token_buffer);
-
- if (include_stack_idx + 1 >= MAX_INCLUDE_DEEP)
- error ("max include deep encourred");
-
- if ((tk = gettoken ()) != ';')
- error ("expected ';' after directive");
-
- include_enter ();
-
- strcpy (current_file_name, buf);
-
- lineno = 1;
-
- if (debug)
- fprintf (stderr, "debug: looking for \"%s\"...\n",
- current_file_name);
-
- if ((current_file = fopen (current_file_name, "r")) == NULL)
- {
- strcpy (current_file_name, DEFAULT_SEARCH_PATH);
- strcat (current_file_name, "/");
- strcat (current_file_name, buf);
-
- if (debug)
- fprintf (stderr, "debug: looking for \"%s\"...\n",
- current_file_name);
-
- if ((current_file = fopen (current_file_name, "r")) == NULL)
- {
- sprintf (buf, "cannot open include file \"%s\"",
- current_file_name);
- error (buf);
- }
- }
-
- break;
- }
-
- case STRING:
- error ("unexpected string");
- }
- }
- }
-
- static int opt_readable_output = 1;
-
- static void
- document_symbol_list (struct symbol_entry *list, char *header)
- {
- struct symbol_entry *p = list;
- char *buf1, *buf2, *buf3;
-
- while (p != NULL)
- {
- buf1 = (char *) xmalloc (strlen (p->name) + 1);
- buf2 = (char *) xmalloc (strlen (p->name) + 1);
- buf3 = (char *) xmalloc (strlen (p->name) + 1);
-
- cinfo_decompact_info (p->name, buf1, buf2, buf3, NULL);
-
- if (opt_readable_output)
- {
- if (strcmp (buf2, "macro") == 0)
- fprintf (output_file, "symbol %s: macro.\n", buf1);
- else if (strcmp (buf2, "func") == 0)
- fprintf (output_file, "symbol %s: function.\n", buf1);
- else if (strcmp (buf2, "struct") == 0)
- fprintf (output_file, "symbol %s: structure.\n", buf1);
- else if (strcmp (buf2, "union") == 0)
- fprintf (output_file, "symbol %s: union.\n", buf1);
- else if (strcmp (buf2, "type") == 0)
- fprintf (output_file, "symbol %s: defined type.\n", buf1);
-
- fprintf (output_file, "\n");
-
- if (buf3[0] == '$')
- fprintf (output_file, "%s\n", buf3 + 1);
- else
- {
- fprintf (output_file, "#include <%s>\n\n", header);
- fprintf (output_file, "%s\n\n", buf3);
- }
- }
- else
- {
- fprintf (output_file, "!%s \"%s\"\n", buf2, buf1);
-
- if (buf3[0] == '$')
- fprintf (output_file, "$\"%s\"\n", buf3 + 1);
- else
- fprintf (output_file, "$\"%s\"\n", buf3);
- }
-
- free (buf1);
- free (buf2);
- free (buf3);
-
- p = p->next;
- }
- }
-
- static void
- document_header_list (struct header_entry *list)
- {
- struct header_entry *p = list;
- char *buf;
-
- while (p != NULL)
- {
- buf = (char *) xmalloc (strlen (p->name) + 1);
-
- cinfo_decompact_info_first (p->name, buf);
-
- if (opt_readable_output)
- fprintf (output_file, "header \"%s\".\n", buf);
- else
- fprintf (output_file, "!header \"%s\"\n", buf);
-
- if (p->head != NULL)
- document_symbol_list (p->head, buf);
-
- free (buf);
-
- p = p->next;
- }
- }
-
- static void
- document_library_list (struct library_entry *list)
- {
- struct library_entry *p = list;
- char *buf;
-
- while (p != NULL)
- {
- buf = (char *) xmalloc (strlen (p->name) + 1);
-
- cinfo_decompact_info_first (p->name, buf);
-
- if (opt_readable_output)
- fprintf (output_file, "In library \"%s\", ", buf);
- else
- fprintf (output_file, "!library \"%s\"\n", buf);
-
- free (buf);
-
- if (p->head != NULL)
- document_header_list (p->head);
-
- p = p->next;
- }
- }
-
- void
- helppage (char *progname)
- {
- fprintf (stderr, "\
- %s %s - c-tools %s - Copyright (C) 1995 Sandro Sigala.\n\
- usage: %s [-hm] [-l libfile] [-o outfile] [symbol]\n\
- -h display this help and exit\n\
- -m make output more program-parseable\n\
- -l libfile specify the library to load instead the default\n\
- -o outfile specify the output file instead the standard output\n\
- ",
- progname, VERSION_CINFO, VERSION_CTOOLS, progname);
- exit (0);
- }
-
- int
- main (int argc, char **argv)
- {
- int c;
- struct library_entry *le;
- char output_file_name[128];
- int opt_out = 0;
- char what[128];
-
- strcpy (current_file_name, "cinfo.lib");
- strcpy (output_file_name, "stdout");
-
- while (1)
- {
- c = getopt (argc, argv, "l:o:dhm");
- if (c == EOF)
- break;
-
- switch (c)
- {
- case 'l':
- opt_lib = 1;
- strcpy (current_file_name, optarg);
- break;
-
- case 'o':
- strcpy (output_file_name, optarg);
- opt_out = 1;
- break;
-
- case 'd':
- debug = 1;
- break;
-
- case 'm':
- opt_readable_output = 0;
- break;
-
- case 'h':
- case '?':
- helppage (argv[0]);
- break;
- }
- }
-
- if (argc - optind != 1)
- helppage (argv[0]);
- strcpy (what, argv[optind]);
-
- if (debug)
- fprintf (stderr, "debug: looking for \"%s\"...\n", current_file_name);
-
- if ((current_file = fopen (current_file_name, "r")) == NULL)
- {
- if (opt_lib == 1)
- {
- fprintf (stderr, "%s: cannot open library file \"%s\"\n",
- argv[0], current_file_name);
- exit (1);
- }
- else
- {
- strcpy (current_file_name, DEFAULT_SEARCH_PATH);
- strcat (current_file_name, "/cinfo.lib");
- if (debug)
- fprintf (stderr, "debug: looking for \"%s\"...\n",
- current_file_name);
-
- if ((current_file = fopen (current_file_name, "r")) == NULL)
- {
- fprintf (stderr, "%s: cannot open library file \"%s\"\n",
- argv[0], current_file_name);
- exit (1);
- }
- }
- }
-
- output_file = stdout;
-
- if (opt_out)
- {
- if ((output_file = fopen (output_file_name, "w")) == NULL)
- {
- fprintf (stderr, "%s: cannot open output file\n", argv[0]);
- exit (1);
- }
- }
-
- lineno = 1;
-
- init_lex (); /* initialize the lexical analizer */
-
- parse ();
-
- done_lex ();
-
-
- if (debug)
- fprintf (stderr, "debug: searching...\n");
-
- le = cinfo_query_library_list_about_symbol (library_head, what);
-
- if (debug)
- fprintf (stderr, "debug: outputting...\n");
-
- document_library_list (le);
-
- return 0;
- }
-
- /* cinfo.c ends here */
-