]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
93760bc820401ffde66e67fa25ece85d40aabebb
[cc65] / src / cc65 / declare.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 declare.c                                 */
4 /*                                                                           */
5 /*                 Parse variable and function declarations                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <errno.h>
39
40 /* common */
41 #include "xmalloc.h"
42
43 /* cc65 */
44 #include "anonname.h"
45 #include "codegen.h"
46 #include "datatype.h"
47 #include "declattr.h"
48 #include "error.h"
49 #include "expr.h"
50 #include "funcdesc.h"
51 #include "function.h"
52 #include "global.h"
53 #include "litpool.h"
54 #include "pragma.h"
55 #include "scanner.h"
56 #include "symtab.h"
57 #include "declare.h"
58
59
60
61 /*****************************************************************************/
62 /*                                 Forwards                                  */
63 /*****************************************************************************/
64
65
66
67 static void ParseTypeSpec (DeclSpec* D, int Default);
68 /* Parse a type specificier */
69
70 static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers);
71 /* Parse initialization of variables. Return the number of data bytes. */
72
73
74
75 /*****************************************************************************/
76 /*                            internal functions                             */
77 /*****************************************************************************/
78
79
80
81 static type OptionalQualifiers (type Q)
82 /* Read type qualifiers if we have any */
83 {
84     while (CurTok.Tok == TOK_CONST || CurTok.Tok == TOK_VOLATILE) {
85
86         switch (CurTok.Tok) {
87
88             case TOK_CONST:
89                 if (Q & T_QUAL_CONST) {
90                     Error ("Duplicate qualifier: `const'");
91                 }
92                 Q |= T_QUAL_CONST;
93                 break;
94
95             case TOK_VOLATILE:
96                 if (Q & T_QUAL_VOLATILE) {
97                     Error ("Duplicate qualifier: `volatile'");
98                 }
99                 Q |= T_QUAL_VOLATILE;
100                 break;
101
102             default:
103                 /* Keep gcc silent */
104                 break;
105
106         }
107
108         /* Skip the token */
109         NextToken ();
110     }
111
112     /* Return the qualifiers read */
113     return Q;
114 }
115
116
117
118 static void optionalint (void)
119 /* Eat an optional "int" token */
120 {
121     if (CurTok.Tok == TOK_INT) {
122         /* Skip it */
123         NextToken ();
124     }
125 }
126
127
128
129 static void optionalsigned (void)
130 /* Eat an optional "signed" token */
131 {
132     if (CurTok.Tok == TOK_SIGNED) {
133         /* Skip it */
134         NextToken ();
135     }
136 }
137
138
139
140 static void InitDeclSpec (DeclSpec* D)
141 /* Initialize the DeclSpec struct for use */
142 {
143     D->StorageClass     = 0;
144     D->Type[0]          = T_END;
145     D->Flags            = 0;
146 }
147
148
149
150 static void InitDeclaration (Declaration* D)
151 /* Initialize the Declaration struct for use */
152 {
153     D->Ident[0]         = '\0';
154     D->Type[0]          = T_END;
155     D->T                = D->Type;
156 }
157
158
159
160 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
161 /* Parse a storage class */
162 {
163     /* Assume we're using an explicit storage class */
164     D->Flags &= ~DS_DEF_STORAGE;
165
166     /* Check the storage class given */
167     switch (CurTok.Tok) {
168
169         case TOK_EXTERN:
170             D->StorageClass = SC_EXTERN | SC_STATIC;
171             NextToken ();
172             break;
173
174         case TOK_STATIC:
175             D->StorageClass = SC_STATIC;
176             NextToken ();
177             break;
178
179         case TOK_REGISTER:
180             D->StorageClass = SC_REGISTER | SC_STATIC;
181             NextToken ();
182             break;
183
184         case TOK_AUTO:
185             D->StorageClass = SC_AUTO;
186             NextToken ();
187             break;
188
189         case TOK_TYPEDEF:
190             D->StorageClass = SC_TYPEDEF;
191             NextToken ();
192             break;
193
194         default:
195             /* No storage class given, use default */
196             D->Flags |= DS_DEF_STORAGE;
197             D->StorageClass = DefStorage;
198             break;
199     }
200 }
201
202
203
204 static void ParseEnumDecl (void)
205 /* Process an enum declaration . */
206 {
207     int EnumVal;
208     ident Ident;
209
210     /* Accept forward definitions */
211     if (CurTok.Tok != TOK_LCURLY) {
212         return;
213     }
214
215     /* Skip the opening curly brace */
216     NextToken ();
217
218     /* Read the enum tags */
219     EnumVal = 0;
220     while (CurTok.Tok != TOK_RCURLY) {
221
222         /* We expect an identifier */
223         if (CurTok.Tok != TOK_IDENT) {
224             Error ("Identifier expected");
225             continue;
226         }
227
228         /* Remember the identifier and skip it */
229         strcpy (Ident, CurTok.Ident);
230         NextToken ();
231
232         /* Check for an assigned value */
233         if (CurTok.Tok == TOK_ASSIGN) {
234             ExprDesc lval;
235             NextToken ();
236             ConstExpr (&lval);
237             EnumVal = lval.ConstVal;
238         }
239
240         /* Add an entry to the symbol table */
241         AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
242
243         /* Check for end of definition */
244         if (CurTok.Tok != TOK_COMMA)
245             break;
246         NextToken ();
247     }
248     ConsumeRCurly ();
249 }
250
251
252
253 static SymEntry* ParseStructDecl (const char* Name, type StructType)
254 /* Parse a struct/union declaration. */
255 {
256
257     unsigned  StructSize;
258     unsigned  FieldSize;
259     unsigned  Offs;
260     int       FlexibleMember;
261     SymTable* FieldTab;
262     SymEntry* Entry;
263
264
265     if (CurTok.Tok != TOK_LCURLY) {
266         /* Just a forward declaration. Try to find a struct with the given
267          * name. If there is none, insert a forward declaration into the
268          * current lexical level.
269          */
270         Entry = FindTagSym (Name);
271         if (Entry == 0) {
272             Entry = AddStructSym (Name, 0, 0);
273         } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
274             /* Already defined in the level but no struct */
275             Error ("Symbol `%s' is already different kind", Name);
276         }
277         return Entry;
278     }
279
280     /* Add a forward declaration for the struct in the current lexical level */
281     Entry = AddStructSym (Name, 0, 0);
282
283     /* Skip the curly brace */
284     NextToken ();
285
286     /* Enter a new lexical level for the struct */
287     EnterStructLevel ();
288
289     /* Parse struct fields */
290     FlexibleMember = 0;
291     StructSize     = 0;
292     while (CurTok.Tok != TOK_RCURLY) {
293
294         /* Get the type of the entry */
295         DeclSpec Spec;
296         InitDeclSpec (&Spec);
297         ParseTypeSpec (&Spec, -1);
298
299         /* Read fields with this type */
300         while (1) {
301
302             Declaration Decl;
303
304             /* If we had a flexible array member before, no other fields can
305              * follow.
306              */
307             if (FlexibleMember) {
308                 Error ("Flexible array member must be last field");
309                 FlexibleMember = 0;     /* Avoid further errors */
310             }
311
312             /* Get type and name of the struct field */
313             ParseDecl (&Spec, &Decl, 0);
314
315             /* Get the offset of this field */
316             Offs = (StructType == T_STRUCT)? StructSize : 0;
317
318             /* Calculate the sizes, handle flexible array members */
319             if (StructType == T_STRUCT) {
320
321                 /* It's a struct. Check if this field is a flexible array
322                  * member, and calculate the size of the field.
323                  */
324                 if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
325                     /* Array with unspecified size */
326                     if (StructSize == 0) {
327                         Error ("Flexible array member cannot be first struct field");
328                     }
329                     FlexibleMember = 1;
330                     /* Assume zero for size calculations */
331                     Encode (Decl.Type + 1, FLEXIBLE);
332                 } else {
333                     StructSize += CheckedSizeOf (Decl.Type);
334                 }
335
336             } else {
337
338                 /* It's a union */
339                 FieldSize = CheckedSizeOf (Decl.Type);
340                 if (FieldSize > StructSize) {
341                     StructSize = FieldSize;
342                 }
343             }
344
345             /* Add a field entry to the table */
346             AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
347
348             if (CurTok.Tok != TOK_COMMA) {
349                 break;
350             }
351             NextToken ();
352         }
353         ConsumeSemi ();
354     }
355
356     /* Skip the closing brace */
357     NextToken ();
358
359     /* Remember the symbol table and leave the struct level */
360     FieldTab = GetSymTab ();
361     LeaveStructLevel ();
362
363     /* Make a real entry from the forward decl and return it */
364     return AddStructSym (Name, StructSize, FieldTab);
365 }
366
367
368
369 static void ParseTypeSpec (DeclSpec* D, int Default)
370 /* Parse a type specificier */
371 {
372     ident       Ident;
373     SymEntry*   Entry;
374     type        StructType;
375     type        Qualifiers;     /* Type qualifiers */
376
377     /* Assume we have an explicit type */
378     D->Flags &= ~DS_DEF_TYPE;
379
380     /* Read type qualifiers if we have any */
381     Qualifiers = OptionalQualifiers (T_QUAL_NONE);
382
383     /* Look at the data type */
384     switch (CurTok.Tok) {
385
386         case TOK_VOID:
387             NextToken ();
388             D->Type[0] = T_VOID;
389             D->Type[1] = T_END;
390             break;
391
392         case TOK_CHAR:
393             NextToken ();
394             D->Type[0] = GetDefaultChar();
395             D->Type[1] = T_END;
396             break;
397
398         case TOK_LONG:
399             NextToken ();
400             if (CurTok.Tok == TOK_UNSIGNED) {
401                 NextToken ();
402                 optionalint ();
403                 D->Type[0] = T_ULONG;
404                 D->Type[1] = T_END;
405             } else {
406                 optionalsigned ();
407                 optionalint ();
408                 D->Type[0] = T_LONG;
409                 D->Type[1] = T_END;
410             }
411             break;
412
413         case TOK_SHORT:
414             NextToken ();
415             if (CurTok.Tok == TOK_UNSIGNED) {
416                 NextToken ();
417                 optionalint ();
418                 D->Type[0] = T_USHORT;
419                 D->Type[1] = T_END;
420             } else {
421                 optionalsigned ();
422                 optionalint ();
423                 D->Type[0] = T_SHORT;
424                 D->Type[1] = T_END;
425             }
426             break;
427
428         case TOK_INT:
429             NextToken ();
430             D->Type[0] = T_INT;
431             D->Type[1] = T_END;
432             break;
433
434        case TOK_SIGNED:
435             NextToken ();
436             switch (CurTok.Tok) {
437
438                 case TOK_CHAR:
439                     NextToken ();
440                     D->Type[0] = T_SCHAR;
441                     D->Type[1] = T_END;
442                     break;
443
444                 case TOK_SHORT:
445                     NextToken ();
446                     optionalint ();
447                     D->Type[0] = T_SHORT;
448                     D->Type[1] = T_END;
449                     break;
450
451                 case TOK_LONG:
452                     NextToken ();
453                     optionalint ();
454                     D->Type[0] = T_LONG;
455                     D->Type[1] = T_END;
456                     break;
457
458                 case TOK_INT:
459                     NextToken ();
460                     /* FALL THROUGH */
461
462                 default:
463                     D->Type[0] = T_INT;
464                     D->Type[1] = T_END;
465                     break;
466             }
467             break;
468
469         case TOK_UNSIGNED:
470             NextToken ();
471             switch (CurTok.Tok) {
472
473                 case TOK_CHAR:
474                     NextToken ();
475                     D->Type[0] = T_UCHAR;
476                     D->Type[1] = T_END;
477                     break;
478
479                 case TOK_SHORT:
480                     NextToken ();
481                     optionalint ();
482                     D->Type[0] = T_USHORT;
483                     D->Type[1] = T_END;
484                     break;
485
486                 case TOK_LONG:
487                     NextToken ();
488                     optionalint ();
489                     D->Type[0] = T_ULONG;
490                     D->Type[1] = T_END;
491                     break;
492
493                 case TOK_INT:
494                     NextToken ();
495                     /* FALL THROUGH */
496
497                 default:
498                     D->Type[0] = T_UINT;
499                     D->Type[1] = T_END;
500                     break;
501             }
502             break;
503
504         case TOK_STRUCT:
505         case TOK_UNION:
506             StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
507             NextToken ();
508             /* */
509             if (CurTok.Tok == TOK_IDENT) {
510                 strcpy (Ident, CurTok.Ident);
511                 NextToken ();
512             } else {
513                 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
514             }
515             /* Remember we have an extra type decl */
516             D->Flags |= DS_EXTRA_TYPE;
517             /* Declare the struct in the current scope */
518             Entry = ParseStructDecl (Ident, StructType);
519             /* Encode the struct entry into the type */
520             D->Type[0] = StructType;
521             EncodePtr (D->Type+1, Entry);
522             D->Type[DECODE_SIZE+1] = T_END;
523             break;
524
525         case TOK_ENUM:
526             NextToken ();
527             if (CurTok.Tok != TOK_LCURLY) {
528                 /* Named enum */
529                 if (CurTok.Tok == TOK_IDENT) {
530                     /* Find an entry with this name */
531                     Entry = FindTagSym (CurTok.Ident);
532                     if (Entry) {
533                         if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
534                             Error ("Symbol `%s' is already different kind", Entry->Name);
535                         }
536                     } else {
537                         /* Insert entry into table ### */
538                     }
539                     /* Skip the identifier */
540                     NextToken ();
541                 } else {
542                     Error ("Identifier expected");
543                 }
544             }
545             /* Remember we have an extra type decl */
546             D->Flags |= DS_EXTRA_TYPE;
547             /* Parse the enum decl */
548             ParseEnumDecl ();
549             D->Type[0] = T_INT;
550             D->Type[1] = T_END;
551             break;
552
553         case TOK_IDENT:
554             Entry = FindSym (CurTok.Ident);
555             if (Entry && SymIsTypeDef (Entry)) {
556                 /* It's a typedef */
557                 NextToken ();
558                 TypeCpy (D->Type, Entry->Type);
559                 break;
560             }
561             /* FALL THROUGH */
562
563         default:
564             if (Default < 0) {
565                 Error ("Type expected");
566                 D->Type[0] = T_INT;
567                 D->Type[1] = T_END;
568             } else {
569                 D->Flags  |= DS_DEF_TYPE;
570                 D->Type[0] = (type) Default;
571                 D->Type[1] = T_END;
572             }
573             break;
574     }
575
576     /* There may also be qualifiers *after* the initial type */
577     D->Type[0] |= OptionalQualifiers (Qualifiers);
578 }
579
580
581
582 static type* ParamTypeCvt (type* T)
583 /* If T is an array, convert it to a pointer else do nothing. Return the
584  * resulting type.
585  */
586 {
587     if (IsTypeArray (T)) {
588         T += DECODE_SIZE;
589         T[0] = T_PTR;
590     }
591     return T;
592 }
593
594
595
596 static void ParseOldStyleParamList (FuncDesc* F)
597 /* Parse an old style (K&R) parameter list */
598 {
599     /* Parse params */
600     while (CurTok.Tok != TOK_RPAREN) {
601
602         /* List of identifiers expected */
603         if (CurTok.Tok != TOK_IDENT) {
604             Error ("Identifier expected");
605         }
606
607         /* Create a symbol table entry with type int */
608         AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
609
610         /* Count arguments */
611         ++F->ParamCount;
612
613         /* Skip the identifier */
614         NextToken ();
615
616         /* Check for more parameters */
617         if (CurTok.Tok == TOK_COMMA) {
618             NextToken ();
619         } else {
620             break;
621         }
622     }
623
624     /* Skip right paren. We must explicitly check for one here, since some of
625      * the breaks above bail out without checking.
626      */
627     ConsumeRParen ();
628
629     /* An optional list of type specifications follows */
630     while (CurTok.Tok != TOK_LCURLY) {
631
632         DeclSpec        Spec;
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, since we use auto anyway.
639          */
640         if ((Spec.StorageClass & SC_AUTO) == 0 &&
641             (Spec.StorageClass & SC_REGISTER) == 0) {
642             Error ("Illegal storage class");
643         }
644
645         /* Parse a comma separated variable list */
646         while (1) {
647
648             Declaration         Decl;
649
650             /* Read the parameter */
651             ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
652             if (Decl.Ident[0] != '\0') {
653
654                 /* We have a name given. Search for the symbol */
655                 SymEntry* Sym = FindLocalSym (Decl.Ident);
656                 if (Sym) {
657                     /* Found it, change the default type to the one given */
658                     ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
659                 } else {
660                     Error ("Unknown identifier: `%s'", Decl.Ident);
661                 }
662             }
663
664             if (CurTok.Tok == TOK_COMMA) {
665                 NextToken ();
666             } else {
667                 break;
668             }
669
670         }
671
672         /* Variable list must be semicolon terminated */
673         ConsumeSemi ();
674     }
675 }
676
677
678
679 static void ParseAnsiParamList (FuncDesc* F)
680 /* Parse a new style (ANSI) parameter list */
681 {
682     /* Parse params */
683     while (CurTok.Tok != TOK_RPAREN) {
684
685         DeclSpec        Spec;
686         Declaration     Decl;
687         DeclAttr        Attr;
688
689         /* Allow an ellipsis as last parameter */
690         if (CurTok.Tok == TOK_ELLIPSIS) {
691             NextToken ();
692             F->Flags |= FD_VARIADIC;
693             break;
694         }
695
696         /* Read the declaration specifier */
697         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
698
699         /* We accept only auto and register as storage class specifiers */
700         if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
701             Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
702         } else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
703             Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
704         } else {
705             Error ("Illegal storage class");
706             Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
707         }
708
709         /* Allow parameters without a name, but remember if we had some to
710          * eventually print an error message later.
711          */
712         ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
713         if (Decl.Ident[0] == '\0') {
714
715             /* Unnamed symbol. Generate a name that is not user accessible,
716              * then handle the symbol normal.
717              */
718             AnonName (Decl.Ident, "param");
719             F->Flags |= FD_UNNAMED_PARAMS;
720
721             /* Clear defined bit on nonames */
722             Spec.StorageClass &= ~SC_DEF;
723         }
724
725         /* Parse an attribute ### */
726         ParseAttribute (&Decl, &Attr);
727
728         /* Create a symbol table entry */
729         AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
730
731         /* Count arguments */
732         ++F->ParamCount;
733
734         /* Check for more parameters */
735         if (CurTok.Tok == TOK_COMMA) {
736             NextToken ();
737         } else {
738             break;
739         }
740     }
741
742     /* Skip right paren. We must explicitly check for one here, since some of
743      * the breaks above bail out without checking.
744      */
745     ConsumeRParen ();
746
747     /* Check if this is a function definition */
748     if (CurTok.Tok == TOK_LCURLY) {
749         /* Print an error if in strict ANSI mode and we have unnamed
750          * parameters.
751          */
752         if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
753             Error ("Parameter name omitted");
754         }
755     }
756 }
757
758
759
760 static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
761 /* Parse the argument list of a function. */
762 {
763     unsigned Offs;
764     SymEntry* Sym;
765
766     /* Create a new function descriptor */
767     FuncDesc* F = NewFuncDesc ();
768
769     /* Enter a new lexical level */
770     EnterFunctionLevel ();
771
772     /* Check for several special parameter lists */
773     if (CurTok.Tok == TOK_RPAREN) {
774         /* Parameter list is empty */
775         F->Flags |= (FD_EMPTY | FD_VARIADIC);
776     } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
777         /* Parameter list declared as void */
778         NextToken ();
779         F->Flags |= FD_VOID_PARAM;
780     } else if (CurTok.Tok == TOK_IDENT &&
781                (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
782         /* If the identifier is a typedef, we have a new style parameter list,
783          * if it's some other identifier, it's an old style parameter list.
784          */
785         Sym = FindSym (CurTok.Ident);
786         if (Sym == 0 || !SymIsTypeDef (Sym)) {
787             /* Old style (K&R) function. Assume variable param list. */
788             F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
789         }
790     }
791
792     /* Check for an implicit int return in the function */
793     if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
794         Spec->Type[0] == T_INT           &&
795         Spec->Type[1] == T_END) {
796         /* Function has an implicit int return */
797         F->Flags |= FD_OLDSTYLE_INTRET;
798     }
799
800     /* Parse params */
801     if ((F->Flags & FD_OLDSTYLE) == 0) {
802         /* New style function */
803         ParseAnsiParamList (F);
804     } else {
805         /* Old style function */
806         ParseOldStyleParamList (F);
807     }
808
809     /* Remember the last function parameter. We need it later for several
810      * purposes, for example when passing stuff to fastcall functions. Since
811      * more symbols are added to the table, it is easier if we remember it
812      * now, since it is currently the last entry in the symbol table.
813      */
814     F->LastParam = GetSymTab()->SymTail;
815
816     /* Assign offsets. If the function has a variable parameter list,
817      * there's one additional byte (the arg size).
818      */
819     Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
820     Sym = F->LastParam;
821     while (Sym) {
822         unsigned Size = CheckedSizeOf (Sym->Type);
823         if (SymIsRegVar (Sym)) {
824             Sym->V.R.SaveOffs = Offs;
825         } else {
826             Sym->V.Offs = Offs;
827         }
828         Offs += Size;
829         F->ParamSize += Size;
830         Sym = Sym->PrevSym;
831     }
832
833     /* Leave the lexical level remembering the symbol tables */
834     RememberFunctionLevel (F);
835
836     /* Return the function descriptor */
837     return F;
838 }
839
840
841
842 static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
843 /* Recursively process declarators. Build a type array in reverse order. */
844 {
845
846     if (CurTok.Tok == TOK_STAR) {
847         type T = T_PTR;
848         NextToken ();
849         /* Allow optional const or volatile qualifiers */
850         T |= OptionalQualifiers (T_QUAL_NONE);
851         Decl (Spec, D, Mode);
852         *D->T++ = T;
853         return;
854     } else if (CurTok.Tok == TOK_LPAREN) {
855         NextToken ();
856         Decl (Spec, D, Mode);
857         ConsumeRParen ();
858     } else if (CurTok.Tok == TOK_FASTCALL) {
859         /* Remember the current type pointer */
860         type* T = D->T;
861         /* Skip the fastcall token */
862         NextToken ();
863         /* Parse the function */
864         Decl (Spec, D, Mode);
865         /* Set the fastcall flag */
866         if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
867             Error ("__fastcall__ modifier applied to non function");
868         } else if (IsVariadicFunc (T)) {
869             Error ("Cannot apply __fastcall__ to functions with variable parameter list");
870         } else {
871             FuncDesc* F = GetFuncDesc (T);
872             F->Flags |= FD_FASTCALL;
873         }
874         return;
875     } else {
876         /* Things depend on Mode now:
877          *  - Mode == DM_NEED_IDENT means:
878          *      we *must* have a type and a variable identifer.
879          *  - Mode == DM_NO_IDENT means:
880          *      we must have a type but no variable identifer
881          *      (if there is one, it's not read).
882          *  - Mode == DM_ACCEPT_IDENT means:
883          *      we *may* have an identifier. If there is an identifier,
884          *      it is read, but it is no error, if there is none.
885          */
886         if (Mode == DM_NO_IDENT) {
887             D->Ident[0] = '\0';
888         } else if (CurTok.Tok == TOK_IDENT) {
889             strcpy (D->Ident, CurTok.Ident);
890             NextToken ();
891         } else {
892             if (Mode == DM_NEED_IDENT) {
893                 Error ("Identifier expected");
894             }
895             D->Ident[0] = '\0';
896         }
897     }
898
899     while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
900         if (CurTok.Tok == TOK_LPAREN) {
901             /* Function declaration */
902             FuncDesc* F;
903             NextToken ();
904             /* Parse the function declaration */
905             F = ParseFuncDecl (Spec);
906             *D->T++ = T_FUNC;
907             EncodePtr (D->T, F);
908             D->T += DECODE_SIZE;
909         } else {
910             /* Array declaration */
911             long Size = UNSPECIFIED;
912             NextToken ();
913             /* Read the size if it is given */
914             if (CurTok.Tok != TOK_RBRACK) {
915                 ExprDesc lval;
916                 ConstExpr (&lval);
917                 if (lval.ConstVal <= 0) {
918                     if (D->Ident[0] != '\0') {
919                         Error ("Size of array `%s' is invalid", D->Ident);
920                     } else {
921                         Error ("Size of array is invalid");
922                     }
923                     lval.ConstVal = 1;
924                 }
925                 Size = lval.ConstVal;
926             }
927             ConsumeRBrack ();
928             *D->T++ = T_ARRAY;
929             Encode (D->T, Size);
930             D->T += DECODE_SIZE;
931         }
932     }
933 }
934
935
936
937 /*****************************************************************************/
938 /*                                   code                                    */
939 /*****************************************************************************/
940
941
942
943 type* ParseType (type* Type)
944 /* Parse a complete type specification */
945 {
946     DeclSpec Spec;
947     Declaration Decl;
948
949     /* Get a type without a default */
950     InitDeclSpec (&Spec);
951     ParseTypeSpec (&Spec, -1);
952
953     /* Parse additional declarators */
954     InitDeclaration (&Decl);
955     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
956
957     /* Copy the type to the target buffer */
958     TypeCpy (Type, Decl.Type);
959
960     /* Return a pointer to the target buffer */
961     return Type;
962 }
963
964
965
966 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
967 /* Parse a variable, type or function declaration */
968 {
969     /* Initialize the Declaration struct */
970     InitDeclaration (D);
971
972     /* Get additional declarators and the identifier */
973     Decl (Spec, D, Mode);
974
975     /* Add the base type. */
976     TypeCpy (D->T, Spec->Type);
977
978     /* Check the size of the generated type */
979     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
980         if (D->Ident[0] != '\0') {
981             Error ("Size of `%s' is invalid", D->Ident);
982         } else {
983             Error ("Invalid size");
984         }
985     }
986 }
987
988
989
990 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
991 /* Parse a declaration specification */
992 {
993     /* Initialize the DeclSpec struct */
994     InitDeclSpec (D);
995
996     /* First, get the storage class specifier for this declaration */
997     ParseStorageClass (D, DefStorage);
998
999     /* Parse the type specifiers */
1000     ParseTypeSpec (D, DefType);
1001 }
1002
1003
1004
1005 void CheckEmptyDecl (const DeclSpec* D)
1006 /* Called after an empty type declaration (that is, a type declaration without
1007  * a variable). Checks if the declaration does really make sense and issues a
1008  * warning if not.
1009  */
1010 {
1011     if ((D->Flags & DS_EXTRA_TYPE) == 0) {
1012         Warning ("Useless declaration");
1013     }
1014 }
1015
1016
1017
1018 static void SkipInitializer (unsigned BracesExpected)
1019 /* Skip the remainder of an initializer in case of errors. Try to be somewhat
1020  * smart so we don't have too many following errors.
1021  */
1022 {
1023     while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) {
1024         switch (CurTok.Tok) {
1025             case TOK_RCURLY:    --BracesExpected;   break;
1026             case TOK_LCURLY:    ++BracesExpected;   break;
1027             default:                                break;
1028         }
1029         NextToken ();
1030     }
1031 }
1032
1033
1034
1035 static unsigned OpeningCurlyBraces (unsigned BracesNeeded)
1036 /* Accept any number of opening curly braces around an initialization, skip
1037  * them and return the number. If the number of curly braces is less than
1038  * BracesNeeded, issue a warning.
1039  */
1040 {
1041     unsigned BraceCount = 0;
1042     while (CurTok.Tok == TOK_LCURLY) {
1043         ++BraceCount;
1044         NextToken ();
1045     }
1046     if (BraceCount < BracesNeeded) {
1047         Error ("`{' expected");
1048     }
1049     return BraceCount;
1050 }
1051
1052
1053
1054 static void ClosingCurlyBraces (unsigned BracesExpected)
1055 /* Accept and skip the given number of closing curly braces together with
1056  * an optional comma. Output an error messages, if the input does not contain
1057  * the expected number of braces.
1058  */
1059 {
1060     while (BracesExpected) {
1061         if (CurTok.Tok == TOK_RCURLY) {
1062             NextToken ();
1063         } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) {
1064             NextToken ();
1065             NextToken ();
1066         } else {
1067             Error ("`}' expected");
1068             return;
1069         }
1070         --BracesExpected;
1071     }
1072 }
1073
1074
1075
1076 static unsigned ParseScalarInit (type* T)
1077 /* Parse initializaton for scalar data types. Return the number of data bytes. */
1078 {
1079     static const unsigned long Masks[] = {
1080         0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
1081     };
1082     unsigned BraceCount;
1083     ExprDesc ED;
1084
1085     /* Get the size of the expected type */
1086     unsigned Size = SizeOf (T);
1087     CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0]));
1088
1089     /* Optional opening brace */
1090     BraceCount = OpeningCurlyBraces (0);
1091
1092     /* We warn if an initializer for a scalar contains braces, because this is
1093      * quite unusual and often a sign for some problem in the input.
1094      */
1095     if (BraceCount > 0) {
1096         Warning ("Braces around scalar initializer");
1097     }
1098
1099     /* Expression */
1100     ConstExpr (&ED);
1101     if ((ED.Flags & E_MCTYPE) == E_TCONST) {
1102         /* Make the const value the correct size */
1103         ED.ConstVal &= Masks[Size-1];
1104     }
1105     assignadjust (T, &ED);
1106
1107     /* Output the data */
1108     DefineData (&ED);
1109
1110     /* Close eventually opening braces */
1111     ClosingCurlyBraces (BraceCount);
1112
1113     /* Done */
1114     return Size;
1115 }
1116
1117
1118
1119 static unsigned ParsePointerInit (type* T)
1120 /* Parse initializaton for pointer data types. Return the number of data bytes. */
1121 {
1122     /* Optional opening brace */
1123     unsigned BraceCount = OpeningCurlyBraces (0);
1124
1125     /* Expression */
1126     ExprDesc ED;
1127     ConstExpr (&ED);
1128     if ((ED.Flags & E_MCTYPE) == E_TCONST) {
1129         /* Make the const value the correct size */
1130         ED.ConstVal &= 0xFFFF;
1131     }
1132     assignadjust (T, &ED);
1133
1134     /* Output the data */
1135     DefineData (&ED);
1136
1137     /* Close eventually opening braces */
1138     ClosingCurlyBraces (BraceCount);
1139
1140     /* Done */
1141     return SIZEOF_PTR;
1142 }
1143
1144
1145
1146 static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
1147 /* Parse initializaton for arrays. Return the number of data bytes. */
1148 {
1149     int Count;
1150
1151     /* Get the array data */
1152     type* ElementType    = GetElementType (T);
1153     unsigned ElementSize = CheckedSizeOf (ElementType);
1154     long ElementCount    = GetElementCount (T);
1155
1156     /* Special handling for a character array initialized by a literal */
1157     if (IsTypeChar (ElementType) && CurTok.Tok == TOK_SCONST) {
1158
1159         /* Char array initialized by string constant */
1160         const char* Str = GetLiteral (CurTok.IVal);
1161         Count = GetLiteralPoolOffs () - CurTok.IVal;
1162
1163         /* Translate into target charset */
1164         TranslateLiteralPool (CurTok.IVal);
1165
1166         /* If the array is one too small for the string literal, omit the
1167          * trailing zero.
1168          */
1169         if (ElementCount != UNSPECIFIED &&
1170             ElementCount != FLEXIBLE    &&
1171             Count        == ElementCount + 1) {
1172             /* Omit the trailing zero */
1173             --Count;
1174         }
1175
1176         /* Output the data */
1177         g_defbytes (Str, Count);
1178
1179         /* Remove string from pool */
1180         ResetLiteralPoolOffs (CurTok.IVal);
1181         NextToken ();
1182
1183     } else {
1184
1185         /* Curly brace */
1186         ConsumeLCurly ();
1187
1188         /* Initialize the array members */
1189         Count = 0;
1190         while (CurTok.Tok != TOK_RCURLY) {
1191             /* Flexible array members may not be initialized within
1192              * an array (because the size of each element may differ
1193              * otherwise).
1194              */
1195             ParseInitInternal (ElementType, 0);
1196             ++Count;
1197             if (CurTok.Tok != TOK_COMMA)
1198                 break;
1199             NextToken ();
1200         }
1201
1202         /* Closing curly braces */
1203         ConsumeRCurly ();
1204     }
1205
1206
1207     if (ElementCount == UNSPECIFIED) {
1208         /* Number of elements determined by initializer */
1209         Encode (T + 1, Count);
1210         ElementCount = Count;
1211     } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
1212         /* In non ANSI mode, allow initialization of flexible array
1213          * members.
1214          */
1215         ElementCount = Count;
1216     } else if (Count < ElementCount) {
1217         g_zerobytes ((ElementCount - Count) * ElementSize);
1218     } else if (Count > ElementCount) {
1219         Error ("Too many initializers");
1220     }
1221     return ElementCount * ElementSize;
1222 }
1223
1224
1225
1226 static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
1227 /* Parse initialization of a struct or union. Return the number of data bytes. */
1228 {
1229     SymEntry* Entry;
1230     SymTable* Tab;
1231     unsigned  StructSize;
1232     unsigned  Size;
1233
1234
1235     /* Consume the opening curly brace */
1236     ConsumeLCurly ();
1237
1238     /* Get a pointer to the struct entry from the type */
1239     Entry = DecodePtr (Type + 1);
1240
1241     /* Get the size of the struct from the symbol table entry */
1242     StructSize = Entry->V.S.Size;
1243
1244     /* Check if this struct definition has a field table. If it doesn't, it
1245      * is an incomplete definition.
1246      */
1247     Tab = Entry->V.S.SymTab;
1248     if (Tab == 0) {
1249         Error ("Cannot initialize variables with incomplete type");
1250         /* Try error recovery */
1251         SkipInitializer (1);
1252         /* Nothing initialized */
1253         return 0;
1254     }
1255
1256     /* Get a pointer to the list of symbols */
1257     Entry = Tab->SymHead;
1258
1259     /* Initialize fields */
1260     Size = 0;
1261     while (CurTok.Tok != TOK_RCURLY) {
1262         if (Entry == 0) {
1263             Error ("Too many initializers");
1264             SkipInitializer (1);
1265             return Size;
1266         }
1267         /* Parse initialization of one field. Flexible array members may
1268          * only be initialized if they are the last field (or part of the
1269          * last struct field).
1270          */
1271         Size += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
1272         Entry = Entry->NextSym;
1273         if (CurTok.Tok != TOK_COMMA)
1274             break;
1275         NextToken ();
1276     }
1277
1278     /* Consume the closing curly brace */
1279     ConsumeRCurly ();
1280
1281     /* If there are struct fields left, reserve additional storage */
1282     if (Size < StructSize) {
1283         g_zerobytes (StructSize - Size);
1284         Size = StructSize;
1285     }
1286
1287     /* Return the actual number of bytes initialized. This number may be
1288      * larger than StructSize if flexible array members are present and were
1289      * initialized (possible in non ANSI mode).
1290      */
1291     return Size;
1292 }
1293
1294
1295
1296 static unsigned ParseVoidInit (void)
1297 /* Parse an initialization of a void variable (special cc65 extension).
1298  * Return the number of bytes initialized.
1299  */
1300 {
1301     ExprDesc lval;
1302     unsigned Size;
1303
1304     /* Opening brace */
1305     ConsumeLCurly ();
1306
1307     /* Allow an arbitrary list of values */
1308     Size = 0;
1309     do {
1310         ConstExpr (&lval);
1311         switch (UnqualifiedType (lval.Type[0])) {
1312
1313             case T_SCHAR:
1314             case T_UCHAR:
1315                 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1316                     /* Make it byte sized */
1317                     lval.ConstVal &= 0xFF;
1318                 }
1319                 DefineData (&lval);
1320                 Size += SIZEOF_CHAR;
1321                 break;
1322
1323             case T_SHORT:
1324             case T_USHORT:
1325             case T_INT:
1326             case T_UINT:
1327             case T_PTR:
1328             case T_ARRAY:
1329                 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1330                     /* Make it word sized */
1331                     lval.ConstVal &= 0xFFFF;
1332                 }
1333                 DefineData (&lval);
1334                 Size += SIZEOF_INT;
1335                 break;
1336
1337             case T_LONG:
1338             case T_ULONG:
1339                 DefineData (&lval);
1340                 Size += SIZEOF_LONG;
1341                 break;
1342
1343             default:
1344                 Error ("Illegal type in initialization");
1345                 break;
1346
1347         }
1348
1349         if (CurTok.Tok != TOK_COMMA) {
1350             break;
1351         }
1352         NextToken ();
1353
1354     } while (CurTok.Tok != TOK_RCURLY);
1355
1356     /* Closing brace */
1357     ConsumeRCurly ();
1358
1359     /* Return the number of bytes initialized */
1360     return Size;
1361 }
1362
1363
1364
1365 static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
1366 /* Parse initialization of variables. Return the number of data bytes. */
1367 {
1368     switch (UnqualifiedType (*T)) {
1369
1370         case T_SCHAR:
1371         case T_UCHAR:
1372         case T_SHORT:
1373         case T_USHORT:
1374         case T_INT:
1375         case T_UINT:
1376         case T_LONG:
1377         case T_ULONG:
1378             return ParseScalarInit (T);
1379
1380         case T_PTR:
1381             return ParsePointerInit (T);
1382
1383         case T_ARRAY:
1384             return ParseArrayInit (T, AllowFlexibleMembers);
1385
1386         case T_STRUCT:
1387         case T_UNION:
1388             return ParseStructInit (T, AllowFlexibleMembers);
1389
1390         case T_VOID:
1391             if (!ANSI) {
1392                 /* Special cc65 extension in non ANSI mode */
1393                 return ParseVoidInit ();
1394             }
1395             /* FALLTHROUGH */
1396
1397         default:
1398             Error ("Illegal type");
1399             return SIZEOF_CHAR;
1400
1401     }
1402 }
1403
1404
1405
1406 unsigned ParseInit (type* T)
1407 /* Parse initialization of variables. Return the number of data bytes. */
1408 {
1409     return ParseInitInternal (T, !ANSI);
1410 }
1411
1412
1413