mirror of
https://github.com/gbdev/rgbds.git
synced 2026-06-09 18:22:35 +00:00
Ensure CRLF line endings are preserved when necessary
Some test cases need CRLF line endings checked out even on Unix. Also some source files had inadvertently contained CR bytes.
This commit is contained in:
+21
-21
@@ -1,21 +1,21 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef RGBDS_CLI_HPP
|
||||
#define RGBDS_CLI_HPP
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#include "extern/getopt.hpp" // option
|
||||
#include "usage.hpp"
|
||||
|
||||
void cli_ParseArgs(
|
||||
int argc,
|
||||
char *argv[],
|
||||
char const *shortOpts,
|
||||
option const *longOpts,
|
||||
void (*parseArg)(int, char *),
|
||||
Usage usage
|
||||
);
|
||||
|
||||
#endif // RGBDS_CLI_HPP
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef RGBDS_CLI_HPP
|
||||
#define RGBDS_CLI_HPP
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#include "extern/getopt.hpp" // option
|
||||
#include "usage.hpp"
|
||||
|
||||
void cli_ParseArgs(
|
||||
int argc,
|
||||
char *argv[],
|
||||
char const *shortOpts,
|
||||
option const *longOpts,
|
||||
void (*parseArg)(int, char *),
|
||||
Usage usage
|
||||
);
|
||||
|
||||
#endif // RGBDS_CLI_HPP
|
||||
|
||||
+23
-23
@@ -1,23 +1,23 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef RGBDS_GFX_FLIP_HPP
|
||||
#define RGBDS_GFX_FLIP_HPP
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
|
||||
// Flipping tends to happen fairly often, so take a bite out of dcache to speed it up
|
||||
static std::array<uint16_t, 256> flipTable = ([]() constexpr {
|
||||
std::array<uint16_t, 256> table{};
|
||||
for (uint16_t i = 0; i < table.size(); ++i) {
|
||||
// To flip all the bits, we'll flip both nibbles, then each nibble half, etc.
|
||||
uint16_t byte = i;
|
||||
byte = (byte & 0b0000'1111) << 4 | (byte & 0b1111'0000) >> 4;
|
||||
byte = (byte & 0b0011'0011) << 2 | (byte & 0b1100'1100) >> 2;
|
||||
byte = (byte & 0b0101'0101) << 1 | (byte & 0b1010'1010) >> 1;
|
||||
table[i] = byte;
|
||||
}
|
||||
return table;
|
||||
})();
|
||||
|
||||
#endif // RGBDS_GFX_FLIP_HPP
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef RGBDS_GFX_FLIP_HPP
|
||||
#define RGBDS_GFX_FLIP_HPP
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
|
||||
// Flipping tends to happen fairly often, so take a bite out of dcache to speed it up
|
||||
static std::array<uint16_t, 256> flipTable = ([]() constexpr {
|
||||
std::array<uint16_t, 256> table{};
|
||||
for (uint16_t i = 0; i < table.size(); ++i) {
|
||||
// To flip all the bits, we'll flip both nibbles, then each nibble half, etc.
|
||||
uint16_t byte = i;
|
||||
byte = (byte & 0b0000'1111) << 4 | (byte & 0b1111'0000) >> 4;
|
||||
byte = (byte & 0b0011'0011) << 2 | (byte & 0b1100'1100) >> 2;
|
||||
byte = (byte & 0b0101'0101) << 1 | (byte & 0b1010'1010) >> 1;
|
||||
table[i] = byte;
|
||||
}
|
||||
return table;
|
||||
})();
|
||||
|
||||
#endif // RGBDS_GFX_FLIP_HPP
|
||||
|
||||
+27
-27
@@ -1,27 +1,27 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef RGBDS_GFX_PALETTE_HPP
|
||||
#define RGBDS_GFX_PALETTE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct Palette {
|
||||
// An array of 4 GBC-native (RGB555) colors
|
||||
std::array<uint16_t, 4> colors{UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX};
|
||||
|
||||
void addColor(uint16_t color);
|
||||
uint8_t indexOf(uint16_t color) const;
|
||||
uint16_t &operator[](size_t index) { return colors[index]; }
|
||||
uint16_t const &operator[](size_t index) const { return colors[index]; }
|
||||
|
||||
decltype(colors)::iterator begin();
|
||||
decltype(colors)::iterator end();
|
||||
decltype(colors)::const_iterator begin() const;
|
||||
decltype(colors)::const_iterator end() const;
|
||||
|
||||
uint8_t size() const;
|
||||
};
|
||||
|
||||
#endif // RGBDS_GFX_PALETTE_HPP
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef RGBDS_GFX_PALETTE_HPP
|
||||
#define RGBDS_GFX_PALETTE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct Palette {
|
||||
// An array of 4 GBC-native (RGB555) colors
|
||||
std::array<uint16_t, 4> colors{UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX};
|
||||
|
||||
void addColor(uint16_t color);
|
||||
uint8_t indexOf(uint16_t color) const;
|
||||
uint16_t &operator[](size_t index) { return colors[index]; }
|
||||
uint16_t const &operator[](size_t index) const { return colors[index]; }
|
||||
|
||||
decltype(colors)::iterator begin();
|
||||
decltype(colors)::iterator end();
|
||||
decltype(colors)::const_iterator begin() const;
|
||||
decltype(colors)::const_iterator end() const;
|
||||
|
||||
uint8_t size() const;
|
||||
};
|
||||
|
||||
#endif // RGBDS_GFX_PALETTE_HPP
|
||||
|
||||
+159
-159
@@ -1,159 +1,159 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "cli.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fstream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "extern/getopt.hpp"
|
||||
#include "style.hpp"
|
||||
#include "usage.hpp"
|
||||
#include "util.hpp" // isBlankSpace
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// Turn an at-file's contents into an argv that `getopt` can handle, appending them to `argPool`.
|
||||
static std::vector<size_t>
|
||||
readAtFile(std::string const &path, std::vector<char> &argPool, Usage usage) {
|
||||
std::vector<size_t> argvOfs;
|
||||
|
||||
std::filebuf file;
|
||||
if (!file.open(path, std::ios_base::in)) {
|
||||
int errnum = errno;
|
||||
style_Set(stderr, STYLE_RED, true);
|
||||
fputs("FATAL: ", stderr);
|
||||
style_Reset(stderr);
|
||||
fprintf(stderr, "Failed to open at-file \"%s\": %s\n", path.c_str(), strerror(errnum));
|
||||
usage.printAndExit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int c = file.sbumpc();
|
||||
|
||||
// First, discard any leading blank space
|
||||
while (isBlankSpace(c)) {
|
||||
c = file.sbumpc();
|
||||
}
|
||||
|
||||
// If it's a comment, discard everything until EOL
|
||||
if (c == '#') {
|
||||
c = file.sbumpc();
|
||||
while (c != EOF && !isNewline(c)) {
|
||||
c = file.sbumpc();
|
||||
}
|
||||
}
|
||||
|
||||
if (c == EOF) {
|
||||
return argvOfs;
|
||||
} else if (isNewline(c)) {
|
||||
continue; // Start processing the next line
|
||||
}
|
||||
|
||||
// Alright, now we can parse the line
|
||||
do {
|
||||
argvOfs.push_back(argPool.size());
|
||||
|
||||
// Read one argument (until the next whitespace char).
|
||||
// We know there is one because we already have its first character in `c`.
|
||||
for (; c != EOF && !isWhitespace(c); c = file.sbumpc()) {
|
||||
argPool.push_back(c);
|
||||
}
|
||||
argPool.push_back('\0');
|
||||
|
||||
// Discard blank space until the next argument (candidate)
|
||||
while (isBlankSpace(c)) {
|
||||
c = file.sbumpc();
|
||||
}
|
||||
} while (c != EOF && !isNewline(c)); // End if we reached EOL
|
||||
}
|
||||
}
|
||||
|
||||
void cli_ParseArgs(
|
||||
int argc,
|
||||
char *argv[],
|
||||
char const *shortOpts,
|
||||
option const *longOpts,
|
||||
void (*parseArg)(int, char *),
|
||||
Usage usage
|
||||
) {
|
||||
struct AtFileStackEntry {
|
||||
int parentInd; // Saved offset into parent argv
|
||||
std::vector<char *> argv; // This context's arg pointer vec
|
||||
|
||||
AtFileStackEntry(int parentInd_, std::vector<char *> argv_)
|
||||
: parentInd(parentInd_), argv(argv_) {}
|
||||
};
|
||||
std::vector<AtFileStackEntry> atFileStack;
|
||||
|
||||
int curArgc = argc;
|
||||
char **curArgv = argv;
|
||||
std::string optString = "-"s + shortOpts; // Request position arguments with a leading '-'
|
||||
std::vector<std::vector<char>> argPools;
|
||||
|
||||
for (;;) {
|
||||
char *atFileName = nullptr;
|
||||
for (int ch;
|
||||
(ch = musl_getopt_long_only(curArgc, curArgv, optString.c_str(), longOpts)) != -1;) {
|
||||
if (ch == 1 && musl_optarg[0] == '@') {
|
||||
atFileName = &musl_optarg[1];
|
||||
break;
|
||||
} else {
|
||||
parseArg(ch, musl_optarg);
|
||||
}
|
||||
}
|
||||
|
||||
if (atFileName) {
|
||||
// We need to allocate a new arg pool for each at-file, so as not to invalidate pointers
|
||||
// previous at-files may have generated to their own arg pools.
|
||||
// But for the same reason, the arg pool must also outlive the at-file's stack entry!
|
||||
std::vector<char> &argPool = argPools.emplace_back();
|
||||
|
||||
// Copy `argv[0]` for error reporting, and because option parsing skips it
|
||||
AtFileStackEntry &stackEntry =
|
||||
atFileStack.emplace_back(musl_optind, std::vector{atFileName});
|
||||
|
||||
// It would be nice to compute the char pointers on the fly, but reallocs don't allow
|
||||
// that; so we must compute the offsets after the pool is fixed
|
||||
std::vector<size_t> offsets = readAtFile(&musl_optarg[1], argPool, usage);
|
||||
stackEntry.argv.reserve(offsets.size() + 2); // Avoid a bunch of reallocs
|
||||
for (size_t ofs : offsets) {
|
||||
stackEntry.argv.push_back(&argPool.data()[ofs]);
|
||||
}
|
||||
stackEntry.argv.push_back(nullptr); // Don't forget the arg vector terminator!
|
||||
|
||||
curArgc = stackEntry.argv.size() - 1;
|
||||
curArgv = stackEntry.argv.data();
|
||||
musl_optind = 1; // Don't use 0 because we're not scanning a different argv per se
|
||||
} else {
|
||||
if (musl_optind != curArgc) {
|
||||
// This happens if `--` is passed, process the remaining arg(s) as positional
|
||||
assume(musl_optind < curArgc);
|
||||
for (int i = musl_optind; i < curArgc; ++i) {
|
||||
parseArg(1, argv[i]); // Positional argument
|
||||
}
|
||||
}
|
||||
|
||||
// Pop off the top stack entry, or end parsing if none
|
||||
if (atFileStack.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// OK to restore `optind` directly, because `optpos` must be 0 right now.
|
||||
// (Providing 0 would be a "proper" reset, but we want to resume parsing)
|
||||
musl_optind = atFileStack.back().parentInd;
|
||||
atFileStack.pop_back();
|
||||
if (atFileStack.empty()) {
|
||||
curArgc = argc;
|
||||
curArgv = argv;
|
||||
} else {
|
||||
std::vector<char *> &vec = atFileStack.back().argv;
|
||||
curArgc = vec.size();
|
||||
curArgv = vec.data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "cli.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fstream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "extern/getopt.hpp"
|
||||
#include "style.hpp"
|
||||
#include "usage.hpp"
|
||||
#include "util.hpp" // isBlankSpace
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// Turn an at-file's contents into an argv that `getopt` can handle, appending them to `argPool`.
|
||||
static std::vector<size_t>
|
||||
readAtFile(std::string const &path, std::vector<char> &argPool, Usage usage) {
|
||||
std::vector<size_t> argvOfs;
|
||||
|
||||
std::filebuf file;
|
||||
if (!file.open(path, std::ios_base::in)) {
|
||||
int errnum = errno;
|
||||
style_Set(stderr, STYLE_RED, true);
|
||||
fputs("FATAL: ", stderr);
|
||||
style_Reset(stderr);
|
||||
fprintf(stderr, "Failed to open at-file \"%s\": %s\n", path.c_str(), strerror(errnum));
|
||||
usage.printAndExit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int c = file.sbumpc();
|
||||
|
||||
// First, discard any leading blank space
|
||||
while (isBlankSpace(c)) {
|
||||
c = file.sbumpc();
|
||||
}
|
||||
|
||||
// If it's a comment, discard everything until EOL
|
||||
if (c == '#') {
|
||||
c = file.sbumpc();
|
||||
while (c != EOF && !isNewline(c)) {
|
||||
c = file.sbumpc();
|
||||
}
|
||||
}
|
||||
|
||||
if (c == EOF) {
|
||||
return argvOfs;
|
||||
} else if (isNewline(c)) {
|
||||
continue; // Start processing the next line
|
||||
}
|
||||
|
||||
// Alright, now we can parse the line
|
||||
do {
|
||||
argvOfs.push_back(argPool.size());
|
||||
|
||||
// Read one argument (until the next whitespace char).
|
||||
// We know there is one because we already have its first character in `c`.
|
||||
for (; c != EOF && !isWhitespace(c); c = file.sbumpc()) {
|
||||
argPool.push_back(c);
|
||||
}
|
||||
argPool.push_back('\0');
|
||||
|
||||
// Discard blank space until the next argument (candidate)
|
||||
while (isBlankSpace(c)) {
|
||||
c = file.sbumpc();
|
||||
}
|
||||
} while (c != EOF && !isNewline(c)); // End if we reached EOL
|
||||
}
|
||||
}
|
||||
|
||||
void cli_ParseArgs(
|
||||
int argc,
|
||||
char *argv[],
|
||||
char const *shortOpts,
|
||||
option const *longOpts,
|
||||
void (*parseArg)(int, char *),
|
||||
Usage usage
|
||||
) {
|
||||
struct AtFileStackEntry {
|
||||
int parentInd; // Saved offset into parent argv
|
||||
std::vector<char *> argv; // This context's arg pointer vec
|
||||
|
||||
AtFileStackEntry(int parentInd_, std::vector<char *> argv_)
|
||||
: parentInd(parentInd_), argv(argv_) {}
|
||||
};
|
||||
std::vector<AtFileStackEntry> atFileStack;
|
||||
|
||||
int curArgc = argc;
|
||||
char **curArgv = argv;
|
||||
std::string optString = "-"s + shortOpts; // Request position arguments with a leading '-'
|
||||
std::vector<std::vector<char>> argPools;
|
||||
|
||||
for (;;) {
|
||||
char *atFileName = nullptr;
|
||||
for (int ch;
|
||||
(ch = musl_getopt_long_only(curArgc, curArgv, optString.c_str(), longOpts)) != -1;) {
|
||||
if (ch == 1 && musl_optarg[0] == '@') {
|
||||
atFileName = &musl_optarg[1];
|
||||
break;
|
||||
} else {
|
||||
parseArg(ch, musl_optarg);
|
||||
}
|
||||
}
|
||||
|
||||
if (atFileName) {
|
||||
// We need to allocate a new arg pool for each at-file, so as not to invalidate pointers
|
||||
// previous at-files may have generated to their own arg pools.
|
||||
// But for the same reason, the arg pool must also outlive the at-file's stack entry!
|
||||
std::vector<char> &argPool = argPools.emplace_back();
|
||||
|
||||
// Copy `argv[0]` for error reporting, and because option parsing skips it
|
||||
AtFileStackEntry &stackEntry =
|
||||
atFileStack.emplace_back(musl_optind, std::vector{atFileName});
|
||||
|
||||
// It would be nice to compute the char pointers on the fly, but reallocs don't allow
|
||||
// that; so we must compute the offsets after the pool is fixed
|
||||
std::vector<size_t> offsets = readAtFile(&musl_optarg[1], argPool, usage);
|
||||
stackEntry.argv.reserve(offsets.size() + 2); // Avoid a bunch of reallocs
|
||||
for (size_t ofs : offsets) {
|
||||
stackEntry.argv.push_back(&argPool.data()[ofs]);
|
||||
}
|
||||
stackEntry.argv.push_back(nullptr); // Don't forget the arg vector terminator!
|
||||
|
||||
curArgc = stackEntry.argv.size() - 1;
|
||||
curArgv = stackEntry.argv.data();
|
||||
musl_optind = 1; // Don't use 0 because we're not scanning a different argv per se
|
||||
} else {
|
||||
if (musl_optind != curArgc) {
|
||||
// This happens if `--` is passed, process the remaining arg(s) as positional
|
||||
assume(musl_optind < curArgc);
|
||||
for (int i = musl_optind; i < curArgc; ++i) {
|
||||
parseArg(1, argv[i]); // Positional argument
|
||||
}
|
||||
}
|
||||
|
||||
// Pop off the top stack entry, or end parsing if none
|
||||
if (atFileStack.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// OK to restore `optind` directly, because `optpos` must be 0 right now.
|
||||
// (Providing 0 would be a "proper" reset, but we want to resume parsing)
|
||||
musl_optind = atFileStack.back().parentInd;
|
||||
atFileStack.pop_back();
|
||||
if (atFileStack.empty()) {
|
||||
curArgc = argc;
|
||||
curArgv = argv;
|
||||
} else {
|
||||
std::vector<char *> &vec = atFileStack.back().argv;
|
||||
curArgc = vec.size();
|
||||
curArgv = vec.data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+55
-55
@@ -1,55 +1,55 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "gfx/palette.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
#include "gfx/main.hpp"
|
||||
#include "gfx/rgba.hpp"
|
||||
|
||||
void Palette::addColor(uint16_t color) {
|
||||
for (size_t i = 0; true; ++i) {
|
||||
assume(i < colors.size()); // The packing should guarantee this
|
||||
if (colors[i] == color) { // The color is already present
|
||||
break;
|
||||
} else if (colors[i] == UINT16_MAX) { // Empty slot
|
||||
colors[i] = color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the ID of the color in the palette, or `size()` if the color is not in
|
||||
uint8_t Palette::indexOf(uint16_t color) const {
|
||||
return color == Rgba::transparent
|
||||
? 0
|
||||
: std::find(begin(), colors.end(), color) - begin() + options.hasTransparentPixels;
|
||||
}
|
||||
|
||||
auto Palette::begin() -> decltype(colors)::iterator {
|
||||
// Skip the first slot if reserved for transparency
|
||||
return colors.begin() + options.hasTransparentPixels;
|
||||
}
|
||||
|
||||
auto Palette::end() -> decltype(colors)::iterator {
|
||||
// Return an iterator pointing past the last non-empty element.
|
||||
// Since the palette may contain gaps, we must scan from the end.
|
||||
return std::find_if(RRANGE(colors), [](uint16_t c) { return c != UINT16_MAX; }).base();
|
||||
}
|
||||
|
||||
auto Palette::begin() const -> decltype(colors)::const_iterator {
|
||||
// Same as the non-const begin().
|
||||
return colors.begin() + options.hasTransparentPixels;
|
||||
}
|
||||
|
||||
auto Palette::end() const -> decltype(colors)::const_iterator {
|
||||
// Same as the non-const end().
|
||||
return std::find_if(RRANGE(colors), [](uint16_t c) { return c != UINT16_MAX; }).base();
|
||||
}
|
||||
|
||||
uint8_t Palette::size() const {
|
||||
return end() - colors.begin();
|
||||
}
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "gfx/palette.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
#include "gfx/main.hpp"
|
||||
#include "gfx/rgba.hpp"
|
||||
|
||||
void Palette::addColor(uint16_t color) {
|
||||
for (size_t i = 0; true; ++i) {
|
||||
assume(i < colors.size()); // The packing should guarantee this
|
||||
if (colors[i] == color) { // The color is already present
|
||||
break;
|
||||
} else if (colors[i] == UINT16_MAX) { // Empty slot
|
||||
colors[i] = color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the ID of the color in the palette, or `size()` if the color is not in
|
||||
uint8_t Palette::indexOf(uint16_t color) const {
|
||||
return color == Rgba::transparent
|
||||
? 0
|
||||
: std::find(begin(), colors.end(), color) - begin() + options.hasTransparentPixels;
|
||||
}
|
||||
|
||||
auto Palette::begin() -> decltype(colors)::iterator {
|
||||
// Skip the first slot if reserved for transparency
|
||||
return colors.begin() + options.hasTransparentPixels;
|
||||
}
|
||||
|
||||
auto Palette::end() -> decltype(colors)::iterator {
|
||||
// Return an iterator pointing past the last non-empty element.
|
||||
// Since the palette may contain gaps, we must scan from the end.
|
||||
return std::find_if(RRANGE(colors), [](uint16_t c) { return c != UINT16_MAX; }).base();
|
||||
}
|
||||
|
||||
auto Palette::begin() const -> decltype(colors)::const_iterator {
|
||||
// Same as the non-const begin().
|
||||
return colors.begin() + options.hasTransparentPixels;
|
||||
}
|
||||
|
||||
auto Palette::end() const -> decltype(colors)::const_iterator {
|
||||
// Same as the non-const end().
|
||||
return std::find_if(RRANGE(colors), [](uint16_t c) { return c != UINT16_MAX; }).base();
|
||||
}
|
||||
|
||||
uint8_t Palette::size() const {
|
||||
return end() - colors.begin();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Some files test CRLF line endings
|
||||
character-escapes.out -text diff
|
||||
crlf.asm text eol=crlf
|
||||
string-literal-macro-arg.out -text diff
|
||||
+11
-2
@@ -8,6 +8,15 @@ assert !strcmp("{s}", "Hello, world!")
|
||||
* block comment
|
||||
*/
|
||||
|
||||
DEF t EQUS """Hello,
|
||||
REPT 2
|
||||
REDEF t EQUS """Hello,
|
||||
world!"""
|
||||
assert !strcmp("{t}", "Hello,\nworld!")
|
||||
assert !strcmp("{t}", "Hello,\nworld!")
|
||||
ENDR
|
||||
|
||||
MACRO m
|
||||
assert "\1" === "Hello, world!"
|
||||
ENDM
|
||||
|
||||
m Hello\, \
|
||||
world!
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
MACRO compare
|
||||
print "\3: "
|
||||
if _NARG == 4
|
||||
def v1 = \3(\4q\1, \1)
|
||||
def v2 = \3(\4q\2, \2)
|
||||
elif _NARG == 5
|
||||
def v1 = \3(\4q\1, \5q\1, \1)
|
||||
def v2 = \3(\4q\2, \5q\2, \2)
|
||||
endc
|
||||
println "{.4q\1f:v1} == {.4q\2f:v2}"
|
||||
ENDM
|
||||
|
||||
compare 8, 16, mul, 6.0, 7.0
|
||||
compare 12, 24, div, 115.625, 9.25
|
||||
compare 7, 14, pow, 3.5, 5.5
|
||||
|
||||
compare 4, 8, sin, 0.25
|
||||
compare 5, 9, cos, 0.75
|
||||
compare 6, 10, asin, 1.0
|
||||
compare 7, 11, acos, 0.0
|
||||
|
||||
compare 3, 6, round, 1.75
|
||||
compare 10, 20, ceil, 123.4
|
||||
compare 13, 17, floor, 567.8
|
||||
MACRO compare
|
||||
print "\3: "
|
||||
if _NARG == 4
|
||||
def v1 = \3(\4q\1, \1)
|
||||
def v2 = \3(\4q\2, \2)
|
||||
elif _NARG == 5
|
||||
def v1 = \3(\4q\1, \5q\1, \1)
|
||||
def v2 = \3(\4q\2, \5q\2, \2)
|
||||
endc
|
||||
println "{.4q\1f:v1} == {.4q\2f:v2}"
|
||||
ENDM
|
||||
|
||||
compare 8, 16, mul, 6.0, 7.0
|
||||
compare 12, 24, div, 115.625, 9.25
|
||||
compare 7, 14, pow, 3.5, 5.5
|
||||
|
||||
compare 4, 8, sin, 0.25
|
||||
compare 5, 9, cos, 0.75
|
||||
compare 6, 10, asin, 1.0
|
||||
compare 7, 11, acos, 0.0
|
||||
|
||||
compare 3, 6, round, 1.75
|
||||
compare 10, 20, ceil, 123.4
|
||||
compare 13, 17, floor, 567.8
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
SECTION UNION "wat", ROM0
|
||||
db 42
|
||||
SECTION UNION "wat", ROM0
|
||||
db 42
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# Some files test CRLF line endings
|
||||
linkerscript-escapes-test.link -text diff
|
||||
Reference in New Issue
Block a user