mirror of
https://github.com/cc65/cc65.git
synced 2025-01-27 09:33:42 +00:00
Merge pull request #401 from greg-king5/void-size
Make C's sizeof operator work with cc65's void variables.
This commit is contained in:
commit
0bbe4f56a5
@ -4,7 +4,7 @@
|
|||||||
<title>cc65 Users Guide
|
<title>cc65 Users Guide
|
||||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
||||||
<url url="mailto:gregdk@users.sf.net" name="Greg King">
|
<url url="mailto:gregdk@users.sf.net" name="Greg King">
|
||||||
<date>2016-06-11
|
<date>2017-02-27
|
||||||
|
|
||||||
<abstract>
|
<abstract>
|
||||||
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
||||||
@ -687,30 +687,37 @@ This cc65 version has some extensions to the ISO C standard.
|
|||||||
string.
|
string.
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<item> cc65 allows the initialization of <tt/void/ variables. This may be
|
<item> cc65 allows the initialization of <tt/void/ variables. This may be
|
||||||
used to create variable structures that are more compatible with
|
used to create arbitrary structures that are more compatible with
|
||||||
interfaces written for assembler languages. Here is an example:
|
interfaces written for assembler languages. Here is an example:
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 };
|
void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 };
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
This will be translated as follows:
|
That will be translated as follows:
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
_GCmd:
|
_GCmd:
|
||||||
.byte 3
|
.byte 3
|
||||||
.word $2000
|
.word $2000
|
||||||
.word $3000
|
.word $3000
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
Since the variable is of type <tt/void/ you may not use it as is.
|
Since the variable is of type <tt/void/, you may not use it as-is.
|
||||||
However, taking the address of the variable results in a <tt/void*/
|
However, taking the address of the variable results in a <tt/void*/
|
||||||
which may be passed to any function expecting a pointer.
|
which may be passed to any function expecting a pointer. Also, the
|
||||||
|
<tt/sizeof/ operator will give the length of the initializer:
|
||||||
|
|
||||||
See the <url url="geos.html" name="GEOS library document"> for examples
|
<tscreen><verb>
|
||||||
on how to use this feature.
|
GLen = sizeof GCmd;
|
||||||
<p>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
will assign the value 5 to <tt/GLen/.
|
||||||
|
|
||||||
|
See the <url url="geos.html" name="GEOS library document"> for examples
|
||||||
|
on how to use that feature.
|
||||||
|
<p>
|
||||||
|
|
||||||
<item> cc65 implements flexible array struct members as defined in the C99 ISO
|
<item> cc65 implements flexible array struct members as defined in the C99 ISO
|
||||||
standard. As an extension, these fields may be initialized. There are
|
standard. As an extension, these fields may be initialized. There are
|
||||||
|
@ -389,7 +389,10 @@ unsigned SizeOf (const Type* T)
|
|||||||
switch (UnqualifiedType (T->C)) {
|
switch (UnqualifiedType (T->C)) {
|
||||||
|
|
||||||
case T_VOID:
|
case T_VOID:
|
||||||
return 0; /* Assume voids have size zero */
|
/* A void variable is a cc65 extension.
|
||||||
|
** Get its size (in bytes).
|
||||||
|
*/
|
||||||
|
return T->A.U;
|
||||||
|
|
||||||
/* Beware: There's a chance that this triggers problems in other parts
|
/* Beware: There's a chance that this triggers problems in other parts
|
||||||
of the compiler. The solution is to fix the callers, because calling
|
of the compiler. The solution is to fix the callers, because calling
|
||||||
@ -438,7 +441,7 @@ unsigned SizeOf (const Type* T)
|
|||||||
/* Array with unspecified size */
|
/* Array with unspecified size */
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return T->A.L * SizeOf (T + 1);
|
return T->A.U * SizeOf (T + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -891,6 +891,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
|||||||
case TOK_VOID:
|
case TOK_VOID:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
D->Type[0].C = T_VOID;
|
D->Type[0].C = T_VOID;
|
||||||
|
D->Type[0].A.U = 0;
|
||||||
D->Type[1].C = T_END;
|
D->Type[1].C = T_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2114,7 +2115,7 @@ NextMember:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned ParseVoidInit (void)
|
static unsigned ParseVoidInit (Type* T)
|
||||||
/* Parse an initialization of a void variable (special cc65 extension).
|
/* Parse an initialization of a void variable (special cc65 extension).
|
||||||
** Return the number of bytes initialized.
|
** Return the number of bytes initialized.
|
||||||
*/
|
*/
|
||||||
@ -2181,6 +2182,9 @@ static unsigned ParseVoidInit (void)
|
|||||||
/* Closing brace */
|
/* Closing brace */
|
||||||
ConsumeRCurly ();
|
ConsumeRCurly ();
|
||||||
|
|
||||||
|
/* Number of bytes determined by initializer */
|
||||||
|
T->A.U = Size;
|
||||||
|
|
||||||
/* Return the number of bytes initialized */
|
/* Return the number of bytes initialized */
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
@ -2216,8 +2220,8 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers)
|
|||||||
|
|
||||||
case T_VOID:
|
case T_VOID:
|
||||||
if (IS_Get (&Standard) == STD_CC65) {
|
if (IS_Get (&Standard) == STD_CC65) {
|
||||||
/* Special cc65 extension in non ANSI mode */
|
/* Special cc65 extension in non-ANSI mode */
|
||||||
return ParseVoidInit ();
|
return ParseVoidInit (T);
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
9
test/err/void-empty.c
Normal file
9
test/err/void-empty.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! Uninitialized void variables
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Greg King
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test;
|
||||||
|
const void list;
|
11
test/err/void-size2.c
Normal file
11
test/err/void-size2.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! Size of void cast
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Greg King
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned test (void)
|
||||||
|
{
|
||||||
|
return sizeof ((void)12345);
|
||||||
|
}
|
56
test/val/void-size1.c
Normal file
56
test/val/void-size1.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! Getting the size of a void-type variable (cc65 extension)
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Greg King
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const void list1 = {
|
||||||
|
(char)1,
|
||||||
|
(char)2,
|
||||||
|
(char)3,
|
||||||
|
(char)4,
|
||||||
|
(char)5,
|
||||||
|
(char)6,
|
||||||
|
(char)7,
|
||||||
|
(char)8,
|
||||||
|
(char)9,
|
||||||
|
(char)0
|
||||||
|
};
|
||||||
|
|
||||||
|
static void list2 = {
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
void list3 = {
|
||||||
|
(char)1,
|
||||||
|
(char)2,
|
||||||
|
(char)3,
|
||||||
|
(char)4,
|
||||||
|
&list1,
|
||||||
|
(char)6,
|
||||||
|
(char)7,
|
||||||
|
(char)8,
|
||||||
|
(char)9,
|
||||||
|
&list2
|
||||||
|
};
|
||||||
|
|
||||||
|
/* We know that the expression is constant; don't tell us. */
|
||||||
|
|
||||||
|
#pragma warn (const-comparison, off)
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
return sizeof list1 != 10
|
||||||
|
|| sizeof list2 != 20
|
||||||
|
|| sizeof list3 != 12;
|
||||||
|
}
|
@ -1,59 +1,55 @@
|
|||||||
/*
|
/*
|
||||||
** testprogram for ANTIC instructions as defined in "_antic.h"
|
** test program for ANTIC instructions as defined in "_antic.h"
|
||||||
**
|
**
|
||||||
** 23-Feb-2017, Christian Krueger
|
** 23-Feb-2017, Christian Krueger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <atari.h>
|
#include <atari.h>
|
||||||
#include <peekpoke.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// code is only for testing purposes, as screen and display list are not aligned
|
// code is only for testing purposes, as screen and display list are not aligned,
|
||||||
// and jumps not set!
|
// and jumps not set!
|
||||||
|
|
||||||
unsigned char DummyScreen[400];
|
unsigned char DummyScreen[400];
|
||||||
|
|
||||||
void DisplayList = {
|
void DisplayList = {
|
||||||
DL_BLK1,
|
DL_BLK1,
|
||||||
DL_BLK2,
|
DL_BLK2,
|
||||||
DL_BLK3,
|
DL_BLK3,
|
||||||
DL_BLK4,
|
DL_BLK4,
|
||||||
DL_BLK5,
|
DL_BLK5,
|
||||||
DL_BLK6,
|
DL_BLK6,
|
||||||
DL_BLK7,
|
DL_BLK7,
|
||||||
DL_DLI(DL_BLK8),
|
DL_DLI(DL_BLK8),
|
||||||
DL_LMS(DL_CHR40x8x1),
|
DL_LMS(DL_CHR40x8x1),
|
||||||
DummyScreen,
|
DummyScreen,
|
||||||
DL_HSCROL(DL_CHR40x10x1),
|
DL_HSCROL(DL_CHR40x10x1),
|
||||||
DL_VSCROL(DL_CHR40x8x4),
|
DL_VSCROL(DL_CHR40x8x4),
|
||||||
DL_CHR40x16x4,
|
DL_CHR40x16x4,
|
||||||
DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_CHR20x8x2)))),
|
DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_CHR20x8x2)))),
|
||||||
DummyScreen+120,
|
DummyScreen+120,
|
||||||
DL_CHR20x16x2,
|
DL_CHR20x16x2,
|
||||||
DL_MAP40x8x4,
|
DL_MAP40x8x4,
|
||||||
DL_MAP80x4x2,
|
DL_MAP80x4x2,
|
||||||
DL_MAP80x4x4,
|
DL_MAP80x4x4,
|
||||||
DL_MAP160x2x2,
|
DL_MAP160x2x2,
|
||||||
DL_MAP160x1x2,
|
DL_MAP160x1x2,
|
||||||
DL_MAP160x2x4,
|
DL_MAP160x2x4,
|
||||||
DL_MAP160x1x4,
|
DL_MAP160x1x4,
|
||||||
DL_MAP320x1x1,
|
DL_MAP320x1x1,
|
||||||
DL_JVB,
|
DL_JVB,
|
||||||
DL_JMP
|
DL_JMP
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned char dlend = 0;
|
|
||||||
|
|
||||||
|
/* We know that the sizeof expression is constant; don't tell us. */
|
||||||
|
|
||||||
|
#pragma warn (const-comparison, off)
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
// unfortunately "sizeof()" doesn't work with void data
|
int returnValue = (sizeof DisplayList != 28); // assure only one byte per instruction!
|
||||||
// (Error: Size of data type is unknown)
|
|
||||||
// so we trick with the addresses at front and end...
|
|
||||||
|
|
||||||
int returnValue = (((unsigned int)&dlend-(unsigned int)&DisplayList) != 28); // assure only one byte per instruction!
|
|
||||||
|
|
||||||
clrscr();
|
clrscr();
|
||||||
if (returnValue)
|
if (returnValue)
|
||||||
@ -66,4 +62,3 @@ main(void)
|
|||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user