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