home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / dev / misc / p2c / src / makeproto.c < prev    next >
C/C++ Source or Header  |  1993-12-21  |  16KB  |  509 lines

  1.  
  2. /* "makeproto"  Copyright 1989, 1990, 1991 Free Software Foundation */
  3.  
  4.  
  5. /* Program to scan old-style source files and make prototypes */
  6.  
  7.  
  8.  
  9. #include <stdio.h>
  10. #include <ctype.h>
  11. #include <time.h>
  12.  
  13. #ifdef FILE       /* a #define in BSD, a typedef in SYSV (hp-ux, at least) */
  14. # ifndef BSD
  15. #  define BSD 1
  16. # endif
  17. #endif
  18.  
  19. #ifdef BSD
  20. # include <strings.h>
  21. #else
  22. # include <string.h>
  23. #endif
  24.  
  25.  
  26.  
  27. #define isidchar(x)    (isalnum(x) || (x) == '_')
  28.  
  29. #define dprintf        if (!debug) ; else printf
  30.  
  31. #define MAXARGS        16
  32.  
  33.  
  34.  
  35. int verbose, debug, incomment;
  36.  
  37.  
  38. struct warnstruct {
  39.     char *bad, *good;
  40. } warntypes[] = {
  41.     { "char",             "int" },
  42.     { "signed char",      "int" },
  43.     { "unsigned char",    "int" },
  44.     { "short",            "int" },
  45.     { "signed short",     "int" },
  46.     { "unsigned short",   "int" },
  47.     { "boolean",          "int" },
  48.     { "Boolean",          "int" },
  49.     { "float",            "double" },
  50.     { NULL, NULL }
  51. } ;
  52.  
  53.  
  54.  
  55. int readline(buf, inf)
  56. char *buf;
  57. FILE *inf;
  58. {
  59.     char *cp, *cp2;
  60.     int spflag;
  61.  
  62.     for (;;) {
  63.         if (fgets(buf, 1000, inf)) {
  64.             cp = buf;
  65.             cp2 = buf;
  66.             spflag = 0;
  67.             while (*cp) {
  68.                 if (incomment) {
  69.                     if (cp[0] == '*' && cp[1] == '/') {
  70.                         incomment = 0;
  71.                         cp += 2;
  72.                     } else
  73.                         cp++;
  74.                     spflag = 1;
  75.                 } else {
  76.                     if (cp[0] == '/' && cp[1] == '*') {
  77.                         incomment = 1;
  78.                         cp += 2;
  79.                     } else if (isspace(*cp)) {
  80.                         spflag = 1;
  81.                         cp++;
  82.                     } else {
  83.                         if (spflag)
  84.                             *cp2++ = ' ';
  85.                         *cp2++ = *cp++;
  86.                         spflag = 0;
  87.                     }
  88.                 }
  89.             }
  90.             *cp2 = 0;
  91.             if (!*buf)
  92.                 continue;
  93.             if (verbose)
  94.                 printf("\217%s\210\n", buf);
  95.             return 1;
  96.         } else
  97.             strcpy(buf, "\001");
  98.             return 0;
  99.     }
  100. }
  101.  
  102.  
  103.  
  104.  
  105. int strbeginsword(s1, s2)
  106. register char *s1, *s2;
  107. {
  108.     while (*s2 && *s1 == *s2)
  109.         s1++, s2++;
  110.     return (!*s2 && !isidchar(*s1));
  111. }
  112.  
  113.  
  114.  
  115.  
  116. void usage()
  117. {
  118.     fprintf(stderr, "usage:  makeproto [options] [infile ...] [-o outfile]]\n");
  119.     fprintf(stderr, "           -tnnn   Tab to nnn after type name [default 15]\n");
  120.     fprintf(stderr, "           -annn   Tab to nnn before arguments [default 30]\n");
  121.     fprintf(stderr, "           -s0     Omit functions declared static\n");
  122.     fprintf(stderr, "           -s1     Omit functions not declared static\n");
  123.     fprintf(stderr, "           -x      Add \"extern\" keyword (-X => \"Extern\")\n");
  124.     fprintf(stderr, "           -n      Include argument names in prototypes\n");
  125.     fprintf(stderr, "           -m      Use PP/PV macro notation\n");
  126. #ifdef MCH_AMIGA
  127.     exit(20);
  128. #else
  129.     exit(1);
  130. #endif
  131. }
  132.  
  133.  
  134.  
  135.  
  136. #define bounce(msg)   do {  if (verbose) printf("Bounced: %s\n", msg); if (stupid) goto Lbounce;  } while (0)
  137.  
  138.  
  139.  
  140.  
  141.  
  142. main(argc, argv)
  143. int argc;
  144. char **argv;
  145. {
  146.     FILE *inf, *outf;
  147.     char outfname[256];
  148.     char buf[1000], ifdefname[256];
  149.     char ftype[256], fname[80], dtype[256], decl[256], dname[80], temp[256];
  150.     char argdecls[MAXARGS][256], argnames[MAXARGS][80];
  151.     char *cp, *cp2, *cp3;
  152.     int i, j, pos, len, thistab, numstars, whichf, nargs, incomment, errors = 0;
  153.     long li;
  154.     int typetab = 15, argtab = 30, width = 80, usenames = 0, usemacros = 0;
  155.     int useextern = 0, staticness = -1, hasheader = 0, useifdefs = 0;
  156.     int stupid = 1, firstdecl;
  157.  
  158.     errors = 0;
  159.     verbose = 0;
  160.     debug = 0;
  161.     *outfname = 0;
  162.     while (argc > 1 && argv[1][0] == '-') {
  163.         if (argv[1][1] == 't') {
  164.             typetab = atoi(argv[1] + 2);
  165.         } else if (argv[1][1] == 'a') {
  166.             argtab = atoi(argv[1] + 2);
  167.         } else if (argv[1][1] == 'w') {
  168.             width = atoi(argv[1] + 2);
  169.         } else if (argv[1][1] == 's') {
  170.             staticness = atoi(argv[1] + 2);
  171.         } else if (argv[1][1] == 'v') {
  172.             verbose = 1;
  173.         } else if (argv[1][1] == 'D') {
  174.             debug = 1;
  175.         } else if (argv[1][1] == 'x') {
  176.             useextern = 1;
  177.         } else if (argv[1][1] == 'X') {
  178.             useextern = 2;
  179.         } else if (argv[1][1] == 'n') {
  180.             usenames = 1;
  181.         } else if (argv[1][1] == 'm') {
  182.             usemacros = 1;
  183.         } else if (argv[1][1] == 'h') {
  184.             hasheader = 1;
  185.         } else if (argv[1][1] == 'i') {
  186.             useifdefs = 1;
  187.         } else if (argv[1][1] == 'o' && argc > 2) {
  188.             strcpy(outfname, argv[2]);
  189.             argc--, argv++;
  190.         } else {
  191.             usage();
  192.         }
  193.         argc--, argv++;
  194.     }
  195.     if (argc > 2 && !strcmp(argv[argc-2], "-o")) {
  196.         strcpy(outfname, argv[argc-1]);
  197.         argc -= 2;
  198.     }
  199.     if (*outfname) {
  200.         outf = fopen(outfname, "w");
  201.         if (!outf) {
  202.             perror(outfname);
  203. #ifdef MCH_AMIGA
  204.             exit(20);
  205. #else
  206.             exit(1);
  207. #endif
  208.         }
  209.     } else
  210.         outf = stdout;
  211.     if (hasheader) {
  212.         time(&li);
  213.         cp = ctime(&li);
  214.         cp[24] = 0;
  215.         fprintf(outf, "\n/* Declarations created by \"makeproto\" on %s */\n", cp);
  216.         fprintf(outf, "\n\n");
  217.     }
  218.     incomment = 0;
  219.     for (whichf = 1; whichf < argc + (argc < 2); whichf++) {
  220.         if (whichf >= argc || !strcmp(argv[whichf], "-")) {
  221.             inf = stdin;
  222.         } else {
  223.             inf = fopen(argv[whichf], "r");
  224.             if (!inf) {
  225.                 perror(argv[whichf]);
  226.                 fprintf(outf, "\n/* Unable to open file %s */\n", argv[whichf]);
  227.                 errors++;
  228.                 continue;
  229.             }
  230.         }
  231.         firstdecl = 1;
  232.         while (readline(buf, inf)) {
  233.             if (!isidchar(*buf))
  234.                 continue;
  235.             cp = buf;
  236.             cp2 = ftype;
  237.             numstars = 0;
  238.             while (isspace(*cp) || isidchar(*cp))
  239.                 *cp2++ = *cp++;
  240.             if (*cp == '*') {
  241.                 while (*cp == '*' || isspace(*cp)) {
  242.                     if (*cp == '*')
  243.                         numstars++;
  244.                     cp++;
  245.                 }
  246.             } else {
  247.                 while (cp > buf && isspace(cp[-1])) cp--, cp2--;
  248.                 while (cp > buf && isidchar(cp[-1])) cp--, cp2--;
  249.             }
  250.             while (cp2 > ftype && isspace(cp2[-1])) cp2--;
  251.             *cp2 = 0;
  252.             if (!*ftype)
  253.                 strcpy(ftype, "int");
  254.             dprintf("numstars is %d\n", numstars);   /***/
  255.             dprintf("ftype is %s\n", ftype);     /***/
  256.             dprintf("cp after ftype is %s\n", cp);     /***/
  257.             if (strbeginsword(ftype, "static") || strbeginsword(ftype, "Static")) {
  258.                 if (staticness == 0)
  259.                     bounce("Function is static");
  260.             } else {
  261.                 if (staticness == 1)
  262.                     bounce("Function is not static");
  263.                 if (useextern &&
  264.                      !strbeginsword(ftype, "extern") && !strbeginsword(ftype, "Extern")) {
  265.                     sprintf(temp, useextern == 2 ? "Extern %s" : "extern %s", ftype);
  266.                     strcpy(ftype, temp);
  267.                 }
  268.             }
  269.             while (isspace(*cp)) cp++;
  270.             if (!*cp) {
  271.                 readline(buf, inf);
  272.                 cp = buf;
  273.             }
  274.             dprintf("cp before fname is %s\n", cp);     /***/
  275.             if (!isidchar(*cp))
  276.                 bounce("No function name");
  277.             cp2 = fname;
  278.             while (isidchar(*cp))
  279.                 *cp2++= *cp++;
  280.             *cp2 = 0;
  281.             dprintf("fname is %s\n", fname);     /***/
  282.             dprintf("cp after fname is %s\n", cp);     /***/
  283.             while (isspace(*cp)) cp++;
  284.             if (*cp++ != '(')
  285.                 bounce("No function '('");
  286.             nargs = 0;
  287.             if (!*cp) {
  288.                 readline(buf, inf);
  289.                 cp = buf;
  290.             }
  291.             while (isspace(*cp)) cp++;
  292.             while (*cp != ')') {
  293.                 if (!isidchar(*cp))
  294.                     bounce("Missing argument name");
  295.                 if (nargs >= MAXARGS)
  296.                     bounce("Too many arguments");
  297.                 cp2 = argnames[nargs];
  298.                 argdecls[nargs][0] = 0;
  299.                 nargs++;
  300.                 while (isidchar(*cp))
  301.                     *cp2++ = *cp++;
  302.                 *cp2 = 0;
  303.                 dprintf("Argument %d is named %s\n", nargs-1, argnames[nargs-1]);    /***/
  304.                 while (isspace(*cp)) cp++;
  305.                 if (*cp == ',') {
  306.                     cp++;
  307.                     if (!*cp) {
  308.                         readline(buf, inf);
  309.                         cp = buf;
  310.                     }
  311.                     while (isspace(*cp)) cp++;
  312.                 } else if (*cp != ')')
  313.                     bounce("Missing function ')'");
  314.             }
  315.             if (cp[1])
  316.                 bounce("Characters after function ')'");
  317.             readline(buf, inf);
  318.             cp = buf;
  319.             for (;;) {
  320.                 while (isspace(*cp)) cp++;
  321.                 if (isidchar(*cp)) {
  322.                     cp2 = dtype;
  323.                     if (strbeginsword(cp, "register")) {
  324.                         cp += 8;
  325.                         while (isspace(*cp)) cp++;
  326.                     }
  327.                     while (isspace(*cp) || isidchar(*cp))
  328.                         *cp2++ = *cp++;
  329.                     if (*cp == ',' || *cp == ';' || *cp == '[') {
  330.                         while (cp2 > dtype && isspace(cp2[-1])) cp--, cp2--;
  331.                         while (cp2 > dtype && isidchar(cp2[-1])) cp--, cp2--;
  332.                     } else if (*cp != '(' && *cp != '*')
  333.                         bounce("Strange character in arg decl");
  334.                     while (cp2 > dtype && isspace(cp2[-1])) cp2--;
  335.                     *cp2 = 0;
  336.                     if (!*dtype)
  337.                         bounce("Empty argument type");
  338.                     for (;;) {
  339.                         cp2 = decl;
  340.                         cp3 = dname;
  341.                         while (*cp == '*' || *cp == '(' || isspace(*cp))
  342.                             *cp2++ = *cp++;
  343.                         if (!isidchar(*cp))
  344.                             bounce("Missing arg decl name");
  345.                         while (isidchar(*cp)) {
  346.                             if (usenames)
  347.                                 *cp2++ = *cp;
  348.                             *cp3++ = *cp++;
  349.                         }
  350.                         if (!usenames) {
  351.                             while (cp2 > decl && isspace(cp2[-1])) cp2--;
  352.                             while (isspace(*cp)) cp++;
  353.                         }
  354.                         i = 0;
  355.                         while (*cp && *cp != ';' && (*cp != ',' || i > 0)) {
  356.                             if (*cp == '(' || *cp == '[') i++;
  357.                             if (*cp == ')' || *cp == ']') i--;
  358.                             *cp2++ = *cp++;
  359.                         }
  360.                         *cp2 = 0;
  361.                         *cp3 = 0;
  362.                         dprintf("Argument %s is %s\n", dname, decl);     /***/
  363.                         if (i > 0)
  364.                             bounce("Unbalanced parens in arg decl");
  365.                         if (!*cp)
  366.                             bounce("Missing ';' or ',' in arg decl");
  367.                         for (i = 0; i < nargs && strcmp(argnames[i], dname); i++) ;
  368.                         if (i >= nargs)
  369.                             bounce("Arg decl name not in argument list");
  370.                         if (*decl)
  371.                             sprintf(argdecls[i], "%s %s", dtype, decl);
  372.                         else
  373.                             strcpy(argdecls[i], dtype);
  374.                         if (*cp == ',') {
  375.                             cp++;
  376.                             if (!*cp) {
  377.                                 readline(buf, inf);
  378.                                 cp = buf;
  379.                             }
  380.                             while (isspace(*cp)) cp++;
  381.                         } else
  382.                             break;
  383.                     }
  384.                     cp++;
  385.                     if (!*cp) {
  386.                         readline(buf, inf);
  387.                         cp = buf;
  388.                     }
  389.                 } else
  390.                     break;
  391.             }
  392.             if (*cp != '{')
  393.                 bounce("Missing function '{'");
  394.             if (firstdecl) {
  395.                 firstdecl = 0;
  396.                 if (argc > 2)
  397.                     fprintf(outf, "\n/* Declarations from %s */\n", argv[whichf]);
  398.                 if (useifdefs && inf != stdin) {
  399.                     strcpy(ifdefname, argv[whichf]);
  400.             cp = ifdefname;
  401.             for (cp2 = ifdefname; *cp2; ) {
  402.             if (*cp2++ == '/')
  403.                 cp = cp2;
  404.             }
  405.                     for (cp2 = ifdefname; *cp; cp++, cp2++) {
  406.                 if (islower(*cp))
  407.                 *cp2 = toupper(*cp);
  408.                         else if (isalnum(*cp))
  409.                             *cp2 = *cp;
  410.                         else
  411.                             *cp2 = '_';
  412.                     }
  413.                     fprintf(outf, "#ifdef PROTO_%s\n", ifdefname);
  414.                 }
  415.             }
  416.             for (i = 0; i < nargs; i++) {
  417.                 if (!argdecls[i][0])
  418.                     sprintf(argdecls[i], "int %s", argnames[i]);
  419.                 for (j = 0; warntypes[j].bad &&
  420.                             !strbeginsword(argdecls[i], warntypes[j].bad); j++) ;
  421.                 if (warntypes[j].bad) {
  422.                     cp = argdecls[i];
  423.                     while (isspace(*cp) || isidchar(*cp)) cp++;
  424.                     if (!*cp) {     /* not, e.g., "char *" */
  425.                         sprintf(temp, "%s%s", warntypes[j].good,
  426.                                               argdecls[i] + strlen(warntypes[j].bad));
  427.                         strcpy(argdecls[i], temp);
  428.                         fprintf(stderr, "Warning: Argument %s of %s has type %s\n",
  429.                                         argnames[i], fname, warntypes[j]);
  430.                     }
  431.                 }
  432.             }
  433.             if (verbose && outf != stdout)
  434.                 printf("Found declaration for %s\n", fname);
  435.             fprintf(outf, "%s", ftype);
  436.             pos = strlen(ftype) + numstars;
  437.             do {
  438.                 putc(' ', outf);
  439.                 pos++;
  440.             } while (pos < typetab);
  441.             for (i = 1; i <= numstars; i++)
  442.                 putc('*', outf);
  443.             fprintf(outf, "%s", fname);
  444.             pos += strlen(fname);
  445.             do {
  446.                 putc(' ', outf);
  447.                 pos++;
  448.             } while (pos < argtab);
  449.             if (nargs == 0) {
  450.                 if (usemacros)
  451.                     fprintf(outf, "PV();");
  452.                 else
  453.                     fprintf(outf, "(void);");
  454.             } else {
  455.                 if (usemacros)
  456.                     fprintf(outf, "PP( ("), pos += 5;
  457.                 else
  458.                     fprintf(outf, "("), pos++;
  459.                 thistab = pos;
  460.                 for (i = 0; i < nargs; i++) {
  461.                     len = strlen(argdecls[i]);
  462.                     if (i > 0) {
  463.                         putc(',', outf);
  464.                         pos++;
  465.                         if (pos > thistab && pos + len >= width) {
  466.                             putc('\n', outf);
  467.                             for (j = 1; j <= thistab; j++)
  468.                                 putc(' ', outf);
  469.                             pos = thistab;
  470.                         } else {
  471.                             putc(' ', outf);
  472.                             pos++;
  473.                         }
  474.                     }
  475.                     fprintf(outf, "%s", argdecls[i]);
  476.                     pos += len;
  477.                 }
  478.                 if (usemacros)
  479.                     fprintf(outf, ") );");
  480.                 else
  481.                     fprintf(outf, ");");
  482.             }
  483.             putc('\n', outf);
  484. Lbounce: ;
  485.         }
  486.         if (inf != stdin) {
  487.             if (useifdefs && !firstdecl)
  488.                 fprintf(outf, "#endif /*PROTO_%s*/\n", ifdefname);
  489.             fclose(inf);
  490.         }
  491.     }
  492.     if (hasheader) {
  493.         fprintf(outf, "\n\n/* End. */\n\n");
  494.     }
  495.     if (outf != stdout)
  496.         fclose(outf);
  497.     if (errors)
  498.         exit(1);
  499.     else
  500.         exit(0);
  501. }
  502.  
  503.  
  504.  
  505. /* End. */
  506.  
  507.  
  508.  
  509.