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