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