1
0
forked from Mirror/wren

Add a minimal path manipulation C module.

This is just for the VM's own internal use, for resolving relative
imports.

Also added a tiny unit test framework for writing tests of low-level
C functionality that isn't exposed directly by the language or VM.
This commit is contained in:
Bob Nystrom
2018-03-24 10:52:16 -07:00
parent 8a71735e0f
commit 5539c59750
12 changed files with 642 additions and 30 deletions

View File

@ -49,23 +49,23 @@ all: debug release
ci: ci_32 ci_64
ci_32:
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=32 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=32 vm cli api_test
$(V) ./util/test.py --suffix=d-32 $(suite)
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=32 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=32 vm cli api_test
$(V) ./util/test.py --suffix=d-cpp-32 $(suite)
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=32 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=32 vm cli api_test
$(V) ./util/test.py --suffix=-32 $(suite)
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=32 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=32 vm cli api_test
$(V) ./util/test.py --suffix=-cpp-32 $(suite)
ci_64:
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=64 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=64 vm cli api_test
$(V) ./util/test.py --suffix=d-64 $(suite)
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=64 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=64 vm cli api_test
$(V) ./util/test.py --suffix=d-cpp-64 $(suite)
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=64 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=64 vm cli api_test
$(V) ./util/test.py --suffix=-64 $(suite)
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=64 vm cli test
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=64 vm cli api_test
$(V) ./util/test.py --suffix=-cpp-64 $(suite)
# Remove all build outputs and intermediate files. Does not remove downloaded
@ -77,13 +77,17 @@ clean:
# Run the tests against the debug build of Wren.
test: debug
$(V) $(MAKE) -f util/wren.mk MODE=debug test
$(V) $(MAKE) -f util/wren.mk MODE=debug api_test
$(V) ./util/test.py $(suite)
benchmark: release
$(V) $(MAKE) -f util/wren.mk test
$(V) $(MAKE) -f util/wren.mk api_test
$(V) ./util/benchmark.py -l wren $(suite)
unit_test:
$(V) $(MAKE) -f util/wren.mk MODE=debug unit_test
$(V) ./build/debug/test/unit_wrend
# Generate the Wren site.
docs:
$(V) ./util/generate_docs.py
@ -104,4 +108,4 @@ gh-pages: docs
amalgamation: src/include/wren.h src/vm/*.h src/vm/*.c
./util/generate_amalgamation.py > build/wren.c
.PHONY: all amalgamation builtin clean debug docs gh-pages release test vm watchdocs ci ci_32 ci_64
.PHONY: all amalgamation benchmark builtin clean debug docs gh-pages release test vm watchdocs ci ci_32 ci_64

254
src/cli/path.c Normal file
View File

@ -0,0 +1,254 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "path.h"
// The maximum number of components in a path. We can't normalize a path that
// contains more than this number of parts. The number here assumes a max path
// length of 4096, which is common on Linux, and then assumes each component is
// at least two characters, "/", and a single-letter directory name.
#define MAX_COMPONENTS 2048
typedef struct {
const char* start;
const char* end;
} Slice;
static void ensureCapacity(Path* path, size_t capacity)
{
// Capacity always needs to be one greater than the actual length to have
// room for the null byte, which is stored in the buffer, but not counted in
// the length. A zero-character path still needs a one-character array to
// store the '\0'.
capacity++;
if (path->capacity >= capacity) return;
// Grow by doubling in size.
size_t newCapacity = 16;
while (newCapacity < capacity) newCapacity *= 2;
path->chars = (char*)realloc(path->chars, newCapacity);
path->capacity = newCapacity;
}
static void appendSlice(Path* path, Slice slice)
{
size_t length = slice.end - slice.start;
ensureCapacity(path, path->length + length);
memcpy(path->chars + path->length, slice.start, length);
path->length += length;
path->chars[path->length] = '\0';
}
Path* pathNew(const char* string)
{
Path* path = (Path*)malloc(sizeof(Path));
path->chars = (char*)malloc(1);
path->chars[0] = '\0';
path->length = 0;
path->capacity = 0;
pathAppendString(path, string);
return path;
}
void pathFree(Path* path)
{
if (path->chars) free(path->chars);
free(path);
}
void pathDirName(Path* path)
{
// Find the last path separator.
for (size_t i = path->length - 1; i < path->length; i--)
{
if (path->chars[i] == '/')
{
path->length = i;
path->chars[i] = '\0';
return;
}
}
// If we got here, there was no separator so it must be a single component.
path->length = 0;
path->chars[0] = '\0';
}
void pathRemoveExtension(Path* path)
{
for (size_t i = path->length - 1; i < path->length; i--)
{
// If we hit a path separator before finding the extension, then the last
// component doesn't have one.
if (path->chars[i] == '/') return;
if (path->chars[i] == '.')
{
path->length = i;
path->chars[path->length] = '\0';
}
}
}
void pathJoin(Path* path, const char* string)
{
if (path->length > 0 && path->chars[path->length - 1] != '/')
{
pathAppendChar(path, '/');
}
pathAppendString(path, string);
}
#ifdef _WIN32
static bool isDriveLetter(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
#endif
bool pathIsAbsolute(Path* path)
{
#ifdef _WIN32
// Absolute path in the current drive.
if (path->length >= 1 && path->chars[0] == '\\') return true;
// Drive letter.
if (path->length >= 3 &&
isDriveLetter(path->chars[0]) &&
path->chars[1] == ':' &&
path->chars[2] == '\\')
{
return true;
}
// UNC path.
return path->length >= 2 && path->chars[0] == '\\' && path->chars[1] == '\\';
#else
// Otherwise, assume POSIX-style paths.
return path->length >= 1 && path->chars[0] == '/';
#endif
}
void pathAppendChar(Path* path, char c)
{
ensureCapacity(path, path->length + 1);
path->chars[path->length++] = c;
path->chars[path->length] = '\0';
}
void pathAppendString(Path* path, const char* string)
{
Slice slice;
slice.start = string;
slice.end = string + strlen(string);
appendSlice(path, slice);
}
Path* pathNormalize(Path* path)
{
Path* result = pathNew("");
// Split the path into components.
Slice components[MAX_COMPONENTS];
int numComponents = 0;
char* start = path->chars;
char* end = path->chars;
// Split into parts and handle "." and "..".
int leadingDoubles = 0;
for (;;)
{
if (*end == '\0' || *end == '/')
{
// Add the current component.
if (start != end)
{
size_t length = end - start;
if (length == 1 && start[0] == '.')
{
// Skip "." components.
}
else if (length == 2 && start[0] == '.' && start[1] == '.')
{
// Walk out of directories on "..".
if (numComponents > 0)
{
// Discard the previous component.
numComponents--;
}
else
{
// Can't back out any further, so preserve the "..".
leadingDoubles++;
}
}
else
{
if (numComponents >= MAX_COMPONENTS)
{
fprintf(stderr, "Path cannot have more than %d path components.\n",
MAX_COMPONENTS);
exit(1);
}
components[numComponents].start = start;
components[numComponents].end = end;
numComponents++;
}
}
// Skip over separators.
while (*end != '\0' && *end == '/') end++;
start = end;
if (*end == '\0') break;
}
end++;
}
// Preserve the absolute prefix, if any.
bool needsSeparator = false;
if (path->length > 0 && path->chars[0] == '/')
{
pathAppendChar(result, '/');
}
else
{
// Add any leading "..".
for (int i = 0; i < leadingDoubles; i++)
{
if (needsSeparator) pathAppendChar(result, '/');
pathAppendString(result, "..");
needsSeparator = true;
}
}
for (int i = 0; i < numComponents; i++)
{
if (needsSeparator) pathAppendChar(result, '/');
appendSlice(result, components[i]);
needsSeparator = true;
}
if (result->length == 0) pathAppendChar(result, '.');
return result;
}
char* pathToString(Path* path)
{
char* string = (char*)malloc(path->length + 1);
memcpy(string, path->chars, path->length);
string[path->length] = '\0';
return string;
}

52
src/cli/path.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef path_h
#define path_h
// Path manipulation functions.
typedef struct
{
// Dynamically allocated array of characters.
char* chars;
// The number of characters currently in use in [chars], not including the
// null terminator.
size_t length;
// Size of the allocated [chars] buffer.
size_t capacity;
} Path;
// Creates a new empty path.
Path* pathNew(const char* string);
// Releases the method associated with [path].
void pathFree(Path* path);
// Strips off the last component of the path name.
void pathDirName(Path* path);
// Strips off the file extension from the last component of the path.
void pathRemoveExtension(Path* path);
// Appends [string] to [path].
void pathJoin(Path* path, const char* string);
// Return true if [path] is an absolute path for the host operating system.
bool pathIsAbsolute(Path* path);
// Appends [c] to the path, growing the buffer if needed.
void pathAppendChar(Path* path, char c);
// Appends [string] to the path, growing the buffer if needed.
void pathAppendString(Path* path, const char* string);
// Simplifies the path string as much as possible.
//
// Applies and removes any "." or ".." components, collapses redundant "/"
// characters, etc.
Path* pathNormalize(Path* path);
// Allocates a new string exactly the right length and copies this path to it.
char* pathToString(Path* path);
#endif

9
test/unit/main.c Normal file
View File

@ -0,0 +1,9 @@
#include "path_test.h"
#include "test.h"
int main()
{
testPath();
return showTestResults();
}

105
test/unit/path_test.c Normal file
View File

@ -0,0 +1,105 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "path.h"
#include "test.h"
static void expectNormalize(const char* input, const char* expected)
{
Path* path = pathNew(input);
Path* result = pathNormalize(path);
if (strcmp(result->chars, expected) != 0)
{
printf("FAIL %-30s Want %s\n", input, expected);
printf(" Got %s\n\n", result->chars);
fail();
}
else
{
#if SHOW_PASSES
printf("PASS %-30s -> %s\n", input, result->chars);
#endif
pass();
}
pathFree(path);
pathFree(result);
}
static void testNormalize()
{
// simple cases
expectNormalize("", ".");
expectNormalize(".", ".");
expectNormalize("..", "..");
expectNormalize("a", "a");
expectNormalize("/", "/");
// collapses redundant separators
expectNormalize("a/b/c", "a/b/c");
expectNormalize("a//b///c////d", "a/b/c/d");
// eliminates "." parts
expectNormalize("./", ".");
expectNormalize("/.", "/");
expectNormalize("/./", "/");
expectNormalize("./.", ".");
expectNormalize("a/./b", "a/b");
expectNormalize("a/.b/c", "a/.b/c");
expectNormalize("a/././b/./c", "a/b/c");
expectNormalize("././a", "a");
expectNormalize("a/./.", "a");
// eliminates ".." parts
expectNormalize("..", "..");
expectNormalize("../", "..");
expectNormalize("../../..", "../../..");
expectNormalize("../../../", "../../..");
expectNormalize("/..", "/");
expectNormalize("/../../..", "/");
expectNormalize("/../../../a", "/a");
expectNormalize("a/..", ".");
expectNormalize("a/b/..", "a");
expectNormalize("a/../b", "b");
expectNormalize("a/./../b", "b");
expectNormalize("a/b/c/../../d/e/..", "a/d");
expectNormalize("a/b/../../../../c", "../../c");
// does not walk before root on absolute paths
expectNormalize("..", "..");
expectNormalize("../", "..");
expectNormalize("/..", "/");
expectNormalize("a/..", ".");
expectNormalize("../a", "../a");
expectNormalize("/../a", "/a");
expectNormalize("/../a", "/a");
expectNormalize("a/b/..", "a");
expectNormalize("../a/b/..", "../a");
expectNormalize("a/../b", "b");
expectNormalize("a/./../b", "b");
expectNormalize("a/b/c/../../d/e/..", "a/d");
expectNormalize("a/b/../../../../c", "../../c");
expectNormalize("a/b/c/../../..d/./.e/f././", "a/..d/.e/f.");
// removes trailing separators
expectNormalize("./", ".");
expectNormalize(".//", ".");
expectNormalize("a/", "a");
expectNormalize("a/b/", "a/b");
expectNormalize("a/b///", "a/b");
expectNormalize("foo/bar/baz", "foo/bar/baz");
expectNormalize("foo", "foo");
expectNormalize("foo/bar/", "foo/bar");
expectNormalize("./foo/././bar/././", "foo/bar");
}
void testPath()
{
// TODO: Test other functions.
testNormalize();
}

1
test/unit/path_test.h Normal file
View File

@ -0,0 +1 @@
void testPath();

29
test/unit/test.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include "test.h"
int passes = 0;
int failures = 0;
void pass()
{
passes++;
}
void fail()
{
failures++;
}
int showTestResults()
{
if (failures > 0)
{
printf("%d out of %d tests failed. :(\n", failures, passes + failures);
return 1;
}
printf("All %d tests passed!\n", passes + failures);
return 0;
}

7
test/unit/test.h Normal file
View File

@ -0,0 +1,7 @@
// Set this to 1 to output passing tests.
#define SHOW_PASSES 0
void pass();
void fail();
int showTestResults();

View File

@ -154,7 +154,7 @@ def run_trial(benchmark, language):
# of the normal Wren build.
if benchmark[0].startswith("api_"):
executable_args = [
os.path.join(WREN_DIR, "build", "release", "test", "wren")
os.path.join(WREN_DIR, "build", "release", "test", "api_wren")
]
args = []

View File

@ -25,7 +25,7 @@ config_dir = ("debug" if is_debug else "release") + config
WREN_DIR = dirname(dirname(realpath(__file__)))
WREN_APP = join(WREN_DIR, 'bin', 'wren' + args.suffix)
TEST_APP = join(WREN_DIR, 'build', config_dir, 'test', 'wren' + args.suffix)
TEST_APP = join(WREN_DIR, 'build', config_dir, 'test', 'api_wren' + args.suffix)
EXPECT_PATTERN = re.compile(r'// expect: ?(.*)')
EXPECT_ERROR_PATTERN = re.compile(r'// expect error(?! line)')

View File

@ -31,8 +31,11 @@ MODULE_SOURCES := $(wildcard src/module/*.c)
VM_HEADERS := $(wildcard src/vm/*.h) $(wildcard src/vm/*.wren.inc)
VM_SOURCES := $(wildcard src/vm/*.c)
TEST_HEADERS := $(wildcard test/api/*.h)
TEST_SOURCES := $(wildcard test/api/*.c)
API_TEST_HEADERS := $(wildcard test/api/*.h)
API_TEST_SOURCES := $(wildcard test/api/*.c)
UNIT_TEST_HEADERS := $(wildcard test/unit/*.h)
UNIT_TEST_SOURCES := $(wildcard test/unit/*.c)
BUILD_DIR := build
@ -124,7 +127,8 @@ OPT_OBJECTS := $(addprefix $(BUILD_DIR)/optional/, $(notdir $(OPT_SOURCES:.c=
CLI_OBJECTS := $(addprefix $(BUILD_DIR)/cli/, $(notdir $(CLI_SOURCES:.c=.o)))
MODULE_OBJECTS := $(addprefix $(BUILD_DIR)/module/, $(notdir $(MODULE_SOURCES:.c=.o)))
VM_OBJECTS := $(addprefix $(BUILD_DIR)/vm/, $(notdir $(VM_SOURCES:.c=.o)))
TEST_OBJECTS := $(patsubst test/api/%.c, $(BUILD_DIR)/test/%.o, $(TEST_SOURCES))
API_TEST_OBJECTS := $(patsubst test/api/%.c, $(BUILD_DIR)/test/api/%.o, $(API_TEST_SOURCES))
UNIT_TEST_OBJECTS := $(patsubst test/unit/%.c, $(BUILD_DIR)/test/unit/%.o, $(UNIT_TEST_SOURCES))
LIBUV_DIR := deps/libuv
LIBUV := build/libuv$(LIBUV_ARCH).a
@ -152,7 +156,10 @@ static: lib/lib$(WREN).a
cli: bin/$(WREN)
# Builds the API test executable.
test: $(BUILD_DIR)/test/$(WREN)
api_test: $(BUILD_DIR)/test/api_$(WREN)
# Builds the unit test executable.
unit_test: $(BUILD_DIR)/test/unit_$(WREN)
# Command-line interpreter.
bin/$(WREN): $(OPT_OBJECTS) $(CLI_OBJECTS) $(MODULE_OBJECTS) $(VM_OBJECTS) \
@ -173,13 +180,22 @@ lib/lib$(WREN).$(SHARED_EXT): $(OPT_OBJECTS) $(VM_OBJECTS)
$(V) mkdir -p lib
$(V) $(CC) $(CFLAGS) -shared $(SHARED_LIB_FLAGS) -o $@ $^
# Test executable.
$(BUILD_DIR)/test/$(WREN): $(OPT_OBJECTS) $(MODULE_OBJECTS) $(TEST_OBJECTS) \
$(VM_OBJECTS) $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o $(LIBUV)
# API test executable.
$(BUILD_DIR)/test/api_$(WREN): $(OPT_OBJECTS) $(MODULE_OBJECTS) $(API_TEST_OBJECTS) \
$(VM_OBJECTS) $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o \
$(BUILD_DIR)/cli/path.o $(LIBUV)
@ printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
$(V) mkdir -p $(BUILD_DIR)/test
$(V) mkdir -p $(BUILD_DIR)/test/api
$(V) $(CC) $(CFLAGS) $^ -o $@ -lm $(LIBUV_LIBS)
# Unit test executable.
$(BUILD_DIR)/test/unit_$(WREN): $(OPT_OBJECTS) $(MODULE_OBJECTS) $(UNIT_TEST_OBJECTS) \
$(VM_OBJECTS) $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o \
$(BUILD_DIR)/cli/path.o $(LIBUV)
@ printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
$(V) mkdir -p $(BUILD_DIR)/test/unit
$(V) $(CC) $(CFLAGS) $^ -o $@
# CLI object files.
$(BUILD_DIR)/cli/%.o: src/cli/%.c $(CLI_HEADERS) $(MODULE_HEADERS) \
$(VM_HEADERS) $(LIBUV)
@ -194,7 +210,7 @@ $(BUILD_DIR)/module/%.o: src/module/%.c $(CLI_HEADERS) $(MODULE_HEADERS) \
$(V) mkdir -p $(BUILD_DIR)/module
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
# Aux object files.
# Optional object files.
$(BUILD_DIR)/optional/%.o: src/optional/%.c $(VM_HEADERS) $(OPT_HEADERS)
@ printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
$(V) mkdir -p $(BUILD_DIR)/optional
@ -206,9 +222,16 @@ $(BUILD_DIR)/vm/%.o: src/vm/%.c $(VM_HEADERS)
$(V) mkdir -p $(BUILD_DIR)/vm
$(V) $(CC) -c $(CFLAGS) -Isrc/include -Isrc/optional -Isrc/vm -o $@ $(FILE_FLAG) $<
# Test object files.
$(BUILD_DIR)/test/%.o: test/api/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
$(VM_HEADERS) $(TEST_HEADERS) $(LIBUV)
# API test object files.
$(BUILD_DIR)/test/api/%.o: test/api/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
$(VM_HEADERS) $(API_TEST_HEADERS) $(LIBUV)
@ printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
$(V) mkdir -p $(dir $@)
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
# Unit test object files.
$(BUILD_DIR)/test/unit/%.o: test/unit/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
$(VM_HEADERS) $(UNIT_TEST_HEADERS) $(LIBUV)
@ printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
$(V) mkdir -p $(dir $@)
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
@ -231,4 +254,4 @@ src/module/%.wren.inc: src/module/%.wren util/wren_to_c_string.py
@ printf "%10s %-30s %s\n" str $<
$(V) ./util/wren_to_c_string.py $@ $<
.PHONY: all cli test vm
.PHONY: all api_test cli unit_test vm

View File

@ -24,9 +24,14 @@
293B255A1CEFD8C7005D9537 /* repl.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 293B25561CEFD8C7005D9537 /* repl.wren.inc */; };
293D46961BB43F9900200083 /* call.c in Sources */ = {isa = PBXBuildFile; fileRef = 293D46941BB43F9900200083 /* call.c */; };
2940E98D2063EC030054503C /* resolution.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E98B2063EC020054503C /* resolution.c */; };
2940E9BB2066067D0054503C /* path_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E9BA2066067D0054503C /* path_test.c */; };
2940E9BC206607830054503C /* path.c in Sources */ = {isa = PBXBuildFile; fileRef = 2952CD1B1FA9941700985F5F /* path.c */; };
2940E9BE2066C3300054503C /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E9BD2066C3300054503C /* main.c */; };
2940E9C12066C35E0054503C /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E9BF2066C35E0054503C /* test.c */; };
2949AA8D1C2F14F000B106BA /* get_variable.c in Sources */ = {isa = PBXBuildFile; fileRef = 2949AA8B1C2F14F000B106BA /* get_variable.c */; };
29512C811B91F8EB008C10E6 /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29512C801B91F8EB008C10E6 /* libuv.a */; };
29512C821B91F901008C10E6 /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29512C801B91F8EB008C10E6 /* libuv.a */; };
2952CD1D1FA9941700985F5F /* path.c in Sources */ = {isa = PBXBuildFile; fileRef = 2952CD1B1FA9941700985F5F /* path.c */; };
29729F311BA70A620099CA20 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29729F2E1BA70A620099CA20 /* io.c */; };
29729F321BA70A620099CA20 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29729F2E1BA70A620099CA20 /* io.c */; };
29729F331BA70A620099CA20 /* io.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 29729F301BA70A620099CA20 /* io.wren.inc */; };
@ -68,6 +73,15 @@
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
2940E9B4206605DE0054503C /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
29AB1F041816E3AD004B501E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@ -118,10 +132,18 @@
293D46951BB43F9900200083 /* call.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = call.h; path = ../../test/api/call.h; sourceTree = "<group>"; };
2940E98B2063EC020054503C /* resolution.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resolution.c; path = ../../test/api/resolution.c; sourceTree = "<group>"; };
2940E98C2063EC020054503C /* resolution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = resolution.h; path = ../../test/api/resolution.h; sourceTree = "<group>"; };
2940E9B8206605DE0054503C /* unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unit_test; sourceTree = BUILT_PRODUCTS_DIR; };
2940E9B92066067D0054503C /* path_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_test.h; path = ../../../test/unit/path_test.h; sourceTree = "<group>"; };
2940E9BA2066067D0054503C /* path_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = path_test.c; path = ../../../test/unit/path_test.c; sourceTree = "<group>"; };
2940E9BD2066C3300054503C /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../../test/unit/main.c; sourceTree = "<group>"; };
2940E9BF2066C35E0054503C /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = test.c; path = ../../../test/unit/test.c; sourceTree = "<group>"; };
2940E9C02066C35E0054503C /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test.h; path = ../../../test/unit/test.h; sourceTree = "<group>"; };
2949AA8B1C2F14F000B106BA /* get_variable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = get_variable.c; path = ../../test/api/get_variable.c; sourceTree = "<group>"; };
2949AA8C1C2F14F000B106BA /* get_variable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = get_variable.h; path = ../../test/api/get_variable.h; sourceTree = "<group>"; };
29512C7F1B91F86E008C10E6 /* api_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = api_test; sourceTree = BUILT_PRODUCTS_DIR; };
29512C801B91F8EB008C10E6 /* libuv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libuv.a; path = ../../build/libuv.a; sourceTree = "<group>"; };
2952CD1B1FA9941700985F5F /* path.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = path.c; path = ../../src/cli/path.c; sourceTree = "<group>"; };
2952CD1C1FA9941700985F5F /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path.h; path = ../../src/cli/path.h; sourceTree = "<group>"; };
296371B31AC713D000079FDA /* wren_opcodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_opcodes.h; path = ../../src/vm/wren_opcodes.h; sourceTree = "<group>"; };
29729F2E1BA70A620099CA20 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = io.c; path = ../../src/module/io.c; sourceTree = "<group>"; };
29729F301BA70A620099CA20 /* io.wren.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = io.wren.inc; path = ../../src/module/io.wren.inc; sourceTree = "<group>"; };
@ -164,6 +186,13 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
2940E9B2206605DE0054503C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
29AB1F031816E3AD004B501E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -233,6 +262,8 @@
29205C8E1AB4E5C90073018D /* main.c */,
291647C61BA5EC5E006142EE /* modules.h */,
291647C51BA5EC5E006142EE /* modules.c */,
2952CD1C1FA9941700985F5F /* path.h */,
2952CD1B1FA9941700985F5F /* path.c */,
29C8A9321AB71FFF00DEC81D /* vm.h */,
29C8A9311AB71FFF00DEC81D /* vm.c */,
);
@ -247,6 +278,18 @@
name = include;
sourceTree = "<group>";
};
2940E98E206605CB0054503C /* unit_test */ = {
isa = PBXGroup;
children = (
2940E9BD2066C3300054503C /* main.c */,
2940E9BA2066067D0054503C /* path_test.c */,
2940E9B92066067D0054503C /* path_test.h */,
2940E9BF2066C35E0054503C /* test.c */,
2940E9C02066C35E0054503C /* test.h */,
);
path = unit_test;
sourceTree = "<group>";
};
29AB1EFD1816E3AD004B501E = {
isa = PBXGroup;
children = (
@ -256,6 +299,7 @@
29AF31EE1BD2E37F00AAD156 /* optional */,
29205CA01AB4E6470073018D /* vm */,
29D0099A1B7E394F000CE58C /* api_test */,
2940E98E206605CB0054503C /* unit_test */,
29512C801B91F8EB008C10E6 /* libuv.a */,
29AB1F071816E3AD004B501E /* Products */,
);
@ -266,6 +310,7 @@
children = (
29AB1F061816E3AD004B501E /* wren */,
29512C7F1B91F86E008C10E6 /* api_test */,
2940E9B8206605DE0054503C /* unit_test */,
);
name = Products;
sourceTree = "<group>";
@ -320,6 +365,23 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
2940E98F206605DE0054503C /* unit_test */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2940E9B5206605DE0054503C /* Build configuration list for PBXNativeTarget "unit_test" */;
buildPhases = (
2940E990206605DE0054503C /* Sources */,
2940E9B2206605DE0054503C /* Frameworks */,
2940E9B4206605DE0054503C /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = unit_test;
productName = api_test;
productReference = 2940E9B8206605DE0054503C /* unit_test */;
productType = "com.apple.product-type.tool";
};
29AB1F051816E3AD004B501E /* wren */ = {
isa = PBXNativeTarget;
buildConfigurationList = 29AB1F0F1816E3AD004B501E /* Build configuration list for PBXNativeTarget "wren" */;
@ -382,11 +444,23 @@
targets = (
29AB1F051816E3AD004B501E /* wren */,
29D0099E1B7E397D000CE58C /* api_test */,
2940E98F206605DE0054503C /* unit_test */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
2940E990206605DE0054503C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2940E9BC206607830054503C /* path.c in Sources */,
2940E9BB2066067D0054503C /* path_test.c in Sources */,
2940E9BE2066C3300054503C /* main.c in Sources */,
2940E9C12066C35E0054503C /* test.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
29AB1F021816E3AD004B501E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -395,6 +469,7 @@
29205C991AB4E6430073018D /* wren_compiler.c in Sources */,
2986F6D71ACF93BA00BCE26C /* wren_primitive.c in Sources */,
291647C71BA5EC5E006142EE /* modules.c in Sources */,
2952CD1D1FA9941700985F5F /* path.c in Sources */,
29A4273A1BDBE435001E6E22 /* wren_opt_random.wren.inc in Sources */,
29205C9A1AB4E6430073018D /* wren_core.c in Sources */,
2901D7641B74F4050083A2C8 /* timer.c in Sources */,
@ -460,6 +535,50 @@
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
2940E9B6206605DE0054503C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_PEDANTIC = NO;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
LIBRARY_SEARCH_PATHS = ../../build;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
};
name = Debug;
};
2940E9B7206605DE0054503C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_PEDANTIC = NO;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
LIBRARY_SEARCH_PATHS = ../../build;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
};
name = Release;
};
29AB1F0D1816E3AD004B501E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -605,6 +724,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
2940E9B5206605DE0054503C /* Build configuration list for PBXNativeTarget "unit_test" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2940E9B6206605DE0054503C /* Debug */,
2940E9B7206605DE0054503C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
29AB1F011816E3AD004B501E /* Build configuration list for PBXProject "wren" */ = {
isa = XCConfigurationList;
buildConfigurations = (