1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-10 13:29:50 +00:00

Compare commits

...

34 Commits

Author SHA1 Message Date
Renan Ribeiro
c5da2d8245
Merge e8e0c41f87 into 2c4d4d3314 2024-05-16 19:06:42 +02:00
mrdudz
2c4d4d3314 add -j2 to make test invocations 2024-05-16 18:57:29 +02:00
mrdudz
86e5acd679 fix race condition as proposed in #2420 2024-05-16 18:57:08 +02:00
Bob Andrews
84153e809e
Merge pull request #2438 from ops/exehdr
Add missing EXEHDR
2024-05-15 14:11:08 +02:00
Bob Andrews
90723d7dd1
Merge pull request #2132 from vrubleg/ulabel
Add support of unnamed labels with @ (.localchar) prefix
2024-05-14 20:10:06 +02:00
Evgeny Vrublevsky
f789316f86 Add a test for the unnamed labels. 2024-04-07 13:34:49 +03:00
Evgeny Vrublevsky
270f3544b5 Document changes in unnamed labels. 2024-04-07 13:34:48 +03:00
Evgeny Vrublevsky
c500cb9086 Add support of unnamed labels with @ (.localchar) prefix. 2024-04-07 13:34:48 +03:00
Olli Savia
074ec82126 Added missing EXEHDR 2024-04-02 19:25:15 +03:00
cosineblast
e8e0c41f87 Fix style issue in preproc.c 2024-01-19 21:21:46 -03:00
cosineblast
8e17cc2692 Remove useless function prototype in pathutil.c 2024-01-19 13:06:11 -03:00
cosineblast
7a5526b19e Remove symlink from tests 2024-01-18 20:13:47 -03:00
cosineblast
d4c7cba521 Update documentation tt tag 2024-01-17 20:36:28 -03:00
cosineblast
9c877fa529 Fix documentation label issue 2024-01-17 19:36:25 -03:00
cosineblast
e10647dca6 Add pathutil.c comments and improve version macros 2024-01-17 19:23:09 -03:00
cosineblast
dfbfe79c71 Add minimum version for pathutil.c 2024-01-17 19:15:59 -03:00
cosineblast
6e203ab2d2 Improve pathutil.c style 2024-01-17 17:47:08 -03:00
cosineblast
57e6c2a4f9 Make pragma once work even in .c files 2024-01-17 17:45:11 -03:00
cosineblast
98208e7e95 Add pragma once to the documentation 2024-01-17 16:49:47 -03:00
cosineblast
30ff2bdc6b Add pragma once tests 2024-01-17 15:05:27 -03:00
cosineblast
167c31c148 Update FindRealPath function object name 2024-01-17 00:47:53 -03:00
cosineblast
a6f207a2a5 Improve FindAbsolutePath documentation and API 2024-01-17 00:33:49 -03:00
cosineblast
346dd7df85 Remove symlink resolve from searchpath to maintain behaviour 2024-01-17 00:07:07 -03:00
cosineblast
aa47b6c1c7 Refactor include file searching 2024-01-16 19:49:47 -03:00
cosineblast
085509c2e1 Improve FindAbsolutePath implementation 2024-01-16 16:02:57 -03:00
cosineblast
d34a6df002 Improve preprocessor pragma once implementation
Pragma once checking now happens in #include
2024-01-14 19:43:34 -03:00
cosineblast
42a93f00d4 Add StrPool lookup 2024-01-14 19:43:05 -03:00
cosineblast
acf9676c0f Move FindAbsolutePath to another .c 2024-01-13 00:30:58 -03:00
cosineblast
7798c7a471 Include corret header for windows 2024-01-12 20:48:05 -03:00
cosineblast
fc619573b4 Add <windef.h> on windows 2024-01-12 18:36:38 -03:00
cosineblast
9d50090769 Update windows build FindAbsolutePath bug 2024-01-12 18:29:54 -03:00
cosineblast
c0285cadc8 Update style to conform to rules 2024-01-12 11:45:59 -03:00
cosineblast
6a276ccac3 Implement pragma once 2024-01-12 10:07:13 -03:00
cosineblast
9d32a84f69 Add pragma result status enum
Makes so that preprocessing a pragma yields a status flag with additional information on how to handle that particular #pragma.
Mostly a prepraration for #pragma once.
2024-01-10 20:19:04 -03:00
26 changed files with 457 additions and 64 deletions

