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