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