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