]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
3f285244b181e1520b437ed4f331a83d7170d49d
[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 "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 (ERR_DUPLICATE_QUALIFIER, "const");
61                 }
62                 Q |= T_QUAL_CONST;
63                 break;
64
65             case TOK_VOLATILE:
66                 if (Q & T_QUAL_VOLATILE) {
67                     Error (ERR_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 (ERR_IDENT_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 (ERR_SYMBOL_KIND);
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_CHAR;
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 (ERR_SYMBOL_KIND);
472                         }
473                     } else {
474                         /* Insert entry into table ### */
475                     }
476                     /* Skip the identifier */
477                     NextToken ();
478                 } else {
479                     Error (ERR_IDENT_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 (ERR_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 (ERR_IDENT_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 (ERR_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 (ERR_UNKNOWN_IDENT, 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
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 (ERR_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         /* Create a symbol table entry */
662         AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
663
664         /* Count arguments */
665         ++F->ParamCount;
666
667         /* Check for more parameters */
668         if (curtok == TOK_COMMA) {
669             NextToken ();
670         } else {
671             break;
672         }
673     }
674
675     /* Skip right paren. We must explicitly check for one here, since some of
676      * the breaks above bail out without checking.
677      */
678     ConsumeRParen ();
679
680     /* Check if this is a function definition */
681     if (curtok == TOK_LCURLY) {
682         /* Print an error if in strict ANSI mode and we have unnamed
683          * parameters.
684          */
685         if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
686             Error (ERR_MISSING_PARAM_NAME);
687         }
688     }
689 }
690
691
692
693 static FuncDesc* ParseFuncDecl (void)
694 /* Parse the argument list of a function. */
695 {
696     unsigned Offs;
697     SymEntry* Sym;
698
699     /* Create a new function descriptor */
700     FuncDesc* F = NewFuncDesc ();
701
702     /* Enter a new lexical level */
703     EnterFunctionLevel ();
704
705     /* Check for several special parameter lists */
706     if (curtok == TOK_RPAREN) {
707         /* Parameter list is empty */
708         F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
709     } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
710         /* Parameter list declared as void */
711         NextToken ();
712         F->Flags |= FD_VOID_PARAM;
713     } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
714         /* Old style (K&R) function. Assume variable param list. */
715         F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
716     }
717
718     /* Parse params */
719     if ((F->Flags & FD_OLDSTYLE) == 0) {
720         /* New style function */
721         ParseAnsiParamList (F);
722     } else {
723         /* Old style function */
724         ParseOldStyleParamList (F);
725     }
726
727     /* Assign offsets. If the function has a variable parameter list,
728      * there's one additional byte (the arg size).
729      */
730     Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
731     Sym = GetSymTab()->SymTail;
732     while (Sym) {
733         unsigned Size = SizeOf (Sym->Type);
734         Sym->V.Offs = Offs;
735         Offs += Size;
736         F->ParamSize += Size;
737         Sym = Sym->PrevSym;
738     }
739
740     /* Leave the lexical level remembering the symbol tables */
741     RememberFunctionLevel (F);
742
743     /* Return the function descriptor */
744     return F;
745 }
746
747
748
749 static void Decl (Declaration* D, unsigned Mode)
750 /* Recursively process declarators. Build a type array in reverse order. */
751 {
752
753     if (curtok == TOK_STAR) {
754         type T = T_PTR;
755         NextToken ();
756         /* Allow optional const or volatile qualifiers */
757         T |= OptionalQualifiers (T_QUAL_NONE);
758         Decl (D, Mode);
759         *D->T++ = T;
760         return;
761     } else if (curtok == TOK_LPAREN) {
762         NextToken ();
763         Decl (D, Mode);
764         ConsumeRParen ();
765     } else if (curtok == TOK_FASTCALL) {
766         /* Remember the current type pointer */
767         type* T = D->T;
768         /* Skip the fastcall token */
769         NextToken ();
770         /* Parse the function */
771         Decl (D, Mode);
772         /* Set the fastcall flag */
773         if (!IsTypeFunc (T)) {
774             Error (ERR_ILLEGAL_MODIFIER);
775         } else {
776             FuncDesc* F = DecodePtr (T+1);
777             F->Flags |= FD_FASTCALL;
778         }
779         return;
780     } else {
781         /* Things depend on Mode now:
782          *  - Mode == DM_NEED_IDENT means:
783          *      we *must* have a type and a variable identifer.
784          *  - Mode == DM_NO_IDENT means:
785          *      we must have a type but no variable identifer
786          *      (if there is one, it's not read).
787          *  - Mode == DM_ACCEPT_IDENT means:
788          *      we *may* have an identifier. If there is an identifier,
789          *      it is read, but it is no error, if there is none.
790          */
791         if (Mode == DM_NO_IDENT) {
792             D->Ident[0] = '\0';
793         } else if (curtok == TOK_IDENT) {
794             strcpy (D->Ident, CurTok.Ident);
795             NextToken ();
796         } else {
797             if (Mode == DM_NEED_IDENT) {
798                 Error (ERR_IDENT_EXPECTED);
799             }
800             D->Ident[0] = '\0';
801             return;
802         }
803     }
804
805     while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
806         if (curtok == TOK_LPAREN) {
807             /* Function declaration */
808             FuncDesc* F;
809             NextToken ();
810             /* Parse the function declaration */
811             F = ParseFuncDecl ();
812             *D->T++ = T_FUNC;
813             EncodePtr (D->T, F);
814             D->T += DECODE_SIZE;
815         } else {
816             /* Array declaration */
817             unsigned long Size = 0;
818             NextToken ();
819             /* Read the size if it is given */
820             if (curtok != TOK_RBRACK) {
821                 struct expent lval;
822                 constexpr (&lval);
823                 Size = lval.e_const;
824             }
825             ConsumeRBrack ();
826             *D->T++ = T_ARRAY;
827             Encode (D->T, Size);
828             D->T += DECODE_SIZE;
829         }
830     }
831 }
832
833
834
835 /*****************************************************************************/
836 /*                                   code                                    */
837 /*****************************************************************************/
838
839
840
841 type* ParseType (type* Type)
842 /* Parse a complete type specification */
843 {
844     DeclSpec Spec;
845     Declaration Decl;
846
847     /* Get a type without a default */
848     InitDeclSpec (&Spec);
849     ParseTypeSpec (&Spec, -1);
850
851     /* Parse additional declarators */
852     InitDeclaration (&Decl);
853     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
854
855     /* Copy the type to the target buffer */
856     TypeCpy (Type, Decl.Type);
857
858     /* Return a pointer to the target buffer */
859     return Type;
860 }
861
862
863
864 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
865 /* Parse a variable, type or function declaration */
866 {
867     /* Initialize the Declaration struct */
868     InitDeclaration (D);
869
870     /* Get additional declarators and the identifier */
871     Decl (D, Mode);
872
873     /* Add the base type. */
874     TypeCpy (D->T, Spec->Type);
875
876     /* Check the size of the generated type */
877     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
878         Error (ERR_ILLEGAL_SIZE);
879     }
880 }
881
882
883
884 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
885 /* Parse a declaration specification */
886 {
887     /* Initialize the DeclSpec struct */
888     InitDeclSpec (D);
889
890     /* First, get the storage class specifier for this declaration */
891     ParseStorageClass (D, DefStorage);
892
893     /* Parse the type specifiers */
894     ParseTypeSpec (D, DefType);
895 }
896
897
898
899 void CheckEmptyDecl (const DeclSpec* D)
900 /* Called after an empty type declaration (that is, a type declaration without
901  * a variable). Checks if the declaration does really make sense and issues a
902  * warning if not.
903  */
904 {
905     if ((D->Flags & DS_EXTRA_TYPE) == 0) {
906         Warning (WARN_USELESS_DECL);
907     }
908 }
909
910
911
912 static void ParseVoidInit (void)
913 /* Parse an initialization of a void variable (special cc65 extension) */
914 {
915     struct expent lval;
916
917     /* Allow an arbitrary list of values */
918     ConsumeLCurly ();
919     do {
920         constexpr (&lval);
921         switch (lval.e_tptr[0]) {
922
923             case T_SCHAR:
924             case T_UCHAR:
925                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
926                     /* Make it byte sized */
927                     lval.e_const &= 0xFF;
928                 }
929                 DefineData (&lval);
930                 break;
931
932             case T_SHORT:
933             case T_USHORT:
934             case T_INT:
935             case T_UINT:
936             case T_PTR:
937             case T_ARRAY:
938                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
939                     /* Make it word sized */
940                     lval.e_const &= 0xFFFF;
941                 }
942                 DefineData (&lval);
943                 break;
944
945             case T_LONG:
946             case T_ULONG:
947                 DefineData (&lval);
948                 break;
949
950             default:
951                 Error (ERR_ILLEGAL_TYPE);
952                 break;
953
954         }
955
956         if (curtok != TOK_COMMA) {
957             break;
958         }
959         NextToken ();
960
961     } while (curtok != TOK_RCURLY);
962
963     ConsumeRCurly ();
964 }
965
966
967
968 static void ParseStructInit (type* Type)
969 /* Parse initialization of a struct or union */
970 {
971     SymEntry* Entry;
972     SymTable* Tab;
973
974     /* Consume the opening curly brace */
975     ConsumeLCurly ();
976
977     /* Get a pointer to the struct entry from the type */
978     Entry = (SymEntry*) Decode (Type + 1);
979
980     /* Check if this struct definition has a field table. If it doesn't, it
981      * is an incomplete definition.
982      */
983     Tab = Entry->V.S.SymTab;
984     if (Tab == 0) {
985         Error (ERR_INIT_INCOMPLETE_TYPE);
986         /* Returning here will cause lots of errors, but recovery is difficult */
987         return;
988     }
989
990     /* Get a pointer to the list of symbols */
991     Entry = Tab->SymHead;
992     while (curtok != TOK_RCURLY) {
993         if (Entry == 0) {
994             Error (ERR_TOO_MANY_INITIALIZERS);
995             return;
996         }
997         ParseInit (Entry->Type);
998         Entry = Entry->NextSym;
999         if (curtok != TOK_COMMA)
1000             break;
1001         NextToken ();
1002     }
1003
1004     /* Consume the closing curly brace */
1005     ConsumeRCurly ();
1006
1007     /* If there are struct fields left, reserve additional storage */
1008     while (Entry) {
1009         g_zerobytes (SizeOf (Entry->Type));
1010         Entry = Entry->NextSym;
1011     }
1012 }
1013
1014
1015
1016 void ParseInit (type* T)
1017 /* Parse initialization of variables. */
1018 {
1019     int count;
1020     struct expent lval;
1021     type* t;
1022     const char* str;
1023     int sz;
1024
1025     switch (UnqualifiedType (*T)) {
1026
1027         case T_SCHAR:
1028         case T_UCHAR:
1029             constexpr (&lval);
1030             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1031                 /* Make it byte sized */
1032                 lval.e_const &= 0xFF;
1033             }
1034             assignadjust (T, &lval);
1035             DefineData (&lval);
1036             break;
1037
1038         case T_SHORT:
1039         case T_USHORT:
1040         case T_INT:
1041         case T_UINT:
1042         case T_PTR:
1043             constexpr (&lval);
1044             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1045                 /* Make it word sized */
1046                 lval.e_const &= 0xFFFF;
1047             }
1048             assignadjust (T, &lval);
1049             DefineData (&lval);
1050             break;
1051
1052         case T_LONG:
1053         case T_ULONG:
1054             constexpr (&lval);
1055             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1056                 /* Make it long sized */
1057                 lval.e_const &= 0xFFFFFFFF;
1058             }
1059             assignadjust (T, &lval);
1060             DefineData (&lval);
1061             break;
1062
1063         case T_ARRAY:
1064             sz = Decode (T + 1);
1065             t = T + DECODE_SIZE + 1;
1066             if (IsTypeChar(t) && curtok == TOK_SCONST) {
1067                 str = GetLiteral (curval);
1068                 count = strlen (str) + 1;
1069                 TranslateLiteralPool (curval);  /* Translate into target charset */
1070                 g_defbytes (str, count);
1071                 ResetLiteralOffs (curval);      /* Remove string from pool */
1072                 NextToken ();
1073             } else {
1074                 ConsumeLCurly ();
1075                 count = 0;
1076                 while (curtok != TOK_RCURLY) {
1077                     ParseInit (T + DECODE_SIZE + 1);
1078                     ++count;
1079                     if (curtok != TOK_COMMA)
1080                         break;
1081                     NextToken ();
1082                 }
1083                 ConsumeRCurly ();
1084             }
1085             if (sz == 0) {
1086                 Encode (T + 1, count);
1087             } else if (count < sz) {
1088                 g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
1089             } else if (count > sz) {
1090                 Error (ERR_TOO_MANY_INITIALIZERS);
1091             }
1092             break;
1093
1094         case T_STRUCT:
1095         case T_UNION:
1096             ParseStructInit (T);
1097             break;
1098
1099         case T_VOID:
1100             if (!ANSI) {
1101                 /* Special cc65 extension in non ANSI mode */
1102                 ParseVoidInit ();
1103                 break;
1104             }
1105             /* FALLTHROUGH */
1106
1107         default:
1108             Error (ERR_ILLEGAL_TYPE);
1109             break;
1110
1111     }
1112 }
1113
1114
1115