⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proto.c

📁 操作系统源代码
💻 C
字号:
/* proto - Generate ANSI C prototypes.	Author:	Eric R. Smith *//* Program to extract function declarations from C source code * Written by Eric R. Smith and placed in the public domain * Thanks are due to Jwahar R. Bammi for fixing several bugs * And providing the Unix makefiles. */#define EXIT_SUCCESS  0#define EXIT_FAILURE  1#include <string.h>#include <ctype.h>#include <stdlib.h>#include <stdio.h>#define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_' ))#define ABORTED ( (Word *) -1 )#define MAXPARAM 20		/* max. number of parameters to a function */typedef struct word {  struct word *next;  char string[1];} Word;int inquote = 0;		/* in a quote? */int newline_seen = 1;		/* are we at the start of a line */long linenum = 1L;		/* line number in current file */long endline = 0L;		/* the last line before the { of a f'n */long symline = 0L;		/* Line that symbol was on, set by getsym() */int dostatic = 0;		/* do static functions? */int donum = 0;			/* print line numbers? */int dohead = 1;			/* do file headers? */int docond = 1;			/* conditionalize for non-ANSI compilers? */int dodiff = 0;			/* Output a diff file to prototype original */int doold = 0;			/* do old style: P() */int glastc = ' ';		/* last char. seen by getsym() */Word *endlist;			/* Parentheses after the parameters */char *progname;			/* name of program (for error messages) */_PROTOTYPE(Word * word_alloc, (char *s));_PROTOTYPE(void word_free, (Word * w));_PROTOTYPE(int List_len, (Word * w));_PROTOTYPE(Word * word_append, (Word * w1, Word * w2));_PROTOTYPE(int foundin, (Word * w1, Word * w2));_PROTOTYPE(void addword, (Word * w, char *s));_PROTOTYPE(void printlist, (Word * p));_PROTOTYPE(Word * typelist, (Word * p));_PROTOTYPE(void typefixhack, (Word * w));_PROTOTYPE(int ngetc, (FILE * f));_PROTOTYPE(int fnextch, (FILE * f));_PROTOTYPE(int nextch, (FILE * f));_PROTOTYPE(int getsym, (char *buf, FILE * f));_PROTOTYPE(int skipit, (char *buf, FILE * f));_PROTOTYPE(Word * getparamlist, (FILE * f));_PROTOTYPE(void emit, (Word * wlist, Word * plist, long startline));_PROTOTYPE(void getdecl, (FILE * f));_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(void Usage, (void));/* Routines for manipulating lists of words. */Word *word_alloc(s)char *s;{  Word *w;  w = (Word *) malloc(sizeof(Word) + strlen(s) + 1);  if (w == NULL) {	fprintf(stderr, "%s: out of memory\n", progname);	exit(1);  }  (void) strcpy(w->string, s);  w->next = NULL;  return w;}void word_free(w)Word *w;{  Word *oldw;  while (w) {	oldw = w;	w = w->next;	free((char *) oldw);  }}/* Return the length of a list; empty words are not counted */int List_len(w)Word *w;{  int count = 0;  while (w) {	if (*w->string) count++;	w = w->next;  }  return count;}/* Append two lists, and return the result */Word *word_append(w1, w2)Word *w1, *w2;{  Word *r, *w;  r = w = word_alloc("");  while (w1) {	w->next = word_alloc(w1->string);	w = w->next;	w1 = w1->next;  }  while (w2) {	w->next = word_alloc(w2->string);	w = w->next;	w2 = w2->next;  }  return r;}/* See if the last entry in w2 is in w1 */int foundin(w1, w2)Word *w1, *w2;{  while (w2->next) w2 = w2->next;  while (w1) {	if (!strcmp(w1->string, w2->string)) return 1;	w1 = w1->next;  }  return 0;}/* Add the string s to the given list of words */void addword(w, s)Word *w;char *s;{  while (w->next) w = w->next;  w->next = word_alloc(s);}/* Printlist: print out a list */void printlist(p)Word *p;{  Word *w;  int i = 0;  for (w = p; w; w = w->next) {	printf("%s", w->string);	if (ISCSYM(w->string[0]) && i > 0) printf(" ");	i++;  }}/* Given a list representing a type and a variable name, extract just * the base type, e.g. "struct word *x" would yield "struct word". * Similarly, "unsigned char x[]" would yield "unsigned char". */Word *typelist(p)Word *p;{  Word *w, *r, *last;  last = r = w = word_alloc("");  while (p && p->next) {	if (p->string[0] == '[') {		word_free(w);		last->next = NULL;		break;	}	if (p->string[0] && !ISCSYM(p->string[0])) break;	w->next = word_alloc(p->string);	last = w;	w = w->next;	p = p->next;  }  return r;}/* Typefixhack: promote formal parameters of type "char", "unsigned char", * "short", or "unsigned short" to "int". */void typefixhack(w)Word *w;{  Word *oldw = 0;  while (w) {	if (*w->string) {		if ((!strcmp(w->string, "char") ||		     !strcmp(w->string, "short"))		    && (List_len(w->next) < 2)) {			if (oldw && !strcmp(oldw->string, "unsigned")) {				oldw->next = w->next;				free((char *) w);				w = oldw;			}			(void) strcpy(w->string, "int");		}	}	w = w->next;  }}/* Read a character: if it's a newline, increment the line count */int ngetc(f)FILE *f;{  int c;  c = getc(f);  if (c == '\n') linenum++;  return c;}/* Read the next character from the file. If the character is '\' then * read and skip the next character. Any comment sequence is converted * to a blank. */int fnextch(f)FILE *f;{  int c, lastc, incomment;  c = ngetc(f);  while (c == '\\') {	c = ngetc(f);		/* skip a character */	c = ngetc(f);  }  if (c == '/' && !inquote) {	c = ngetc(f);	if (c == '*') {		incomment = 1;		c = ' ';		while (incomment) {			lastc = c;			c = ngetc(f);			if (lastc == '*' && c == '/')				incomment = 0;			else if (c < 0)				return c;		}		return fnextch(f);	} else {		if (c == '\n') linenum--;		(void) ungetc(c, f);		return '/';	}  }  return c;}/* Get the next "interesting" character. Comments are skipped, and strings * are converted to "0". Also, if a line starts with "#" it is skipped. */int nextch(f)FILE *f;{  int c;  c = fnextch(f);  if (newline_seen && c == '#') {	do {		c = fnextch(f);	} while (c >= 0 && c != '\n');	if (c < 0) return c;  }  newline_seen = (c == '\n');  if (c == '\'' || c == '\"') {	inquote = c;	while ((c = fnextch(f)) >= 0) {		if (c == inquote) {			inquote = 0;			return '0';		}	}  }  return c;}/* Get the next symbol from the file, skipping blanks. * Return 0 if OK, -1 for EOF. * Also collapses everything between { and } */int getsym(buf, f)char *buf;FILE *f;{  register int c;  int inbrack = 0;  c = glastc;  while ((c > 0) && isspace(c)) c = nextch(f);  if (c < 0) return -1;  if (c == '{') {	inbrack = 1;	endline = linenum;	while (inbrack) {		c = nextch(f);		if (c < 0) {			glastc = c;			return c;		}		if (c == '{')			inbrack++;		else if (c == '}')			inbrack--;	}	(void) strcpy(buf, "{}");	glastc = nextch(f);	return 0;  }  if (!ISCSYM(c)) {	*buf++ = c;	glastc = nextch(f);	if (c == '(' && glastc == '*') {	/* Look for a 'f'n pointer */		*buf++ = glastc;		glastc = nextch(f);	}	*buf = 0;	return 0;  }  symline = linenum;  while (ISCSYM(c)) {	*buf++ = c;	c = nextch(f);  }  *buf = 0;  glastc = c;  return 0;}/* Skipit: skip until a ";" or the end of a function declaration is seen */int skipit(buf, f)char *buf;FILE *f;{  int i;  do {	i = getsym(buf, f);	if (i < 0) return i;  } while (*buf != ';' && *buf != '{');  return 0;}/* Get a parameter list; when this is called the next symbol in line * should be the first thing in the list. */Word *getparamlist(f)FILE *f;{  static Word *pname[MAXPARAM];	/* parameter names */  Word *tlist,			/* type name */  *plist;			/* temporary */  int np = 0;			/* number of parameters */  int typed[MAXPARAM];		/* parameter has been given a type */  int tlistdone;		/* finished finding the type name */  int sawsomething;  int i;  int inparen = 0;  char buf[80];  for (i = 0; i < MAXPARAM; i++) typed[i] = 0;  plist = word_alloc("");  endlist = word_alloc("");  /* First, get the stuff inside brackets (if anything) */  sawsomething = 0;		/* gets set nonzero when we see an arg */  for (;;) {	if (getsym(buf, f) < 0) return(NULL);	if (*buf == ')' && (--inparen < 0)) {		if (sawsomething) {	/* if we've seen an arg */			pname[np] = plist;			plist = word_alloc("");			np++;		}		break;	}	if (*buf == ';') {	/* something weird */		return ABORTED;	}	sawsomething = 1;	/* there's something in the arg. list */	if (*buf == ',' && inparen == 0) {		pname[np] = plist;		plist = word_alloc("");		np++;	} else {		addword(plist, buf);		if (*buf == '(') inparen++;	}  }  /* Next, get the declarations after the function header */  inparen = 0;  tlist = word_alloc("");  plist = word_alloc("");  tlistdone = 0;  sawsomething = 0;  for (;;) {	if (getsym(buf, f) < 0) return(NULL);	/* Handle parentheses, which should indicate func pointer rtn values */	if (*buf == '(') {		addword(endlist, buf);		addword(endlist, " void ");		inparen++;	} else if (*buf == ')') {		if (symline == linenum) {			addword(endlist, buf);			addword(endlist, buf);		}		inparen--;	} else if (*buf == ',' && !inparen) {		/* Handle a list like "int x,y,z" */		if (!sawsomething) return(NULL);		for (i = 0; i < np; i++) {			if (!typed[i] && foundin(plist, pname[i])) {				typed[i] = 1;				word_free(pname[i]);				pname[i] = word_append(tlist, plist);				/* Promote types */				typefixhack(pname[i]);				break;			}		}		if (!tlistdone) {			tlist = typelist(plist);			tlistdone = 1;		}		word_free(plist);		plist = word_alloc("");	} else if (*buf == ';') {		/* Handle the end of a list */		if (!sawsomething) return ABORTED;		for (i = 0; i < np; i++) {			if (!typed[i] && foundin(plist, pname[i])) {				typed[i] = 1;				word_free(pname[i]);				pname[i] = word_append(tlist, plist);				typefixhack(pname[i]);				break;			}		}		tlistdone = 0;		word_free(tlist);		word_free(plist);		tlist = word_alloc("");		plist = word_alloc("");	} else if (!strcmp(buf, "{}"))		break;	/* Handle the  beginning of the function */		/* Otherwise, throw word into list (except for "register") */	else if (strcmp(buf, "register")) {		sawsomething = 1;		addword(plist, buf);		if (*buf == '(') inparen++;		if (*buf == ')') inparen--;	}  }  /* Now take the info we have and build a prototype list */  /* Empty parameter list means "void" */  if (np == 0) return word_alloc("void");  plist = tlist = word_alloc("");  for (i = 0; i < np; i++) {  /* If no type provided, make it an "int" */	if (!(pname[i]->next) ||	    (!(pname[i]->next->next)&&strcmp(pname[i]->next->string,"void"))) {		addword(tlist, "int");	}	while (tlist->next) tlist = tlist->next;	tlist->next = pname[i];	if (i < np - 1) addword(tlist, ", ");  }  return plist;}/* Emit a function declaration. The attributes and name of the function * are in wlist; the parameters are in plist. */void emit(wlist, plist, startline)Word *wlist, *plist;long startline;{  Word *w;  int count = 0;  if (doold == 0) printf("_PROTOTYPE(");  if (dodiff) {	printf("%lda%ld,%ld\n", startline - 1, startline, startline +2);	printf("> #ifdef __STDC__\n> ");  }  if (donum) printf("/*%8ld */ ", startline);  for (w = wlist; w; w = w->next) {	if (w->string[0]) count++;  }  if (count < 2) printf("int ");  printlist(wlist);  if (docond) {	if (doold)		printf("P((");	else		printf(", (");  } else {	printf("( ");  }  printlist(plist);  printlist(endlist);  if (docond)	printf("))");  else	printf(")");  if (!dodiff)	printf(";\n");  else	printf("\n");  if (dodiff) {	printf("> #else\n");	printf("%lda%ld\n", endline - 1, endline);	printf("> #endif\n");  }}/* Get all the function declarations */void getdecl(f)FILE *f;{  Word *plist, *wlist = NULL;  char buf[80];  int sawsomething;  long startline = 0L;		/* line where declaration started */  int oktoprint;again:				/* SHAME SHAME */  word_free(wlist);  wlist = word_alloc("");  sawsomething = 0;  oktoprint = 1;  for (;;) {	if (getsym(buf, f) < 0) return;	/* Guess when a declaration is not an external function definition */	if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||	    !strcmp(buf, "=") || !strcmp(buf, "typedef") ||	    !strcmp(buf, "extern")) {		(void) skipit(buf, f);		goto again;	}	if (!dostatic && !strcmp(buf, "static")) oktoprint = 0;	/* For the benefit of compilers that allow "inline" declarations */	if (!strcmp(buf, "inline") && !sawsomething) continue;	if (!strcmp(buf, ";")) goto again;	/* A left parenthesis *might* indicate a function definition */	if (!strcmp(buf, "(")) {		if (!sawsomething || !(plist = getparamlist(f))) {			(void) skipit(buf, f);			goto again;		}		if (plist == ABORTED) goto again;		/* It seems to have been what we wanted */		if (oktoprint) emit(wlist, plist, startline);		word_free(plist);		goto again;	}	addword(wlist, buf);	if (!sawsomething) startline = symline;	sawsomething = 1;  }}int main(argc, argv)int argc;char **argv;{  FILE *f, *g;  char *t;  char newname[40];  progname = argv[0];  argv++;  argc--;  g = stdout;  while (*argv && **argv == '-') {	t = *argv++;	--argc;	t++;	while (*t) {		if (*t == 's')			dostatic = 1;		else if (*t == 'n')			donum = 1;		else if (*t == 'p')			docond = 0;		else if (*t == 'P')			doold =1;		else if (*t == 'd') {			dodiff = 1;			docond = 0;			donum = 0;			dostatic = 1;		} else			Usage();		t++;	}  }  if (docond && doold) {	printf("#ifdef __STDC__\n");	printf("# define\tP(s) s\n");	printf("#else\n");	printf("# define P(s) ()\n");	printf("#endif\n\n");  }  if (argc == 0)	getdecl(stdin);  else	while (argc > 0 && *argv) {		if (!(f = fopen(*argv, "r"))) {			perror(*argv);			exit(EXIT_FAILURE);		}		if (dodiff) {			(void) sprintf(newname, "%sdif", *argv);			(void) fclose(g);			if (!(g = fopen(newname, "w"))) {				perror(newname);				exit(EXIT_FAILURE);			}		}		if (doold && dohead && !dodiff) printf("\n/* %s */\n", *argv);		linenum = 1;		newline_seen = 1;		glastc = ' ';		getdecl(f);		argc--;		argv++;		(void) fclose(f);	}  if (docond && doold) printf("\n#undef P\n");	/* clean up namespace */  (void) fclose(g);  return(EXIT_SUCCESS);}void Usage(){  fputs("Usage: ", stderr);  fputs(progname, stderr);  fputs(" [-d][-n][-p][-s] [files ...]\n", stderr);  fputs("   -P: use P() style instead of _PROTOTYPE\n", stderr);  fputs("   -d: produce a diff file to prototype original source\n", stderr);  fputs("   -n: put line numbers of declarations as comments\n", stderr);  fputs("   -p: don't make header files readable by K&R compilers\n", stderr);  fputs("   -s: include declarations for static functions\n", stderr);  exit(EXIT_FAILURE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -