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