home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / pascal2c / makeprot.c < prev    next >
C/C++ Source or Header  |  1992-08-03  |  17KB  |  501 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.     exit(1);
  127. }
  128.  
  129.  
  130.  
  131.  
  132. #define bounce(msg)   do {  if (verbose) printf("Bounced: %s\n", msg); if (stupid) goto Lbounce;  } while (0)
  133.  
  134.  
  135.  
  136.  
  137.  
  138. main(argc, argv)
  139. int argc;
  140. char **argv;
  141. {
  142.     FILE *inf, *outf;
  143.     char outfname[256];
  144.     char buf[1000], ifdefname[256];
  145.     char ftype[256], fname[80], dtype[256], decl[256], dname[80], temp[256];
  146.     char argdecls[MAXARGS][256], argnames[MAXARGS][80];
  147.     char *cp, *cp2, *cp3;
  148.     int i, j, pos, len, thistab, numstars, whichf, nargs, incomment, errors = 0;
  149.     long li;
  150.     int typetab = 15, argtab = 30, width = 80, usenames = 0, usemacros = 0;
  151.     int useextern = 0, staticness = -1, hasheader = 0, useifdefs = 0;
  152.     int stupid = 1, firstdecl;
  153.  
  154.     errors = 0;
  155.     verbose = 0;
  156.     debug = 0;
  157.     *outfname = 0;
  158.     while (argc > 1 && argv[1][0] == '-') {
  159.         if (argv[1][1] == 't') {
  160.             typetab = atoi(argv[1] + 2);
  161.         } else if (argv[1][1] == 'a') {
  162.             argtab = atoi(argv[1] + 2);
  163.         } else if (argv[1][1] == 'w') {
  164.             width = atoi(argv[1] + 2);
  165.         } else if (argv[1][1] == 's') {
  166.             staticness = atoi(argv[1] + 2);
  167.         } else if (argv[1][1] == 'v') {
  168.             verbose = 1;
  169.         } else if (argv[1][1] == 'D') {
  170.             debug = 1;
  171.         } else if (argv[1][1] == 'x') {
  172.             useextern = 1;
  173.         } else if (argv[1][1] == 'X') {
  174.             useextern = 2;
  175.         } else if (argv[1][1] == 'n') {
  176.             usenames = 1;
  177.         } else if (argv[1][1] == 'm') {
  178.             usemacros = 1;
  179.         } else if (argv[1][1] == 'h') {
  180.             hasheader = 1;
  181.         } else if (argv[1][1] == 'i') {
  182.             useifdefs = 1;
  183.         } else if (argv[1][1] == 'o' && argc > 2) {
  184.             strcpy(outfname, argv[2]);
  185.             argc--, argv++;
  186.         } else {
  187.             usage();
  188.         }
  189.         argc--, argv++;
  190.     }
  191.     if (argc > 2 && !strcmp(argv[argc-2], "-o")) {
  192.         strcpy(outfname, argv[argc-1]);
  193.         argc -= 2;
  194.     }
  195.     if (*outfname) {
  196.         outf = fopen(outfname, "w");
  197.         if (!outf) {
  198.             perror(outfname);
  199.             exit(1);
  200.         }
  201.     } else
  202.         outf = stdout;
  203.     if (hasheader) {
  204.         time(&li);
  205.         cp = ctime(&li);
  206.         cp[24] = 0;
  207.         fprintf(outf, "\n/* Declarations created by \"makeproto\" on %s */\n", cp);
  208.         fprintf(outf, "\n\n");
  209.     }
  210.     incomment = 0;
  211.     for (whichf = 1; whichf < argc + (argc < 2); whichf++) {
  212.         if (whichf >= argc || !strcmp(argv[whichf], "-")) {
  213.             inf = stdin;
  214.         } else {
  215.             inf = fopen(argv[whichf], "r");
  216.             if (!inf) {
  217.                 perror(argv[whichf]);
  218.                 fprintf(outf, "\n/* Unable to open file %s */\n", argv[whichf]);
  219.                 errors++;
  220.                 continue;
  221.             }
  222.         }
  223.         firstdecl = 1;
  224.         while (readline(buf, inf)) {
  225.             if (!isidchar(*buf))
  226.                 continue;
  227.             cp = buf;
  228.             cp2 = ftype;
  229.             numstars = 0;
  230.             while (isspace(*cp) || isidchar(*cp))
  231.                 *cp2++ = *cp++;
  232.             if (*cp == '*') {
  233.                 while (*cp == '*' || isspace(*cp)) {
  234.                     if (*cp == '*')
  235.                         numstars++;
  236.                     cp++;
  237.                 }
  238.             } else {
  239.                 while (cp > buf && isspace(cp[-1])) cp--, cp2--;
  240.                 while (cp > buf && isidchar(cp[-1])) cp--, cp2--;
  241.             }
  242.             while (cp2 > ftype && isspace(cp2[-1])) cp2--;
  243.             *cp2 = 0;
  244.             if (!*ftype)
  245.                 strcpy(ftype, "int");
  246.             dprintf("numstars is %d\n", numstars);   /***/
  247.             dprintf("ftype is %s\n", ftype);     /***/
  248.             dprintf("cp after ftype is %s\n", cp);     /***/
  249.             if (strbeginsword(ftype, "static") || strbeginsword(ftype, "Static")) {
  250.                 if (staticness == 0)
  251.                     bounce("Function is static");
  252.             } else {
  253.                 if (staticness == 1)
  254.                     bounce("Function is not static");
  255.                 if (useextern &&
  256.                      !strbeginsword(ftype, "extern") && !strbeginsword(ftype, "Extern")) {
  257.                     sprintf(temp, useextern == 2 ? "Extern %s" : "extern %s", ftype);
  258.                     strcpy(ftype, temp);
  259.                 }
  260.             }
  261.             while (isspace(*cp)) cp++;
  262.             if (!*cp) {
  263.                 readline(buf, inf);
  264.                 cp = buf;
  265.             }
  266.             dprintf("cp before fname is %s\n", cp);     /***/
  267.             if (!isidchar(*cp))
  268.                 bounce("No function name");
  269.             cp2 = fname;
  270.             while (isidchar(*cp))
  271.                 *cp2++= *cp++;
  272.             *cp2 = 0;
  273.             dprintf("fname is %s\n", fname);     /***/
  274.             dprintf("cp after fname is %s\n", cp);     /***/
  275.             while (isspace(*cp)) cp++;
  276.             if (*cp++ != '(')
  277.                 bounce("No function '('");
  278.             nargs = 0;
  279.             if (!*cp) {
  280.                 readline(buf, inf);
  281.                 cp = buf;
  282.             }
  283.             while (isspace(*cp)) cp++;
  284.             while (*cp != ')') {
  285.                 if (!isidchar(*cp))
  286.                     bounce("Missing argument name");
  287.                 if (nargs >= MAXARGS)
  288.                     bounce("Too many arguments");
  289.                 cp2 = argnames[nargs];
  290.                 argdecls[nargs][0] = 0;
  291.                 nargs++;
  292.                 while (isidchar(*cp))
  293.                     *cp2++ = *cp++;
  294.                 *cp2 = 0;
  295.                 dprintf("Argument %d is named %s\n", nargs-1, argnames[nargs-1]);    /***/
  296.                 while (isspace(*cp)) cp++;
  297.                 if (*cp == ',') {
  298.                     cp++;
  299.                     if (!*cp) {
  300.                         readline(buf, inf);
  301.                         cp = buf;
  302.                     }
  303.                     while (isspace(*cp)) cp++;
  304.                 } else if (*cp != ')')
  305.                     bounce("Missing function ')'");
  306.             }
  307.             if (cp[1])
  308.                 bounce("Characters after function ')'");
  309.             readline(buf, inf);
  310.             cp = buf;
  311.             for (;;) {
  312.                 while (isspace(*cp)) cp++;
  313.                 if (isidchar(*cp)) {
  314.                     cp2 = dtype;
  315.                     if (strbeginsword(cp, "register")) {
  316.                         cp += 8;
  317.                         while (isspace(*cp)) cp++;
  318.                     }
  319.                     while (isspace(*cp) || isidchar(*cp))
  320.                         *cp2++ = *cp++;
  321.                     if (*cp == ',' || *cp == ';' || *cp == '[') {
  322.                         while (cp2 > dtype && isspace(cp2[-1])) cp--, cp2--;
  323.                         while (cp2 > dtype && isidchar(cp2[-1])) cp--, cp2--;
  324.                     } else if (*cp != '(' && *cp != '*')
  325.                         bounce("Strange character in arg decl");
  326.                     while (cp2 > dtype && isspace(cp2[-1])) cp2--;
  327.                     *cp2 = 0;
  328.                     if (!*dtype)
  329.                         bounce("Empty argument type");
  330.                     for (;;) {
  331.                         cp2 = decl;
  332.                         cp3 = dname;
  333.                         while (*cp == '*' || *cp == '(' || isspace(*cp))
  334.                             *cp2++ = *cp++;
  335.                         if (!isidchar(*cp))
  336.                             bounce("Missing arg decl name");
  337.                         while (isidchar(*cp)) {
  338.                             if (usenames)
  339.                                 *cp2++ = *cp;
  340.                             *cp3++ = *cp++;
  341.                         }
  342.                         if (!usenames) {
  343.                             while (cp2 > decl && isspace(cp2[-1])) cp2--;
  344.                             while (isspace(*cp)) cp++;
  345.                         }
  346.                         i = 0;
  347.                         while (*cp && *cp != ';' && (*cp != ',' || i > 0)) {
  348.                             if (*cp == '(' || *cp == '[') i++;
  349.                             if (*cp == ')' || *cp == ']') i--;
  350.                             *cp2++ = *cp++;
  351.                         }
  352.                         *cp2 = 0;
  353.                         *cp3 = 0;
  354.                         dprintf("Argument %s is %s\n", dname, decl);     /***/
  355.                         if (i > 0)
  356.                             bounce("Unbalanced parens in arg decl");
  357.                         if (!*cp)
  358.                             bounce("Missing ';' or ',' in arg decl");
  359.                         for (i = 0; i < nargs && strcmp(argnames[i], dname); i++) ;
  360.                         if (i >= nargs)
  361.                             bounce("Arg decl name not in argument list");
  362.                         if (*decl)
  363.                             sprintf(argdecls[i], "%s %s", dtype, decl);
  364.                         else
  365.                             strcpy(argdecls[i], dtype);
  366.                         if (*cp == ',') {
  367.                             cp++;
  368.                             if (!*cp) {
  369.                                 readline(buf, inf);
  370.                                 cp = buf;
  371.                             }
  372.                             while (isspace(*cp)) cp++;
  373.                         } else
  374.                             break;
  375.                     }
  376.                     cp++;
  377.                     if (!*cp) {
  378.                         readline(buf, inf);
  379.                         cp = buf;
  380.                     }
  381.                 } else
  382.                     break;
  383.             }
  384.             if (*cp != '{')
  385.                 bounce("Missing function '{'");
  386.             if (firstdecl) {
  387.                 firstdecl = 0;
  388.                 if (argc > 2)
  389.                     fprintf(outf, "\n/* Declarations from %s */\n", argv[whichf]);
  390.                 if (useifdefs && inf != stdin) {
  391.                     strcpy(ifdefname, argv[whichf]);
  392.             cp = ifdefname;
  393.             for (cp2 = ifdefname; *cp2; ) {
  394.             if (*cp2++ == '/')
  395.                 cp = cp2;
  396.             }
  397.                     for (cp2 = ifdefname; *cp; cp++, cp2++) {
  398.                 if (islower(*cp))
  399.                 *cp2 = toupper(*cp);
  400.                         else if (isalnum(*cp))
  401.                             *cp2 = *cp;
  402.                         else
  403.                             *cp2 = '_';
  404.                     }
  405.                     fprintf(outf, "#ifdef PROTO_%s\n", ifdefname);
  406.                 }
  407.             }
  408.             for (i = 0; i < nargs; i++) {
  409.                 if (!argdecls[i][0])
  410.                     sprintf(argdecls[i], "int %s", argnames[i]);
  411.                 for (j = 0; warntypes[j].bad &&
  412.                             !strbeginsword(argdecls[i], warntypes[j].bad); j++) ;
  413.                 if (warntypes[j].bad) {
  414.                     cp = argdecls[i];
  415.                     while (isspace(*cp) || isidchar(*cp)) cp++;
  416.                     if (!*cp) {     /* not, e.g., "char *" */
  417.                         sprintf(temp, "%s%s", warntypes[j].good,
  418.                                               argdecls[i] + strlen(warntypes[j].bad));
  419.                         strcpy(argdecls[i], temp);
  420.                         fprintf(stderr, "Warning: Argument %s of %s has type %s\n",
  421.                                         argnames[i], fname, warntypes[j]);
  422.                     }
  423.                 }
  424.             }
  425.             if (verbose && outf != stdout)
  426.                 printf("Found declaration for %s\n", fname);
  427.             fprintf(outf, "%s", ftype);
  428.             pos = strlen(ftype) + numstars;
  429.             do {
  430.                 putc(' ', outf);
  431.                 pos++;
  432.             } while (pos < typetab);
  433.             for (i = 1; i <= numstars; i++)
  434.                 putc('*', outf);
  435.             fprintf(outf, "%s", fname);
  436.             pos += strlen(fname);
  437.             do {
  438.                 putc(' ', outf);
  439.                 pos++;
  440.             } while (pos < argtab);
  441.             if (nargs == 0) {
  442.                 if (usemacros)
  443.                     fprintf(outf, "PV();");
  444.                 else
  445.                     fprintf(outf, "(void);");
  446.             } else {
  447.                 if (usemacros)
  448.                     fprintf(outf, "PP( ("), pos += 5;
  449.                 else
  450.                     fprintf(outf, "("), pos++;
  451.                 thistab = pos;
  452.                 for (i = 0; i < nargs; i++) {
  453.                     len = strlen(argdecls[i]);
  454.                     if (i > 0) {
  455.                         putc(',', outf);
  456.                         pos++;
  457.                         if (pos > thistab && pos + len >= width) {
  458.                             putc('\n', outf);
  459.                             for (j = 1; j <= thistab; j++)
  460.                                 putc(' ', outf);
  461.                             pos = thistab;
  462.                         } else {
  463.                             putc(' ', outf);
  464.                             pos++;
  465.                         }
  466.                     }
  467.                     fprintf(outf, "%s", argdecls[i]);
  468.                     pos += len;
  469.                 }
  470.                 if (usemacros)
  471.                     fprintf(outf, ") );");
  472.                 else
  473.                     fprintf(outf, ");");
  474.             }
  475.             putc('\n', outf);
  476. Lbounce: ;
  477.         }
  478.         if (inf != stdin) {
  479.             if (useifdefs && !firstdecl)
  480.                 fprintf(outf, "#endif /*PROTO_%s*/\n", ifdefname);
  481.             fclose(inf);
  482.         }
  483.     }
  484.     if (hasheader) {
  485.         fprintf(outf, "\n\n/* End. */\n\n");
  486.     }
  487.     if (outf != stdout)
  488.         fclose(outf);
  489.     if (errors)
  490.         exit(1);
  491.     else
  492.         exit(0);
  493. }
  494.  
  495.  
  496.  
  497. /* End. */
  498.  
  499.  
  500.  
  501.