home *** CD-ROM | disk | FTP | other *** search
- From decwrl!sun-barr!cs.utexas.edu!uunet!allbery Fri Sep 8 21:40:06 PDT 1989
- Article 1072 of comp.sources.misc:
- Path: decwrl!sun-barr!cs.utexas.edu!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v08i030: mkproto -- make ANSI style prototypes
- Message-ID: <66800@uunet.UU.NET>
- Date: 7 Sep 89 02:05:45 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: ersmith@uwovax.uwo.ca
- Lines: 930
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 8, Issue 30
- Submitted-by: ersmith@uwovax.uwo.ca
- Archive-name: mkproto
-
- Here is mkproto, a program for generating prototype declarations for all
- functions appearing in a C source file. The input C code may be either
- K&R or ANSI C (i.e. it's OK if the functions are defined using prototypes).
- Unlike some of the sed-based scripts floating around, it correctly
- handles prototype promotion (e.g. the prototype for 'int foo() char x;...'
- is 'int foo(int x)'). Also, it should work OK on just about any computer,
- not just Unix-based ones (it's been tested under minix, Unix, and TOS).
-
- Use: typically, you would type 'mkproto *.c >proto.h' and then add a
- '#include "proto.h"' line to all the C source files. An ANSI conformant
- compiler will then be able to do type checking on function calls across
- module boundaries. As a bonus, proto.h will tell you which source files
- functions were defined in, and (if you gave the -n function to mkproto)
- their line numbers. The resulting include file may also be used by
- non-ANSI compilers; you can disable this feature (for cleaner, strictly
- ANSI-conforming output) with the -p flag.
-
- Please read the description of bugs in mkproto.man; definitely mkproto
- will not handle all programs correctly, but it does work on the majority of
- them. A sample of its output is provided in the file "mkproto.h"; this
- is the result of 'mkproto mkproto.c >mkproto.h'.
-
- There is ABSOLUTELY NO WARRANTY for the program; as I said, it doesn't work
- on all programs (complicated function definitions can make it produce bogus
- output). It does what I need, though, and it can certainly make porting stuff
- to ANSI compilers easier.
-
- Mkproto is in the public domain. If you find any bugs (other than the ones
- documented) please let me know.
- --
- Eric R. Smith email:
- Dept. of Mathematics ersmith@uwovax.uwo.ca
- University of Western Ontario ersmith@uwovax.bitnet
- London, Ont. Canada N6A 5B7
- ph: (519) 661-3638
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # makefile.min
- # makefile.tos
- # makefile.unx
- # mkproto.c
- # mkproto.h
- # mkproto.man
- # README
- # This archive created: 05 September 1989 05:51:28 PM EDT
- # By: eric (at home)
- echo shar: extracting makefile.min
- sed 's/^X//' << \SHAR_EOF > makefile.min
- XCC = mgcc
- XALL = mkproto
- X
- Xmkproto : mkproto.c mkproto.h
- X $(CC) -O -o mkproto mkproto.c -mshort -s
- Xclean:
- X rm -f *.o
- X
- Xrealclean: clean
- X rm -f $(ALL) report core
- SHAR_EOF
- if test 159 -ne "`wc -c makefile.min`"
- then
- echo shar: error transmitting makefile.min '(should have been 159 characters)'
- fi
- echo shar: extracting makefile.tos
- sed 's/^X//' << \SHAR_EOF > makefile.tos
- XCC = gcc
- XALL = mkproto.ttp
- X
- Xmkproto.ttp : mkproto.c mkproto.h
- X $(CC) -O -o mkproto.ttp mkproto.c -mshort -s
- Xclean:
- X rm -f *.o
- X
- Xrealclean: clean
- X rm -f $(ALL) report core
- SHAR_EOF
- if test 170 -ne "`wc -c makefile.tos`"
- then
- echo shar: error transmitting makefile.tos '(should have been 170 characters)'
- fi
- echo shar: extracting makefile.unx
- sed 's/^X//' << \SHAR_EOF > makefile.unx
- XCC = cc
- XALL = mkproto
- X
- Xmkproto : mkproto.c mkproto.h
- X $(CC) -O -o mkproto mkproto.c
- Xclean:
- X rm -f *.o
- X
- Xrealclean: clean
- X rm -f $(ALL) report core
- SHAR_EOF
- if test 147 -ne "`wc -c makefile.unx`"
- then
- echo shar: error transmitting makefile.unx '(should have been 147 characters)'
- fi
- echo shar: extracting mkproto.c
- sed 's/^X//' << \SHAR_EOF > mkproto.c
- X/* Program to extract function declarations from C source code */
- X/* Written by Eric R. Smith and placed in the public domain */
- X/* Thanks are due to Jwahar R. Bammi for fixing several bugs */
- X/* and providing the Unix makefiles. */
- X
- X#if defined(__STDC__) && !defined(minix)
- X#include <stddef.h>
- X#include <stdlib.h>
- X#else
- X#define EXIT_SUCCESS 0
- X#define EXIT_FAILURE 1
- Xextern char *malloc();
- X#endif
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <string.h>
- X
- X/*#define DEBUG(s) (fputs(s, stderr)) /* */
- X#define DEBUG(s) /* */
- X
- X#define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
- X#define ABORTED ( (Word *) -1 )
- X#define MAXPARAM 20 /* max. number of parameters to a function */
- X#define NEWBUFSIZ (20480*sizeof(char)) /* new buffer size */
- X
- Xint inquote = 0; /* in a quote?? */
- Xint newline_seen = 1; /* are we at the start of a line */
- Xlong linenum = 1L; /* line number in current file */
- Xint dostatic = 0; /* do static functions? */
- Xint donum = 0; /* print line numbers? */
- Xint dohead = 1; /* do file headers? */
- Xint docond = 1; /* conditionalize for non-ANSI compilers? */
- Xint glastc = ' '; /* last char. seen by getsym() */
- X
- Xtypedef struct word {
- X struct word *next;
- X char string[1];
- X} Word;
- X
- X#include "mkproto.h"
- X
- X/*
- X * Routines for manipulating lists of words.
- X */
- X
- XWord *word_alloc(s)
- X char *s;
- X{
- X Word *w;
- X
- X w = (Word *) malloc(sizeof(Word) + strlen(s) + 1); /* ++jrb */
- X strcpy(w->string, s);
- X w->next = NULL;
- X return w;
- X}
- X
- Xvoid word_free(w)
- X Word *w;
- X{
- X Word *oldw;
- X while (w) {
- X oldw = w;
- X w = w->next;
- X free(oldw);
- X }
- X}
- X
- X/* return the length of a list; empty words are not counted */
- Xint
- XList_len(w)
- X Word *w;
- X{
- X int count = 0;
- X
- X while (w) {
- X if (*w->string) count++;
- X w = w->next;
- X }
- X return count;
- X}
- X
- X/* Append two lists, and return the result */
- X
- XWord *word_append(w1, w2)
- X Word *w1, *w2;
- X{
- X Word *r, *w;
- X
- X r = w = word_alloc("");
- X
- X while (w1) {
- X w->next = word_alloc(w1->string);
- X w = w->next;
- X w1 = w1->next;
- X }
- X while (w2) {
- X w->next = word_alloc(w2->string);
- X w = w->next;
- X w2 = w2->next;
- X }
- X
- X return r;
- X}
- X
- X/* see if the last entry in w2 is in w1 */
- X
- Xint
- Xfoundin(w1, w2)
- X Word *w1, *w2;
- X{
- X while (w2->next)
- X w2 = w2->next;
- X
- X while (w1) {
- X if (!strcmp(w1->string, w2->string))
- X return 1;
- X w1 = w1->next;
- X }
- X return 0;
- X}
- X
- X/* add the string s to the given list of words */
- X
- Xvoid addword(w, s)
- X Word *w; char *s;
- X{
- X while (w->next) w = w->next;
- X w->next = word_alloc(s);
- X}
- X
- X/* given a list representing a type and a variable name, extract just
- X * the base type, e.g. "struct word *x" would yield "struct word"
- X */
- X
- XWord *typelist(p)
- X Word *p;
- X{
- X Word *w, *r;
- X
- X r = w = word_alloc("");
- X while (p && p->next) {
- X if (p->string[0] && !ISCSYM(p->string[0]))
- X break;
- X w->next = word_alloc(p->string);
- X w = w->next;
- X p = p->next;
- X }
- X return r;
- X}
- X
- X/* typefixhack: promote formal parameters of type "char", "unsigned char",
- X "short", or "unsigned short" to "int".
- X*/
- X
- Xvoid typefixhack(w)
- X Word *w;
- X{
- X Word *oldw = 0;
- X
- X while (w) {
- X if (*w->string) {
- X if ( (!strcmp(w->string, "char") ||
- X !strcmp(w->string, "short") )
- X && (List_len(w->next) < 2) )
- X {
- X if (oldw && !strcmp(oldw->string, "unsigned")) {
- X oldw->next = w->next;
- X free(w);
- X w = oldw;
- X }
- X strcpy(w->string, "int");
- X }
- X }
- X w = w->next;
- X }
- X}
- X
- X/* read a character: if it's a newline, increment the line count */
- X
- X#ifdef __GNUC__ /* ++jrb */
- Xinline
- X#endif
- Xint ngetc(f)
- X FILE *f;
- X{
- X int c;
- X
- X c = getc(f);
- X if (c == '\n') linenum++;
- X
- X return c;
- X}
- X
- X/* read the next character from the file. If the character is '\' then
- X * read and skip the next character. Any comment sequence is converted
- X * to a blank.
- X */
- X
- Xint fnextch(f)
- X FILE *f;
- X{
- X int c, lastc, incomment;
- X
- X c = ngetc(f);
- X while (c == '\\') {
- XDEBUG("fnextch: in backslash loop\n");
- X c = ngetc(f); /* skip a character */
- X c = ngetc(f);
- X }
- X if (c == '/' && !inquote) {
- X c = ngetc(f);
- X if (c == '*') {
- X incomment = 1;
- X c = ' ';
- XDEBUG("fnextch: comment seen\n");
- X while (incomment) {
- X lastc = c;
- X c = ngetc(f);
- X if (lastc == '*' && c == '/')
- X incomment = 0;
- X else if (c < 0)
- X return c;
- X }
- X return fnextch(f);
- X }
- X else {
- X if (c == '\n') linenum--;
- X ungetc(c, f);
- X return '/';
- X }
- X }
- X return c;
- X}
- X
- X
- X/* Get the next "interesting" character. Comments are skipped, and strings
- X * are converted to "0". Also, if a line starts with "#" it is skipped.
- X */
- X
- Xint nextch(f)
- X FILE *f;
- X{
- X int c;
- X
- X c = fnextch(f);
- X if (newline_seen && c == '#') {
- X do {
- X c = fnextch(f);
- X } while (c >= 0 && c != '\n');
- X if (c < 0)
- X return c;
- X }
- X newline_seen = (c == '\n');
- X
- X if (c == '\'' || c == '\"') {
- XDEBUG("nextch: in a quote\n");
- X inquote = c;
- X while ( (c = fnextch(f)) >= 0 ) {
- X if (c == inquote) {
- X inquote = 0;
- XDEBUG("nextch: out of quote\n");
- X return '0';
- X }
- X }
- XDEBUG("nextch: EOF in a quote\n");
- X }
- X return c;
- X}
- X
- X/*
- X * Get the next symbol from the file, skipping blanks.
- X * Return 0 if OK, -1 for EOF.
- X * Also collapses everything between { and }
- X */
- X
- Xint
- Xgetsym(buf, f)
- X char *buf; FILE *f;
- X{
- X register int c;
- X int inbrack = 0;
- X
- XDEBUG("in getsym\n");
- X c = glastc;
- X while ((c > 0) && isspace(c)) {
- X c = nextch(f);
- X }
- XDEBUG("getsym: spaces skipped\n");
- X if (c < 0) {
- XDEBUG("EOF read in getsym\n");
- X return -1;
- X }
- X if (c == '{') {
- X inbrack = 1;
- XDEBUG("getsym: in bracket\n");
- X while (inbrack) {
- X c = nextch(f);
- X if (c < 0) {
- XDEBUG("getsym: EOF seen in bracket loop\n");
- X glastc = c;
- X return c;
- X }
- X if (c == '{') inbrack++;
- X else if (c == '}') inbrack--;
- X }
- X strcpy(buf, "{}");
- X glastc = nextch(f);
- XDEBUG("getsym: out of in bracket loop\n");
- X return 0;
- X }
- X if (!ISCSYM(c)) {
- X *buf++ = c;
- X *buf = 0;
- X glastc = nextch(f);
- XDEBUG("getsym: returning special symbol\n");
- X return 0;
- X }
- X while (ISCSYM(c)) {
- X *buf++ = c;
- X c = nextch(f);
- X }
- X *buf = 0;
- X glastc = c;
- XDEBUG("getsym: returning word\n");
- X return 0;
- X}
- X
- X/*
- X * skipit: skip until a ";" or the end of a function declaration is seen
- X */
- Xint skipit(buf, f)
- X char *buf;
- X FILE *f;
- X{
- X int i;
- X
- X do {
- XDEBUG("in skipit loop\n");
- X i = getsym(buf, f);
- X if (i < 0) return i;
- X } while (*buf != ';' && *buf != '{');
- X
- X return 0;
- X}
- X
- X/*
- X * Get a parameter list; when this is called the next symbol in line
- X * should be the first thing in the list.
- X */
- X
- XWord *getparamlist(f)
- X FILE *f;
- X{
- X static Word *pname[MAXPARAM]; /* parameter names */
- X Word *tlist, /* type name */
- X *plist; /* temporary */
- X int np = 0; /* number of parameters */
- X int typed[MAXPARAM]; /* parameter has been given a type */
- X int tlistdone; /* finished finding the type name */
- X int sawsomething;
- X int i;
- X int inparen = 0;
- X char buf[80];
- X
- XDEBUG("in getparamlist\n");
- X for (i = 0; i < MAXPARAM; i++)
- X typed[i] = 0;
- X
- X plist = word_alloc("");
- X
- X/* first, get the stuff inside brackets (if anything) */
- X
- X sawsomething = 0; /* gets set nonzero when we see an arg */
- X for (;;) {
- X if (getsym(buf, f) < 0) return NULL;
- X if (*buf == ')' && (--inparen < 0)) {
- X if (sawsomething) { /* if we've seen an arg */
- X pname[np] = plist;
- X plist = word_alloc("");
- X np++;
- X }
- X break;
- X }
- X if (*buf == ';') { /* something weird */
- X return ABORTED;
- X }
- X sawsomething = 1; /* there's something in the arg. list */
- X if (*buf == ',' && inparen == 0) {
- X pname[np] = plist;
- X plist = word_alloc("");
- X np++;
- X }
- X else {
- X addword(plist, buf);
- X if (*buf == '(') inparen++;
- X }
- X }
- X
- X/* next, get the declarations after the function header */
- X
- X inparen = 0;
- X
- X tlist = word_alloc("");
- X plist = word_alloc("");
- X tlistdone = 0;
- X sawsomething = 0;
- X for(;;) {
- X if (getsym(buf, f) < 0) return NULL;
- X
- X/* handle a list like "int x,y,z" */
- X if (*buf == ',' && !inparen) {
- X if (!sawsomething)
- X return NULL;
- X for (i = 0; i < np; i++) {
- X if (!typed[i] && foundin(plist, pname[i])) {
- X typed[i] = 1;
- X word_free(pname[i]);
- X pname[i] = word_append(tlist, plist);
- X /* promote types */
- X typefixhack(pname[i]);
- X break;
- X }
- X }
- X if (!tlistdone) {
- X tlist = typelist(plist);
- X tlistdone = 1;
- X }
- X word_free(plist);
- X plist = word_alloc("");
- X }
- X/* handle the end of a list */
- X else if (*buf == ';') {
- X if (!sawsomething)
- X return ABORTED;
- X for (i = 0; i < np; i++) {
- X if (!typed[i] && foundin(plist, pname[i])) {
- X typed[i] = 1;
- X word_free(pname[i]);
- X pname[i] = word_append(tlist, plist);
- X typefixhack(pname[i]);
- X break;
- X }
- X }
- X tlistdone = 0;
- X word_free(tlist); word_free(plist);
- X tlist = word_alloc("");
- X plist = word_alloc("");
- X }
- X/* handle the beginning of the function */
- X else if (!strcmp(buf, "{}")) break;
- X/* otherwise, throw the word into the list (except for "register") */
- X else if (strcmp(buf, "register")) {
- X sawsomething = 1;
- X addword(plist, buf);
- X if (*buf == '(') inparen++;
- X if (*buf == ')') inparen--;
- X }
- X }
- X
- X/* Now take the info we have and build a prototype list */
- X
- X/* empty parameter list means "void" */
- X if (np == 0)
- X return word_alloc("void");
- X
- X plist = tlist = word_alloc("");
- X for (i = 0; i < np; i++) {
- X
- X/* If no type provided, make it an "int" */
- X if ( !(pname[i]->next) ||
- X (!(pname[i]->next->next)&&strcmp(pname[i]->next->string, "void"))) {
- X addword(tlist, "int");
- X }
- X while (tlist->next) tlist = tlist->next;
- X tlist->next = pname[i];
- X if (i < np - 1)
- X addword(tlist, ", ");
- X }
- X return plist;
- X}
- X
- X/*
- X * emit a function declaration. The attributes and name of the function
- X * are in wlist; the parameters are in plist.
- X */
- Xvoid emit(wlist, plist, startline)
- X Word *wlist, *plist;
- X long startline;
- X{
- X Word *w;
- X int count = 0;
- X
- XDEBUG("emit called\n");
- X if (donum)
- X printf("/*%8ld */ ", startline);
- X
- X for (w = wlist; w; w = w->next) {
- X if (w->string[0])
- X count ++;
- X }
- X
- X if (count < 2)
- X printf("int ");
- X
- X for (w = wlist; w; w = w->next) {
- X printf("%s", w->string);
- X if (ISCSYM(w->string[0]))
- X printf(" ");
- X }
- X if (docond)
- X printf("P((");
- X else
- X printf("( ");
- X for (w = plist; w; w = w->next) {
- X printf("%s", w->string);
- X if (ISCSYM(w->string[0]))
- X printf(" ");
- X }
- X if (docond)
- X printf("));\n");
- X else
- X printf(");\n");
- X}
- X
- X/*
- X * get all the function declarations
- X */
- X
- Xvoid getdecl(f)
- X FILE *f;
- X{
- X Word *plist, *wlist = NULL;
- X char buf[80];
- X int sawsomething;
- X long startline; /* line where declaration started */
- X int oktoprint;
- Xagain:
- X word_free(wlist);
- X wlist = word_alloc("");
- X sawsomething = 0;
- X oktoprint = 1;
- X
- X for(;;) {
- XDEBUG("main getdecl loop\n");
- X if (getsym(buf,f) < 0) {
- XDEBUG("EOF in getdecl loop\n");
- X return;
- X }
- X/* try to guess when a declaration is not an external function definition */
- X if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
- X !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
- X !strcmp(buf, "extern")) {
- X skipit(buf, f);
- X goto again;
- X }
- X if (!dostatic && !strcmp(buf, "static")) {
- X oktoprint = 0;
- X }
- X/* for the benefit of compilers that allow "inline" declarations */
- X if (!strcmp(buf, "inline") && !sawsomething)
- X continue;
- X if (!strcmp(buf, ";")) goto again;
- X
- X/* A left parenthesis *might* indicate a function definition */
- X if (!strcmp(buf, "(")) {
- X startline = linenum;
- X if (!sawsomething || !(plist = getparamlist(f))) {
- X skipit(buf, f);
- X goto again;
- X }
- X if (plist == ABORTED)
- X goto again;
- X
- X/* It seems to have been what we wanted */
- X if (oktoprint)
- X emit(wlist, plist, startline);
- X word_free(plist);
- X goto again;
- X }
- X addword(wlist, buf);
- X sawsomething = 1;
- X }
- X}
- X
- Xvoid
- Xmain(argc, argv)
- Xint argc; char **argv;
- X{
- X FILE *f;
- X char *t, *iobuf;
- X extern void Usage();
- X
- X argv++; argc--;
- X
- X iobuf = malloc(NEWBUFSIZ);
- X while (*argv && **argv == '-') {
- X t = *argv++; --argc; t++;
- X while (*t) {
- X if (*t == 's')
- X dostatic = 1;
- X else if (*t == 'n')
- X donum = 1;
- X else if (*t == 'p')
- X docond = 0;
- X else
- X Usage();
- X t++;
- X }
- X }
- X
- X if (docond) {
- X printf("#ifdef __STDC__\n");
- X printf("# define\tP(s) s\n");
- X printf("#else\n");
- X printf("# define P(s) ()\n");
- X printf("#endif\n\n");
- X }
- X if (argc == 0)
- X getdecl(stdin);
- X else
- X while (argc > 0 && *argv) {
- XDEBUG("trying a new file\n");
- X if (!(f = fopen(*argv, "r"))) {
- X perror(*argv);
- X exit(EXIT_FAILURE);
- X }
- X if (iobuf)
- X setvbuf(f, iobuf, _IOFBF, NEWBUFSIZ);
- X if (dohead)
- X printf("\n/* %s */\n", *argv);
- X linenum = 1;
- X newline_seen = 1;
- X glastc = ' ';
- XDEBUG("calling getdecl\n");
- X getdecl(f);
- XDEBUG("back from getdecl\n");
- X argc--; argv++;
- X fclose(f);
- XDEBUG("back from fclose\n");
- X }
- X if (docond) {
- X printf("\n#undef P\n"); /* clean up namespace */
- X }
- X exit(EXIT_SUCCESS);
- X}
- X
- X
- Xvoid Usage()
- X{
- X fputs("Usage: mkproto [-n][-s][-p][files ...]\n",stderr);
- X fputs(" -n: put line numbers of declarations as comments\n",stderr);
- X fputs(" -s: include declarations for static functions\n", stderr);
- X fputs(" -p: don't make header files readable by non-ANSI compilers\n",
- X stderr);
- X exit(EXIT_FAILURE);
- X}
- SHAR_EOF
- if test 12844 -ne "`wc -c mkproto.c`"
- then
- echo shar: error transmitting mkproto.c '(should have been 12844 characters)'
- fi
- echo shar: extracting mkproto.h
- sed 's/^X//' << \SHAR_EOF > mkproto.h
- X#ifdef __STDC__
- X# define P(s) s
- X#else
- X# define P(s) ()
- X#endif
- X
- X
- X/* mkproto.c */
- XWord *word_alloc P((char *s ));
- Xvoid word_free P((Word *w ));
- Xint List_len P((Word *w ));
- XWord *word_append P((Word *w1 , Word *w2 ));
- Xint foundin P((Word *w1 , Word *w2 ));
- Xvoid addword P((Word *w , char *s ));
- XWord *typelist P((Word *p ));
- Xvoid typefixhack P((Word *w ));
- Xint ngetc P((FILE *f ));
- Xint fnextch P((FILE *f ));
- Xint nextch P((FILE *f ));
- Xint getsym P((char *buf , FILE *f ));
- Xint skipit P((char *buf , FILE *f ));
- XWord *getparamlist P((FILE *f ));
- Xvoid emit P((Word *wlist , Word *plist , long startline ));
- Xvoid getdecl P((FILE *f ));
- Xvoid main P((int argc , char **argv ));
- Xvoid Usage P((void ));
- X
- X#undef P
- SHAR_EOF
- if test 703 -ne "`wc -c mkproto.h`"
- then
- echo shar: error transmitting mkproto.h '(should have been 703 characters)'
- fi
- echo shar: extracting mkproto.man
- sed 's/^X//' << \SHAR_EOF > mkproto.man
- XNAME
- X mkproto - make prototypes for functions
- X
- X
- XSYNOPSIS
- X mkproto [-n] [-s] [-p] [ file ] ...
- X
- X
- XDESCRIPTION
- X Mkproto takes as input one or more C source code files, and
- Xproduces as output (on the standard output stream) a list of function
- Xprototypes (a la ANSI) for the external functions defined in the
- Xgiven source files. This output, redirected to a file, is suitable
- Xfor #include'ing in a C source file.
- X The function definitions in the original source
- Xmay be either "old-style" (in which case appropriate prototypes are
- Xgenerated for the functions) or "new-style" (in which the definition
- Xincludes a prototype already).
- X A -n option causes the line number where each function was defined
- Xto be prepended to the prototype declaration as a comment.
- X A -s option causes prototypes to be generated for functions declard
- X"static" as well as extern functions.
- X A -p option causes the prototypes emitted to be only readable by ANSI
- Xcompilers. Normally, the prototypes are "macro-ized" so that compilers
- Xwith __STDC__ not defined don't see them.
- X If files are specified on the command line, then a comment specifying
- Xthe file of origin is emitted before the prototypes constructed from
- Xthat file. If no files are given, then no comments are emitted and
- Xthe C source code is taken from the standard input stream.
- X
- XBUGS
- X Mkproto is easily confused by complicated declarations, such as
- X int ((*signal)())() { ...
- Xor
- X struct foo { int x, y; } foofunc() { ...
- X
- X Float types are not properly promoted in old style definitions,
- Xi.e.
- X int test(f) float f; { ...
- Xshould (because of the default type conversion rules) have prototype
- X int test(double f);
- Xrather than the incorrect
- X int test(float f);
- Xgenerated by mkproto.
- X
- X Some programs may need to be run through the preprocessor before
- Xbeing run through mkproto. The -n option is unlikely to work as desired
- Xon the output of a preprocessor.
- X
- X Typedef'd types aren't correctly promoted, e.g. for
- X typedef schar char; int foo(x) schar x;...
- Xmkproto incorrectly generates the prototype int foo(schar x) rather than
- Xthe (correct) int foo(int x).
- X
- X Functions named "inline" with no explicit type qualifiers are not
- Xrecognized.
- X
- XSEE ALSO
- X cc(1), lint(1)
- X
- XAUTHOR
- X Eric R. Smith.
- X
- XNOTE
- X There is no warranty for this program (as noted above, it's guaranteed
- Xto break sometimes anyways!). Mkproto is in the public domain.
- SHAR_EOF
- if test 2433 -ne "`wc -c mkproto.man`"
- then
- echo shar: error transmitting mkproto.man '(should have been 2433 characters)'
- fi
- echo shar: extracting README
- sed 's/^X//' << \SHAR_EOF > README
- XHere is mkproto, a program for generating prototype declarations for all
- Xfunctions appearing in a C source file. The input C code may be either
- XK&R or ANSI C (i.e. it's OK if the functions are defined using prototypes).
- XUnlike some of the sed-based scripts floating around, it correctly
- Xhandles prototype promotion (e.g. the prototype for 'int foo() char x;...'
- Xis 'int foo(int x)'). Also, it should work OK on just about any computer,
- Xnot just Unix-based ones (it's been tested under minix, Unix, and TOS).
- X
- XUse: typically, you would type 'mkproto *.c >proto.h' and then add a
- X'#include "proto.h"' line to all the C source files. An ANSI conformant
- Xcompiler will then be able to do type checking on function calls across
- Xmodule boundaries. As a bonus, proto.h will tell you which source files
- Xfunctions were defined in, and (if you gave the -n function to mkproto)
- Xtheir line numbers. The resulting include file may also be used by
- Xnon-ANSI compilers; you can disable this feature (for cleaner, strictly
- XANSI-conforming output) with the -p flag.
- X
- XPlease read the description of bugs in mkproto.man; definitely mkproto
- Xwill not handle all programs correctly, but it does work on the majority of
- Xthem. A sample of its output is provided in the file "mkproto.h"; this
- Xis the result of 'mkproto mkproto.c >mkproto.h'.
- X
- XThere is ABSOLUTELY NO WARRANTY for the program; as I said, it doesn't work
- Xon all programs (complicated function definitions can make it produce bogus
- Xoutput). It does what I need, though, and it can certainly make porting stuff
- Xto ANSI compilers easier.
- X
- XMkproto is in the public domain. If you find any bugs (other than the ones
- Xdocumented) please let me know.
- X--
- XEric R. Smith email:
- XDept. of Mathematics ersmith@uwovax.uwo.ca
- XUniversity of Western Ontario ersmith@uwovax.bitnet
- XLondon, Ont. Canada N6A 5B7
- Xph: (519) 661-3638
- SHAR_EOF
- if test 1879 -ne "`wc -c README`"
- then
- echo shar: error transmitting README '(should have been 1879 characters)'
- fi
- # End of shell archive
- exit 0
- --
- --
- Eric R. Smith email:
- Dept. of Mathematics ERSMITH@uwovax.uwo.ca
- University of Western Ontario ERSMITH@uwovax.bitnet
- London, Ont. Canada N6A 5B7
- ph: (519) 661-3638
-
-
-