]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
Make AddConstSym from AddEnumSym
[cc65] / src / cc65 / declare.c
1 /*
2  * declare.c
3  *
4  * Ullrich von Bassewitz, 20.06.1998
5  */
6
7
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12
13 /* common */
14 #include "xmalloc.h"
15
16 /* cc65 */
17 #include "anonname.h"
18 #include "codegen.h"
19 #include "datatype.h"
20 #include "declattr.h"
21 #include "error.h"
22 #include "expr.h"
23 #include "funcdesc.h"
24 #include "function.h"
25 #include "global.h"
26 #include "litpool.h"
27 #include "pragma.h"
28 #include "scanner.h"
29 #include "symtab.h"
30 #include "declare.h"
31
32
33
34 /*****************************************************************************/
35 /*                                 Forwards                                  */
36 /*****************************************************************************/
37
38
39
40 static void ParseTypeSpec (DeclSpec* D, int Default);
41 /* Parse a type specificier */
42
43
44
45 /*****************************************************************************/
46 /*                            internal functions                             */
47 /*****************************************************************************/
48
49
50
51 static type OptionalQualifiers (type Q)
52 /* Read type qualifiers if we have any */
53 {
54     while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
55
56         switch (curtok) {
57
58             case TOK_CONST:
59                 if (Q & T_QUAL_CONST) {
60                     Error ("Duplicate qualifier: `const'");
61                 }
62                 Q |= T_QUAL_CONST;
63                 break;
64
65             case TOK_VOLATILE:
66                 if (Q & T_QUAL_VOLATILE) {
67                     Error ("Duplicate qualifier: `volatile'");
68                 }
69                 Q |= T_QUAL_VOLATILE;
70                 break;
71
72             default:
73                 /* Keep gcc silent */
74                 break;
75
76         }
77
78         /* Skip the token */
79         NextToken ();
80     }
81
82     /* Return the qualifiers read */
83     return Q;
84 }
85
86
87
88 static void optionalint (void)
89 /* Eat an optional "int" token */
90 {
91     if (curtok == TOK_INT) {
92         /* Skip it */
93         NextToken ();
94     }
95 }
96
97
98
99 static void optionalsigned (void)
100 /* Eat an optional "signed" token */
101 {
102     if (curtok == TOK_SIGNED) {
103         /* Skip it */
104         NextToken ();
105     }
106 }
107
108
109
110 static void InitDeclSpec (DeclSpec* D)
111 /* Initialize the DeclSpec struct for use */
112 {
113     D->StorageClass     = 0;
114     D->Type[0]          = T_END;
115     D->Flags            = 0;
116 }
117
118
119
120 static void InitDeclaration (Declaration* D)
121 /* Initialize the Declaration struct for use */
122 {
123     D->Ident[0]         = '\0';
124     D->Type[0]          = T_END;
125     D->T                = D->Type;
126 }
127
128
129
130 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
131 /* Parse a storage class */
132 {
133     /* Assume we're using an explicit storage class */
134     D->Flags &= ~DS_DEF_STORAGE;
135
136     /* Check the storage class given */
137     switch (curtok) {
138
139         case TOK_EXTERN:
140             D->StorageClass = SC_EXTERN | SC_STATIC;
141             NextToken ();
142             break;
143
144         case TOK_STATIC:
145             D->StorageClass = SC_STATIC;
146             NextToken ();
147             break;
148
149         case TOK_REGISTER:
150             D->StorageClass = SC_REGISTER | SC_STATIC;
151             NextToken ();
152             break;
153
154         case TOK_AUTO:
155             D->StorageClass = SC_AUTO;
156             NextToken ();
157             break;
158
159         case TOK_TYPEDEF:
160             D->StorageClass = SC_TYPEDEF;
161             NextToken ();
162             break;
163
164         default:
165             /* No storage class given, use default */
166             D->Flags |= DS_DEF_STORAGE;
167             D->StorageClass = DefStorage;
168             break;
169     }
170 }
171
172
173
174 static void ParseEnumDecl (void)
175 /* Process an enum declaration . */
176 {
177     int EnumVal;
178     ident Ident;
179
180     /* Accept forward definitions */
181     if (curtok != TOK_LCURLY) {
182         return;
183     }
184
185     /* Skip the opening curly brace */
186     NextToken ();
187
188     /* Read the enum tags */
189     EnumVal = 0;
190     while (curtok != TOK_RCURLY) {
191
192         /* We expect an identifier */
193         if (curtok != TOK_IDENT) {
194             Error ("Identifier expected");
195             continue;
196         }
197
198         /* Remember the identifier and skip it */
199         strcpy (Ident, CurTok.Ident);
200         NextToken ();
201
202         /* Check for an assigned value */
203         if (curtok == TOK_ASSIGN) {
204             struct expent lval;
205             NextToken ();
206             constexpr (&lval);
207             EnumVal = lval.e_const;
208         }
209
210         /* Add an entry to the symbol table */
211         AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
212
213         /* Check for end of definition */
214         if (curtok != TOK_COMMA)
215             break;
216         NextToken ();
217     }
218     ConsumeRCurly ();
219 }
220
221
222
223 static SymEntry* ParseStructDecl (const char* Name, type StructType)
224 /* Parse a struct/union declaration. */
225 {
226
227     unsigned Size;
228     unsigned Offs;
229     SymTable* FieldTab;
230     SymEntry* Entry;
231
232
233     if (curtok != TOK_LCURLY) {
234         /* Just a forward declaration. Try to find a struct with the given
235          * name. If there is none, insert a forward declaration into the
236          * current lexical level.
237          */
238         Entry = FindTagSym (Name);
239         if (Entry == 0) {
240             Entry = AddStructSym (Name, 0, 0);
241         } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
242             /* Already defined in the level but no struct */
243             Error ("Symbol `%s' is already different kind", Name);
244         }
245         return Entry;
246     }
247
248     /* Add a forward declaration for the struct in the current lexical level */
249     Entry = AddStructSym (Name, 0, 0);
250
251     /* Skip the curly brace */
252     NextToken ();
253
254     /* Enter a new lexical level for the struct */
255     EnterStructLevel ();
256
257     /* Parse struct fields */
258     Size = 0;
259     while (curtok != TOK_RCURLY) {
260
261         /* Get the type of the entry */
262         DeclSpec Spec;
263         InitDeclSpec (&Spec);
264         ParseTypeSpec (&Spec, -1);
265
266         /* Read fields with this type */
267         while (1) {
268
269             /* Get type and name of the struct field */
270             Declaration Decl;
271             ParseDecl (&Spec, &Decl, 0);
272
273             /* Add a field entry to the table */
274             AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
275
276             /* Calculate offset of next field/size of the union */
277             Offs = SizeOf (Decl.Type);
278             if (StructType == T_STRUCT) {
279                 Size += Offs;
280             } else {
281                 if (Offs > Size) {
282                     Size = Offs;
283                 }
284             }
285
286             if (curtok != TOK_COMMA)
287                 break;
288             NextToken ();
289         }
290         ConsumeSemi ();
291     }
292
293     /* Skip the closing brace */
294     NextToken ();
295
296     /* Remember the symbol table and leave the struct level */
297     FieldTab = GetSymTab ();
298     LeaveStructLevel ();
299
300     /* Make a real entry from the forward decl and return it */
301     return AddStructSym (Name, Size, FieldTab);
302 }
303
304
305
306 static void ParseTypeSpec (DeclSpec* D, int Default)
307 /* Parse a type specificier */
308 {
309     ident       Ident;
310     SymEntry*   Entry;
311     type        StructType;
312     type        Qualifiers;     /* Type qualifiers */
313
314     /* Assume we have an explicit type */
315     D->Flags &= ~DS_DEF_TYPE;
316
317     /* Read type qualifiers if we have any */
318     Qualifiers = OptionalQualifiers (T_QUAL_NONE);
319
320     /* Look at the data type */
321     switch (curtok) {
322
323         case TOK_VOID:
324             NextToken ();
325             D->Type[0] = T_VOID;
326             D->Type[1] = T_END;
327             break;
328
329         case TOK_CHAR:
330             NextToken ();
331             D->Type[0] = GetDefaultChar();
332             D->Type[1] = T_END;
333             break;
334
335         case TOK_LONG:
336             NextToken ();
337             if (curtok == TOK_UNSIGNED) {
338                 NextToken ();
339                 optionalint ();
340                 D->Type[0] = T_ULONG;
341                 D->Type[1] = T_END;
342             } else {
343                 optionalsigned ();
344                 optionalint ();
345                 D->Type[0] = T_LONG;
346                 D->Type[1] = T_END;
347             }
348             break;
349
350         case TOK_SHORT:
351             NextToken ();
352             if (curtok == TOK_UNSIGNED) {
353                 NextToken ();
354                 optionalint ();
355                 D->Type[0] = T_USHORT;
356                 D->Type[1] = T_END;
357             } else {
358                 optionalsigned ();
359                 optionalint ();
360                 D->Type[0] = T_SHORT;
361                 D->Type[1] = T_END;
362             }
363             break;
364
365         case TOK_INT:
366             NextToken ();
367             D->Type[0] = T_INT;
368             D->Type[1] = T_END;
369             break;
370
371        case TOK_SIGNED:
372             NextToken ();
373             switch (curtok) {
374
375                 case TOK_CHAR:
376                     NextToken ();
377                     D->Type[0] = T_SCHAR;
378                     D->Type[1] = T_END;
379                     break;
380
381                 case TOK_SHORT:
382                     NextToken ();
383                     optionalint ();
384                     D->Type[0] = T_SHORT;
385                     D->Type[1] = T_END;
386                     break;
387
388                 case TOK_LONG:
389                     NextToken ();
390                     optionalint ();
391                     D->Type[0] = T_LONG;
392                     D->Type[1] = T_END;
393                     break;
394
395                 case TOK_INT:
396                     NextToken ();
397                     /* FALL THROUGH */
398
399                 default:
400                     D->Type[0] = T_INT;
401                     D->Type[1] = T_END;
402                     break;
403             }
404             break;
405
406         case TOK_UNSIGNED:
407             NextToken ();
408             switch (curtok) {
409
410                 case TOK_CHAR:
411                     NextToken ();
412                     D->Type[0] = T_UCHAR;
413                     D->Type[1] = T_END;
414                     break;
415
416                 case TOK_SHORT:
417                     NextToken ();
418                     optionalint ();
419                     D->Type[0] = T_USHORT;
420                     D->Type[1] = T_END;
421                     break;
422
423                 case TOK_LONG:
424                     NextToken ();
425                     optionalint ();
426                     D->Type[0] = T_ULONG;
427                     D->Type[1] = T_END;
428                     break;
429
430                 case TOK_INT:
431                     NextToken ();
432                     /* FALL THROUGH */
433
434                 default:
435                     D->Type[0] = T_UINT;
436                     D->Type[1] = T_END;
437                     break;
438             }
439             break;
440
441         case TOK_STRUCT:
442         case TOK_UNION:
443             StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
444             NextToken ();
445             /* */
446             if (curtok == TOK_IDENT) {
447                 strcpy (Ident, CurTok.Ident);
448                 NextToken ();
449             } else {
450                 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
451             }
452             /* Remember we have an extra type decl */
453             D->Flags |= DS_EXTRA_TYPE;
454             /* Declare the struct in the current scope */
455             Entry = ParseStructDecl (Ident, StructType);
456             /* Encode the struct entry into the type */
457             D->Type[0] = StructType;
458             EncodePtr (D->Type+1, Entry);
459             D->Type[DECODE_SIZE+1] = T_END;
460             break;
461
462         case TOK_ENUM:
463             NextToken ();
464             if (curtok != TOK_LCURLY) {
465                 /* Named enum */
466                 if (curtok == TOK_IDENT) {
467                     /* Find an entry with this name */
468                     Entry = FindTagSym (CurTok.Ident);
469                     if (Entry) {
470                         if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
471                             Error ("Symbol `%s' is already different kind", Entry->Name);
472                         }
473                     } else {
474                         /* Insert entry into table ### */
475                     }
476                     /* Skip the identifier */
477                     NextToken ();
478                 } else {
479                     Error ("Identifier expected");
480                 }
481             }
482             /* Remember we have an extra type decl */
483             D->Flags |= DS_EXTRA_TYPE;
484             /* Parse the enum decl */
485             ParseEnumDecl ();
486             D->Type[0] = T_INT;
487             D->Type[1] = T_END;
488             break;
489
490         case TOK_IDENT:
491             Entry = FindSym (CurTok.Ident);
492             if (Entry && IsTypeDef (Entry)) {
493                 /* It's a typedef */
494                 NextToken ();
495                 TypeCpy (D->Type, Entry->Type);
496                 break;
497             }
498             /* FALL THROUGH */
499
500         default:
501             if (Default < 0) {
502                 Error ("Type expected");
503                 D->Type[0] = T_INT;
504                 D->Type[1] = T_END;
505             } else {
506                 D->Flags  |= DS_DEF_TYPE;
507                 D->Type[0] = (type) Default;
508                 D->Type[1] = T_END;
509             }
510             break;
511     }
512
513     /* There may also be qualifiers *after* the initial type */
514     D->Type[0] |= OptionalQualifiers (Qualifiers);
515 }
516
517
518
519 static type* ParamTypeCvt (type* T)
520 /* If T is an array, convert it to a pointer else do nothing. Return the
521  * resulting type.
522  */
523 {
524     if (IsTypeArray (T)) {
525         T += DECODE_SIZE;
526         T[0] = T_PTR;
527     }
528     return T;
529 }
530
531
532
533 static void ParseOldStyleParamList (FuncDesc* F)
534 /* Parse an old style (K&R) parameter list */
535 {
536     /* Parse params */
537     while (curtok != TOK_RPAREN) {
538
539         /* List of identifiers expected */
540         if (curtok != TOK_IDENT) {
541             Error ("Identifier expected");
542         }
543
544         /* Create a symbol table entry with type int */
545         AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
546
547         /* Count arguments */
548         ++F->ParamCount;
549
550         /* Skip the identifier */
551         NextToken ();
552
553         /* Check for more parameters */
554         if (curtok == TOK_COMMA) {
555             NextToken ();
556         } else {
557             break;
558         }
559     }
560
561     /* Skip right paren. We must explicitly check for one here, since some of
562      * the breaks above bail out without checking.
563      */
564     ConsumeRParen ();
565
566     /* An optional list of type specifications follows */
567     while (curtok != TOK_LCURLY) {
568
569         DeclSpec        Spec;
570
571         /* Read the declaration specifier */
572         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
573
574         /* We accept only auto and register as storage class specifiers, but
575          * we ignore all this, since we use auto anyway.
576          */
577         if ((Spec.StorageClass & SC_AUTO) == 0 &&
578             (Spec.StorageClass & SC_REGISTER) == 0) {
579             Error ("Illegal storage class");
580         }
581
582         /* Parse a comma separated variable list */
583         while (1) {
584
585             Declaration         Decl;
586
587             /* Read the parameter */
588             ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
589             if (Decl.Ident[0] != '\0') {
590
591                 /* We have a name given. Search for the symbol */
592                 SymEntry* Sym = FindLocalSym (Decl.Ident);
593                 if (Sym) {
594                     /* Found it, change the default type to the one given */
595                     ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
596                 } else {
597                     Error ("Unknown identifier: `%s'", Decl.Ident);
598                 }
599             }
600
601             if (curtok == TOK_COMMA) {
602                 NextToken ();
603             } else {
604                 break;
605             }
606
607         }
608
609         /* Variable list must be semicolon terminated */
610         ConsumeSemi ();
611     }
612 }
613
614
615
616 static void ParseAnsiParamList (FuncDesc* F)
617 /* Parse a new style (ANSI) parameter list */
618 {
619     /* Parse params */
620     while (curtok != TOK_RPAREN) {
621
622         DeclSpec        Spec;
623         Declaration     Decl;
624         DeclAttr        Attr;
625
626         /* Allow an ellipsis as last parameter */
627         if (curtok == TOK_ELLIPSIS) {
628             NextToken ();
629             F->Flags |= FD_ELLIPSIS;
630             break;
631         }
632
633         /* Read the declaration specifier */
634         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
635
636         /* We accept only auto and register as storage class specifiers, but
637          * we ignore all this and use auto.
638          */
639         if ((Spec.StorageClass & SC_AUTO) == 0 &&
640             (Spec.StorageClass & SC_REGISTER) == 0) {
641             Error ("Illegal storage class");
642         }
643         Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
644
645         /* Allow parameters without a name, but remember if we had some to
646          * eventually print an error message later.
647          */
648         ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
649         if (Decl.Ident[0] == '\0') {
650
651             /* Unnamed symbol. Generate a name that is not user accessible,
652              * then handle the symbol normal.
653              */
654             AnonName (Decl.Ident, "param");
655             F->Flags |= FD_UNNAMED_PARAMS;
656
657             /* Clear defined bit on nonames */
658             Spec.StorageClass &= ~SC_DEF;
659         }
660
661         /* Parse an attribute ### */
662         ParseAttribute (&Decl, &Attr);
663
664         /* Create a symbol table entry */
665         AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
666
667         /* Count arguments */
668         ++F->ParamCount;
669
670         /* Check for more parameters */
671         if (curtok == TOK_COMMA) {
672             NextToken ();
673         } else {
674             break;
675         }
676     }
677
678     /* Skip right paren. We must explicitly check for one here, since some of
679      * the breaks above bail out without checking.
680      */
681     ConsumeRParen ();
682
683     /* Check if this is a function definition */
684     if (curtok == TOK_LCURLY) {
685         /* Print an error if in strict ANSI mode and we have unnamed
686          * parameters.
687          */
688         if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
689             Error ("Parameter name omitted");
690         }
691     }
692 }
693
694
695
696 static FuncDesc* ParseFuncDecl (void)
697 /* Parse the argument list of a function. */
698 {
699     unsigned Offs;
700     SymEntry* Sym;
701
702     /* Create a new function descriptor */
703     FuncDesc* F = NewFuncDesc ();
704
705     /* Enter a new lexical level */
706     EnterFunctionLevel ();
707
708     /* Check for several special parameter lists */
709     if (curtok == TOK_RPAREN) {
710         /* Parameter list is empty */
711         F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
712     } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
713         /* Parameter list declared as void */
714         NextToken ();
715         F->Flags |= FD_VOID_PARAM;
716     } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
717         /* Old style (K&R) function. Assume variable param list. */
718         F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
719     }
720
721     /* Parse params */
722     if ((F->Flags & FD_OLDSTYLE) == 0) {
723         /* New style function */
724         ParseAnsiParamList (F);
725     } else {
726         /* Old style function */
727         ParseOldStyleParamList (F);
728     }
729
730     /* Assign offsets. If the function has a variable parameter list,
731      * there's one additional byte (the arg size).
732      */
733     Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
734     Sym = GetSymTab()->SymTail;
735     while (Sym) {
736         unsigned Size = SizeOf (Sym->Type);
737         Sym->V.Offs = Offs;
738         Offs += Size;
739         F->ParamSize += Size;
740         Sym = Sym->PrevSym;
741     }
742
743     /* Leave the lexical level remembering the symbol tables */
744     RememberFunctionLevel (F);
745
746     /* Return the function descriptor */
747     return F;
748 }
749
750
751
752 static void Decl (Declaration* D, unsigned Mode)
753 /* Recursively process declarators. Build a type array in reverse order. */
754 {
755
756     if (curtok == TOK_STAR) {
757         type T = T_PTR;
758         NextToken ();
759         /* Allow optional const or volatile qualifiers */
760         T |= OptionalQualifiers (T_QUAL_NONE);
761         Decl (D, Mode);
762         *D->T++ = T;
763         return;
764     } else if (curtok == TOK_LPAREN) {
765         NextToken ();
766         Decl (D, Mode);
767         ConsumeRParen ();
768     } else if (curtok == TOK_FASTCALL) {
769         /* Remember the current type pointer */
770         type* T = D->T;
771         /* Skip the fastcall token */
772         NextToken ();
773         /* Parse the function */
774         Decl (D, Mode);
775         /* Set the fastcall flag */
776         if (!IsTypeFunc (T)) {
777             Error ("__fastcall__ modifier applied to non function");
778         } else if (IsVariadicFunc (T)) {
779             Error ("Cannot apply __fastcall__ to functions with variable parameter list");
780         } else {
781             FuncDesc* F = (FuncDesc*) DecodePtr (T+1);
782             F->Flags |= FD_FASTCALL;
783         }
784         return;
785     } else {
786         /* Things depend on Mode now:
787          *  - Mode == DM_NEED_IDENT means:
788          *      we *must* have a type and a variable identifer.
789          *  - Mode == DM_NO_IDENT means:
790          *      we must have a type but no variable identifer
791          *      (if there is one, it's not read).
792          *  - Mode == DM_ACCEPT_IDENT means:
793          *      we *may* have an identifier. If there is an identifier,
794          *      it is read, but it is no error, if there is none.
795          */
796         if (Mode == DM_NO_IDENT) {
797             D->Ident[0] = '\0';
798         } else if (curtok == TOK_IDENT) {
799             strcpy (D->Ident, CurTok.Ident);
800             NextToken ();
801         } else {
802             if (Mode == DM_NEED_IDENT) {
803                 Error ("Identifier expected");
804             }
805             D->Ident[0] = '\0';
806             return;
807         }
808     }
809
810     while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
811         if (curtok == TOK_LPAREN) {
812             /* Function declaration */
813             FuncDesc* F;
814             NextToken ();
815             /* Parse the function declaration */
816             F = ParseFuncDecl ();
817             *D->T++ = T_FUNC;
818             EncodePtr (D->T, F);
819             D->T += DECODE_SIZE;
820         } else {
821             /* Array declaration */
822             unsigned long Size = 0;
823             NextToken ();
824             /* Read the size if it is given */
825             if (curtok != TOK_RBRACK) {
826                 struct expent lval;
827                 constexpr (&lval);
828                 Size = lval.e_const;
829             }
830             ConsumeRBrack ();
831             *D->T++ = T_ARRAY;
832             Encode (D->T, Size);
833             D->T += DECODE_SIZE;
834         }
835     }
836 }
837
838
839
840 /*****************************************************************************/
841 /*                                   code                                    */
842 /*****************************************************************************/
843
844
845
846 type* ParseType (type* Type)
847 /* Parse a complete type specification */
848 {
849     DeclSpec Spec;
850     Declaration Decl;
851
852     /* Get a type without a default */
853     InitDeclSpec (&Spec);
854     ParseTypeSpec (&Spec, -1);
855
856     /* Parse additional declarators */
857     InitDeclaration (&Decl);
858     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
859
860     /* Copy the type to the target buffer */
861     TypeCpy (Type, Decl.Type);
862
863     /* Return a pointer to the target buffer */
864     return Type;
865 }
866
867
868
869 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
870 /* Parse a variable, type or function declaration */
871 {
872     /* Initialize the Declaration struct */
873     InitDeclaration (D);
874
875     /* Get additional declarators and the identifier */
876     Decl (D, Mode);
877
878     /* Add the base type. */
879     TypeCpy (D->T, Spec->Type);
880
881     /* Check the size of the generated type */
882     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
883         if (D->Ident[0] != '\0') {
884             Error ("Size of `%s' is invalid", D->Ident);
885         } else {
886             Error ("Invalid size");
887         }
888     }
889 }
890
891
892
893 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
894 /* Parse a declaration specification */
895 {
896     /* Initialize the DeclSpec struct */
897     InitDeclSpec (D);
898
899     /* First, get the storage class specifier for this declaration */
900     ParseStorageClass (D, DefStorage);
901
902     /* Parse the type specifiers */
903     ParseTypeSpec (D, DefType);
904 }
905
906
907
908 void CheckEmptyDecl (const DeclSpec* D)
909 /* Called after an empty type declaration (that is, a type declaration without
910  * a variable). Checks if the declaration does really make sense and issues a
911  * warning if not.
912  */
913 {
914     if ((D->Flags & DS_EXTRA_TYPE) == 0) {
915         Warning ("Useless declaration");
916     }
917 }
918
919
920
921 static void ParseVoidInit (void)
922 /* Parse an initialization of a void variable (special cc65 extension) */
923 {
924     struct expent lval;
925
926     /* Allow an arbitrary list of values */
927     ConsumeLCurly ();
928     do {
929         constexpr (&lval);
930         switch (lval.e_tptr[0]) {
931
932             case T_SCHAR:
933             case T_UCHAR:
934                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
935                     /* Make it byte sized */
936                     lval.e_const &= 0xFF;
937                 }
938                 DefineData (&lval);
939                 break;
940
941             case T_SHORT:
942             case T_USHORT:
943             case T_INT:
944             case T_UINT:
945             case T_PTR:
946             case T_ARRAY:
947                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
948                     /* Make it word sized */
949                     lval.e_const &= 0xFFFF;
950                 }
951                 DefineData (&lval);
952                 break;
953
954             case T_LONG:
955             case T_ULONG:
956                 DefineData (&lval);
957                 break;
958
959             default:
960                 Error ("Illegal type in initialization");
961                 break;
962
963         }
964
965         if (curtok != TOK_COMMA) {
966             break;
967         }
968         NextToken ();
969
970     } while (curtok != TOK_RCURLY);
971
972     ConsumeRCurly ();
973 }
974
975
976
977 static void ParseStructInit (type* Type)
978 /* Parse initialization of a struct or union */
979 {
980     SymEntry* Entry;
981     SymTable* Tab;
982
983     /* Consume the opening curly brace */
984     ConsumeLCurly ();
985
986     /* Get a pointer to the struct entry from the type */
987     Entry = (SymEntry*) Decode (Type + 1);
988
989     /* Check if this struct definition has a field table. If it doesn't, it
990      * is an incomplete definition.
991      */
992     Tab = Entry->V.S.SymTab;
993     if (Tab == 0) {
994         Error ("Cannot initialize variables with incomplete type");
995         /* Returning here will cause lots of errors, but recovery is difficult */
996         return;
997     }
998
999     /* Get a pointer to the list of symbols */
1000     Entry = Tab->SymHead;
1001     while (curtok != TOK_RCURLY) {
1002         if (Entry == 0) {
1003             Error ("Too many initializers");
1004             return;
1005         }
1006         ParseInit (Entry->Type);
1007         Entry = Entry->NextSym;
1008         if (curtok != TOK_COMMA)
1009             break;
1010         NextToken ();
1011     }
1012
1013     /* Consume the closing curly brace */
1014     ConsumeRCurly ();
1015
1016     /* If there are struct fields left, reserve additional storage */
1017     while (Entry) {
1018         g_zerobytes (SizeOf (Entry->Type));
1019         Entry = Entry->NextSym;
1020     }
1021 }
1022
1023
1024
1025 void ParseInit (type* T)
1026 /* Parse initialization of variables. */
1027 {
1028     int count;
1029     struct expent lval;
1030     type* t;
1031     const char* str;
1032     int sz;
1033
1034     switch (UnqualifiedType (*T)) {
1035
1036         case T_SCHAR:
1037         case T_UCHAR:
1038             constexpr (&lval);
1039             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1040                 /* Make it byte sized */
1041                 lval.e_const &= 0xFF;
1042             }
1043             assignadjust (T, &lval);
1044             DefineData (&lval);
1045             break;
1046
1047         case T_SHORT:
1048         case T_USHORT:
1049         case T_INT:
1050         case T_UINT:
1051         case T_PTR:
1052             constexpr (&lval);
1053             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1054                 /* Make it word sized */
1055                 lval.e_const &= 0xFFFF;
1056             }
1057             assignadjust (T, &lval);
1058             DefineData (&lval);
1059             break;
1060
1061         case T_LONG:
1062         case T_ULONG:
1063             constexpr (&lval);
1064             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1065                 /* Make it long sized */
1066                 lval.e_const &= 0xFFFFFFFF;
1067             }
1068             assignadjust (T, &lval);
1069             DefineData (&lval);
1070             break;
1071
1072         case T_ARRAY:
1073             sz = Decode (T + 1);
1074             t = T + DECODE_SIZE + 1;
1075             if (IsTypeChar(t) && curtok == TOK_SCONST) {
1076                 str = GetLiteral (curval);
1077                 count = strlen (str) + 1;
1078                 TranslateLiteralPool (curval);  /* Translate into target charset */
1079                 g_defbytes (str, count);
1080                 ResetLiteralOffs (curval);      /* Remove string from pool */
1081                 NextToken ();
1082             } else {
1083                 ConsumeLCurly ();
1084                 count = 0;
1085                 while (curtok != TOK_RCURLY) {
1086                     ParseInit (T + DECODE_SIZE + 1);
1087                     ++count;
1088                     if (curtok != TOK_COMMA)
1089                         break;
1090                     NextToken ();
1091                 }
1092                 ConsumeRCurly ();
1093             }
1094             if (sz == 0) {
1095                 Encode (T + 1, count);
1096             } else if (count < sz) {
1097                 g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
1098             } else if (count > sz) {
1099                 Error ("Too many initializers");
1100             }
1101             break;
1102
1103         case T_STRUCT:
1104         case T_UNION:
1105             ParseStructInit (T);
1106             break;
1107
1108         case T_VOID:
1109             if (!ANSI) {
1110                 /* Special cc65 extension in non ANSI mode */
1111                 ParseVoidInit ();
1112                 break;
1113             }
1114             /* FALLTHROUGH */
1115
1116         default:
1117             Error ("Illegal type");
1118             break;
1119
1120     }
1121 }
1122
1123
1124