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