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