/* "makeproto" Copyright 1989, 1990, 1991 Free Software Foundation */ /* Program to scan old-style source files and make prototypes */ #include #include #include #ifdef FILE /* a #define in BSD, a typedef in SYSV (hp-ux, at least) */ # ifndef BSD # define BSD 1 # endif #endif #ifdef BSD # include #else # include #endif #define isidchar(x) (isalnum(x) || (x) == '_') #define dprintf if (!debug) ; else printf #define MAXARGS 16 int verbose, debug, incomment; struct warnstruct { char *bad, *good; } warntypes[] = { { "char", "int" }, { "signed char", "int" }, { "unsigned char", "int" }, { "short", "int" }, { "signed short", "int" }, { "unsigned short", "int" }, { "boolean", "int" }, { "Boolean", "int" }, { "float", "double" }, { NULL, NULL } } ; int readline(buf, inf) char *buf; FILE *inf; { char *cp, *cp2; int spflag; for (;;) { if (fgets(buf, 1000, inf)) { cp = buf; cp2 = buf; spflag = 0; while (*cp) { if (incomment) { if (cp[0] == '*' && cp[1] == '/') { incomment = 0; cp += 2; } else cp++; spflag = 1; } else { if (cp[0] == '/' && cp[1] == '*') { incomment = 1; cp += 2; } else if (isspace(*cp)) { spflag = 1; cp++; } else { if (spflag) *cp2++ = ' '; *cp2++ = *cp++; spflag = 0; } } } *cp2 = 0; if (!*buf) continue; if (verbose) printf("\217%s\210\n", buf); return 1; } else strcpy(buf, "\001"); return 0; } } int strbeginsword(s1, s2) register char *s1, *s2; { while (*s2 && *s1 == *s2) s1++, s2++; return (!*s2 && !isidchar(*s1)); } void usage() { fprintf(stderr, "usage: makeproto [options] [infile ...] [-o outfile]]\n"); fprintf(stderr, " -tnnn Tab to nnn after type name [default 15]\n"); fprintf(stderr, " -annn Tab to nnn before arguments [default 30]\n"); fprintf(stderr, " -s0 Omit functions declared static\n"); fprintf(stderr, " -s1 Omit functions not declared static\n"); fprintf(stderr, " -x Add \"extern\" keyword (-X => \"Extern\")\n"); fprintf(stderr, " -n Include argument names in prototypes\n"); fprintf(stderr, " -m Use PP/PV macro notation\n"); exit(1); } #define bounce(msg) do { if (verbose) printf("Bounced: %s\n", msg); if (stupid) goto Lbounce; } while (0) main(argc, argv) int argc; char **argv; { FILE *inf, *outf; char outfname[256]; char buf[1000], ifdefname[256]; char ftype[256], fname[80], dtype[256], decl[256], dname[80], temp[256]; char argdecls[MAXARGS][256], argnames[MAXARGS][80]; char *cp, *cp2, *cp3; int i, j, pos, len, thistab, numstars, whichf, nargs, incomment, errors = 0; long li; int typetab = 15, argtab = 30, width = 80, usenames = 0, usemacros = 0; int useextern = 0, staticness = -1, hasheader = 0, useifdefs = 0; int stupid = 1, firstdecl; errors = 0; verbose = 0; debug = 0; *outfname = 0; while (argc > 1 && argv[1][0] == '-') { if (argv[1][1] == 't') { typetab = atoi(argv[1] + 2); } else if (argv[1][1] == 'a') { argtab = atoi(argv[1] + 2); } else if (argv[1][1] == 'w') { width = atoi(argv[1] + 2); } else if (argv[1][1] == 's') { staticness = atoi(argv[1] + 2); } else if (argv[1][1] == 'v') { verbose = 1; } else if (argv[1][1] == 'D') { debug = 1; } else if (argv[1][1] == 'x') { useextern = 1; } else if (argv[1][1] == 'X') { useextern = 2; } else if (argv[1][1] == 'n') { usenames = 1; } else if (argv[1][1] == 'm') { usemacros = 1; } else if (argv[1][1] == 'h') { hasheader = 1; } else if (argv[1][1] == 'i') { useifdefs = 1; } else if (argv[1][1] == 'o' && argc > 2) { strcpy(outfname, argv[2]); argc--, argv++; } else { usage(); } argc--, argv++; } if (argc > 2 && !strcmp(argv[argc-2], "-o")) { strcpy(outfname, argv[argc-1]); argc -= 2; } if (*outfname) { outf = fopen(outfname, "w"); if (!outf) { perror(outfname); exit(1); } } else outf = stdout; if (hasheader) { time(&li); cp = ctime(&li); cp[24] = 0; fprintf(outf, "\n/* Declarations created by \"makeproto\" on %s */\n", cp); fprintf(outf, "\n\n"); } incomment = 0; for (whichf = 1; whichf < argc + (argc < 2); whichf++) { if (whichf >= argc || !strcmp(argv[whichf], "-")) { inf = stdin; } else { inf = fopen(argv[whichf], "r"); if (!inf) { perror(argv[whichf]); fprintf(outf, "\n/* Unable to open file %s */\n", argv[whichf]); errors++; continue; } } firstdecl = 1; while (readline(buf, inf)) { if (!isidchar(*buf)) continue; cp = buf; cp2 = ftype; numstars = 0; while (isspace(*cp) || isidchar(*cp)) *cp2++ = *cp++; if (*cp == '*') { while (*cp == '*' || isspace(*cp)) { if (*cp == '*') numstars++; cp++; } } else { while (cp > buf && isspace(cp[-1])) cp--, cp2--; while (cp > buf && isidchar(cp[-1])) cp--, cp2--; } while (cp2 > ftype && isspace(cp2[-1])) cp2--; *cp2 = 0; if (!*ftype) strcpy(ftype, "int"); dprintf("numstars is %d\n", numstars); /***/ dprintf("ftype is %s\n", ftype); /***/ dprintf("cp after ftype is %s\n", cp); /***/ if (strbeginsword(ftype, "static") || strbeginsword(ftype, "Static")) { if (staticness == 0) bounce("Function is static"); } else { if (staticness == 1) bounce("Function is not static"); if (useextern && !strbeginsword(ftype, "extern") && !strbeginsword(ftype, "Extern")) { sprintf(temp, useextern == 2 ? "Extern %s" : "extern %s", ftype); strcpy(ftype, temp); } } while (isspace(*cp)) cp++; if (!*cp) { readline(buf, inf); cp = buf; } dprintf("cp before fname is %s\n", cp); /***/ if (!isidchar(*cp)) bounce("No function name"); cp2 = fname; while (isidchar(*cp)) *cp2++= *cp++; *cp2 = 0; dprintf("fname is %s\n", fname); /***/ dprintf("cp after fname is %s\n", cp); /***/ while (isspace(*cp)) cp++; if (*cp++ != '(') bounce("No function '('"); nargs = 0; if (!*cp) { readline(buf, inf); cp = buf; } while (isspace(*cp)) cp++; while (*cp != ')') { if (!isidchar(*cp)) bounce("Missing argument name"); if (nargs >= MAXARGS) bounce("Too many arguments"); cp2 = argnames[nargs]; argdecls[nargs][0] = 0; nargs++; while (isidchar(*cp)) *cp2++ = *cp++; *cp2 = 0; dprintf("Argument %d is named %s\n", nargs-1, argnames[nargs-1]); /***/ while (isspace(*cp)) cp++; if (*cp == ',') { cp++; if (!*cp) { readline(buf, inf); cp = buf; } while (isspace(*cp)) cp++; } else if (*cp != ')') bounce("Missing function ')'"); } if (cp[1]) bounce("Characters after function ')'"); readline(buf, inf); cp = buf; for (;;) { while (isspace(*cp)) cp++; if (isidchar(*cp)) { cp2 = dtype; if (strbeginsword(cp, "register")) { cp += 8; while (isspace(*cp)) cp++; } while (isspace(*cp) || isidchar(*cp)) *cp2++ = *cp++; if (*cp == ',' || *cp == ';' || *cp == '[') { while (cp2 > dtype && isspace(cp2[-1])) cp--, cp2--; while (cp2 > dtype && isidchar(cp2[-1])) cp--, cp2--; } else if (*cp != '(' && *cp != '*') bounce("Strange character in arg decl"); while (cp2 > dtype && isspace(cp2[-1])) cp2--; *cp2 = 0; if (!*dtype) bounce("Empty argument type"); for (;;) { cp2 = decl; cp3 = dname; while (*cp == '*' || *cp == '(' || isspace(*cp)) *cp2++ = *cp++; if (!isidchar(*cp)) bounce("Missing arg decl name"); while (isidchar(*cp)) { if (usenames) *cp2++ = *cp; *cp3++ = *cp++; } if (!usenames) { while (cp2 > decl && isspace(cp2[-1])) cp2--; while (isspace(*cp)) cp++; } i = 0; while (*cp && *cp != ';' && (*cp != ',' || i > 0)) { if (*cp == '(' || *cp == '[') i++; if (*cp == ')' || *cp == ']') i--; *cp2++ = *cp++; } *cp2 = 0; *cp3 = 0; dprintf("Argument %s is %s\n", dname, decl); /***/ if (i > 0) bounce("Unbalanced parens in arg decl"); if (!*cp) bounce("Missing ';' or ',' in arg decl"); for (i = 0; i < nargs && strcmp(argnames[i], dname); i++) ; if (i >= nargs) bounce("Arg decl name not in argument list"); if (*decl) sprintf(argdecls[i], "%s %s", dtype, decl); else strcpy(argdecls[i], dtype); if (*cp == ',') { cp++; if (!*cp) { readline(buf, inf); cp = buf; } while (isspace(*cp)) cp++; } else break; } cp++; if (!*cp) { readline(buf, inf); cp = buf; } } else break; } if (*cp != '{') bounce("Missing function '{'"); if (firstdecl) { firstdecl = 0; if (argc > 2) fprintf(outf, "\n/* Declarations from %s */\n", argv[whichf]); if (useifdefs && inf != stdin) { strcpy(ifdefname, argv[whichf]); cp = ifdefname; for (cp2 = ifdefname; *cp2; ) { if (*cp2++ == '/') cp = cp2; } for (cp2 = ifdefname; *cp; cp++, cp2++) { if (islower(*cp)) *cp2 = toupper(*cp); else if (isalnum(*cp)) *cp2 = *cp; else *cp2 = '_'; } fprintf(outf, "#ifdef PROTO_%s\n", ifdefname); } } for (i = 0; i < nargs; i++) { if (!argdecls[i][0]) sprintf(argdecls[i], "int %s", argnames[i]); for (j = 0; warntypes[j].bad && !strbeginsword(argdecls[i], warntypes[j].bad); j++) ; if (warntypes[j].bad) { cp = argdecls[i]; while (isspace(*cp) || isidchar(*cp)) cp++; if (!*cp) { /* not, e.g., "char *" */ sprintf(temp, "%s%s", warntypes[j].good, argdecls[i] + strlen(warntypes[j].bad)); strcpy(argdecls[i], temp); fprintf(stderr, "Warning: Argument %s of %s has type %s\n", argnames[i], fname, warntypes[j]); } } } if (verbose && outf != stdout) printf("Found declaration for %s\n", fname); fprintf(outf, "%s", ftype); pos = strlen(ftype) + numstars; do { putc(' ', outf); pos++; } while (pos < typetab); for (i = 1; i <= numstars; i++) putc('*', outf); fprintf(outf, "%s", fname); pos += strlen(fname); do { putc(' ', outf); pos++; } while (pos < argtab); if (nargs == 0) { if (usemacros) fprintf(outf, "PV();"); else fprintf(outf, "(void);"); } else { if (usemacros) fprintf(outf, "PP( ("), pos += 5; else fprintf(outf, "("), pos++; thistab = pos; for (i = 0; i < nargs; i++) { len = strlen(argdecls[i]); if (i > 0) { putc(',', outf); pos++; if (pos > thistab && pos + len >= width) { putc('\n', outf); for (j = 1; j <= thistab; j++) putc(' ', outf); pos = thistab; } else { putc(' ', outf); pos++; } } fprintf(outf, "%s", argdecls[i]); pos += len; } if (usemacros) fprintf(outf, ") );"); else fprintf(outf, ");"); } putc('\n', outf); Lbounce: ; } if (inf != stdin) { if (useifdefs && !firstdecl) fprintf(outf, "#endif /*PROTO_%s*/\n", ifdefname); fclose(inf); } } if (hasheader) { fprintf(outf, "\n\n/* End. */\n\n"); } if (outf != stdout) fclose(outf); if (errors) exit(1); else exit(0); } /* End. */