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