Others have addressed the "typedef int /* no alias here */;" issue:
typedef's syntax is funky, in that it takes the existing type, then
a series of variable declarations, and changes the variable declarations
into alias-declarations instead.
No one has, however, directly mentioned the more important thing:
C's "typedef" does not define types at all.
C's "struct" (and "union" and "enum" keywords as well, but they
are "lesser", as it were) is what actually declares new types.
Unlike Pascal, where you really want to declare a bunch of types
first, then use them in variable declarations, C lets you mix everything
together. It does this by requiring the "struct" keyword each time.
Just think of "struct" as meaning "type" and you will be fine.
Similarly, you need the word "enum" to mean "(enumerated) type", when
referring back to an enumeration. In Pascal you would make up type
names for your records and enumerations, and then use those; in C,
you do them all at once:
typedef struct SpellRec {
char name[12];
enum TokenKind kind;
SymbolTableEntry symbol;
struct SpellRec* next;
};
If you drop the "typedef" entirely, you will have:
struct SpellRec { ...contents... };
which defines a type named "struct SpellRec" (complete with the
"struct" keyword). This contains something of type "char [12]",
then something of type "enum TokenKind" (complete with the "enum"
keyword), then something of type "SymbolTableEntry" (no keyword --
must be a typedef-alias for some other "real" type), then something
of type "struct SpellRec *" (pointer to struct SpellRec, using the
"struct" keyword).
Except in a few peculiar corner cases involving <stdarg.h>, you
never *need* the typedef keyword at all, in C. You may decide
that you like it -- especially if you have been programming in
Pascal -- but you need to learn, deep in your gut as it were,
that typedef does not create types. If you write, for instance:
typedef double Temperature;
typedef double Area;
you probably want to prevent people from doing silly things like:
Temperature t;
Area a;
...
a = t; /* same area as a temperature (?!?) */
In C, though, typedefs are just aliases. "a" and "t" are really
both just "double"s, just as if you had written:
double t;
double a;
and therefore "a = t" is a perfectly good assignment.
To create new types, so that "a = t" becomes an error, you have
to encapsulate your data inside a "struct" (or union, or -- except
that enumerations are just integers -- enum):
struct temperature { double val; };
struct area { double val; };
...
struct temperature t;
struct area a;
...
a = t; /* error, and a C compiler must emit a diagnostic */
Although the structures have the same "shape" (one double) and
element-names ("val"), they are different types, and you cannot
pass a "struct temperature" where a "struct area" is required,
for instance.
typedef char ShortString[100];
typedef struct SpellRec* SpellTableEntry;
These just make aliases for the existing types "char [100]" (array
of size 100 of char) and "struct SpellRec *" (pointer to struct
SpellRec).
Note that you can make an alias for a structure type before
defining the (new) structure type:
typedef struct newtype alias_for_newtype;
struct newtype { ...contents... };
In general, I prefer not to use such typedefs at all, but this is
a matter of taste (I know chocolate is better than vanilla, and
dark chocolate better than milk chocolate, but I realize other
people believe otherwise, no matter how wrong they are
).
Then, I have the following function in one of my .c files:
SpellTableEntry NewSpell(ShortString na, TokenKind k,
SpellTableEntry ne) {
SpellTableEntry spell =
(SpellTableEntry)malloc(sizeof(SpellTableEntry));
spell->name = na;
spell->kind = k;
spell->symbol = NULL;
spell->next = ne;
return spell;
} /* NewSpell */
This is because there is no typedef-alias named "TokenKind".
Your structure uses a type named "enum TokenKind", and presumably
this is what "k" should be, so the function should read:
struct SpellRec *NewSpell(char na[100], enum TokenKind k,
struct SpellRec *ne) {
...
}
(or put in some or all of your typedef-aliases if you prefer
them).
Note that the "value" of an array is a pointer to its first element,
and "na" is declared as if it were an array. Since C always passes
by value (there is nothing directly equivalent to Pascal's "var";
you have to simulate it with pointers), a C function that *appears*
to take an array as a paremter actually receives a pointer to the
array's first element. (See also <
http://web.torek.net/torek/c/pa.html>
and "The Rule" about arrays and pointers in C.) Thus, I would
actually change the above even a bit more, to read:
struct SpellRec *NewSpell(char *na, enum TokenKind k,
struct SpellRec *ne) {
...
}
Because arrays have this peculiar behavior when passed as parameters,
I think one should *never* use a typedef to make an alias for an
array type. It is not that you cannot make this work, it is just
that, without knowing whether "T" is the name of an array type, you
cannot predict how a parameter of type "T" behaves.
The remaining errors:
scanner.c: In function 'NewSpell':
scanner.c:24: error: incompatible types in assignment
scanner.c:25: error: 'k' undeclared (first use in this function)
scanner.c:25: error: (Each undeclared identifier is reported only once for
each function it appears in.)
scanner.c:27: error: 'ne' undeclared (first use in this function)
are just "cascades" produced because of the first error.