]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
Fixed a bug
[cc65] / src / cc65 / declare.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 declare.c                                 */
4 /*                                                                           */
5 /*                 Parse variable and function declarations                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2002 Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
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 Size;
255     unsigned Offs;
256     SymTable* FieldTab;
257     SymEntry* Entry;
258
259
260     if (CurTok.Tok != TOK_LCURLY) {
261         /* Just a forward declaration. Try to find a struct with the given
262          * name. If there is none, insert a forward declaration into the
263          * current lexical level.
264          */
265         Entry = FindTagSym (Name);
266         if (Entry == 0) {
267             Entry = AddStructSym (Name, 0, 0);
268         } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
269             /* Already defined in the level but no struct */
270             Error ("Symbol `%s' is already different kind", Name);
271         }
272         return Entry;
273     }
274
275     /* Add a forward declaration for the struct in the current lexical level */
276     Entry = AddStructSym (Name, 0, 0);
277
278     /* Skip the curly brace */
279     NextToken ();
280
281     /* Enter a new lexical level for the struct */
282     EnterStructLevel ();
283
284     /* Parse struct fields */
285     Size = 0;
286     while (CurTok.Tok != TOK_RCURLY) {
287
288         /* Get the type of the entry */
289         DeclSpec Spec;
290         InitDeclSpec (&Spec);
291         ParseTypeSpec (&Spec, -1);
292
293         /* Read fields with this type */
294         while (1) {
295
296             /* Get type and name of the struct field */
297             Declaration Decl;
298             ParseDecl (&Spec, &Decl, 0);
299
300             /* Get the offset of this field */
301             Offs = (StructType == T_STRUCT)? Size : 0;
302
303             /* Add a field entry to the table */
304             AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
305
306             /* Calculate offset of next field/size of the union */
307             Offs = CheckedSizeOf (Decl.Type);
308             if (StructType == T_STRUCT) {
309                 Size += Offs;
310             } else {
311                 if (Offs > Size) {
312                     Size = Offs;
313                 }
314             }
315
316             if (CurTok.Tok != TOK_COMMA)
317                 break;
318             NextToken ();
319         }
320         ConsumeSemi ();
321     }
322
323     /* Skip the closing brace */
324     NextToken ();
325
326     /* Remember the symbol table and leave the struct level */
327     FieldTab = GetSymTab ();
328     LeaveStructLevel ();
329
330     /* Make a real entry from the forward decl and return it */
331     return AddStructSym (Name, Size, FieldTab);
332 }
333
334
335
336 static void ParseTypeSpec (DeclSpec* D, int Default)
337 /* Parse a type specificier */
338 {
339     ident       Ident;
340     SymEntry*   Entry;
341     type        StructType;
342     type        Qualifiers;     /* Type qualifiers */
343
344     /* Assume we have an explicit type */
345     D->Flags &= ~DS_DEF_TYPE;
346
347     /* Read type qualifiers if we have any */
348     Qualifiers = OptionalQualifiers (T_QUAL_NONE);
349
350     /* Look at the data type */
351     switch (CurTok.Tok) {
352
353         case TOK_VOID:
354             NextToken ();
355             D->Type[0] = T_VOID;
356             D->Type[1] = T_END;
357             break;
358
359         case TOK_CHAR:
360             NextToken ();
361             D->Type[0] = GetDefaultChar();
362             D->Type[1] = T_END;
363             break;
364
365         case TOK_LONG:
366             NextToken ();
367             if (CurTok.Tok == TOK_UNSIGNED) {
368                 NextToken ();
369                 optionalint ();
370                 D->Type[0] = T_ULONG;
371                 D->Type[1] = T_END;
372             } else {
373                 optionalsigned ();
374                 optionalint ();
375                 D->Type[0] = T_LONG;
376                 D->Type[1] = T_END;
377             }
378             break;
379
380         case TOK_SHORT:
381             NextToken ();
382             if (CurTok.Tok == TOK_UNSIGNED) {
383                 NextToken ();
384                 optionalint ();
385                 D->Type[0] = T_USHORT;
386                 D->Type[1] = T_END;
387             } else {
388                 optionalsigned ();
389                 optionalint ();
390                 D->Type[0] = T_SHORT;
391                 D->Type[1] = T_END;
392             }
393             break;
394
395         case TOK_INT:
396             NextToken ();
397             D->Type[0] = T_INT;
398             D->Type[1] = T_END;
399             break;
400
401        case TOK_SIGNED:
402             NextToken ();
403             switch (CurTok.Tok) {
404
405                 case TOK_CHAR:
406                     NextToken ();
407                     D->Type[0] = T_SCHAR;
408                     D->Type[1] = T_END;
409                     break;
410
411                 case TOK_SHORT:
412                     NextToken ();
413                     optionalint ();
414                     D->Type[0] = T_SHORT;
415                     D->Type[1] = T_END;
416                     break;
417
418                 case TOK_LONG:
419                     NextToken ();
420                     optionalint ();
421                     D->Type[0] = T_LONG;
422                     D->Type[1] = T_END;
423                     break;
424
425                 case TOK_INT:
426                     NextToken ();
427                     /* FALL THROUGH */
428
429                 default:
430                     D->Type[0] = T_INT;
431                     D->Type[1] = T_END;
432                     break;
433             }
434             break;
435
436         case TOK_UNSIGNED:
437             NextToken ();
438             switch (CurTok.Tok) {
439
440                 case TOK_CHAR:
441                     NextToken ();
442                     D->Type[0] = T_UCHAR;
443                     D->Type[1] = T_END;
444                     break;
445
446                 case TOK_SHORT:
447                     NextToken ();
448                     optionalint ();
449                     D->Type[0] = T_USHORT;
450                     D->Type[1] = T_END;
451                     break;
452
453                 case TOK_LONG:
454                     NextToken ();
455                     optionalint ();
456                     D->Type[0] = T_ULONG;
457                     D->Type[1] = T_END;
458                     break;
459
460                 case TOK_INT:
461                     NextToken ();
462                     /* FALL THROUGH */
463
464                 default:
465                     D->Type[0] = T_UINT;
466                     D->Type[1] = T_END;
467                     break;
468             }
469             break;
470
471         case TOK_STRUCT:
472         case TOK_UNION:
473             StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
474             NextToken ();
475             /* */
476             if (CurTok.Tok == TOK_IDENT) {
477                 strcpy (Ident, CurTok.Ident);
478                 NextToken ();
479             } else {
480                 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
481             }
482             /* Remember we have an extra type decl */
483             D->Flags |= DS_EXTRA_TYPE;
484             /* Declare the struct in the current scope */
485             Entry = ParseStructDecl (Ident, StructType);
486             /* Encode the struct entry into the type */
487             D->Type[0] = StructType;
488             EncodePtr (D->Type+1, Entry);
489             D->Type[DECODE_SIZE+1] = T_END;
490             break;
491
492         case TOK_ENUM:
493             NextToken ();
494             if (CurTok.Tok != TOK_LCURLY) {
495                 /* Named enum */
496                 if (CurTok.Tok == TOK_IDENT) {
497                     /* Find an entry with this name */
498                     Entry = FindTagSym (CurTok.Ident);
499                     if (Entry) {
500                         if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
501                             Error ("Symbol `%s' is already different kind", Entry->Name);
502                         }
503                     } else {
504                         /* Insert entry into table ### */
505                     }
506                     /* Skip the identifier */
507                     NextToken ();
508                 } else {
509                     Error ("Identifier expected");
510                 }
511             }
512             /* Remember we have an extra type decl */
513             D->Flags |= DS_EXTRA_TYPE;
514             /* Parse the enum decl */
515             ParseEnumDecl ();
516             D->Type[0] = T_INT;
517             D->Type[1] = T_END;
518             break;
519
520         case TOK_IDENT:
521             Entry = FindSym (CurTok.Ident);
522             if (Entry && SymIsTypeDef (Entry)) {
523                 /* It's a typedef */
524                 NextToken ();
525                 TypeCpy (D->Type, Entry->Type);
526                 break;
527             }
528             /* FALL THROUGH */
529
530         default:
531             if (Default < 0) {
532                 Error ("Type expected");
533                 D->Type[0] = T_INT;
534                 D->Type[1] = T_END;
535             } else {
536                 D->Flags  |= DS_DEF_TYPE;
537                 D->Type[0] = (type) Default;
538                 D->Type[1] = T_END;
539             }
540             break;
541     }
542
543     /* There may also be qualifiers *after* the initial type */
544     D->Type[0] |= OptionalQualifiers (Qualifiers);
545 }
546
547
548
549 static type* ParamTypeCvt (type* T)
550 /* If T is an array, convert it to a pointer else do nothing. Return the
551  * resulting type.
552  */
553 {
554     if (IsTypeArray (T)) {
555         T += DECODE_SIZE;
556         T[0] = T_PTR;
557     }
558     return T;
559 }
560
561
562
563 static void ParseOldStyleParamList (FuncDesc* F)
564 /* Parse an old style (K&R) parameter list */
565 {
566     /* Parse params */
567     while (CurTok.Tok != TOK_RPAREN) {
568
569         /* List of identifiers expected */
570         if (CurTok.Tok != TOK_IDENT) {
571             Error ("Identifier expected");
572         }
573
574         /* Create a symbol table entry with type int */
575         AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
576
577         /* Count arguments */
578         ++F->ParamCount;
579
580         /* Skip the identifier */
581         NextToken ();
582
583         /* Check for more parameters */
584         if (CurTok.Tok == TOK_COMMA) {
585             NextToken ();
586         } else {
587             break;
588         }
589     }
590
591     /* Skip right paren. We must explicitly check for one here, since some of
592      * the breaks above bail out without checking.
593      */
594     ConsumeRParen ();
595
596     /* An optional list of type specifications follows */
597     while (CurTok.Tok != TOK_LCURLY) {
598
599         DeclSpec        Spec;
600
601         /* Read the declaration specifier */
602         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
603
604         /* We accept only auto and register as storage class specifiers, but
605          * we ignore all this, since we use auto anyway.
606          */
607         if ((Spec.StorageClass & SC_AUTO) == 0 &&
608             (Spec.StorageClass & SC_REGISTER) == 0) {
609             Error ("Illegal storage class");
610         }
611
612         /* Parse a comma separated variable list */
613         while (1) {
614
615             Declaration         Decl;
616
617             /* Read the parameter */
618             ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
619             if (Decl.Ident[0] != '\0') {
620
621                 /* We have a name given. Search for the symbol */
622                 SymEntry* Sym = FindLocalSym (Decl.Ident);
623                 if (Sym) {
624                     /* Found it, change the default type to the one given */
625                     ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
626                 } else {
627                     Error ("Unknown identifier: `%s'", Decl.Ident);
628                 }
629             }
630
631             if (CurTok.Tok == TOK_COMMA) {
632                 NextToken ();
633             } else {
634                 break;
635             }
636
637         }
638
639         /* Variable list must be semicolon terminated */
640         ConsumeSemi ();
641     }
642 }
643
644
645
646 static void ParseAnsiParamList (FuncDesc* F)
647 /* Parse a new style (ANSI) parameter list */
648 {
649     /* Parse params */
650     while (CurTok.Tok != TOK_RPAREN) {
651
652         DeclSpec        Spec;
653         Declaration     Decl;
654         DeclAttr        Attr;
655
656         /* Allow an ellipsis as last parameter */
657         if (CurTok.Tok == TOK_ELLIPSIS) {
658             NextToken ();
659             F->Flags |= FD_VARIADIC;
660             break;
661         }
662
663         /* Read the declaration specifier */
664         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
665
666         /* We accept only auto and register as storage class specifiers, but
667          * we ignore all this and use auto.
668          */
669         if ((Spec.StorageClass & SC_AUTO) == 0 &&
670             (Spec.StorageClass & SC_REGISTER) == 0) {
671             Error ("Illegal storage class");
672         }
673         Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
674
675         /* Allow parameters without a name, but remember if we had some to
676          * eventually print an error message later.
677          */
678         ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
679         if (Decl.Ident[0] == '\0') {
680
681             /* Unnamed symbol. Generate a name that is not user accessible,
682              * then handle the symbol normal.
683              */
684             AnonName (Decl.Ident, "param");
685             F->Flags |= FD_UNNAMED_PARAMS;
686
687             /* Clear defined bit on nonames */
688             Spec.StorageClass &= ~SC_DEF;
689         }
690
691         /* Parse an attribute ### */
692         ParseAttribute (&Decl, &Attr);
693
694         /* Create a symbol table entry */
695         AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
696
697         /* Count arguments */
698         ++F->ParamCount;
699
700         /* Check for more parameters */
701         if (CurTok.Tok == TOK_COMMA) {
702             NextToken ();
703         } else {
704             break;
705         }
706     }
707
708     /* Skip right paren. We must explicitly check for one here, since some of
709      * the breaks above bail out without checking.
710      */
711     ConsumeRParen ();
712
713     /* Check if this is a function definition */
714     if (CurTok.Tok == TOK_LCURLY) {
715         /* Print an error if in strict ANSI mode and we have unnamed
716          * parameters.
717          */
718         if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
719             Error ("Parameter name omitted");
720         }
721     }
722 }
723
724
725
726 static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
727 /* Parse the argument list of a function. */
728 {
729     unsigned Offs;
730     SymEntry* Sym;
731
732     /* Create a new function descriptor */
733     FuncDesc* F = NewFuncDesc ();
734
735     /* Enter a new lexical level */
736     EnterFunctionLevel ();
737
738     /* Check for several special parameter lists */
739     if (CurTok.Tok == TOK_RPAREN) {
740         /* Parameter list is empty */
741         F->Flags |= (FD_EMPTY | FD_VARIADIC);
742     } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
743         /* Parameter list declared as void */
744         NextToken ();
745         F->Flags |= FD_VOID_PARAM;
746     } else if (CurTok.Tok == TOK_IDENT &&
747                (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
748         /* If the identifier is a typedef, we have a new style parameter list,
749          * if it's some other identifier, it's an old style parameter list.
750          */
751         Sym = FindSym (CurTok.Ident);
752         if (Sym == 0 || !SymIsTypeDef (Sym)) {
753             /* Old style (K&R) function. Assume variable param list. */
754             F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
755
756             /* Check for an implicit int return in the K&R function */
757             if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
758                 Spec->Type[0] == T_INT   &&
759                 Spec->Type[1] == T_END) {
760                 /* Function has an implicit int return */
761                 F->Flags |= FD_OLDSTYLE_INTRET;
762             }
763         }
764     }
765
766     /* Parse params */
767     if ((F->Flags & FD_OLDSTYLE) == 0) {
768         /* New style function */
769         ParseAnsiParamList (F);
770     } else {
771         /* Old style function */
772         ParseOldStyleParamList (F);
773     }
774
775     /* Assign offsets. If the function has a variable parameter list,
776      * there's one additional byte (the arg size).
777      */
778     Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
779     Sym = GetSymTab()->SymTail;
780     while (Sym) {
781         unsigned Size = CheckedSizeOf (Sym->Type);
782         Sym->V.Offs = Offs;
783         Offs += Size;
784         F->ParamSize += Size;
785         Sym = Sym->PrevSym;
786     }
787
788     /* Leave the lexical level remembering the symbol tables */
789     RememberFunctionLevel (F);
790
791     /* Return the function descriptor */
792     return F;
793 }
794
795
796
797 static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
798 /* Recursively process declarators. Build a type array in reverse order. */
799 {
800
801     if (CurTok.Tok == TOK_STAR) {
802         type T = T_PTR;
803         NextToken ();
804         /* Allow optional const or volatile qualifiers */
805         T |= OptionalQualifiers (T_QUAL_NONE);
806         Decl (Spec, D, Mode);
807         *D->T++ = T;
808         return;
809     } else if (CurTok.Tok == TOK_LPAREN) {
810         NextToken ();
811         Decl (Spec, D, Mode);
812         ConsumeRParen ();
813     } else if (CurTok.Tok == TOK_FASTCALL) {
814         /* Remember the current type pointer */
815         type* T = D->T;
816         /* Skip the fastcall token */
817         NextToken ();
818         /* Parse the function */
819         Decl (Spec, D, Mode);
820         /* Set the fastcall flag */
821         if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
822             Error ("__fastcall__ modifier applied to non function");
823         } else if (IsVariadicFunc (T)) {
824             Error ("Cannot apply __fastcall__ to functions with variable parameter list");
825         } else {
826             FuncDesc* F = GetFuncDesc (T);
827             F->Flags |= FD_FASTCALL;
828         }
829         return;
830     } else {
831         /* Things depend on Mode now:
832          *  - Mode == DM_NEED_IDENT means:
833          *      we *must* have a type and a variable identifer.
834          *  - Mode == DM_NO_IDENT means:
835          *      we must have a type but no variable identifer
836          *      (if there is one, it's not read).
837          *  - Mode == DM_ACCEPT_IDENT means:
838          *      we *may* have an identifier. If there is an identifier,
839          *      it is read, but it is no error, if there is none.
840          */
841         if (Mode == DM_NO_IDENT) {
842             D->Ident[0] = '\0';
843         } else if (CurTok.Tok == TOK_IDENT) {
844             strcpy (D->Ident, CurTok.Ident);
845             NextToken ();
846         } else {
847             if (Mode == DM_NEED_IDENT) {
848                 Error ("Identifier expected");
849             }
850             D->Ident[0] = '\0';
851         }
852     }
853
854     while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
855         if (CurTok.Tok == TOK_LPAREN) {
856             /* Function declaration */
857             FuncDesc* F;
858             NextToken ();
859             /* Parse the function declaration */
860             F = ParseFuncDecl (Spec);
861             *D->T++ = T_FUNC;
862             EncodePtr (D->T, F);
863             D->T += DECODE_SIZE;
864         } else {
865             /* Array declaration */
866             unsigned long Size = 0;
867             NextToken ();
868             /* Read the size if it is given */
869             if (CurTok.Tok != TOK_RBRACK) {
870                 ExprDesc lval;
871                 ConstExpr (&lval);
872                 Size = lval.ConstVal;
873             }
874             ConsumeRBrack ();
875             *D->T++ = T_ARRAY;
876             Encode (D->T, Size);
877             D->T += DECODE_SIZE;
878         }
879     }
880 }
881
882
883
884 /*****************************************************************************/
885 /*                                   code                                    */
886 /*****************************************************************************/
887
888
889
890 type* ParseType (type* Type)
891 /* Parse a complete type specification */
892 {
893     DeclSpec Spec;
894     Declaration Decl;
895
896     /* Get a type without a default */
897     InitDeclSpec (&Spec);
898     ParseTypeSpec (&Spec, -1);
899
900     /* Parse additional declarators */
901     InitDeclaration (&Decl);
902     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
903
904     /* Copy the type to the target buffer */
905     TypeCpy (Type, Decl.Type);
906
907     /* Return a pointer to the target buffer */
908     return Type;
909 }
910
911
912
913 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
914 /* Parse a variable, type or function declaration */
915 {
916     /* Initialize the Declaration struct */
917     InitDeclaration (D);
918
919     /* Get additional declarators and the identifier */
920     Decl (Spec, D, Mode);
921
922     /* Add the base type. */
923     TypeCpy (D->T, Spec->Type);
924
925     /* Check the size of the generated type */
926     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
927         if (D->Ident[0] != '\0') {
928             Error ("Size of `%s' is invalid", D->Ident);
929         } else {
930             Error ("Invalid size");
931         }
932     }
933 }
934
935
936
937 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
938 /* Parse a declaration specification */
939 {
940     /* Initialize the DeclSpec struct */
941     InitDeclSpec (D);
942
943     /* First, get the storage class specifier for this declaration */
944     ParseStorageClass (D, DefStorage);
945
946     /* Parse the type specifiers */
947     ParseTypeSpec (D, DefType);
948 }
949
950
951
952 void CheckEmptyDecl (const DeclSpec* D)
953 /* Called after an empty type declaration (that is, a type declaration without
954  * a variable). Checks if the declaration does really make sense and issues a
955  * warning if not.
956  */
957 {
958     if ((D->Flags & DS_EXTRA_TYPE) == 0) {
959         Warning ("Useless declaration");
960     }
961 }
962
963
964
965 static void ParseVoidInit (void)
966 /* Parse an initialization of a void variable (special cc65 extension) */
967 {
968     ExprDesc lval;
969
970     /* Allow an arbitrary list of values */
971     ConsumeLCurly ();
972     do {
973         ConstExpr (&lval);
974         switch (lval.Type[0]) {
975
976             case T_SCHAR:
977             case T_UCHAR:
978                 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
979                     /* Make it byte sized */
980                     lval.ConstVal &= 0xFF;
981                 }
982                 DefineData (&lval);
983                 break;
984
985             case T_SHORT:
986             case T_USHORT:
987             case T_INT:
988             case T_UINT:
989             case T_PTR:
990             case T_ARRAY:
991                 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
992                     /* Make it word sized */
993                     lval.ConstVal &= 0xFFFF;
994                 }
995                 DefineData (&lval);
996                 break;
997
998             case T_LONG:
999             case T_ULONG:
1000                 DefineData (&lval);
1001                 break;
1002
1003             default:
1004                 Error ("Illegal type in initialization");
1005                 break;
1006
1007         }
1008
1009         if (CurTok.Tok != TOK_COMMA) {
1010             break;
1011         }
1012         NextToken ();
1013
1014     } while (CurTok.Tok != TOK_RCURLY);
1015
1016     ConsumeRCurly ();
1017 }
1018
1019
1020
1021 static void ParseStructInit (type* Type)
1022 /* Parse initialization of a struct or union */
1023 {
1024     SymEntry* Entry;
1025     SymTable* Tab;
1026
1027     /* Consume the opening curly brace */
1028     ConsumeLCurly ();
1029
1030     /* Get a pointer to the struct entry from the type */
1031     Entry = (SymEntry*) Decode (Type + 1);
1032
1033     /* Check if this struct definition has a field table. If it doesn't, it
1034      * is an incomplete definition.
1035      */
1036     Tab = Entry->V.S.SymTab;
1037     if (Tab == 0) {
1038         Error ("Cannot initialize variables with incomplete type");
1039         /* Returning here will cause lots of errors, but recovery is difficult */
1040         return;
1041     }
1042
1043     /* Get a pointer to the list of symbols */
1044     Entry = Tab->SymHead;
1045     while (CurTok.Tok != TOK_RCURLY) {
1046         if (Entry == 0) {
1047             Error ("Too many initializers");
1048             return;
1049         }
1050         ParseInit (Entry->Type);
1051         Entry = Entry->NextSym;
1052         if (CurTok.Tok != TOK_COMMA)
1053             break;
1054         NextToken ();
1055     }
1056
1057     /* Consume the closing curly brace */
1058     ConsumeRCurly ();
1059
1060     /* If there are struct fields left, reserve additional storage */
1061     while (Entry) {
1062         g_zerobytes (CheckedSizeOf (Entry->Type));
1063         Entry = Entry->NextSym;
1064     }
1065 }
1066
1067
1068
1069 void ParseInit (type* T)
1070 /* Parse initialization of variables. */
1071 {
1072     ExprDesc lval;
1073     type* t;
1074     const char* str;
1075     int Count;
1076     int Size;
1077
1078     switch (UnqualifiedType (*T)) {
1079
1080         case T_SCHAR:
1081         case T_UCHAR:
1082             ConstExpr (&lval);
1083             if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1084                 /* Make it byte sized */
1085                 lval.ConstVal &= 0xFF;
1086             }
1087             assignadjust (T, &lval);
1088             DefineData (&lval);
1089             break;
1090
1091         case T_SHORT:
1092         case T_USHORT:
1093         case T_INT:
1094         case T_UINT:
1095         case T_PTR:
1096             ConstExpr (&lval);
1097             if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1098                 /* Make it word sized */
1099                 lval.ConstVal &= 0xFFFF;
1100             }
1101             assignadjust (T, &lval);
1102             DefineData (&lval);
1103             break;
1104
1105         case T_LONG:
1106         case T_ULONG:
1107             ConstExpr (&lval);
1108             if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1109                 /* Make it long sized */
1110                 lval.ConstVal &= 0xFFFFFFFF;
1111             }
1112             assignadjust (T, &lval);
1113             DefineData (&lval);
1114             break;
1115
1116         case T_ARRAY:
1117             Size = Decode (T + 1);
1118             t = T + DECODE_SIZE + 1;
1119             if (IsTypeChar(t) && CurTok.Tok == TOK_SCONST) {
1120                 str = GetLiteral (CurTok.IVal);
1121                 Count = strlen (str) + 1;
1122                 TranslateLiteralPool (CurTok.IVal);     /* Translate into target charset */
1123                 g_defbytes (str, Count);
1124                 ResetLiteralPoolOffs (CurTok.IVal);     /* Remove string from pool */
1125                 NextToken ();
1126             } else {
1127                 ConsumeLCurly ();
1128                 Count = 0;
1129                 while (CurTok.Tok != TOK_RCURLY) {
1130                     ParseInit (T + DECODE_SIZE + 1);
1131                     ++Count;
1132                     if (CurTok.Tok != TOK_COMMA)
1133                         break;
1134                     NextToken ();
1135                 }
1136                 ConsumeRCurly ();
1137             }
1138             if (Size == 0) {
1139                 Encode (T + 1, Count);
1140             } else if (Count < Size) {
1141                 g_zerobytes ((Size - Count) * CheckedSizeOf (T + DECODE_SIZE + 1));
1142             } else if (Count > Size) {
1143                 Error ("Too many initializers");
1144             }
1145             break;
1146
1147         case T_STRUCT:
1148         case T_UNION:
1149             ParseStructInit (T);
1150             break;
1151
1152         case T_VOID:
1153             if (!ANSI) {
1154                 /* Special cc65 extension in non ANSI mode */
1155                 ParseVoidInit ();
1156                 break;
1157             }
1158             /* FALLTHROUGH */
1159
1160         default:
1161             Error ("Illegal type");
1162             break;
1163
1164     }
1165 }
1166
1167
1168