]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
Use chartype.h instead of ctype.h
[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         AddEnumSym (Ident, 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 {
779             FuncDesc* F = DecodePtr (T+1);
780             F->Flags |= FD_FASTCALL;
781         }
782         return;
783     } else {
784         /* Things depend on Mode now:
785          *  - Mode == DM_NEED_IDENT means:
786          *      we *must* have a type and a variable identifer.
787          *  - Mode == DM_NO_IDENT means:
788          *      we must have a type but no variable identifer
789          *      (if there is one, it's not read).
790          *  - Mode == DM_ACCEPT_IDENT means:
791          *      we *may* have an identifier. If there is an identifier,
792          *      it is read, but it is no error, if there is none.
793          */
794         if (Mode == DM_NO_IDENT) {
795             D->Ident[0] = '\0';
796         } else if (curtok == TOK_IDENT) {
797             strcpy (D->Ident, CurTok.Ident);
798             NextToken ();
799         } else {
800             if (Mode == DM_NEED_IDENT) {
801                 Error ("Identifier expected");
802             }
803             D->Ident[0] = '\0';
804             return;
805         }
806     }
807
808     while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
809         if (curtok == TOK_LPAREN) {
810             /* Function declaration */
811             FuncDesc* F;
812             NextToken ();
813             /* Parse the function declaration */
814             F = ParseFuncDecl ();
815             *D->T++ = T_FUNC;
816             EncodePtr (D->T, F);
817             D->T += DECODE_SIZE;
818         } else {
819             /* Array declaration */
820             unsigned long Size = 0;
821             NextToken ();
822             /* Read the size if it is given */
823             if (curtok != TOK_RBRACK) {
824                 struct expent lval;
825                 constexpr (&lval);
826                 Size = lval.e_const;
827             }
828             ConsumeRBrack ();
829             *D->T++ = T_ARRAY;
830             Encode (D->T, Size);
831             D->T += DECODE_SIZE;
832         }
833     }
834 }
835
836
837
838 /*****************************************************************************/
839 /*                                   code                                    */
840 /*****************************************************************************/
841
842
843
844 type* ParseType (type* Type)
845 /* Parse a complete type specification */
846 {
847     DeclSpec Spec;
848     Declaration Decl;
849
850     /* Get a type without a default */
851     InitDeclSpec (&Spec);
852     ParseTypeSpec (&Spec, -1);
853
854     /* Parse additional declarators */
855     InitDeclaration (&Decl);
856     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
857
858     /* Copy the type to the target buffer */
859     TypeCpy (Type, Decl.Type);
860
861     /* Return a pointer to the target buffer */
862     return Type;
863 }
864
865
866
867 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
868 /* Parse a variable, type or function declaration */
869 {
870     /* Initialize the Declaration struct */
871     InitDeclaration (D);
872
873     /* Get additional declarators and the identifier */
874     Decl (D, Mode);
875
876     /* Add the base type. */
877     TypeCpy (D->T, Spec->Type);
878
879     /* Check the size of the generated type */
880     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
881         if (D->Ident[0] != '\0') {
882             Error ("Size of `%s' is invalid", D->Ident);
883         } else {
884             Error ("Invalid size");
885         }
886     }
887 }
888
889
890
891 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
892 /* Parse a declaration specification */
893 {
894     /* Initialize the DeclSpec struct */
895     InitDeclSpec (D);
896
897     /* First, get the storage class specifier for this declaration */
898     ParseStorageClass (D, DefStorage);
899
900     /* Parse the type specifiers */
901     ParseTypeSpec (D, DefType);
902 }
903
904
905
906 void CheckEmptyDecl (const DeclSpec* D)
907 /* Called after an empty type declaration (that is, a type declaration without
908  * a variable). Checks if the declaration does really make sense and issues a
909  * warning if not.
910  */
911 {
912     if ((D->Flags & DS_EXTRA_TYPE) == 0) {
913         Warning ("Useless declaration");
914     }
915 }
916
917
918
919 static void ParseVoidInit (void)
920 /* Parse an initialization of a void variable (special cc65 extension) */
921 {
922     struct expent lval;
923
924     /* Allow an arbitrary list of values */
925     ConsumeLCurly ();
926     do {
927         constexpr (&lval);
928         switch (lval.e_tptr[0]) {
929
930             case T_SCHAR:
931             case T_UCHAR:
932                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
933                     /* Make it byte sized */
934                     lval.e_const &= 0xFF;
935                 }
936                 DefineData (&lval);
937                 break;
938
939             case T_SHORT:
940             case T_USHORT:
941             case T_INT:
942             case T_UINT:
943             case T_PTR:
944             case T_ARRAY:
945                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
946                     /* Make it word sized */
947                     lval.e_const &= 0xFFFF;
948                 }
949                 DefineData (&lval);
950                 break;
951
952             case T_LONG:
953             case T_ULONG:
954                 DefineData (&lval);
955                 break;
956
957             default:
958                 Error ("Illegal type in initialization");
959                 break;
960
961         }
962
963         if (curtok != TOK_COMMA) {
964             break;
965         }
966         NextToken ();
967
968     } while (curtok != TOK_RCURLY);
969
970     ConsumeRCurly ();
971 }
972
973
974
975 static void ParseStructInit (type* Type)
976 /* Parse initialization of a struct or union */
977 {
978     SymEntry* Entry;
979     SymTable* Tab;
980
981     /* Consume the opening curly brace */
982     ConsumeLCurly ();
983
984     /* Get a pointer to the struct entry from the type */
985     Entry = (SymEntry*) Decode (Type + 1);
986
987     /* Check if this struct definition has a field table. If it doesn't, it
988      * is an incomplete definition.
989      */
990     Tab = Entry->V.S.SymTab;
991     if (Tab == 0) {
992         Error ("Cannot initialize variables with incomplete type");
993         /* Returning here will cause lots of errors, but recovery is difficult */
994         return;
995     }
996
997     /* Get a pointer to the list of symbols */
998     Entry = Tab->SymHead;
999     while (curtok != TOK_RCURLY) {
1000         if (Entry == 0) {
1001             Error ("Too many initializers");
1002             return;
1003         }
1004         ParseInit (Entry->Type);
1005         Entry = Entry->NextSym;
1006         if (curtok != TOK_COMMA)
1007             break;
1008         NextToken ();
1009     }
1010
1011     /* Consume the closing curly brace */
1012     ConsumeRCurly ();
1013
1014     /* If there are struct fields left, reserve additional storage */
1015     while (Entry) {
1016         g_zerobytes (SizeOf (Entry->Type));
1017         Entry = Entry->NextSym;
1018     }
1019 }
1020
1021
1022
1023 void ParseInit (type* T)
1024 /* Parse initialization of variables. */
1025 {
1026     int count;
1027     struct expent lval;
1028     type* t;
1029     const char* str;
1030     int sz;
1031
1032     switch (UnqualifiedType (*T)) {
1033
1034         case T_SCHAR:
1035         case T_UCHAR:
1036             constexpr (&lval);
1037             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1038                 /* Make it byte sized */
1039                 lval.e_const &= 0xFF;
1040             }
1041             assignadjust (T, &lval);
1042             DefineData (&lval);
1043             break;
1044
1045         case T_SHORT:
1046         case T_USHORT:
1047         case T_INT:
1048         case T_UINT:
1049         case T_PTR:
1050             constexpr (&lval);
1051             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1052                 /* Make it word sized */
1053                 lval.e_const &= 0xFFFF;
1054             }
1055             assignadjust (T, &lval);
1056             DefineData (&lval);
1057             break;
1058
1059         case T_LONG:
1060         case T_ULONG:
1061             constexpr (&lval);
1062             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1063                 /* Make it long sized */
1064                 lval.e_const &= 0xFFFFFFFF;
1065             }
1066             assignadjust (T, &lval);
1067             DefineData (&lval);
1068             break;
1069
1070         case T_ARRAY:
1071             sz = Decode (T + 1);
1072             t = T + DECODE_SIZE + 1;
1073             if (IsTypeChar(t) && curtok == TOK_SCONST) {
1074                 str = GetLiteral (curval);
1075                 count = strlen (str) + 1;
1076                 TranslateLiteralPool (curval);  /* Translate into target charset */
1077                 g_defbytes (str, count);
1078                 ResetLiteralOffs (curval);      /* Remove string from pool */
1079                 NextToken ();
1080             } else {
1081                 ConsumeLCurly ();
1082                 count = 0;
1083                 while (curtok != TOK_RCURLY) {
1084                     ParseInit (T + DECODE_SIZE + 1);
1085                     ++count;
1086                     if (curtok != TOK_COMMA)
1087                         break;
1088                     NextToken ();
1089                 }
1090                 ConsumeRCurly ();
1091             }
1092             if (sz == 0) {
1093                 Encode (T + 1, count);
1094             } else if (count < sz) {
1095                 g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
1096             } else if (count > sz) {
1097                 Error ("Too many initializers");
1098             }
1099             break;
1100
1101         case T_STRUCT:
1102         case T_UNION:
1103             ParseStructInit (T);
1104             break;
1105
1106         case T_VOID:
1107             if (!ANSI) {
1108                 /* Special cc65 extension in non ANSI mode */
1109                 ParseVoidInit ();
1110                 break;
1111             }
1112             /* FALLTHROUGH */
1113
1114         default:
1115             Error ("Illegal type");
1116             break;
1117
1118     }
1119 }
1120
1121
1122