[comp.lang.c] HELP NEEDED in Project to Make Yacc Identifiers Static

bobg+@andrew.cmu.edu (Robert Steven Glickstein) (07/05/89)

You may recall that, a while ago, I asked the net about the demand that
would exist for a C-program filter which could take the output of Yacc
or Lex and make all global "yy" variables and functions "static".  There
was a large demand, and I have now written such a program.  This program
does not presently work, and its failure has to do with a deficiency in
the C language.  Perhaps one of you bright C wizards out there can
help...?

The original objective for "yyhide":
	Change the storage class of all defined identifiers in C source whose
names begin with "yy" or "YY" to static.  So for example,

    int yyfoo, *yybar;

becomes

    static int yyfoo, *yybar;

This didn't work because of the possible degenerate case

    int yyfoo, bar;

so yyhide was changed to do this:

static int yyfoo;
int bar;

This also didn't work because of this case:

    struct foo {
        int a, b;
    } yyfoo, yybar;

which became

    static struct foo {
        int a, b;
    } yyfoo;
    static struct foo {
        int a, b;
    } yybar;

(struct foo redefined).  So yyhide's solution was to do this:

    struct foo {
        int a, b;
    };

    static struct foo yyfoo;
    static struct foo yybar;

So far, so good.  The next problem was this case:

    extern int yyfoo;
    /* Arbitrary amount of code */
    int yyfoo;

which became

    extern int yyfoo;
    /* Arbitrary amount of code */
    static int yyfoo;

(yyfoo redefined).  So yyhide did this:

    /* Arbitrary amount of code */
    static int yyfoo;

This was fine when yyfoo was an int, but when yyhide changed this

    extern struct foo yyfoo;
    /* Arbitrary amount of code */
    struct foo yyfoo;

to this

    /* Arbitrary amount of code */
    static struct foo yyfoo;

and something in the /* Arbitrary amount of code */ referred to yyfoo,
the result was "yyfoo undefined".  The provisional solution to this (and
the current state of yyhide) was to change

    extern SomeRandomType yyfoo;
    /* Arbitrary amount of code */
    SomeRandomType yyfoo;

to

    static SomeRandomType yyfoo;
    /* Arbitrary amount of code */

But even this doesn't work because of this case:

    extern int *yyfoo;
    /* Arbitrary amount of code */
    int yybar[] = {1, 2, 3};
    /* Arbitrary amount of code */
    int *yyfoo = yybar;

which becomes

    static int *yyfoo = yybar;
    /* Arbitrary amount of code */
    static int yybar[] = {1, 2, 3};
    /* Arbitrary amount of code */

(yybar undefined [in definition of yyfoo]).  The next step in the
development of yyhide seems to be to do a dependency sort on the
variable declarations, but that seems needlessly complicated.

The problem, in effect, is that the Yacc and Lex templates both use
"extern" declarations as a forward-declaration device, and that this
hack does not work when the forwardly declared variable winds up being
static.  "Extern" is being overloaded in this sense, and it's kludgy,
but there you have it.  There seems to be no way to make a forward
declaration for a static variable.  If that's true, then does anyone
have any good ideas?  If that's false (you can forwardly declare a
static variable in C), how is it done?


	Bob Glickstein