home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume08 / mkproto < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  23.2 KB

  1. From decwrl!sun-barr!cs.utexas.edu!uunet!allbery Fri Sep  8 21:40:06 PDT 1989
  2. Article 1072 of comp.sources.misc:
  3. Path: decwrl!sun-barr!cs.utexas.edu!uunet!allbery
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Newsgroups: comp.sources.misc
  6. Subject: v08i030: mkproto -- make ANSI style prototypes
  7. Message-ID: <66800@uunet.UU.NET>
  8. Date: 7 Sep 89 02:05:45 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Reply-To: ersmith@uwovax.uwo.ca
  11. Lines: 930
  12. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  13.  
  14. Posting-number: Volume 8, Issue 30
  15. Submitted-by: ersmith@uwovax.uwo.ca
  16. Archive-name: mkproto
  17.  
  18. Here is mkproto, a program for generating prototype declarations for all
  19. functions appearing in a C source file. The input C code may be either
  20. K&R or ANSI C (i.e. it's OK if the functions are defined using prototypes).
  21. Unlike some of the sed-based scripts floating around, it correctly
  22. handles prototype promotion (e.g. the prototype for 'int foo() char x;...'
  23. is 'int foo(int x)'). Also, it should work OK on just about any computer,
  24. not just Unix-based ones (it's been tested under minix, Unix, and TOS).
  25.  
  26. Use: typically, you would type 'mkproto *.c >proto.h' and then add a
  27. '#include "proto.h"' line to all the C source files. An ANSI conformant
  28. compiler will then be able to do type checking on function calls across
  29. module boundaries. As a bonus, proto.h will tell you which source files
  30. functions were defined in, and (if you gave the -n function to mkproto)
  31. their line numbers. The resulting include file may also be used by
  32. non-ANSI compilers; you can disable this feature (for cleaner, strictly
  33. ANSI-conforming output) with the -p flag.
  34.  
  35. Please read the description of bugs in mkproto.man; definitely mkproto
  36. will not handle all programs correctly, but it does work on the majority of
  37. them. A sample of its output is provided in the file "mkproto.h"; this
  38. is the result of 'mkproto mkproto.c >mkproto.h'.
  39.  
  40. There is ABSOLUTELY NO WARRANTY for the program; as I said, it doesn't work
  41. on all programs (complicated function definitions can make it produce bogus
  42. output). It does what I need, though, and it can certainly make porting stuff
  43. to ANSI compilers easier.
  44.  
  45. Mkproto is in the public domain. If you find any bugs (other than the ones
  46. documented) please let me know.
  47. --
  48. Eric R. Smith                     email:
  49. Dept. of Mathematics            ersmith@uwovax.uwo.ca
  50. University of Western Ontario   ersmith@uwovax.bitnet
  51. London, Ont. Canada N6A 5B7
  52. ph: (519) 661-3638
  53.  
  54. #    This is a shell archive.
  55. #    Remove everything above and including the cut line.
  56. #    Then run the rest of the file through sh.
  57. #----cut here-----cut here-----cut here-----cut here----#
  58. #!/bin/sh
  59. # shar:    Shell Archiver
  60. #    Run the following text with /bin/sh to create:
  61. #    makefile.min
  62. #    makefile.tos
  63. #    makefile.unx
  64. #    mkproto.c
  65. #    mkproto.h
  66. #    mkproto.man
  67. #    README
  68. # This archive created: 05 September 1989 05:51:28 PM EDT
  69. # By:    eric (at home)
  70. echo shar: extracting makefile.min
  71. sed 's/^X//' << \SHAR_EOF > makefile.min
  72. XCC = mgcc
  73. XALL = mkproto
  74. X
  75. Xmkproto : mkproto.c mkproto.h
  76. X    $(CC) -O -o mkproto mkproto.c -mshort -s
  77. Xclean:
  78. X    rm -f *.o
  79. X
  80. Xrealclean: clean
  81. X    rm -f $(ALL) report core
  82. SHAR_EOF
  83. if test 159 -ne "`wc -c makefile.min`"
  84. then
  85. echo shar: error transmitting makefile.min '(should have been 159 characters)'
  86. fi
  87. echo shar: extracting makefile.tos
  88. sed 's/^X//' << \SHAR_EOF > makefile.tos
  89. XCC = gcc
  90. XALL = mkproto.ttp
  91. X
  92. Xmkproto.ttp : mkproto.c mkproto.h
  93. X    $(CC) -O -o mkproto.ttp mkproto.c -mshort -s
  94. Xclean:
  95. X    rm -f *.o
  96. X
  97. Xrealclean: clean
  98. X    rm -f $(ALL) report core
  99. SHAR_EOF
  100. if test 170 -ne "`wc -c makefile.tos`"
  101. then
  102. echo shar: error transmitting makefile.tos '(should have been 170 characters)'
  103. fi
  104. echo shar: extracting makefile.unx
  105. sed 's/^X//' << \SHAR_EOF > makefile.unx
  106. XCC = cc
  107. XALL =  mkproto
  108. X
  109. Xmkproto : mkproto.c mkproto.h
  110. X    $(CC) -O -o mkproto mkproto.c
  111. Xclean:
  112. X    rm -f *.o
  113. X
  114. Xrealclean: clean
  115. X    rm -f $(ALL) report core
  116. SHAR_EOF
  117. if test 147 -ne "`wc -c makefile.unx`"
  118. then
  119. echo shar: error transmitting makefile.unx '(should have been 147 characters)'
  120. fi
  121. echo shar: extracting mkproto.c
  122. sed 's/^X//' << \SHAR_EOF > mkproto.c
  123. X/* Program to extract function declarations from C source code */
  124. X/* Written by Eric R. Smith and placed in the public domain    */
  125. X/* Thanks are due to Jwahar R. Bammi for fixing several bugs   */
  126. X/* and providing the Unix makefiles.                           */
  127. X
  128. X#if defined(__STDC__) && !defined(minix)
  129. X#include <stddef.h>
  130. X#include <stdlib.h>
  131. X#else
  132. X#define EXIT_SUCCESS  0
  133. X#define EXIT_FAILURE  1
  134. Xextern char *malloc();
  135. X#endif
  136. X
  137. X#include <stdio.h>
  138. X#include <ctype.h>
  139. X#include <string.h>
  140. X
  141. X/*#define DEBUG(s) (fputs(s, stderr)) /* */
  142. X#define DEBUG(s) /* */
  143. X
  144. X#define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
  145. X#define ABORTED ( (Word *) -1 )
  146. X#define MAXPARAM 20         /* max. number of parameters to a function */
  147. X#define NEWBUFSIZ (20480*sizeof(char)) /* new buffer size */
  148. X
  149. Xint inquote = 0;        /* in a quote?? */
  150. Xint newline_seen = 1;        /* are we at the start of a line */
  151. Xlong linenum  = 1L;        /* line number in current file */
  152. Xint dostatic = 0;        /* do static functions? */
  153. Xint donum    = 0;        /* print line numbers? */
  154. Xint dohead   = 1;        /* do file headers? */
  155. Xint docond   = 1;        /* conditionalize for non-ANSI compilers? */
  156. Xint glastc   = ' ';        /* last char. seen by getsym() */
  157. X
  158. Xtypedef struct word {
  159. X    struct word *next;
  160. X    char   string[1];
  161. X} Word;
  162. X
  163. X#include "mkproto.h"
  164. X
  165. X/*
  166. X * Routines for manipulating lists of words.
  167. X */
  168. X
  169. XWord *word_alloc(s)
  170. X    char *s;
  171. X{
  172. X    Word *w;
  173. X
  174. X    w = (Word *) malloc(sizeof(Word) + strlen(s) + 1); /* ++jrb */
  175. X    strcpy(w->string, s);
  176. X    w->next = NULL;
  177. X    return w;
  178. X}
  179. X
  180. Xvoid word_free(w)
  181. X    Word *w;
  182. X{
  183. X    Word *oldw;
  184. X    while (w) {
  185. X        oldw = w;
  186. X        w = w->next;
  187. X        free(oldw);
  188. X    }
  189. X}
  190. X
  191. X/* return the length of a list; empty words are not counted */
  192. Xint
  193. XList_len(w)
  194. X    Word *w;
  195. X{
  196. X    int count = 0;
  197. X
  198. X    while (w) {
  199. X        if (*w->string) count++;
  200. X        w = w->next;
  201. X    }
  202. X    return count;
  203. X}
  204. X
  205. X/* Append two lists, and return the result */
  206. X
  207. XWord *word_append(w1, w2)
  208. X    Word *w1, *w2;
  209. X{
  210. X    Word *r, *w;
  211. X
  212. X    r = w = word_alloc("");
  213. X
  214. X    while (w1) {
  215. X        w->next = word_alloc(w1->string);
  216. X        w = w->next;
  217. X        w1 = w1->next;
  218. X    }
  219. X    while (w2) {
  220. X        w->next = word_alloc(w2->string);
  221. X        w = w->next;
  222. X        w2 = w2->next;
  223. X    }
  224. X
  225. X    return r;
  226. X}
  227. X    
  228. X/* see if the last entry in w2 is in w1 */
  229. X
  230. Xint
  231. Xfoundin(w1, w2)
  232. X    Word *w1, *w2;
  233. X{
  234. X    while (w2->next)
  235. X        w2 = w2->next;
  236. X
  237. X    while (w1) {
  238. X        if (!strcmp(w1->string, w2->string))
  239. X            return 1;
  240. X        w1 = w1->next;
  241. X    }
  242. X    return 0;
  243. X}
  244. X
  245. X/* add the string s to the given list of words */
  246. X
  247. Xvoid addword(w, s)
  248. X    Word *w; char *s;
  249. X{
  250. X    while (w->next) w = w->next;
  251. X    w->next = word_alloc(s);
  252. X}
  253. X
  254. X/* given a list representing a type and a variable name, extract just
  255. X * the base type, e.g. "struct word *x" would yield "struct word"
  256. X */
  257. X
  258. XWord *typelist(p)
  259. X    Word *p;
  260. X{
  261. X    Word *w, *r;
  262. X
  263. X    r = w = word_alloc("");
  264. X    while (p && p->next) {
  265. X        if (p->string[0] && !ISCSYM(p->string[0]))
  266. X            break;
  267. X        w->next = word_alloc(p->string);
  268. X        w = w->next;
  269. X        p = p->next;
  270. X    }
  271. X    return r;
  272. X}
  273. X
  274. X/* typefixhack: promote formal parameters of type "char", "unsigned char",
  275. X   "short", or "unsigned short" to "int".
  276. X*/
  277. X
  278. Xvoid typefixhack(w)
  279. X    Word *w;
  280. X{
  281. X    Word *oldw = 0;
  282. X
  283. X    while (w) {
  284. X        if (*w->string) {
  285. X            if ( (!strcmp(w->string, "char") ||
  286. X                  !strcmp(w->string, "short") )
  287. X                && (List_len(w->next) < 2) )
  288. X            {
  289. X                if (oldw && !strcmp(oldw->string, "unsigned")) {
  290. X                    oldw->next = w->next;
  291. X                    free(w);
  292. X                    w = oldw;
  293. X                }
  294. X                strcpy(w->string, "int");
  295. X            }
  296. X        }
  297. X        w = w->next;
  298. X    }
  299. X}
  300. X
  301. X/* read a character: if it's a newline, increment the line count */
  302. X
  303. X#ifdef __GNUC__    /* ++jrb */
  304. Xinline
  305. X#endif
  306. Xint ngetc(f)
  307. X    FILE *f;
  308. X{
  309. X    int c;
  310. X
  311. X    c = getc(f);
  312. X    if (c == '\n') linenum++;
  313. X
  314. X    return c;
  315. X}
  316. X
  317. X/* read the next character from the file. If the character is '\' then
  318. X * read and skip the next character. Any comment sequence is converted
  319. X * to a blank.
  320. X */
  321. X
  322. Xint fnextch(f)
  323. X    FILE *f;
  324. X{
  325. X    int c, lastc, incomment;
  326. X
  327. X    c = ngetc(f);
  328. X    while (c == '\\') {
  329. XDEBUG("fnextch: in backslash loop\n");
  330. X        c = ngetc(f);    /* skip a character */
  331. X        c = ngetc(f);
  332. X    }
  333. X    if (c == '/' && !inquote) {
  334. X        c = ngetc(f);
  335. X        if (c == '*') {
  336. X            incomment = 1;
  337. X            c = ' ';
  338. XDEBUG("fnextch: comment seen\n");
  339. X            while (incomment) {
  340. X                lastc = c;
  341. X                c = ngetc(f);
  342. X                if (lastc == '*' && c == '/')
  343. X                    incomment = 0;
  344. X                else if (c < 0)
  345. X                    return c;
  346. X            }
  347. X            return fnextch(f);
  348. X        }
  349. X        else {
  350. X            if (c == '\n') linenum--;
  351. X            ungetc(c, f);
  352. X            return '/';
  353. X        }
  354. X    }
  355. X    return c;
  356. X}
  357. X
  358. X
  359. X/* Get the next "interesting" character. Comments are skipped, and strings
  360. X * are converted to "0". Also, if a line starts with "#" it is skipped.
  361. X */
  362. X
  363. Xint nextch(f)
  364. X    FILE *f;
  365. X{
  366. X    int c;
  367. X
  368. X    c = fnextch(f);
  369. X    if (newline_seen && c == '#') {
  370. X        do {
  371. X            c = fnextch(f);
  372. X        } while (c >= 0 && c != '\n');
  373. X        if (c < 0)
  374. X            return c;
  375. X    }
  376. X    newline_seen = (c == '\n');
  377. X
  378. X    if (c == '\'' || c == '\"') {
  379. XDEBUG("nextch: in a quote\n");
  380. X        inquote = c;
  381. X        while ( (c = fnextch(f)) >= 0 ) {
  382. X            if (c == inquote) {
  383. X                inquote = 0;
  384. XDEBUG("nextch: out of quote\n");
  385. X                return '0';
  386. X            }
  387. X        }
  388. XDEBUG("nextch: EOF in a quote\n");
  389. X    }
  390. X    return c;
  391. X}
  392. X
  393. X/*
  394. X * Get the next symbol from the file, skipping blanks.
  395. X * Return 0 if OK, -1 for EOF.
  396. X * Also collapses everything between { and }
  397. X */
  398. X
  399. Xint
  400. Xgetsym(buf, f)
  401. X    char *buf; FILE *f;
  402. X{
  403. X    register int c;
  404. X    int inbrack = 0;
  405. X
  406. XDEBUG("in getsym\n");
  407. X    c = glastc;
  408. X    while ((c > 0) && isspace(c)) {
  409. X        c = nextch(f);
  410. X    }
  411. XDEBUG("getsym: spaces skipped\n");
  412. X    if (c < 0) {
  413. XDEBUG("EOF read in getsym\n");
  414. X        return -1;
  415. X    }
  416. X    if (c == '{') {
  417. X        inbrack = 1;
  418. XDEBUG("getsym: in bracket\n");
  419. X        while (inbrack) {
  420. X            c = nextch(f);
  421. X            if (c < 0) {
  422. XDEBUG("getsym: EOF seen in bracket loop\n");
  423. X                glastc = c;
  424. X                return c;
  425. X            }
  426. X            if (c == '{') inbrack++;
  427. X            else if (c == '}') inbrack--;
  428. X        }
  429. X        strcpy(buf, "{}");
  430. X        glastc = nextch(f);
  431. XDEBUG("getsym: out of in bracket loop\n");
  432. X        return 0;
  433. X    }
  434. X    if (!ISCSYM(c)) {
  435. X        *buf++ = c;
  436. X        *buf = 0;
  437. X        glastc = nextch(f);
  438. XDEBUG("getsym: returning special symbol\n");
  439. X        return 0;
  440. X    }
  441. X    while (ISCSYM(c)) {
  442. X        *buf++ = c;
  443. X        c = nextch(f);
  444. X    }
  445. X    *buf = 0;
  446. X    glastc = c;
  447. XDEBUG("getsym: returning word\n");
  448. X    return 0;
  449. X}
  450. X
  451. X/*
  452. X * skipit: skip until a ";" or the end of a function declaration is seen
  453. X */
  454. Xint skipit(buf, f)
  455. X    char *buf;
  456. X    FILE *f;
  457. X{
  458. X    int i;
  459. X
  460. X    do {
  461. XDEBUG("in skipit loop\n");
  462. X        i = getsym(buf, f);
  463. X        if (i < 0) return i;
  464. X    } while (*buf != ';' && *buf != '{');
  465. X
  466. X    return 0;
  467. X}
  468. X
  469. X/*
  470. X * Get a parameter list; when this is called the next symbol in line
  471. X * should be the first thing in the list.
  472. X */
  473. X
  474. XWord *getparamlist(f)
  475. X    FILE *f;
  476. X{
  477. X    static Word *pname[MAXPARAM]; /* parameter names */
  478. X    Word    *tlist,        /* type name */
  479. X        *plist;        /* temporary */
  480. X    int      np = 0;        /* number of parameters */
  481. X    int      typed[MAXPARAM];  /* parameter has been given a type */
  482. X    int    tlistdone;    /* finished finding the type name */
  483. X    int    sawsomething;
  484. X    int      i;
  485. X    int    inparen = 0;
  486. X    char buf[80];
  487. X
  488. XDEBUG("in getparamlist\n");
  489. X    for (i = 0; i < MAXPARAM; i++)
  490. X        typed[i] = 0;
  491. X
  492. X    plist = word_alloc("");
  493. X
  494. X/* first, get the stuff inside brackets (if anything) */
  495. X
  496. X    sawsomething = 0;    /* gets set nonzero when we see an arg */
  497. X    for (;;) {
  498. X        if (getsym(buf, f) < 0) return NULL;
  499. X        if (*buf == ')' && (--inparen < 0)) {
  500. X            if (sawsomething) {    /* if we've seen an arg */
  501. X                pname[np] = plist;
  502. X                plist = word_alloc("");
  503. X                np++;
  504. X            }
  505. X            break;
  506. X        }
  507. X        if (*buf == ';') {    /* something weird */
  508. X            return ABORTED;
  509. X        }
  510. X        sawsomething = 1;    /* there's something in the arg. list */
  511. X        if (*buf == ',' && inparen == 0) {
  512. X            pname[np] = plist;
  513. X            plist = word_alloc("");
  514. X            np++;
  515. X        }
  516. X        else {
  517. X            addword(plist, buf);
  518. X            if (*buf == '(') inparen++;
  519. X        }
  520. X    }
  521. X
  522. X/* next, get the declarations after the function header */
  523. X
  524. X    inparen = 0;
  525. X
  526. X    tlist = word_alloc("");
  527. X    plist = word_alloc("");
  528. X    tlistdone = 0;
  529. X    sawsomething = 0;
  530. X    for(;;) {
  531. X        if (getsym(buf, f) < 0) return NULL;
  532. X
  533. X/* handle a list like "int x,y,z" */
  534. X        if (*buf == ',' && !inparen) {
  535. X            if (!sawsomething)
  536. X                return NULL;
  537. X            for (i = 0; i < np; i++) {
  538. X                if (!typed[i] && foundin(plist, pname[i])) {
  539. X                    typed[i] = 1;
  540. X                    word_free(pname[i]);
  541. X                    pname[i] = word_append(tlist, plist);
  542. X                /* promote types */
  543. X                    typefixhack(pname[i]);
  544. X                    break;
  545. X                }
  546. X            }
  547. X            if (!tlistdone) {
  548. X                tlist = typelist(plist);
  549. X                tlistdone = 1;
  550. X            }
  551. X            word_free(plist);
  552. X            plist = word_alloc("");
  553. X        }
  554. X/* handle the end of a list */
  555. X        else if (*buf == ';') {
  556. X            if (!sawsomething)
  557. X                return ABORTED;
  558. X            for (i = 0; i < np; i++) {
  559. X                if (!typed[i] && foundin(plist, pname[i])) {
  560. X                    typed[i] = 1;
  561. X                    word_free(pname[i]);
  562. X                    pname[i] = word_append(tlist, plist);
  563. X                    typefixhack(pname[i]);
  564. X                    break;
  565. X                }
  566. X            }
  567. X            tlistdone = 0;
  568. X            word_free(tlist); word_free(plist);
  569. X            tlist = word_alloc("");
  570. X            plist = word_alloc("");
  571. X        }
  572. X/* handle the  beginning of the function */
  573. X        else if (!strcmp(buf, "{}")) break;
  574. X/* otherwise, throw the word into the list (except for "register") */
  575. X        else if (strcmp(buf, "register")) {
  576. X            sawsomething = 1;
  577. X            addword(plist, buf);
  578. X            if (*buf == '(') inparen++;
  579. X            if (*buf == ')') inparen--;
  580. X        }
  581. X    }
  582. X
  583. X/* Now take the info we have and build a prototype list */
  584. X
  585. X/* empty parameter list means "void" */
  586. X    if (np == 0)
  587. X        return word_alloc("void");
  588. X
  589. X    plist = tlist = word_alloc("");
  590. X    for (i = 0; i < np; i++) {
  591. X
  592. X/* If no type provided, make it an "int" */
  593. X        if ( !(pname[i]->next) ||
  594. X       (!(pname[i]->next->next)&&strcmp(pname[i]->next->string, "void"))) {
  595. X            addword(tlist, "int");
  596. X        }
  597. X        while (tlist->next) tlist = tlist->next;
  598. X        tlist->next = pname[i];
  599. X        if (i < np - 1)
  600. X            addword(tlist, ", ");
  601. X    }
  602. X    return plist;
  603. X}
  604. X
  605. X/*
  606. X * emit a function declaration. The attributes and name of the function
  607. X * are in wlist; the parameters are in plist.
  608. X */
  609. Xvoid emit(wlist, plist, startline)
  610. X    Word *wlist, *plist;
  611. X    long  startline;
  612. X{
  613. X    Word *w;
  614. X    int count = 0;
  615. X
  616. XDEBUG("emit called\n");
  617. X    if (donum)
  618. X        printf("/*%8ld */ ", startline);
  619. X
  620. X    for (w = wlist; w; w = w->next) {
  621. X        if (w->string[0])
  622. X            count ++;
  623. X    }
  624. X
  625. X    if (count < 2)
  626. X        printf("int ");
  627. X
  628. X    for (w = wlist; w; w = w->next) {
  629. X        printf("%s", w->string);
  630. X        if (ISCSYM(w->string[0]))
  631. X            printf(" ");
  632. X    }
  633. X    if (docond)
  634. X        printf("P((");
  635. X    else
  636. X        printf("( ");
  637. X    for (w = plist; w; w = w->next) {
  638. X        printf("%s", w->string);
  639. X        if (ISCSYM(w->string[0]))
  640. X            printf(" ");
  641. X    }
  642. X    if (docond)
  643. X        printf("));\n");
  644. X    else
  645. X        printf(");\n");
  646. X}
  647. X
  648. X/*
  649. X * get all the function declarations
  650. X */
  651. X
  652. Xvoid getdecl(f)
  653. X    FILE *f;
  654. X{
  655. X    Word *plist, *wlist = NULL;
  656. X    char buf[80];
  657. X    int sawsomething;
  658. X    long startline;        /* line where declaration started */
  659. X    int oktoprint;
  660. Xagain:
  661. X    word_free(wlist);
  662. X    wlist = word_alloc("");
  663. X    sawsomething = 0;
  664. X    oktoprint = 1;
  665. X
  666. X    for(;;) {
  667. XDEBUG("main getdecl loop\n");
  668. X        if (getsym(buf,f) < 0) {
  669. XDEBUG("EOF in getdecl loop\n");
  670. X             return;
  671. X        }
  672. X/* try to guess when a declaration is not an external function definition */
  673. X        if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
  674. X            !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
  675. X            !strcmp(buf, "extern")) {
  676. X            skipit(buf, f);
  677. X            goto again;
  678. X        }
  679. X        if (!dostatic && !strcmp(buf, "static")) {
  680. X            oktoprint = 0;
  681. X        }
  682. X/* for the benefit of compilers that allow "inline" declarations */
  683. X        if (!strcmp(buf, "inline") && !sawsomething)
  684. X            continue;
  685. X        if (!strcmp(buf, ";")) goto again;
  686. X
  687. X/* A left parenthesis *might* indicate a function definition */
  688. X        if (!strcmp(buf, "(")) {
  689. X            startline = linenum;
  690. X            if (!sawsomething || !(plist = getparamlist(f))) {
  691. X                skipit(buf, f);
  692. X                goto again;
  693. X            }
  694. X            if (plist == ABORTED)
  695. X                goto again;
  696. X
  697. X/* It seems to have been what we wanted */
  698. X            if (oktoprint)
  699. X                emit(wlist, plist, startline);
  700. X            word_free(plist);
  701. X            goto again;
  702. X        }
  703. X        addword(wlist, buf);
  704. X        sawsomething = 1;
  705. X    }
  706. X}
  707. X
  708. Xvoid
  709. Xmain(argc, argv)
  710. Xint argc; char **argv;
  711. X{
  712. X    FILE *f;
  713. X    char *t, *iobuf;
  714. X    extern void Usage();
  715. X
  716. X    argv++; argc--;
  717. X
  718. X    iobuf = malloc(NEWBUFSIZ);
  719. X    while (*argv && **argv == '-') {
  720. X        t = *argv++; --argc; t++;
  721. X        while (*t) {
  722. X            if (*t == 's')
  723. X                dostatic = 1;
  724. X            else if (*t == 'n')
  725. X                donum = 1;
  726. X            else if (*t == 'p')
  727. X                docond = 0;
  728. X            else
  729. X                Usage();
  730. X            t++;
  731. X        }
  732. X    }
  733. X
  734. X    if (docond) {
  735. X        printf("#ifdef __STDC__\n");
  736. X        printf("# define\tP(s) s\n");
  737. X        printf("#else\n");
  738. X        printf("# define P(s) ()\n");
  739. X        printf("#endif\n\n");
  740. X    }
  741. X    if (argc == 0)
  742. X        getdecl(stdin);
  743. X    else
  744. X        while (argc > 0 && *argv) {
  745. XDEBUG("trying a new file\n");
  746. X            if (!(f = fopen(*argv, "r"))) {
  747. X                perror(*argv);
  748. X                exit(EXIT_FAILURE);
  749. X            }
  750. X            if (iobuf)
  751. X                setvbuf(f, iobuf, _IOFBF, NEWBUFSIZ);
  752. X            if (dohead)
  753. X                printf("\n/* %s */\n", *argv);
  754. X            linenum = 1;
  755. X            newline_seen = 1;
  756. X            glastc = ' ';
  757. XDEBUG("calling getdecl\n");
  758. X            getdecl(f);
  759. XDEBUG("back from getdecl\n");
  760. X            argc--; argv++;
  761. X            fclose(f);
  762. XDEBUG("back from fclose\n");
  763. X        }
  764. X    if (docond) {
  765. X        printf("\n#undef P\n");    /* clean up namespace */
  766. X    }
  767. X    exit(EXIT_SUCCESS);
  768. X}
  769. X
  770. X
  771. Xvoid Usage()
  772. X{
  773. X    fputs("Usage: mkproto [-n][-s][-p][files ...]\n",stderr);
  774. X    fputs("   -n: put line numbers of declarations as comments\n",stderr);
  775. X    fputs("   -s: include declarations for static functions\n", stderr);
  776. X    fputs("   -p: don't make header files readable by non-ANSI compilers\n",
  777. X          stderr);
  778. X    exit(EXIT_FAILURE);
  779. X}
  780. SHAR_EOF
  781. if test 12844 -ne "`wc -c mkproto.c`"
  782. then
  783. echo shar: error transmitting mkproto.c '(should have been 12844 characters)'
  784. fi
  785. echo shar: extracting mkproto.h
  786. sed 's/^X//' << \SHAR_EOF > mkproto.h
  787. X#ifdef __STDC__
  788. X# define    P(s) s
  789. X#else
  790. X# define P(s) ()
  791. X#endif
  792. X
  793. X
  794. X/* mkproto.c */
  795. XWord *word_alloc P((char *s ));
  796. Xvoid word_free P((Word *w ));
  797. Xint List_len P((Word *w ));
  798. XWord *word_append P((Word *w1 , Word *w2 ));
  799. Xint foundin P((Word *w1 , Word *w2 ));
  800. Xvoid addword P((Word *w , char *s ));
  801. XWord *typelist P((Word *p ));
  802. Xvoid typefixhack P((Word *w ));
  803. Xint ngetc P((FILE *f ));
  804. Xint fnextch P((FILE *f ));
  805. Xint nextch P((FILE *f ));
  806. Xint getsym P((char *buf , FILE *f ));
  807. Xint skipit P((char *buf , FILE *f ));
  808. XWord *getparamlist P((FILE *f ));
  809. Xvoid emit P((Word *wlist , Word *plist , long startline ));
  810. Xvoid getdecl P((FILE *f ));
  811. Xvoid main P((int argc , char **argv ));
  812. Xvoid Usage P((void ));
  813. X
  814. X#undef P
  815. SHAR_EOF
  816. if test 703 -ne "`wc -c mkproto.h`"
  817. then
  818. echo shar: error transmitting mkproto.h '(should have been 703 characters)'
  819. fi
  820. echo shar: extracting mkproto.man
  821. sed 's/^X//' << \SHAR_EOF > mkproto.man
  822. XNAME
  823. X   mkproto - make prototypes for functions
  824. X
  825. X
  826. XSYNOPSIS
  827. X   mkproto [-n] [-s] [-p] [ file ] ...
  828. X
  829. X
  830. XDESCRIPTION
  831. X   Mkproto takes as input one or more C source code files, and
  832. Xproduces as output (on the standard output stream) a list of function
  833. Xprototypes (a la ANSI) for the external functions defined in the
  834. Xgiven source files. This output, redirected to a file, is suitable
  835. Xfor #include'ing in a C source file.
  836. X   The function definitions in the original source
  837. Xmay be either "old-style" (in which case appropriate prototypes are
  838. Xgenerated for the functions) or "new-style" (in which the definition
  839. Xincludes a prototype already).
  840. X   A -n option causes the line number where each function was defined
  841. Xto be prepended to the prototype declaration as a comment.
  842. X   A -s option causes prototypes to be generated for functions declard
  843. X"static" as well as extern functions.
  844. X   A -p option causes the prototypes emitted to be only readable by ANSI
  845. Xcompilers. Normally, the prototypes are "macro-ized" so that compilers
  846. Xwith __STDC__ not defined don't see them. 
  847. X   If files are specified on the command line, then a comment specifying
  848. Xthe file of origin is emitted before the prototypes constructed from
  849. Xthat file. If no files are given, then no comments are emitted and
  850. Xthe C source code is taken from the standard input stream.
  851. X
  852. XBUGS
  853. X   Mkproto is easily confused by complicated declarations, such as
  854. X         int ((*signal)())() { ...
  855. Xor
  856. X         struct foo { int x, y; } foofunc() { ...
  857. X
  858. X   Float types are not properly promoted in old style definitions,
  859. Xi.e.
  860. X         int test(f) float f; { ...
  861. Xshould (because of the default type conversion rules) have prototype
  862. X         int test(double f);
  863. Xrather than the incorrect
  864. X         int test(float f);
  865. Xgenerated by mkproto.
  866. X
  867. X   Some programs may need to be run through the preprocessor before
  868. Xbeing run through mkproto. The -n option is unlikely to work as desired
  869. Xon the output of a preprocessor.
  870. X
  871. X   Typedef'd types aren't correctly promoted, e.g. for
  872. X        typedef schar char; int foo(x) schar x;...
  873. Xmkproto incorrectly generates the prototype int foo(schar x) rather than
  874. Xthe (correct) int foo(int x).
  875. X
  876. X   Functions named "inline" with no explicit type qualifiers are not
  877. Xrecognized.
  878. X
  879. XSEE ALSO
  880. X   cc(1), lint(1)
  881. X
  882. XAUTHOR
  883. X   Eric R. Smith.
  884. X
  885. XNOTE
  886. X   There is no warranty for this program (as noted above, it's guaranteed
  887. Xto break sometimes anyways!). Mkproto is in the public domain.
  888. SHAR_EOF
  889. if test 2433 -ne "`wc -c mkproto.man`"
  890. then
  891. echo shar: error transmitting mkproto.man '(should have been 2433 characters)'
  892. fi
  893. echo shar: extracting README
  894. sed 's/^X//' << \SHAR_EOF > README
  895. XHere is mkproto, a program for generating prototype declarations for all
  896. Xfunctions appearing in a C source file. The input C code may be either
  897. XK&R or ANSI C (i.e. it's OK if the functions are defined using prototypes).
  898. XUnlike some of the sed-based scripts floating around, it correctly
  899. Xhandles prototype promotion (e.g. the prototype for 'int foo() char x;...'
  900. Xis 'int foo(int x)'). Also, it should work OK on just about any computer,
  901. Xnot just Unix-based ones (it's been tested under minix, Unix, and TOS).
  902. X
  903. XUse: typically, you would type 'mkproto *.c >proto.h' and then add a
  904. X'#include "proto.h"' line to all the C source files. An ANSI conformant
  905. Xcompiler will then be able to do type checking on function calls across
  906. Xmodule boundaries. As a bonus, proto.h will tell you which source files
  907. Xfunctions were defined in, and (if you gave the -n function to mkproto)
  908. Xtheir line numbers. The resulting include file may also be used by
  909. Xnon-ANSI compilers; you can disable this feature (for cleaner, strictly
  910. XANSI-conforming output) with the -p flag.
  911. X
  912. XPlease read the description of bugs in mkproto.man; definitely mkproto
  913. Xwill not handle all programs correctly, but it does work on the majority of
  914. Xthem. A sample of its output is provided in the file "mkproto.h"; this
  915. Xis the result of 'mkproto mkproto.c >mkproto.h'.
  916. X
  917. XThere is ABSOLUTELY NO WARRANTY for the program; as I said, it doesn't work
  918. Xon all programs (complicated function definitions can make it produce bogus
  919. Xoutput). It does what I need, though, and it can certainly make porting stuff
  920. Xto ANSI compilers easier.
  921. X
  922. XMkproto is in the public domain. If you find any bugs (other than the ones
  923. Xdocumented) please let me know.
  924. X--
  925. XEric R. Smith                     email:
  926. XDept. of Mathematics            ersmith@uwovax.uwo.ca
  927. XUniversity of Western Ontario   ersmith@uwovax.bitnet
  928. XLondon, Ont. Canada N6A 5B7
  929. Xph: (519) 661-3638
  930. SHAR_EOF
  931. if test 1879 -ne "`wc -c README`"
  932. then
  933. echo shar: error transmitting README '(should have been 1879 characters)'
  934. fi
  935. #    End of shell archive
  936. exit 0
  937. -- 
  938. --
  939. Eric R. Smith                     email:
  940. Dept. of Mathematics            ERSMITH@uwovax.uwo.ca
  941. University of Western Ontario   ERSMITH@uwovax.bitnet
  942. London, Ont. Canada N6A 5B7
  943. ph: (519) 661-3638
  944.  
  945.  
  946.