diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 5c074991b..d08e8418d 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -824,6 +824,11 @@ and the one defined by the ISO standard: as it sounds, since the 6502 has so few registers that it isn't possible to keep values in registers anyway.

+ In + command line option. +

There may be some more minor differences I'm currently not aware of. The diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 45823fab6..166176f5e 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -507,13 +507,13 @@ void g_enter (unsigned flags, unsigned argsize) -void g_leave (int IsMainFunc) +void g_leave (int DoCleanup) /* Function epilogue */ { - /* In the main function nothing has to be dropped because the program - ** is terminated anyway. + /* In the main function in cc65 mode nothing has to be dropped because + ** the program is terminated anyway. */ - if (!IsMainFunc) { + if (DoCleanup) { /* How many bytes of locals do we have to drop? */ unsigned ToDrop = (unsigned) -StackPtr; diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index b95df5cfb..734c95372 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -247,7 +247,7 @@ void g_scale (unsigned flags, long val); void g_enter (unsigned flags, unsigned argsize); /* Function prologue */ -void g_leave (int IsMainFunc); +void g_leave (int DoCleanup); /* Function epilogue */ diff --git a/src/cc65/expr.c b/src/cc65/expr.c index f6c681db8..2939ab1cc 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1219,9 +1219,6 @@ static void Primary (ExprDesc* E) /* Is the symbol known? */ if (Sym) { - /* We found the symbol - skip the name token */ - NextToken (); - /* Check for illegal symbol types */ CHECK ((Sym->Flags & SC_TYPEMASK) != SC_LABEL); if ((Sym->Flags & SC_TYPEMASK) == SC_TYPEDEF) { @@ -1230,9 +1227,14 @@ static void Primary (ExprDesc* E) /* Assume an int type to make E valid */ E->Flags = E_LOC_STACK | E_RTYPE_LVAL; E->Type = type_int; + /* Skip the erroneous token */ + NextToken (); break; } + /* Skip the name token */ + NextToken (); + /* Mark the symbol as referenced */ Sym->Flags |= SC_REF; @@ -1286,7 +1288,23 @@ static void Primary (ExprDesc* E) ** rvalue, too, because we cannot store anything in a function. ** So fix the flags depending on the type. */ - if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) { + if (IsTypeArray (E->Type)) { + ED_AddrExpr (E); + } else if (IsTypeFunc (E->Type)) { + /* In cc65 mode we cannot call or take the address of + ** main(). + */ + if (IS_Get (&Standard) == STD_CC65 && + strcmp (Sym->Name, "main") == 0) { + /* Adjust the error message depending on a call or an + ** address operation. + */ + if (CurTok.Tok == TOK_LPAREN) { + Error ("'main' must not be called recursively"); + } else { + Error ("The address of 'main' cannot be taken"); + } + } ED_AddrExpr (E); } diff --git a/src/cc65/function.c b/src/cc65/function.c index d5cab3993..fed0349dd 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -646,13 +646,17 @@ void NewFunc (SymEntry* Func, FuncDesc* D) /* Output the function exit code label */ g_defcodelabel (F_GetRetLab (CurrentFunc)); - /* Restore the register variables (not necessary for main function) */ - if (!F_IsMainFunc (CurrentFunc)) { + /* Restore the register variables (not necessary for the main function in + ** cc65 mode) + */ + int CleanupOnExit = (IS_Get (&Standard) != STD_CC65) || + !F_IsMainFunc (CurrentFunc); + if (CleanupOnExit) { F_RestoreRegVars (CurrentFunc); } /* Generate the exit code */ - g_leave (F_IsMainFunc (CurrentFunc)); + g_leave (CleanupOnExit); /* Emit references to imports/exports */ EmitExternals (); diff --git a/src/cc65/locals.c b/src/cc65/locals.c index c4d0aa25b..08e41918e 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -111,6 +111,13 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg) /* Get the size of the variable */ unsigned Size = SizeOf (Decl->Type); + /* Check if this is the main function and we are in cc65 mode. If so, we + ** won't save the old contents of the register variables since in cc65 + ** mode main() may not be called recursively. + */ + int SaveRegVars = (IS_Get (&Standard) != STD_CC65) || + !F_IsMainFunc (CurrentFunc); + /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { @@ -126,13 +133,13 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg) /* Save the current contents of the register variable on stack. This is ** not necessary for the main function. */ - if (!F_IsMainFunc (CurrentFunc)) { + if (SaveRegVars) { g_save_regvars (Reg, Size); } /* Add the symbol to the symbol table. We do that now, because for ** register variables the current stack pointer is implicitly used - ** as location for the save area (unused in case of main()). + ** as location for the save area (maybe unused in case of main()). */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); @@ -187,14 +194,14 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg) /* Save the current contents of the register variable on stack. This is ** not necessary for the main function. */ - if (!F_IsMainFunc (CurrentFunc)) { + if (SaveRegVars) { F_AllocLocalSpace (CurrentFunc); g_save_regvars (Reg, Size); } /* Add the symbol to the symbol table. We do that now, because for ** register variables the current stack pointer is implicitly used - ** as location for the save area (unused in case of main()). + ** as location for the save area (maybe unused in case of main()). */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); } diff --git a/targettest/atari/mem.c b/targettest/atari/mem.c index bc70aded6..b15b215ed 100644 --- a/targettest/atari/mem.c +++ b/targettest/atari/mem.c @@ -21,6 +21,8 @@ unsigned int *MEMTOP = (unsigned int *)741; unsigned int *MEMLO = (unsigned int *)743; void *allocmem; +void code(void) { } + int main(void) { allocmem = malloc(257); @@ -35,7 +37,7 @@ int main(void) printf(" MEMLO = $%04X (%u)\n", *MEMLO, *MEMLO); printf(" ----------------------\n"); - printf(" main: $%04X (code)\n", &main); + printf(" code: $%04X (code)\n", &code); printf(" data: $%04X (data)\n", &data); printf(" _dos_type: $%04X (bss)\n", &_dos_type); printf(" allocmem: $%04X (dyn. data)\n", allocmem); diff --git a/targettest/pce/conio.c b/targettest/pce/conio.c index 55f828f26..819e601be 100644 --- a/targettest/pce/conio.c +++ b/targettest/pce/conio.c @@ -11,6 +11,8 @@ static char hex[16] = { "0123456789abcdef" }; static char charbuf[0x20]; static char colbuf[0x20]; +void func(void) { } + void main(void) { int stackvar = 42; @@ -65,7 +67,7 @@ void main(void) p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15] ); } - memcpy(p, main, i = 0); /* test that a zero length doesn't copy 64K */ + memcpy(p, func, i = 0); /* test that a zero length doesn't copy 64K */ gotoxy(0,ysize - 1); for (i = 0; i < xsize; ++i) { diff --git a/targettest/scanf-test.c b/targettest/scanf-test.c index f17b62294..e0ab95756 100644 --- a/targettest/scanf-test.c +++ b/targettest/scanf-test.c @@ -159,12 +159,14 @@ static void Pause(void) { #endif } +static void Nil() { } + int main(void) { long n0; unsigned t; int c, n1 = 12345, n2, n3; char s1[80], s2[80]; - void *p1 = main, *p2 = main, *p3 = main, *p4 = main; + void *p1 = Nil, *p2 = Nil, *p3 = Nil, *p4 = Nil; #ifndef USE_STDIO clrscr(); diff --git a/test/ref/custom-reference-error.c b/test/ref/custom-reference-error.c index e98fb024d..455e0276d 100644 --- a/test/ref/custom-reference-error.c +++ b/test/ref/custom-reference-error.c @@ -22,6 +22,5 @@ return_t main(int argc, char* argv[]) n = 0; /* produce an error */ /* produce a warning */ } - -int arr[main(0, 0)]; /* produce an error */ int b = 0; +int arr[b]; /* produce an error */ diff --git a/test/val/nullptr.c b/test/val/nullptr.c index e64b82ee2..a5b72e8c5 100644 --- a/test/val/nullptr.c +++ b/test/val/nullptr.c @@ -28,6 +28,8 @@ struct S { } \ } while(0); +void func() { } + int main() { int a; @@ -60,7 +62,7 @@ int main() TEST_NON_NULL(((struct S*)&a)->a) /* Non-null pointer obtained with cast and -> */ - TEST_NON_NULL(((struct S*)&main)->a) + TEST_NON_NULL(((struct S*)&func)->a) if (failures != 0) {