Suggestion for function prototypes in CWEB


From:     Phil Jensen
Date: 21 Apr 1994
Hello literate programmers, or more specifically CWEB users: I have implemented a small enhancement to CWEB on which I solicit comments. The necessity to predeclare functions is one of the misfeatures of C (compared to a `real' language like, say, Modula-3 ... but that's another subject). The inevitable sections that run:
    @ @<Predecl...@>=
    void silly_function(void);  /* Hey compiler!  Not an |int| function! */
are simply an annoyance. Therefore, what do y'all think about the following lightweight scheme to handle this. (BTW, you must be using ANSI C, i.e., with prototypes, for this...) Precede all function declarations with an extra control code `@~', thus:
    @~double sqrt(double N)
    {
      ... and so on
At one place in the w file, use the control code `@n'; usually right after @<Global variables@>.

The function headers are collected and duplicated at the point where the @n occurs (and ctangle could be made to say <Function prototypes> just the way it now says <Preprocessor definitions>). The @~ construct does not need a closing delimiter, because the function header ends with the first un-nested right parenthesis. At the point where the prototypes are emitted, of course, each header is followed by <semicolon><newline>. [ I know that one might come up with pathological return types that use parentheses; but it seems to me that the simplicity of this scheme is preferable: you can always use typedefs to avoid this pitfall. ] If anyone wants to play around with this in practice, I can send the .ch file.


From:     Preston Briggs
Date: 22 Apr 1994
The necessity to predeclare functions is one of the misfeatures of C (compared to a `real' language like, say, Modula-3 ... but that's another subject). The inevitable sections that run:
    @ @<Predecl...@>=
    void silly_function(void);  /* Hey compiler!  Not an |int| function! */
are simply an annoyance. Therefore, what do y'all think about the following lightweight scheme to handle this. (BTW, you must be using ANSI C, i.e., with prototypes, for this...) Precede all function declarations with an extra control code `@~', thus:
    @~double sqrt(double N)
    {
      ... and so on
At one place in the w file, use the control code `@n'; usually right after @<Global variables@>.

The way I usually handle these things is to collect all the prototypes in an appendix at the end of the document. This gives me a place to describe, cleanly, the interface for each routine, with types and means of each parameters. Inside the appendix, the prototypes for related groups of rotuines can be grouped together into subsections (sort of like the methods of a class). Overall, the hope is that it'll turn out something like another index that the reader or maintainer can refer to for quick answers. Of course, if your particular language doesn't require prototypes (or other interface specifications), you might still do this, as a matter of style.


From:     Stuart Ferguson
Date: 25 Apr 1994
The necessity to predeclare functions is one of the misfeatures of C (compared to a `real' language like, say, Modula-3 ... but that's another subject). The inevitable sections that run:
    @ @<Predecl...@>=
    void silly_function(void);  /* Hey compiler!  Not an |int| function! */
are simply an annoyance. Therefore, what do y'all think about the following [reasonable suggestion deleted]

I too have found this a problem, and since I use a language-independent web, I can't use your extension. There is a problem with this extension as well in that some functions might be global and need to be in the external header file and some might be private, whereas your scheme only provides a single blob of prototypes.

I have developed a style to deal with this problem. For the types of code I am writing, which is mostly libraries of tools, I break my document into two parts. The first part is an interface description which includes types and function declarations that the user of the library will need, and the second part is the implementation which contains the actual code. I can usually just deliver the first part to my users and it acts as a reference. In the first part I define things of the type:

<< ExternalEntryPoint usage >> =
void
ExternalEntryPoint (
    int arg1,
    Thingee arg2)
@
I embed a bunch of these in appropriate text along with some << Public Type >> declarations and I have the user guide and an interface description from which to derive the implementational code. In the second part, the "usage" tags occur in two places:
<< Public Functions >> =
    << ExternalEntryPoint usage >>
    {
        << implementation code body >>
    }
@

And:

<< Public Prototypes >> =
    extern << ExternalEntryPoint usage >>;
@
I dislike having to write the prototype statement for each entry point, but once I do it the type for the function is written in one place and can easily be changed.

For private functions which are present in a single module and not used outside, I try to organize them into an appropriate order in the source file so that they are defined before they are used. Three classes are usually enough. "Public Functions" (as shown above) come last since they all have prototypes. "Private Functions" come before them since they will be used by the public functions, and "Private Utilities" comes first. Public functions can use all types of functions; private functions can use public functions and private utilities; private utilities cannot use either of the other function types. With the exception of loops, this almost always gives me enough distinctions to have all functions defined before they are used. For loops -- A uses B and B uses A -- I code the prototypes manually.