View File

@ -35,7 +35,7 @@ jobs:
run: make -j2 lib QUIET=1
- name: Run the regression tests.
shell: bash
run: make test QUIET=1
run: make -j2 test QUIET=1
- name: Test that the samples can be built.
run: make -C samples platforms
- name: Test that the targettest programs can be built.
@ -89,4 +89,4 @@ jobs:
- name: Run the regression tests (make test)
shell: cmd
run: make test QUIET=1 SHELL=cmd
run: make -j2 test QUIET=1 SHELL=cmd

View File

@ -59,7 +59,7 @@ jobs:
run: make -j2 lib QUIET=1
- name: Run the regression tests.
shell: bash
run: make test QUIET=1
run: make -j2 test QUIET=1
- name: Test that the samples can be built.
shell: bash
run: make -j2 samples

View File

@ -70,7 +70,7 @@ jobs:
- name: Run the regression tests (make test)
if: steps.check-sha.outputs.cache-hit != 'true'
shell: cmd
run: make test QUIET=1 SHELL=cmd
run: make -j2 test QUIET=1 SHELL=cmd
- name: Test that the samples can be built (make samples)
if: steps.check-sha.outputs.cache-hit != 'true'

View File

@ -14,6 +14,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -14,6 +14,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -14,6 +14,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -829,49 +829,42 @@ names like "Loop". Here is an example:
bne @Loop ; ERROR: Unknown identifier!
</verb></tscreen>
<sect1>Unnamed labels<p>
If you really want to write messy code, there are also unnamed labels. These
labels do not have a name (you guessed that already, didn't you?). A colon is
used to mark the absence of the name.
If you really want to write messy code, there are also unnamed labels. To define
an unnamed label, use either <tt>@:</tt> (<tt>.LOCALCHAR</tt> is respected if it
is set) or sole <tt>:</tt>.
Unnamed labels may be accessed by using the colon plus several minus or plus
characters as a label designator. Using the '-' characters will create a back
reference (use the n'th label backwards), using '+' will create a forward
reference (use the n'th label in forward direction). An example will help to
understand this:
To reference an unnamed label, use <tt>@</tt> (<tt>.LOCALCHAR</tt> is respected
if it is set) or <tt>:</tt> with several <tt>-</tt> or <tt>+</tt> characters.
The <tt>-</tt> characters will create a back reference (n'th label backwards),
the <tt>+</tt> will create a forward reference (n'th label in forward direction).
As an alternative, angle brackets <tt>&lt;</tt> and <tt>&gt;</tt> may be used
instead of <tt>-</tt> and <tt>+</tt> with the same meaning.
Example:
<tscreen><verb>
: lda (ptr1),y ; #1
cmp (ptr2),y
bne :+ ; -> #2
tax
beq :+++ ; -> #4
iny
bne :- ; -> #1
inc ptr1+1
inc ptr2+1
bne :- ; -> #1
: bcs :+ ; #2 -> #3
ldx #$FF
rts
: ldx #$01 ; #3
: rts ; #4
cpy #0
beq @++
@:
sta $2007
dey
bne @-
@:
rts
</verb></tscreen>
As you can see from the example, unnamed labels will make even short
sections of code hard to understand, because you have to count labels
to find branch targets (this is the reason why I for my part do
prefer the "cheap" local labels). Nevertheless, unnamed labels are
convenient in some situations, so it's your decision.
Unnamed labels may make even short sections of code hard to understand, because
you have to count labels to find branch targets. It's better to prefer the
"cheap" local labels. Nevertheless, unnamed labels are convenient in some
situations, so it's up to your discretion.
<em/Note:/ <ref id="scopes" name="Scopes"> organize named symbols, not
unnamed ones, so scopes don't have an effect on unnamed labels.
<sect1>Using macros to define labels and constants<p>
While there are drawbacks with this approach, it may be handy in a few rare

View File

@ -1681,6 +1681,16 @@ void somefunc2(int, char *);
</verb></tscreen>
<sect1><tt>#pragma once</tt><label id="pragma-once"><p>
This pragma is used to prevent multiple inclusion of a header file.
If this pragma is preprocessed in a file, any posterior
<tt>#include</tt> which targets the current file will be ignored.
Two files are considered to be the same by this directive if they
share the same absolute path. In the case of symbolic links,
the canonical, resolved path is considered instead.
<sect>Register variables<label id="register-vars"><p>

View File

@ -707,6 +707,24 @@ static void OneLine (void)
NextTok ();
}
/* Handle @-style unnamed labels */
if (CurTok.Tok == TOK_ULABEL) {
if (CurTok.IVal != 0) {
Error ("Invalid unnamed label definition");
}
ULabDef ();
NextTok ();
/* Skip the colon. If NoColonLabels is enabled, allow labels without
** a colon if there is no whitespace before the identifier.
*/
if (CurTok.Tok == TOK_COLON) {
NextTok ();
} else if (CurTok.WS || !NoColonLabels) {
Error ("':' expected");
}
}
/* If the first token on the line is an identifier, check for a macro or
** an instruction.
*/

View File

@ -1124,17 +1124,33 @@ Again:
/* Local symbol? */
if (C == LocalStart) {
/* Read the identifier. */
ReadIdent ();
NextChar ();
/* Start character alone is not enough */
if (SB_GetLen (&CurTok.SVal) == 1) {
Error ("Invalid cheap local symbol");
goto Again;
if (IsIdChar (C)) {
/* Read a local identifier */
CurTok.Tok = TOK_LOCAL_IDENT;
SB_AppendChar (&CurTok.SVal, LocalStart);
ReadIdent ();
} else {
/* Read an unnamed label */
CurTok.IVal = 0;
CurTok.Tok = TOK_ULABEL;
if (C == '-' || C == '<') {
int PrevC = C;
do {
--CurTok.IVal;
NextChar ();
} while (C == PrevC);
} else if (C == '+' || C == '>') {
int PrevC = C;
do {
++CurTok.IVal;
NextChar ();
} while (C == PrevC);
}
}
/* A local identifier */
CurTok.Tok = TOK_LOCAL_IDENT;
return;
}
@ -1314,22 +1330,30 @@ CharAgain:
break;
case '-':
case '<':
{
int PrevC = C;
CurTok.IVal = 0;
do {
--CurTok.IVal;
NextChar ();
} while (C == '-');
} while (C == PrevC);
CurTok.Tok = TOK_ULABEL;
break;
}
case '+':
case '>':
{
int PrevC = C;
CurTok.IVal = 0;
do {
++CurTok.IVal;
NextChar ();
} while (C == '+');
} while (C == PrevC);
CurTok.Tok = TOK_ULABEL;
break;
}
case '=':
NextChar ();

View File

@ -71,7 +71,7 @@ typedef enum token_t {
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* :++ or :-- */
TOK_ULABEL, /* An unnamed label */
TOK_EQ, /* = */
TOK_NE, /* <> */

View File

@ -107,8 +107,12 @@ ExprNode* ULabRef (int Which)
int Index;
ULabel* L;
/* Which can never be 0 */
PRECONDITION (Which != 0);
/* Which should not be 0 */
if (Which == 0) {
Error ("Invalid unnamed label reference");
/* We must return something valid */
return GenCurrentPC();
}
/* Get the index of the referenced label */
if (Which > 0) {

View File

@ -45,6 +45,7 @@
#include "print.h"
#include "strbuf.h"
#include "xmalloc.h"
#include "pathutil.h"
/* cc65 */
#include "codegen.h"
@ -296,10 +297,11 @@ void OpenMainFile (const char* Name)
void OpenIncludeFile (const char* Name, InputType IT)
void OpenIncludeFile (const char* Name, InputType IT, StringPool *FilesToIgnore)
/* Open an include file and insert it into the tables. */
{
char* N;
char* M;
FILE* F;
IFile* IF;
AFile* AF;
@ -317,6 +319,23 @@ void OpenIncludeFile (const char* Name, InputType IT)
return;
}
/* Resolve real path of file in case of a symlink */
M = FindRealPath(N);
if (M == 0) {
PPError ("Cannot resolve absolute path of '%s'", N);
xfree (N);
return;
}
if (SP_LookupStr(FilesToIgnore, M) != 0) {
/* This file should not be included. */
xfree (M);
xfree (N);
return;
}
xfree (M);
/* Search the list of all input files for this file. If we don't find
** it, create a new IFile object.
*/

View File

@ -43,6 +43,7 @@
/* common */
#include "coll.h"
#include "strbuf.h"
#include "strpool.h"
@ -83,8 +84,10 @@ extern char NextC;
void OpenMainFile (const char* Name);
/* Open the main file. Will call Fatal() in case of failures. */
void OpenIncludeFile (const char* Name, InputType IT);
/* Open an include file and insert it into the tables. */
void OpenIncludeFile (const char* Name, InputType IT, StringPool* FilesToIgnore);
/* Open an include file and insert it into the tables.
** Does nothing if the resolved file is present in the pool.
*/
void CloseIncludeFile (void);
/* Close an include file and switch to the higher level file. Set Input to

View File

@ -44,6 +44,9 @@
#include "inline.h"
#include "print.h"
#include "xmalloc.h"
#include "strpool.h"
#include "abend.h"
#include "pathutil.h"
/* cc65 */
#include "codegen.h"
@ -113,6 +116,8 @@ static StrBuf* PLine; /* Buffer for macro expansion */
static StrBuf* MLine; /* Buffer for macro expansion in #pragma */
static StrBuf* OLine; /* Buffer for #pragma output */
static StringPool* PragmaOnceSeenFiles;
/* Newlines to be added to preprocessed text */
static unsigned PendingNewLines;
static unsigned ContinuedLines;
@ -2804,7 +2809,6 @@ static int DoIfDef (int skip, int flag)
}
static void DoInclude (void)
/* Open an include file. */
{
@ -2854,8 +2858,8 @@ static void DoInclude (void)
NextChar ();
/* Check for extra tokens following the filename */
CheckExtraTokens ("include");
/* Open the include file */
OpenIncludeFile (SB_GetConstBuf (&Filename), IT);
/* Open the include file, if it is not marked with #pragma once */
OpenIncludeFile (SB_GetConstBuf (&Filename), IT, PragmaOnceSeenFiles);
} else {
/* No terminator found */
PPError ("#include expects \"FILENAME\" or <FILENAME>");
@ -2963,14 +2967,28 @@ static void DoLine (void)
MLine = InitLine (MLine);
}
static void DoPragmaOnce (void)
/* Marks the current file as seen by #pragma once. */
{
const char * const Filename = GetCurrentFilename ();
char * const FullPath = FindRealPath (Filename);
if (FullPath == NULL) {
AbEnd ("Failed to find the real path for the file %s", Filename);
}
SP_AddStr (PragmaOnceSeenFiles, FullPath);
free (FullPath);
}
static void DoPragma (void)
/* Handle a #pragma line by converting the #pragma preprocessor directive into
** the _Pragma() compiler operator.
*/
{
StrBuf* PragmaLine = OLine;
StrBuf* const PragmaLine = OLine;
PRECONDITION (PragmaLine != 0);
@ -2981,11 +2999,16 @@ static void DoPragma (void)
SB_Clear (MLine);
PreprocessDirective (Line, MLine, MSM_NONE);
/* Convert #pragma to _Pragma () */
SB_AppendStr (PragmaLine, "_Pragma (");
SB_Reset (MLine);
Stringize (MLine, PragmaLine);
SB_AppendChar (PragmaLine, ')');
if (SB_CompareStr(MLine, "once") == 0) {
DoPragmaOnce ();
}
else {
/* Convert #pragma to _Pragma () */
SB_AppendStr (PragmaLine, "_Pragma (");
SB_Reset (MLine);
Stringize (MLine, PragmaLine);
SB_AppendChar (PragmaLine, ')');
}
/* End this line */
SB_SetIndex (PragmaLine, SB_GetLen (PragmaLine));
@ -3157,6 +3180,7 @@ static int ParseDirectives (unsigned ModeFlags)
if (!PPSkip) {
if ((ModeFlags & MSM_IN_ARG_LIST) == 0) {
DoPragma ();
return Whitespace;
} else {
PPError ("Embedded #pragma directive within macro arguments is unsupported");
@ -3348,6 +3372,9 @@ void InitPreprocess (void)
/* Create the output buffers */
MLine = NewStrBuf ();
PLine = NewStrBuf ();
/* 64 is a sensible number of slots for the hash table */
PragmaOnceSeenFiles = NewStringPool(64);
}
@ -3358,6 +3385,7 @@ void DonePreprocess (void)
/* Done with the output buffers */
SB_Done (MLine);
SB_Done (PLine);
FreeStringPool(PragmaOnceSeenFiles);
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -110,6 +110,7 @@
<ClInclude Include="common\objdefs.h" />
<ClInclude Include="common\optdefs.h" />
<ClInclude Include="common\print.h" />
<ClInclude Include="common\pathutil.h" />
<ClInclude Include="common\scopedefs.h" />
<ClInclude Include="common\searchpath.h" />
<ClInclude Include="common\segdefs.h" />
@ -155,6 +156,7 @@
<ClCompile Include="common\matchpat.c" />
<ClCompile Include="common\mmodel.c" />
<ClCompile Include="common\print.c" />
<ClCompile Include="common\pathutil.c" />
<ClCompile Include="common\searchpath.c" />
<ClCompile Include="common\segnames.c" />
<ClCompile Include="common\shift.c" />
@ -171,4 +173,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

119
src/common/pathutil.c Normal file
View File

@ -0,0 +1,119 @@
/*****************************************************************************/
/* */
/* pathutil.c */
/* Path manipulation utilities */
/* */
/* */
/* */
/* (C) 2003-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#if defined(_WIN32)
#if !defined(_WIN32_WINNT) && !defined(NTDDI_VERSION)
/* Set minimum windows version for GetFinalPathNameByHandleA */
/* NTDDI_VISTA */
#define NTDDI_VERSION 0x06000000
/* _WIN32_WINNT_VISTA */
#define _WIN32_WINNT 0x600
#endif
#include "xmalloc.h"
#include <windows.h>
#include <fileapi.h>
#endif
#include <stdlib.h>
/*****************************************************************************/
/* code */
/*****************************************************************************/
#if defined(_WIN32)
char *FindRealPath (const char *Path)
/*
** Returns a malloced buffer containing the canonical path of the given path.
** If the path points to a non-existent file, or if any error occurs, NULL is returned.
** If the path points to a symlink, the resolved symlink path is returned.
** Note: The returned path's separator is system specific.
*/
{
HANDLE Handle = CreateFileA (Path,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ |
FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (Handle == INVALID_HANDLE_VALUE) {
return NULL;
}
size_t BufferSize = MAX_PATH + 10;
char* Buffer = xmalloc (BufferSize);
DWORD Status = GetFinalPathNameByHandleA (Handle,
Buffer,
BufferSize,
FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS);
if (Status == 0) {
xfree (Buffer);
CloseHandle (Handle);
return NULL;
}
CloseHandle (Handle);
return Buffer;
}
#else
char* FindRealPath (const char* path)
/*
** Returns a malloced buffer containing the canonical path of the given path.
** If the path points to a non-existent file, or if any error occurs, NULL is returned.
** If the path points to a symlink, the resolved symlink path is returned.
** Note: The returned path's separator is system specific.
*/
{
return realpath (path, NULL);
}
#endif

55
src/common/pathutil.h Normal file
View File

@ -0,0 +1,55 @@
/*****************************************************************************/
/* */
/* pathutil.h */
/* Path manipulation utilities */
/* */
/* */
/* */
/* (C) 2003-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef PATHUTIL_H
#define PATHUTIL_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char *FindRealPath (const char *path);
/*
** Returns a malloced buffer containing the canonical path of the given path.
** If the path points to a non-existent file, or if any error occurs, NULL is returned.
** If the path points to a symlink, the resolved symlink path is returned.
** Note: The returned path's separator is system specific.
*/
/* End of pathutil.h */
#endif

View File

@ -377,6 +377,7 @@ char* SearchFile (const SearchPaths* P, const char* File)
SB_AppendStr (&PathName, File);
SB_Terminate (&PathName);
/* Check if this file exists */
if (access (SB_GetBuf (&PathName), 0) == 0) {
/* The file exists, we're done */

View File

@ -281,3 +281,22 @@ unsigned SP_GetCount (const StringPool* P)
{
return CollCount (&P->Entries);
}
unsigned SP_Lookup(StringPool *P, const StrBuf *S)
/*
** Determine whether the given string is in the pool.
** Returns 1 if the string is in the pool, 0 otherwise.
*/
{
return HT_Find (&P->Tab, S) != 0;
}
unsigned SP_LookupStr(StringPool *P, const char *S)
/*
** Determine whether the given string is in the pool.
** Returns 1 if the string is in the pool, 0 otherwise.
*/
{
StrBuf Buf;
return SP_Lookup (P, SB_InitFromString (&Buf, S));
}

View File

@ -84,7 +84,7 @@ const StrBuf* SP_Get (const StringPool* P, unsigned Index);
unsigned SP_Add (StringPool* P, const StrBuf* S);
/* Add a string buffer to the buffer and return the index. If the string does
** already exist in the pool, SP_AddBuf will just return the index of the
** already exist in the pool, SP_Add will just return the index of the
** existing string.
*/
@ -96,6 +96,18 @@ unsigned SP_AddStr (StringPool* P, const char* S);
unsigned SP_GetCount (const StringPool* P);
/* Return the number of strings in the pool */
unsigned SP_Lookup(StringPool *P, const StrBuf *S);
/*
** Determine whether the given string is in the pool.
** Returns 1 if the string is in the pool, 0 otherwise.
*/
unsigned SP_LookupStr(StringPool *P, const char *S);
/*
** Determine whether the given string is in the pool.
** Returns 1 if the string is in the pool, 0 otherwise.
*/
/* End of strpool.h */

View File

@ -14,7 +14,9 @@ WORKDIR = ../testwrk
.PHONY: test continue mostlyclean clean
test: mostlyclean continue
test:
@$(MAKE) mostlyclean
@$(MAKE) continue
continue:
@$(MAKE) -C asm all

View File

@ -0,0 +1,25 @@
; Test new-style (@:) and legacy-style (:) unnamed labels.
; Make sure that they have identical behavior.
.ORG $0000
@: nop
: nop
.ASSERT @<< = $0000, error
.ASSERT @-- = $0000, error
.ASSERT :<< = $0000, error
.ASSERT :-- = $0000, error
.ASSERT @< = $0001, error
.ASSERT @- = $0001, error
.ASSERT :< = $0001, error
.ASSERT :- = $0001, error
.ASSERT @> = $0002, error
.ASSERT @+ = $0002, error
.ASSERT :> = $0002, error
.ASSERT :+ = $0002, error
.ASSERT @>> = $0003, error
.ASSERT @++ = $0003, error
.ASSERT :>> = $0003, error
.ASSERT :++ = $0003, error
@: nop
: nop

View File

@ -0,0 +1,8 @@
/*
** !!DESCRIPTION!! Simple #pragma once directive tests
** !!ORIGIN!! cc65 regression tests
** !!LICENCE!! Public Domain
*/
#include "pragma-once-sample.h";

View File

@ -0,0 +1,21 @@
/*
** !!DESCRIPTION!! Simple #pragma once directive tests
** !!ORIGIN!! cc65 regression tests
** !!LICENCE!! Public Domain
*/
#ifdef FILE_INCLUDED
#error "This file should not have been included twice"
#define INCLUDED_TWICE
#else
#define FILE_INCLUDED
#endif
/* a pragma once directive should work regardless of where it is located in
the file, as long as it is seen by the preprocessor */
#pragma once

View File

@ -0,0 +1,27 @@
/*
** !!DESCRIPTION!! Simple #pragma once directive tests
** !!ORIGIN!! cc65 regression tests
** !!LICENCE!! Public Domain
*/
#pragma once
#include "pragma-once-sample-2.h"
#include "pragma-once-sample-2.h"
#include "pragma-once-sample.h"
#include "pragma-once-sample.h"
#include <stdio.h>
int main() {
#ifdef INCLUDED_TWICE
printf("pragma-once-sample.h included more than once\n");
return 1;
#else
printf("pragma-once-sample included once\n");
return 0;
#endif
}