Move tons of stuff into oldstuff/
This commit is contained in:
6
oldstuff/lcthw-remnants-2/.gitignore
vendored
Normal file
6
oldstuff/lcthw-remnants-2/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.dat
|
||||
ex*
|
||||
!ex29
|
||||
!ex*.c
|
||||
devpkgzed
|
||||
*.log
|
20
oldstuff/lcthw-remnants-2/Dockerfile
Normal file
20
oldstuff/lcthw-remnants-2/Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM ubuntu:xenial
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update -yq
|
||||
RUN apt-get install -yq --no-install-recommends --no-install-suggests \
|
||||
build-essential \
|
||||
curl \
|
||||
file \
|
||||
gdb \
|
||||
git \
|
||||
man \
|
||||
sudo \
|
||||
vim-tiny \
|
||||
zsh
|
||||
RUN echo "kernel.yama.ptrace_scope = 0" > /etc/sysctl.d/10-ptrace.conf
|
||||
|
||||
CMD ["zsh", "-l"]
|
29
oldstuff/lcthw-remnants-2/Makefile
Normal file
29
oldstuff/lcthw-remnants-2/Makefile
Normal file
@@ -0,0 +1,29 @@
|
||||
SHELL = /bin/bash
|
||||
CFLAGS = -Wall -g -DNDEBUG -fPIC
|
||||
LDLIBS = -ldl
|
||||
|
||||
EXERCISES := $(shell ./list-exercises)
|
||||
|
||||
all: $(EXERCISES)
|
||||
|
||||
ex19: object.o
|
||||
|
||||
ex22_main: ex22.o
|
||||
|
||||
clean:
|
||||
shopt -s nullglob ; \
|
||||
$(RM) $(EXERCISES) *.o *.a
|
||||
|
||||
test:
|
||||
@./runtests
|
||||
|
||||
exercises:
|
||||
@echo $(EXERCISES)
|
||||
|
||||
.PHONY: docker-image
|
||||
docker-image:
|
||||
docker build -t meatballhat/lcthw:latest .
|
||||
|
||||
.PHONY: docker-run
|
||||
docker-run:
|
||||
docker run -it -v $(PWD):/app meatballhat/lcthw
|
3
oldstuff/lcthw-remnants-2/c-skeleton/.gitignore
vendored
Normal file
3
oldstuff/lcthw-remnants-2/c-skeleton/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
tests/runtests
|
||||
tests/*_tests
|
||||
tests/**/*_tests
|
21
oldstuff/lcthw-remnants-2/c-skeleton/LICENSE
Normal file
21
oldstuff/lcthw-remnants-2/c-skeleton/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
Copyright (C) 2016 Dan Buch
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
59
oldstuff/lcthw-remnants-2/c-skeleton/Makefile
Normal file
59
oldstuff/lcthw-remnants-2/c-skeleton/Makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
|
||||
LDLIBS = -ldl $(OPTLIBS)
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
SOURCES = $(wildcard src/**/*.c src/*.c)
|
||||
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
|
||||
|
||||
TEST_SRC = $(wildcard tests/*_tests.c)
|
||||
TESTS = $(patsubst %.c,%,$(TEST_SRC))
|
||||
|
||||
LIBNAME = YOUR_LIBRARY
|
||||
TARGET = build/lib$(LIBNAME).a
|
||||
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
|
||||
|
||||
# The Target Build
|
||||
all: $(TARGET) $(SO_TARGET) tests
|
||||
|
||||
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
|
||||
dev: all
|
||||
|
||||
$(TARGET): CFLAGS += -fPIC
|
||||
$(TARGET): build $(OBJECTS)
|
||||
$(AR) rcs $@ $(OBJECTS)
|
||||
ranlib $@
|
||||
|
||||
$(SO_TARGET): $(TARGET) $(OBJECTS)
|
||||
$(CC) -shared -o $@ $(OBJECTS)
|
||||
|
||||
build:
|
||||
@mkdir -p build
|
||||
@mkdir -p bin
|
||||
|
||||
# The Unit Tests
|
||||
.PHONY: tests
|
||||
tests: LDLIBS += -static -l$(LIBNAME)
|
||||
tests: ./tests/runtests $(TESTS)
|
||||
./tests/runtests
|
||||
|
||||
valgrind:
|
||||
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
|
||||
|
||||
# The Cleaner
|
||||
clean:
|
||||
rm -rf build $(OBJECTS) $(TESTS)
|
||||
rm -f tests/tests.log tests/runtests
|
||||
find . -name "*.gc*" -exec rm {} \;
|
||||
rm -rf `find . -name "*.dSYM" -print`
|
||||
|
||||
# The Install
|
||||
install: all
|
||||
install -d $(DESTDIR)/$(PREFIX)/lib/
|
||||
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
|
||||
|
||||
# The Checker
|
||||
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
|
||||
check:
|
||||
@echo Files with potentially dangerous functions
|
||||
@egrep $(BADFUNCS) $(SOURCES) || true
|
0
oldstuff/lcthw-remnants-2/c-skeleton/README.md
Normal file
0
oldstuff/lcthw-remnants-2/c-skeleton/README.md
Normal file
30
oldstuff/lcthw-remnants-2/c-skeleton/src/dbg.h
Normal file
30
oldstuff/lcthw-remnants-2/c-skeleton/src/dbg.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __dbg_h__
|
||||
#define __dbg_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(M, ...)
|
||||
#else
|
||||
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||
|
||||
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
|
||||
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define check_mem(A) check((A), "Out of memory.")
|
||||
|
||||
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#endif
|
6
oldstuff/lcthw-remnants-2/c-skeleton/src/your_library.c
Normal file
6
oldstuff/lcthw-remnants-2/c-skeleton/src/your_library.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "your_library.h"
|
||||
|
||||
int howmanyweasels()
|
||||
{
|
||||
return WEASELS;
|
||||
}
|
8
oldstuff/lcthw-remnants-2/c-skeleton/src/your_library.h
Normal file
8
oldstuff/lcthw-remnants-2/c-skeleton/src/your_library.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _your_library_h
|
||||
#define _your_library_h
|
||||
|
||||
#define WEASELS 23
|
||||
|
||||
int howmanyweasels();
|
||||
|
||||
#endif
|
38
oldstuff/lcthw-remnants-2/c-skeleton/tests/minunit.h
Normal file
38
oldstuff/lcthw-remnants-2/c-skeleton/tests/minunit.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#undef DNDEBUG
|
||||
#ifndef _minunit_h
|
||||
#define _minunit_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dbg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define mu_suite_start() char *message = NULL
|
||||
|
||||
#define mu_assert(test, message) if (!(test)) {\
|
||||
log_err(message); return message;\
|
||||
}\
|
||||
assertions_made++;
|
||||
#define mu_run_test(test) debug("\n-----%s", " " #test); \
|
||||
message = test(); tests_run++; if (message) return message;
|
||||
|
||||
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
|
||||
argc = argc; \
|
||||
argv = argv; \
|
||||
debug("----- RUNNING: %s", argv[0]);\
|
||||
printf("----\nRUNNING: %s\n", argv[0]);\
|
||||
char *result = name();\
|
||||
if (result != 0) {\
|
||||
printf("FAILED: %s\n", result);\
|
||||
}\
|
||||
else {\
|
||||
printf("ALL TESTS PASSED\n");\
|
||||
}\
|
||||
printf("Tests run: %d\n", tests_run);\
|
||||
printf("Assertions made: %d\n", assertions_made);\
|
||||
exit(result != 0);\
|
||||
}
|
||||
|
||||
int tests_run;
|
||||
int assertions_made;
|
||||
|
||||
#endif
|
107
oldstuff/lcthw-remnants-2/c-skeleton/tests/runtests.c
Normal file
107
oldstuff/lcthw-remnants-2/c-skeleton/tests/runtests.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <fnmatch.h>
|
||||
#include <dbg.h>
|
||||
|
||||
int test_selector(const struct dirent *ep)
|
||||
{
|
||||
return fnmatch("*_tests", ep->d_name, 0) == 0;
|
||||
}
|
||||
|
||||
int run_tests_file(char *filename)
|
||||
{
|
||||
if(access(filename, R_OK | X_OK) == 0) {
|
||||
return system(filename);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int entcount = 0;
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
int ntests = 0;
|
||||
char *testsdir = NULL;
|
||||
char *valgrind = getenv("VALGRIND");
|
||||
struct dirent **namelist = NULL;
|
||||
struct dirent *ep = NULL;
|
||||
|
||||
if(argc > 1) {
|
||||
testsdir = argv[1];
|
||||
}
|
||||
|
||||
if(!testsdir) {
|
||||
testsdir = getenv("TESTS");
|
||||
}
|
||||
|
||||
if(!testsdir) {
|
||||
testsdir = "./tests";
|
||||
}
|
||||
|
||||
entcount = scandir((const char *)testsdir, &namelist, test_selector, alphasort);
|
||||
check(entcount > -1, "Failed to scan tests dir");
|
||||
|
||||
for(i = 0; i < entcount; i++) {
|
||||
ep = namelist[i];
|
||||
check(ep, "Dirent is missing.");
|
||||
|
||||
char filename[256];
|
||||
rc = sprintf(filename, "%s/%s", testsdir, ep->d_name);
|
||||
check(rc > -1, "Failed to build filename.");
|
||||
debug("Found filename '%s'", filename);
|
||||
|
||||
free(ep);
|
||||
|
||||
if(valgrind) {
|
||||
char command[1024];
|
||||
rc = sprintf(command, "%s %s", valgrind, filename);
|
||||
check(rc > -1, "Failed to build command with valgrind.");
|
||||
rc = run_tests_file(command);
|
||||
} else {
|
||||
rc = run_tests_file(filename);
|
||||
}
|
||||
|
||||
if(rc > 0) {
|
||||
debug("Skipping '%s'", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
ntests++;
|
||||
|
||||
if(rc == 0) {
|
||||
printf("%s PASS\n", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("ERROR in test %s", filename);
|
||||
if(access("tests/tests.log", R_OK) == 0) {
|
||||
printf(": here's tests/tests.log\n");
|
||||
printf("------\n");
|
||||
rc = system("tail tests/tests.log");
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("------\n");
|
||||
printf("Total of %d test file%s run.\n", ntests, ntests > 1 ? "s" : "");
|
||||
|
||||
if(namelist) {
|
||||
free(namelist);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(namelist) {
|
||||
free(namelist);
|
||||
}
|
||||
|
||||
return rc != 0 ? rc : 1;
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include "your_library.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("WEASELS: %d\n", howmanyweasels());
|
||||
return 0;
|
||||
}
|
30
oldstuff/lcthw-remnants-2/dbg.h
Normal file
30
oldstuff/lcthw-remnants-2/dbg.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __dbg_h__
|
||||
#define __dbg_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(M, ...)
|
||||
#else
|
||||
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||
|
||||
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
|
||||
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define check_mem(A) check((A), "Out of memory.")
|
||||
|
||||
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#endif
|
2
oldstuff/lcthw-remnants-2/devpkg/.gitignore
vendored
Normal file
2
oldstuff/lcthw-remnants-2/devpkg/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bstrlib.*
|
||||
devpkg
|
30
oldstuff/lcthw-remnants-2/devpkg/Makefile
Normal file
30
oldstuff/lcthw-remnants-2/devpkg/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
BSTRLIB_BASE_URL ?= https://raw.githubusercontent.com/websnarf/bstrlib/208b1f2a4dfc96b806ed499bd1909e87ec15981d
|
||||
PREFIX ?= /usr/local
|
||||
CFLAGS = -g -Wall -I${PREFIX}/apr/include/apr-1 -I${PREFIX}/apr/include/apr-util-1
|
||||
LDFLAGS = -L${PREFIX}/apr/lib
|
||||
LDLIBS = -lapr-1 -pthread -laprutil-1
|
||||
|
||||
all: devpkg
|
||||
|
||||
devpkg: bstrlib.o db.o shell.o commands.o
|
||||
|
||||
prebuild:
|
||||
sudo mkdir -p /etc/ld.so.conf.d
|
||||
echo $(DESTDIR)/$(PREFIX)/lib | sudo tee /etc/ld.so.conf.d/devpkg.conf
|
||||
sudo ldconfig
|
||||
|
||||
install: all
|
||||
install -d $(DESTDIR)/$(PREFIX)/bin/
|
||||
install devpkg $(DESTDIR)/$(PREFIX)/bin/
|
||||
|
||||
clean:
|
||||
$(RM) *.o
|
||||
$(RM) devpkg
|
||||
$(RM) *.dSYM
|
||||
$(RM) bstrlib.c bstrlib.h
|
||||
|
||||
bstrlib.c: bstrlib.h
|
||||
curl -sSLO $(BSTRLIB_BASE_URL)/bstrlib.c
|
||||
|
||||
bstrlib.h:
|
||||
curl -sSLO $(BSTRLIB_BASE_URL)/bstrlib.h
|
47
oldstuff/lcthw-remnants-2/devpkg/README
Normal file
47
oldstuff/lcthw-remnants-2/devpkg/README
Normal file
@@ -0,0 +1,47 @@
|
||||
# `devpkg`
|
||||
|
||||
This is a thingy that downloads, builds, and installs stuff!
|
||||
|
||||
## usage
|
||||
|
||||
Before you can do the fun part, you need to initialize the bits:
|
||||
|
||||
``` bash
|
||||
devpkg -S
|
||||
```
|
||||
|
||||
Install something via URL:
|
||||
|
||||
``` bash
|
||||
devpkg -I http://example.org/foo.tar.bz2
|
||||
```
|
||||
|
||||
Install something via URL with custom arguments for configure, make, and
|
||||
install:
|
||||
|
||||
``` bash
|
||||
devpkg -I http://example.org/foo.tar.bz2 -c '--no-flair' -m 'CFLAGS+=-Wall' -i '-n'
|
||||
```
|
||||
|
||||
Perform a fetch *only* without building or installing:
|
||||
|
||||
``` bash
|
||||
devpkg -F http://example.org/foo.tar.bz2
|
||||
```
|
||||
|
||||
Perform a build *only* without installing:
|
||||
|
||||
``` bash
|
||||
devpkg -B http://example.org/foo.tar.bz2
|
||||
```
|
||||
|
||||
List the stuff that's been installed:
|
||||
|
||||
``` bash
|
||||
devpkg -L
|
||||
```
|
||||
|
||||
|
||||
<!--
|
||||
vim:filetype=markdown
|
||||
-->
|
174
oldstuff/lcthw-remnants-2/devpkg/commands.c
Normal file
174
oldstuff/lcthw-remnants-2/devpkg/commands.c
Normal file
@@ -0,0 +1,174 @@
|
||||
#include <apr_uri.h>
|
||||
#include <apr_fnmatch.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "dbg.h"
|
||||
#include "bstrlib.h"
|
||||
#include "db.h"
|
||||
#include "shell.h"
|
||||
|
||||
|
||||
int Command_depends(apr_pool_t *p, const char *path)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
bstring line = NULL;
|
||||
|
||||
in = fopen(path, "r");
|
||||
check(in != NULL, "Failed to open downloaded depends: %s", path);
|
||||
|
||||
for(line = bgets((bNgetc)fgetc, in, '\n'); line != NULL;
|
||||
line = bgets((bNgetc)fgetc, in, '\n'))
|
||||
{
|
||||
btrimws(line);
|
||||
log_info("Processing depends: %s", bdata(line));
|
||||
int rc = Command_install(p, bdata(line), NULL, NULL, NULL);
|
||||
check(rc == 0, "Failed to install: %s", bdata(line));
|
||||
bdestroy(line);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(line) bdestroy(line);
|
||||
if(in) fclose(in);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Command_fetch(apr_pool_t *p, const char *url, int fetch_only)
|
||||
{
|
||||
apr_uri_t info = {.port = 0};
|
||||
int rc = 0;
|
||||
const char *depends_file = NULL;
|
||||
apr_status_t rv = apr_uri_parse(p, url, &info);
|
||||
|
||||
check(rv == APR_SUCCESS, "Failed to parse URL: %s", url);
|
||||
|
||||
if(apr_fnmatch(GIT_PAT, info.path, 0) == APR_SUCCESS) {
|
||||
rc = Shell_exec(GIT_SH, "URL", url, NULL);
|
||||
check(rc == 0, "git failed.");
|
||||
} else if(apr_fnmatch(DEPEND_PAT, info.path, 0) == APR_SUCCESS) {
|
||||
check(!fetch_only, "No point in fetching a DEPENDS file.");
|
||||
|
||||
if(info.scheme) {
|
||||
depends_file = DEPENDS_PATH;
|
||||
rc = Shell_exec(CURL_SH, "URL", url, "TARGET", depends_file, NULL);
|
||||
check(rc == 0, "Curl failed.");
|
||||
} else {
|
||||
depends_file = info.path;
|
||||
}
|
||||
|
||||
// recursively process the devpkg list
|
||||
log_info("Building according to DEPENDS: %s", url);
|
||||
rv = Command_depends(p, depends_file);
|
||||
check(rv == 0, "Failed to process the DEPENDS: %s", url);
|
||||
|
||||
// this indicates that nothing needs to be done
|
||||
return 0;
|
||||
|
||||
} else if(apr_fnmatch(TAR_GZ_PAT, info.path, 0) == APR_SUCCESS) {
|
||||
if(info.scheme) {
|
||||
rc = Shell_exec(CURL_SH,
|
||||
"URL", url,
|
||||
"TARGET", TAR_GZ_SRC, NULL);
|
||||
check(rc == 0, "Failed to curl source: %s", url);
|
||||
}
|
||||
|
||||
rv = apr_dir_make_recursive(BUILD_DIR,
|
||||
APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
|
||||
check(rv == APR_SUCCESS, "Failed to make directory %s", BUILD_DIR);
|
||||
|
||||
rc = Shell_exec(TAR_SH, "FILE", TAR_GZ_SRC, NULL);
|
||||
check(rc == 0, "Failed to untar %s", TAR_GZ_SRC);
|
||||
} else if(apr_fnmatch(TAR_BZ2_PAT, info.path, 0) == APR_SUCCESS) {
|
||||
if(info.scheme) {
|
||||
rc = Shell_exec(CURL_SH, "URL", url, "TARGET", TAR_BZ2_SRC, NULL);
|
||||
check(rc == 0, "Curl failed.");
|
||||
}
|
||||
|
||||
apr_status_t rc = apr_dir_make_recursive(BUILD_DIR,
|
||||
APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
|
||||
|
||||
check(rc == 0, "Failed to make directory %s", BUILD_DIR);
|
||||
rc = Shell_exec(TAR_SH, "FILE", TAR_BZ2_SRC, NULL);
|
||||
check(rc == 0, "Failed to untar %s", TAR_BZ2_SRC);
|
||||
} else {
|
||||
sentinel("Don't know how to handle %s", url);
|
||||
}
|
||||
|
||||
// indicates that an install needs to actually run
|
||||
return 1;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Command_build(apr_pool_t *p, const char *url, const char *configure_opts,
|
||||
const char *make_opts, const char *install_opts)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
check(access(BUILD_DIR, X_OK | R_OK | W_OK) == 0,
|
||||
"Build directory doesn't exist: %s", BUILD_DIR);
|
||||
|
||||
// actually do an install
|
||||
if(access(CONFIG_SCRIPT, X_OK) == 0) {
|
||||
log_info("Has a configure script, running it.");
|
||||
rc = Shell_exec(CONFIGURE_SH, "OPTS", configure_opts, NULL);
|
||||
check(rc == 0, "Failed to configure");
|
||||
}
|
||||
|
||||
rc = Shell_exec(MAKE_SH, "OPTS", make_opts, NULL);
|
||||
check(rc == 0, "Failed to build.");
|
||||
|
||||
rc = Shell_exec(INSTALL_SH,
|
||||
"TARGET", install_opts ? install_opts : "install",
|
||||
NULL);
|
||||
check(rc == 0, "Failed to install.");
|
||||
|
||||
rc = Shell_exec(CLEANUP_SH, NULL);
|
||||
check(rc == 0, "Failed to cleanup after build.");
|
||||
|
||||
rc = DB_update(url);
|
||||
check(rc == 0, "Failed to add this package to the database.");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Command_install(apr_pool_t *p, const char *url, const char *configure_opts,
|
||||
const char *make_opts, const char *install_opts)
|
||||
{
|
||||
int rc = 0;
|
||||
check(Shell_exec(CLEANUP_SH, NULL) == 0, "Failed to cleanup before building.");
|
||||
|
||||
rc = DB_find(url);
|
||||
check(rc != -1, "Error checking the install database.");
|
||||
|
||||
if(rc == 1) {
|
||||
log_info("Package %s already installed.", url);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = Command_fetch(p, url, 0);
|
||||
|
||||
if(rc == 1) {
|
||||
rc = Command_build(p, url, configure_opts, make_opts, install_opts);
|
||||
check(rc == 0, "Failed to build: %s", url);
|
||||
} else if(rc == 0) {
|
||||
// no install needed
|
||||
log_info("Depends successfully installed: %s", url);
|
||||
} else {
|
||||
// had an error
|
||||
sentinel("Install failed: %s", url);
|
||||
}
|
||||
|
||||
Shell_exec(CLEANUP_SH, NULL);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Shell_exec(CLEANUP_SH, NULL);
|
||||
return -1;
|
||||
}
|
31
oldstuff/lcthw-remnants-2/devpkg/commands.h
Normal file
31
oldstuff/lcthw-remnants-2/devpkg/commands.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _commands_h
|
||||
#define _commands_h
|
||||
|
||||
#include <apr_pools.h>
|
||||
|
||||
#define DEPENDS_PATH "/tmp/DEPENDS"
|
||||
#define TAR_GZ_SRC "/tmp/pkg-src.tar.gz"
|
||||
#define TAR_BZ2_SRC "/tmp/pkg-src.tar.bz2"
|
||||
#define BUILD_DIR "/tmp/pkg-build"
|
||||
#define GIT_PAT "*.git"
|
||||
#define DEPEND_PAT "*DEPENDS"
|
||||
#define TAR_GZ_PAT "*.tar.gz"
|
||||
#define TAR_BZ2_PAT "*.tar.bz2"
|
||||
#define CONFIG_SCRIPT "/tmp/pkg-build/configure"
|
||||
|
||||
enum CommandType {
|
||||
COMMAND_NONE, COMMAND_INSTALL, COMMAND_LIST, COMMAND_FETCH,
|
||||
COMMAND_INIT, COMMAND_BUILD
|
||||
};
|
||||
|
||||
int Command_fetch(apr_pool_t *p, const char *url, int fetch_only);
|
||||
|
||||
int Command_install(apr_pool_t *p, const char *url, const char *configure_opts,
|
||||
const char *make_opts, const char *install_opts);
|
||||
|
||||
int Command_depends(apr_pool_t *p, const char *path);
|
||||
|
||||
int Command_build(apr_pool_t *p, const char *url, const char *configure_opts,
|
||||
const char *make_opts, const char *install_opts);
|
||||
|
||||
#endif
|
125
oldstuff/lcthw-remnants-2/devpkg/db.c
Normal file
125
oldstuff/lcthw-remnants-2/devpkg/db.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <unistd.h>
|
||||
#include <apr_errno.h>
|
||||
#include <apr_file_io.h>
|
||||
|
||||
#include "db.h"
|
||||
#include "bstrlib.h"
|
||||
#include "dbg.h"
|
||||
|
||||
static FILE *DB_open(const char *path, const char *mode)
|
||||
{
|
||||
return fopen(path, mode);
|
||||
}
|
||||
|
||||
|
||||
static void DB_close(FILE *db)
|
||||
{
|
||||
fclose(db);
|
||||
}
|
||||
|
||||
|
||||
static bstring DB_load()
|
||||
{
|
||||
FILE *db = NULL;
|
||||
bstring data = NULL;
|
||||
|
||||
db = DB_open(DB_FILE, "r");
|
||||
check(db, "Failed to open database: %s", DB_FILE);
|
||||
|
||||
data = bread((bNread)fread, db);
|
||||
check(data, "Failed to read from db file: %s", DB_FILE);
|
||||
|
||||
DB_close(db);
|
||||
return data;
|
||||
|
||||
error:
|
||||
if(db) DB_close(db);
|
||||
if(data) bdestroy(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int DB_update(const char *url)
|
||||
{
|
||||
if(DB_find(url)) {
|
||||
log_info("Already recorded as installed: %s", url);
|
||||
}
|
||||
|
||||
FILE *db = DB_open(DB_FILE, "a+");
|
||||
check(db, "Failed to open DB file: %s", DB_FILE);
|
||||
|
||||
bstring line = bfromcstr(url);
|
||||
bconchar(line, '\n');
|
||||
int rc = fwrite(line->data, blength(line), 1, db);
|
||||
check(rc == 1, "Failed to append to the db.");
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if(db) DB_close(db);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DB_find(const char *url)
|
||||
{
|
||||
bstring data = NULL;
|
||||
bstring line = bfromcstr(url);
|
||||
int res = -1;
|
||||
|
||||
data = DB_load();
|
||||
check(data, "Failed to load: %s", DB_FILE);
|
||||
|
||||
if(binstr(data, 0, line) == BSTR_ERR) {
|
||||
res = 0;
|
||||
} else {
|
||||
res = 1;
|
||||
}
|
||||
|
||||
error: // fallthrough
|
||||
if(data) bdestroy(data);
|
||||
if(line) bdestroy(line);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int DB_init()
|
||||
{
|
||||
apr_pool_t *p = NULL;
|
||||
apr_pool_initialize();
|
||||
apr_pool_create(&p, NULL);
|
||||
|
||||
if(access(DB_DIR, W_OK | X_OK) == -1) {
|
||||
apr_status_t rc = apr_dir_make_recursive(DB_DIR,
|
||||
APR_UREAD | APR_UWRITE | APR_UEXECUTE |
|
||||
APR_GREAD | APR_GWRITE | APR_GEXECUTE, p);
|
||||
check(rc == APR_SUCCESS, "Failed to make database dir: %s", DB_DIR);
|
||||
}
|
||||
|
||||
if(access(DB_FILE, W_OK) == -1) {
|
||||
FILE *db = DB_open(DB_FILE, "w");
|
||||
check(db, "Cannot open database: %s", DB_FILE);
|
||||
DB_close(db);
|
||||
}
|
||||
|
||||
apr_pool_destroy(p);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
apr_pool_destroy(p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DB_list()
|
||||
{
|
||||
bstring data = DB_load();
|
||||
check(data, "Failed to read load: %s", DB_FILE);
|
||||
|
||||
printf("%s", bdata(data));
|
||||
bdestroy(data);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
12
oldstuff/lcthw-remnants-2/devpkg/db.h
Normal file
12
oldstuff/lcthw-remnants-2/devpkg/db.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _db_h
|
||||
#define _db_h
|
||||
|
||||
#define DB_FILE "/usr/local/.devpkg/db"
|
||||
#define DB_DIR "/usr/local/.devpkg"
|
||||
|
||||
int DB_init();
|
||||
int DB_list();
|
||||
int DB_update(const char *url);
|
||||
int DB_find(const char *url);
|
||||
|
||||
#endif
|
30
oldstuff/lcthw-remnants-2/devpkg/dbg.h
Normal file
30
oldstuff/lcthw-remnants-2/devpkg/dbg.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __dbg_h__
|
||||
#define __dbg_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(M, ...)
|
||||
#else
|
||||
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||
|
||||
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
|
||||
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define check_mem(A) check((A), "Out of memory.")
|
||||
|
||||
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#endif
|
104
oldstuff/lcthw-remnants-2/devpkg/devpkg.c
Normal file
104
oldstuff/lcthw-remnants-2/devpkg/devpkg.c
Normal file
@@ -0,0 +1,104 @@
|
||||
#include <stdio.h>
|
||||
#include <apr_general.h>
|
||||
#include <apr_getopt.h>
|
||||
#include <apr_strings.h>
|
||||
#include <apr_lib.h>
|
||||
|
||||
#include "dbg.h"
|
||||
#include "db.h"
|
||||
#include "commands.h"
|
||||
|
||||
int main(int argc, const char const *argv[])
|
||||
{
|
||||
apr_pool_t *p = NULL;
|
||||
apr_pool_initialize();
|
||||
apr_pool_create(&p, NULL);
|
||||
|
||||
apr_getopt_t *opt;
|
||||
apr_status_t rv;
|
||||
|
||||
char ch = '\0';
|
||||
const char *optarg = NULL;
|
||||
const char *config_opts = NULL;
|
||||
const char *install_opts = NULL;
|
||||
const char *make_opts = NULL;
|
||||
const char *url = NULL;
|
||||
enum CommandType request = COMMAND_NONE;
|
||||
|
||||
|
||||
rv = apr_getopt_init(&opt, p, argc, argv);
|
||||
|
||||
while(apr_getopt(opt, "I:Lc:m:i:d:SF:B:", &ch, &optarg) == APR_SUCCESS) {
|
||||
switch(ch) {
|
||||
case 'I':
|
||||
request = COMMAND_INSTALL;
|
||||
url = optarg;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
request = COMMAND_LIST;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
config_opts = optarg;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
make_opts = optarg;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
install_opts = optarg;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
request = COMMAND_INIT;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
request = COMMAND_FETCH;
|
||||
url = optarg;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
request = COMMAND_BUILD;
|
||||
url = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(request) {
|
||||
case COMMAND_INSTALL:
|
||||
check(url, "You must at least give a URL.");
|
||||
Command_install(p, url, config_opts, make_opts, install_opts);
|
||||
break;
|
||||
|
||||
case COMMAND_LIST:
|
||||
DB_list();
|
||||
break;
|
||||
|
||||
case COMMAND_FETCH:
|
||||
check(url != NULL, "You must give a URL.");
|
||||
Command_fetch(p, url, 1);
|
||||
log_info("Downloaded to %s and in /tmp/", BUILD_DIR);
|
||||
break;
|
||||
|
||||
case COMMAND_BUILD:
|
||||
check(url, "You must at least give a URL.");
|
||||
Command_build(p, url, config_opts, make_opts, install_opts);
|
||||
break;
|
||||
|
||||
case COMMAND_INIT:
|
||||
rv = DB_init();
|
||||
check(rv == 0, "Failed to make the database.");
|
||||
break;
|
||||
|
||||
default:
|
||||
sentinel("Invalid command given.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return 1;
|
||||
}
|
120
oldstuff/lcthw-remnants-2/devpkg/shell.c
Normal file
120
oldstuff/lcthw-remnants-2/devpkg/shell.c
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "shell.h"
|
||||
#include "dbg.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
int Shell_exec(Shell template, ...)
|
||||
{
|
||||
apr_pool_t *p = NULL;
|
||||
int rc = -1;
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
va_list argp;
|
||||
const char *key = NULL;
|
||||
const char *arg = NULL;
|
||||
int i = 0;
|
||||
|
||||
rv = apr_pool_create(&p, NULL);
|
||||
check(rv == APR_SUCCESS, "Failed to create pool.");
|
||||
|
||||
va_start(argp, template);
|
||||
|
||||
for(key = va_arg(argp, const char *);
|
||||
key != NULL;
|
||||
key = va_arg(argp, const char *))
|
||||
{
|
||||
arg = va_arg(argp, const char *);
|
||||
|
||||
for(i = 0; template.args[i] != NULL; i++) {
|
||||
if(strcmp(template.args[i], key) == 0) {
|
||||
template.args[i] = arg;
|
||||
break; // found it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = Shell_run(p, &template);
|
||||
apr_pool_destroy(p);
|
||||
va_end(argp);
|
||||
return rc;
|
||||
|
||||
error:
|
||||
if(p) {
|
||||
apr_pool_destroy(p);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Shell_run(apr_pool_t *p, Shell *cmd)
|
||||
{
|
||||
apr_procattr_t *attr;
|
||||
apr_status_t rv;
|
||||
apr_proc_t newproc;
|
||||
|
||||
rv = apr_procattr_create(&attr, p);
|
||||
check(rv == APR_SUCCESS, "Failed to create proc attr.");
|
||||
|
||||
rv = apr_procattr_io_set(attr, APR_NO_PIPE, APR_NO_PIPE, APR_NO_PIPE);
|
||||
check(rv == APR_SUCCESS, "Failed to set IO of command.");
|
||||
|
||||
rv = apr_procattr_dir_set(attr, cmd->dir);
|
||||
check(rv == APR_SUCCESS, "Failed to set root to %s", cmd->dir);
|
||||
|
||||
rv = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
|
||||
check(rv == APR_SUCCESS, "Failed to set cmd type.");
|
||||
|
||||
rv = apr_proc_create(&newproc, cmd->exe, cmd->args, NULL, attr, p);
|
||||
check(rv == APR_SUCCESS, "Failed to run command.");
|
||||
|
||||
rv = apr_proc_wait(&newproc, &cmd->exit_code, &cmd->exit_why, APR_WAIT);
|
||||
check(rv == APR_CHILD_DONE, "Failed to wait.");
|
||||
|
||||
check(cmd->exit_code == 0, "%s exited badly.", cmd->exe);
|
||||
check(cmd->exit_why == APR_PROC_EXIT, "%s was killed or crashed", cmd->exe);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
Shell CLEANUP_SH = {
|
||||
.exe = "rm",
|
||||
.dir = "/tmp",
|
||||
.args = {"rm", "-rf", "/tmp/pkg-build", "/tmp/pkg-src.tar.gz",
|
||||
"/tmp/pkg-src.tar.bz2", "/tmp/DEPENDS", NULL}
|
||||
};
|
||||
|
||||
Shell GIT_SH = {
|
||||
.dir = "/tmp",
|
||||
.exe = "git",
|
||||
.args = {"git", "clone", "URL", "pkg-build", NULL}
|
||||
};
|
||||
|
||||
Shell TAR_SH = {
|
||||
.dir = "/tmp/pkg-build",
|
||||
.exe = "tar",
|
||||
.args = {"tar", "-xzf", "FILE", "--strip-components", "1", NULL}
|
||||
};
|
||||
|
||||
Shell CURL_SH = {
|
||||
.dir = "/tmp",
|
||||
.exe = "curl",
|
||||
.args = {"curl", "-L", "-o", "TARGET", "URL", NULL}
|
||||
};
|
||||
|
||||
Shell CONFIGURE_SH = {
|
||||
.exe = "./configure",
|
||||
.dir = "/tmp/pkg-build",
|
||||
.args = {"configure", "OPTS", NULL},
|
||||
};
|
||||
|
||||
Shell MAKE_SH = {
|
||||
.exe = "make",
|
||||
.dir = "/tmp/pkg-build",
|
||||
.args = {"make", "OPTS", NULL}
|
||||
};
|
||||
|
||||
Shell INSTALL_SH = {
|
||||
.exe = "sudo",
|
||||
.dir = "/tmp/pkg-build",
|
||||
.args = {"sudo", "make", "TARGET", NULL}
|
||||
};
|
31
oldstuff/lcthw-remnants-2/devpkg/shell.h
Normal file
31
oldstuff/lcthw-remnants-2/devpkg/shell.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _shell_h
|
||||
#define _shell_h
|
||||
|
||||
#define MAX_COMMAND_ARGS 100
|
||||
|
||||
#include <apr_thread_proc.h>
|
||||
|
||||
typedef struct Shell {
|
||||
const char *dir;
|
||||
const char *exe;
|
||||
|
||||
apr_procattr_t *attr;
|
||||
apr_proc_t proc;
|
||||
apr_exit_why_e exit_why;
|
||||
int exit_code;
|
||||
|
||||
const char *args[MAX_COMMAND_ARGS];
|
||||
} Shell;
|
||||
|
||||
int Shell_run(apr_pool_t *p, Shell *cmd);
|
||||
int Shell_exec(Shell cmd, ...);
|
||||
|
||||
extern Shell CLEANUP_SH;
|
||||
extern Shell GIT_SH;
|
||||
extern Shell TAR_SH;
|
||||
extern Shell CURL_SH;
|
||||
extern Shell CONFIGURE_SH;
|
||||
extern Shell MAKE_SH;
|
||||
extern Shell INSTALL_SH;
|
||||
|
||||
#endif
|
8
oldstuff/lcthw-remnants-2/ex1.c
Normal file
8
oldstuff/lcthw-remnants-2/ex1.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
puts("Hello world.");
|
||||
|
||||
return 0;
|
||||
}
|
25
oldstuff/lcthw-remnants-2/ex10.c
Normal file
25
oldstuff/lcthw-remnants-2/ex10.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// go through each string in argv
|
||||
// why am I skipping argv[0];
|
||||
for(i = 1; i < argc; i++) {
|
||||
printf("arg %d: %s\n", i, argv[i]);
|
||||
}
|
||||
|
||||
// let's make our own array of strings
|
||||
char *states[] = {
|
||||
"California", "Oregon",
|
||||
"Washington", "Texas"
|
||||
};
|
||||
int num_states = 4;
|
||||
|
||||
for(i = 0; i < num_states; i++) {
|
||||
printf("state %d: %s\n", i, states[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
27
oldstuff/lcthw-remnants-2/ex11.c
Normal file
27
oldstuff/lcthw-remnants-2/ex11.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// go through each string in argv
|
||||
|
||||
int i = 0;
|
||||
while(i < argc) {
|
||||
printf("arg %d: %s\n", i, argv[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
// let's make our own array of strings
|
||||
char *states[] = {
|
||||
"California", "Oregon",
|
||||
"Washington", "Texas"
|
||||
};
|
||||
|
||||
int num_states = 4;
|
||||
i = 0; // watch for this
|
||||
while(i < num_states) {
|
||||
printf("state %d: %s\n", i, states[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
21
oldstuff/lcthw-remnants-2/ex12.c
Normal file
21
oldstuff/lcthw-remnants-2/ex12.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if(argc == 1) {
|
||||
printf("You only have one argument. You suck.\n");
|
||||
} else if(argc > 1 && argc < 4) {
|
||||
printf("Here's your arguments:\n");
|
||||
|
||||
for(i = 0; i < argc; i++) {
|
||||
printf("%s ", argv[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("You have too many arguments. You suck.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
55
oldstuff/lcthw-remnants-2/ex13.c
Normal file
55
oldstuff/lcthw-remnants-2/ex13.c
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc != 2) {
|
||||
printf("ERROR: You need one argument.\n");
|
||||
// this is how you abort a program
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for(i = 0; argv[1][i] != '\0'; i++) {
|
||||
char letter = argv[1][i];
|
||||
|
||||
switch(letter) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
printf("%d: 'A'\n", i);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
printf("%d: 'E'\n", i);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
case 'I':
|
||||
printf("%d: 'I'\n", i);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'O':
|
||||
printf("%d: 'O'\n", i);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
case 'U':
|
||||
printf("%d: 'U'\n", i);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
case 'Y':
|
||||
if(i > 2) {
|
||||
// it's only sometimes y
|
||||
printf("%d: 'Y'\n", i);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%d: %c is not a vowel\n", i, letter);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
41
oldstuff/lcthw-remnants-2/ex14.c
Normal file
41
oldstuff/lcthw-remnants-2/ex14.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// forward declarations
|
||||
int can_print_it(char ch);
|
||||
void print_letters(char arg[]);
|
||||
|
||||
void print_arguments(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < argc; i++) {
|
||||
print_letters(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_letters(char arg[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; arg[i] != '\0'; i++) {
|
||||
char ch = arg[i];
|
||||
|
||||
if(can_print_it(ch)) {
|
||||
printf("'%c' == %d ", ch, ch);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int can_print_it(char ch)
|
||||
{
|
||||
return isalpha(ch) || isblank(ch);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
print_arguments(argc, argv);
|
||||
return 0;
|
||||
}
|
54
oldstuff/lcthw-remnants-2/ex15.c
Normal file
54
oldstuff/lcthw-remnants-2/ex15.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// create two arrays we care about
|
||||
int ages[] = {23, 43, 12, 89, 2};
|
||||
char *names[] = {
|
||||
"Alan", "Frank",
|
||||
"Mary", "John", "Lisa"
|
||||
};
|
||||
|
||||
// safely get the size of ages
|
||||
int count = sizeof(ages) / sizeof(int);
|
||||
int i = 0;
|
||||
|
||||
// first way using indexing
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%s has %d years alive.\n",
|
||||
names[i], ages[i]);
|
||||
}
|
||||
|
||||
printf("---\n");
|
||||
|
||||
// setup the pointers to the start of the arrays
|
||||
int *cur_age = ages;
|
||||
char **cur_name = names;
|
||||
|
||||
// second way using pointers
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%s is %d years old.\n",
|
||||
*(cur_name+i), *(cur_age+i));
|
||||
}
|
||||
|
||||
printf("---\n");
|
||||
|
||||
// third way, pointers are just arrays
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%s is %d years old again.\n",
|
||||
cur_name[i], cur_age[i]);
|
||||
}
|
||||
|
||||
printf("---\n");
|
||||
|
||||
// fourth way with pointers in a stupid complex way
|
||||
for(cur_name = names, cur_age = ages;
|
||||
(cur_age - ages) < count;
|
||||
cur_name++, cur_age++)
|
||||
{
|
||||
printf("%s lived %d years so far.\n",
|
||||
*cur_name, *cur_age);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
73
oldstuff/lcthw-remnants-2/ex16.c
Normal file
73
oldstuff/lcthw-remnants-2/ex16.c
Normal file
@@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct Person {
|
||||
char *name;
|
||||
int age;
|
||||
int height;
|
||||
int weight;
|
||||
};
|
||||
|
||||
struct Person *Person_create(char *name, int age, int height, int weight)
|
||||
{
|
||||
struct Person *who = malloc(sizeof(struct Person));
|
||||
assert(who != NULL);
|
||||
|
||||
who->name = strdup(name);
|
||||
who->age = age;
|
||||
who->height = height;
|
||||
who->weight = weight;
|
||||
|
||||
return who;
|
||||
}
|
||||
|
||||
void Person_destroy(struct Person *who)
|
||||
{
|
||||
assert(who != NULL);
|
||||
|
||||
free(who->name);
|
||||
free(who);
|
||||
}
|
||||
|
||||
void Person_print(struct Person *who)
|
||||
{
|
||||
printf("Name: %s\n", who->name);
|
||||
printf("\tAge: %d\n", who->age);
|
||||
printf("\tHeight: %d\n", who->height);
|
||||
printf("\tWeight: %d\n", who->weight);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// make two people structures
|
||||
struct Person *joe = Person_create(
|
||||
"Joe Alex", 32, 64, 140);
|
||||
|
||||
struct Person *frank = Person_create(
|
||||
"Frank Blank", 20, 72, 180);
|
||||
|
||||
// print them out and where they are in memory
|
||||
printf("Joe is at memory location %p:\n", joe);
|
||||
Person_print(joe);
|
||||
|
||||
printf("Frank is at memory location %p:\n", frank);
|
||||
Person_print(frank);
|
||||
|
||||
// make everyone age 20 years and print them again
|
||||
joe->age += 20;
|
||||
joe->height -= 2;
|
||||
joe->weight += 40;
|
||||
Person_print(joe);
|
||||
|
||||
frank->age += 20;
|
||||
frank->weight += 20;
|
||||
Person_print(frank);
|
||||
|
||||
// destroy them both so we clean up
|
||||
Person_destroy(joe);
|
||||
Person_destroy(frank);
|
||||
|
||||
return 0;
|
||||
}
|
234
oldstuff/lcthw-remnants-2/ex17-ec.c
Normal file
234
oldstuff/lcthw-remnants-2/ex17-ec.c
Normal file
@@ -0,0 +1,234 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#define MAX_DATA 512
|
||||
#define MAX_ROWS 100
|
||||
|
||||
struct Address {
|
||||
int id;
|
||||
int set;
|
||||
char name[MAX_DATA];
|
||||
char email[MAX_DATA];
|
||||
char street[MAX_DATA];
|
||||
};
|
||||
|
||||
struct Database {
|
||||
struct Address rows[MAX_ROWS];
|
||||
};
|
||||
|
||||
struct Connection {
|
||||
FILE *file;
|
||||
struct Database *db;
|
||||
};
|
||||
|
||||
void Database_close(struct Connection *conn);
|
||||
|
||||
void die(const char *message, struct Connection *conn)
|
||||
{
|
||||
if(errno) {
|
||||
perror(message);
|
||||
} else {
|
||||
printf("ERROR: %s\n", message);
|
||||
}
|
||||
|
||||
Database_close(conn);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Address_print(struct Address *addr)
|
||||
{
|
||||
printf("%d %s %s \"%s\"\n",
|
||||
addr->id, addr->name, addr->email, addr->street);
|
||||
}
|
||||
|
||||
void Database_load(struct Connection *conn)
|
||||
{
|
||||
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
|
||||
if(rc != 1) die("Failed to load database.", conn);
|
||||
}
|
||||
|
||||
struct Connection *Database_open(const char *filename, char mode)
|
||||
{
|
||||
struct Connection *conn = malloc(sizeof(struct Connection));
|
||||
if(!conn) die("Memory error", conn);
|
||||
|
||||
conn->db = malloc(sizeof(struct Database));
|
||||
if(!conn->db) die("Memory error", conn);
|
||||
|
||||
if(mode == 'c') {
|
||||
conn->file = fopen(filename, "w");
|
||||
} else {
|
||||
conn->file = fopen(filename, "r+");
|
||||
|
||||
if(conn->file) {
|
||||
Database_load(conn);
|
||||
}
|
||||
}
|
||||
|
||||
if(!conn->file) die("Failed to open the file", conn);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
void Database_close(struct Connection *conn)
|
||||
{
|
||||
if(conn) {
|
||||
if(conn->file) fclose(conn->file);
|
||||
if(conn->db) free(conn->db);
|
||||
free(conn);
|
||||
}
|
||||
}
|
||||
|
||||
void Database_write(struct Connection *conn)
|
||||
{
|
||||
rewind(conn->file);
|
||||
|
||||
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
|
||||
if(rc != 1) die("Failed to write database.", conn);
|
||||
|
||||
rc = fflush(conn->file);
|
||||
if(rc == -1) die("Connot flush database.", conn);
|
||||
}
|
||||
|
||||
void Database_create(struct Connection *conn)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
// make a prototype to initialize it
|
||||
struct Address addr = {.id = i, .set = 0};
|
||||
// then just assign it
|
||||
conn->db->rows[i] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
void Database_set(struct Connection *conn, int id, const char *name,
|
||||
const char *email, const char *street)
|
||||
{
|
||||
struct Address *addr = &conn->db->rows[id];
|
||||
if(addr->set) die("Already set, delete it first", conn);
|
||||
|
||||
addr->set = 1;
|
||||
// WARNING: bug, read the "How To Break It" and fix this
|
||||
char *res = strncpy(addr->name, name, MAX_DATA);
|
||||
// demonstrate the strncpy bug
|
||||
if(!res) die("Name copy failed", conn);
|
||||
|
||||
res = strncpy(addr->email, email, MAX_DATA);
|
||||
if(!res) die("Email copy failed", conn);
|
||||
|
||||
res = strncpy(addr->street, street, MAX_DATA);
|
||||
if(!res) die("Street copy failed", conn);
|
||||
}
|
||||
|
||||
void Database_get(struct Connection *conn, int id)
|
||||
{
|
||||
struct Address *addr = &conn->db->rows[id];
|
||||
|
||||
if(addr->set) {
|
||||
Address_print(addr);
|
||||
} else {
|
||||
die("ID is not set", conn);
|
||||
}
|
||||
}
|
||||
|
||||
void Database_delete(struct Connection *conn, int id)
|
||||
{
|
||||
struct Address addr = {.id = id, .set = 0};
|
||||
conn->db->rows[id] = addr;
|
||||
}
|
||||
|
||||
void Database_list(struct Connection *conn)
|
||||
{
|
||||
int i = 0;
|
||||
struct Database *db = conn->db;
|
||||
|
||||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
struct Address *cur = &db->rows[i];
|
||||
|
||||
if(cur->set) {
|
||||
Address_print(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database_find(struct Connection *conn, char *search)
|
||||
{
|
||||
int i = 0;
|
||||
struct Database *db = conn->db;
|
||||
|
||||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
struct Address *cur = &db->rows[i];
|
||||
|
||||
if(cur->set) {
|
||||
if(strstr(cur->email, search) != NULL ||
|
||||
strstr(cur->name, search) != NULL ||
|
||||
strstr(cur->street, search) != NULL) {
|
||||
Address_print(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char usage[64];
|
||||
sprintf(usage, "USAGE: %s <dbfile> <action> [action params]", basename(argv[0]));
|
||||
|
||||
if(argc < 3) die(usage, NULL);
|
||||
|
||||
char *filename = argv[1];
|
||||
char action = argv[2][0];
|
||||
struct Connection *conn = Database_open(filename, action);
|
||||
int id = 0;
|
||||
|
||||
if(argc > 3) id = atoi(argv[3]);
|
||||
if(id >= MAX_ROWS) die("There's not that many records.", conn);
|
||||
|
||||
switch(action) {
|
||||
case 'c':
|
||||
Database_create(conn);
|
||||
Database_write(conn);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
if(argc != 4) die("Need an id to get", conn);
|
||||
|
||||
Database_get(conn, id);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if(argc != 7) die("Need id, name, email, and street to set", conn);
|
||||
|
||||
Database_set(conn, id, argv[4], argv[5], argv[6]);
|
||||
Database_write(conn);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if(argc != 4) die("Need id to delete", conn);
|
||||
|
||||
Database_delete(conn, id);
|
||||
Database_write(conn);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if(argc != 4) die("Need something to find", conn);
|
||||
Database_find(conn, argv[3]);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
Database_list(conn);
|
||||
break;
|
||||
default:
|
||||
die("Invalid action, only: c=create, g=get, s=set, d=del, l=list, f=find", conn);
|
||||
}
|
||||
|
||||
Database_close(conn);
|
||||
|
||||
return 0;
|
||||
}
|
86
oldstuff/lcthw-remnants-2/ex17-ec2.c
Normal file
86
oldstuff/lcthw-remnants-2/ex17-ec2.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_STACK 1024
|
||||
#define STACK_SENTINEL -1
|
||||
|
||||
struct Stack {
|
||||
int l[MAX_STACK];
|
||||
};
|
||||
|
||||
struct Stack *Stack_create()
|
||||
{
|
||||
struct Stack *s = malloc(sizeof(struct Stack));
|
||||
if(!s) { return NULL; }
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < MAX_STACK; i++) {
|
||||
s->l[i] = STACK_SENTINEL;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int Stack_push(struct Stack *s, int v)
|
||||
{
|
||||
if(v <= STACK_SENTINEL) {
|
||||
return STACK_SENTINEL;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for(i = 0; i < MAX_STACK; i++) {
|
||||
if(s->l[i] == STACK_SENTINEL) {
|
||||
s->l[i] = v;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return STACK_SENTINEL;
|
||||
}
|
||||
|
||||
int Stack_pop(struct Stack *s)
|
||||
{
|
||||
int i = 0;
|
||||
int v = 0;
|
||||
for(i = 0; i < MAX_STACK; i++) {
|
||||
if(s->l[i] == STACK_SENTINEL) {
|
||||
v = s->l[i-1];
|
||||
s->l[i-1] = STACK_SENTINEL;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
return STACK_SENTINEL;
|
||||
}
|
||||
|
||||
int Stack_size(struct Stack *s)
|
||||
{
|
||||
int i = 0;
|
||||
for(i = 0; i < MAX_STACK; i++) {
|
||||
if(s->l[i] == STACK_SENTINEL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return STACK_SENTINEL;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct Stack *s = Stack_create();
|
||||
|
||||
printf("size: %d\n", Stack_size(s));
|
||||
Stack_push(s, 10);
|
||||
Stack_push(s, 20);
|
||||
Stack_push(s, 40);
|
||||
|
||||
printf("size: %d\n", Stack_size(s));
|
||||
printf("pop: %d\n", Stack_pop(s));
|
||||
printf("pop: %d\n", Stack_pop(s));
|
||||
printf("size: %d\n", Stack_size(s));
|
||||
printf("pop: %d\n", Stack_pop(s));
|
||||
printf("pop: %d\n", Stack_pop(s));
|
||||
|
||||
return 0;
|
||||
}
|
198
oldstuff/lcthw-remnants-2/ex17.c
Normal file
198
oldstuff/lcthw-remnants-2/ex17.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_DATA 512
|
||||
#define MAX_ROWS 100
|
||||
|
||||
struct Address {
|
||||
int id;
|
||||
int set;
|
||||
char name[MAX_DATA];
|
||||
char email[MAX_DATA];
|
||||
};
|
||||
|
||||
struct Database {
|
||||
struct Address rows[MAX_ROWS];
|
||||
};
|
||||
|
||||
struct Connection {
|
||||
FILE *file;
|
||||
struct Database *db;
|
||||
};
|
||||
|
||||
void die(const char *message)
|
||||
{
|
||||
if(errno) {
|
||||
perror(message);
|
||||
} else {
|
||||
printf("ERROR: %s\n", message);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Address_print(struct Address *addr)
|
||||
{
|
||||
printf("%d %s %s\n",
|
||||
addr->id, addr->name, addr->email);
|
||||
}
|
||||
|
||||
void Database_load(struct Connection *conn)
|
||||
{
|
||||
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
|
||||
if(rc != 1) die("Failed to load database.");
|
||||
}
|
||||
|
||||
struct Connection *Database_open(const char *filename, char mode)
|
||||
{
|
||||
struct Connection *conn = malloc(sizeof(struct Connection));
|
||||
if(!conn) die("Memory error");
|
||||
|
||||
conn->db = malloc(sizeof(struct Database));
|
||||
if(!conn->db) die("Memory error");
|
||||
|
||||
if(mode == 'c') {
|
||||
conn->file = fopen(filename, "w");
|
||||
} else {
|
||||
conn->file = fopen(filename, "r+");
|
||||
|
||||
if(conn->file) {
|
||||
Database_load(conn);
|
||||
}
|
||||
}
|
||||
|
||||
if(!conn->file) die("Failed to open the file");
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
void Database_close(struct Connection *conn)
|
||||
{
|
||||
if(conn) {
|
||||
if(conn->file) fclose(conn->file);
|
||||
if(conn->db) free(conn->db);
|
||||
free(conn);
|
||||
}
|
||||
}
|
||||
|
||||
void Database_write(struct Connection *conn)
|
||||
{
|
||||
rewind(conn->file);
|
||||
|
||||
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
|
||||
if(rc != 1) die("Failed to write database.");
|
||||
|
||||
rc = fflush(conn->file);
|
||||
if(rc == -1) die("Connot flush database.");
|
||||
}
|
||||
|
||||
void Database_create(struct Connection *conn)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
// make a prototype to initialize it
|
||||
struct Address addr = {.id = i, .set = 0};
|
||||
// then just assign it
|
||||
conn->db->rows[i] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
void Database_set(struct Connection *conn, int id, const char *name, const char *email)
|
||||
{
|
||||
struct Address *addr = &conn->db->rows[id];
|
||||
if(addr->set) die("Already set, delete it first");
|
||||
|
||||
addr->set = 1;
|
||||
// WARNING: bug, read the "How To Break It" and fix this
|
||||
char *res = strncpy(addr->name, name, MAX_DATA);
|
||||
// demonstrate the strncpy bug
|
||||
if(!res) die("Name copy failed");
|
||||
|
||||
res = strncpy(addr->email, email, MAX_DATA);
|
||||
if(!res) die("Email copy failed");
|
||||
}
|
||||
|
||||
void Database_get(struct Connection *conn, int id)
|
||||
{
|
||||
struct Address *addr = &conn->db->rows[id];
|
||||
|
||||
if(addr->set) {
|
||||
Address_print(addr);
|
||||
} else {
|
||||
die("ID is not set");
|
||||
}
|
||||
}
|
||||
|
||||
void Database_delete(struct Connection *conn, int id)
|
||||
{
|
||||
struct Address addr = {.id = id, .set = 0};
|
||||
conn->db->rows[id] = addr;
|
||||
}
|
||||
|
||||
void Database_list(struct Connection *conn)
|
||||
{
|
||||
int i = 0;
|
||||
struct Database *db = conn->db;
|
||||
|
||||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
struct Address *cur = &db->rows[i];
|
||||
|
||||
if(cur->set) {
|
||||
Address_print(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc < 3) die("USAGE: ex17 <dbfile> <action> [action params]");
|
||||
|
||||
char *filename = argv[1];
|
||||
char action = argv[2][0];
|
||||
struct Connection *conn = Database_open(filename, action);
|
||||
int id = 0;
|
||||
|
||||
if(argc > 3) id = atoi(argv[3]);
|
||||
if(id >= MAX_ROWS) die("There's not that many records.");
|
||||
|
||||
switch(action) {
|
||||
case 'c':
|
||||
Database_create(conn);
|
||||
Database_write(conn);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
if(argc != 4) die("Need an id to get");
|
||||
|
||||
Database_get(conn, id);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if(argc != 6) die("Need id, name, email to set");
|
||||
|
||||
Database_set(conn, id, argv[4], argv[5]);
|
||||
Database_write(conn);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if(argc != 4) die("Need id to delete");
|
||||
|
||||
Database_delete(conn, id);
|
||||
Database_write(conn);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
Database_list(conn);
|
||||
break;
|
||||
default:
|
||||
die("Invalid action, only: c=create, g=get, s=set, d=del, l=list");
|
||||
}
|
||||
|
||||
Database_close(conn);
|
||||
|
||||
return 0;
|
||||
}
|
119
oldstuff/lcthw-remnants-2/ex18-ec.c
Normal file
119
oldstuff/lcthw-remnants-2/ex18-ec.c
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
/** Our old friend die from ex17. */
|
||||
void die(const char *message)
|
||||
{
|
||||
if(errno) {
|
||||
perror(message);
|
||||
} else {
|
||||
printf("ERROR: %s\n", message);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// a typedef creates a fake type, in this
|
||||
// case for a function pointer
|
||||
typedef int (*compare_cb)(int a, int b);
|
||||
|
||||
/**
|
||||
* A classic bubble sort function that uses the
|
||||
* compare_cb to do the sorting.
|
||||
*/
|
||||
int *bubble_sort(int *numbers, int count, compare_cb cmp)
|
||||
{
|
||||
int temp = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int *target = malloc(count * sizeof(int));
|
||||
|
||||
if(!target) die("Memory error.");
|
||||
|
||||
memcpy(target, numbers, count * sizeof(int));
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
for(j = 0; j < count - 1; j++) {
|
||||
if(cmp(target[j], target[j+1]) > 0) {
|
||||
temp = target[j+1];
|
||||
target[j+1] = target[j];
|
||||
target[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
int sorted_order(int a, int b)
|
||||
{
|
||||
return a - b;
|
||||
}
|
||||
|
||||
int reverse_order(int a, int b)
|
||||
{
|
||||
return b - a;
|
||||
}
|
||||
|
||||
int strange_order(int a, int b)
|
||||
{
|
||||
if(a == 0 || b == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to test that we are sorting things correctly
|
||||
* by doing the sort and printing it out.
|
||||
*/
|
||||
void test_sorting(int *numbers, int count, compare_cb cmp)
|
||||
{
|
||||
int i = 0;
|
||||
int *sorted = bubble_sort(numbers, count, cmp);
|
||||
|
||||
if(!sorted) die("Failed to sort as requested.");
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%d ", sorted[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
free(sorted);
|
||||
|
||||
unsigned char *data = (unsigned char *)cmp;
|
||||
|
||||
for(i = 0; i < 25; i++) {
|
||||
printf("%02x:", data[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc < 2) die("USAGE: ex18 4 3 1 5 6");
|
||||
|
||||
int count = argc - 1;
|
||||
int i = 0;
|
||||
char **inputs = argv + 1;
|
||||
|
||||
int *numbers = malloc(count * sizeof(int));
|
||||
if(!numbers) die("Memory error.");
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
numbers[i] = atoi(inputs[i]);
|
||||
}
|
||||
|
||||
test_sorting(numbers, count, sorted_order);
|
||||
test_sorting(numbers, count, reverse_order);
|
||||
test_sorting(numbers, count, strange_order);
|
||||
|
||||
free(numbers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
111
oldstuff/lcthw-remnants-2/ex18.c
Normal file
111
oldstuff/lcthw-remnants-2/ex18.c
Normal file
@@ -0,0 +1,111 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
/** Our old friend die from ex17. */
|
||||
void die(const char *message)
|
||||
{
|
||||
if(errno) {
|
||||
perror(message);
|
||||
} else {
|
||||
printf("ERROR: %s\n", message);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// a typedef creates a fake type, in this
|
||||
// case for a function pointer
|
||||
typedef int (*compare_cb)(int a, int b);
|
||||
|
||||
/**
|
||||
* A classic bubble sort function that uses the
|
||||
* compare_cb to do the sorting.
|
||||
*/
|
||||
int *bubble_sort(int *numbers, int count, compare_cb cmp)
|
||||
{
|
||||
int temp = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int *target = malloc(count * sizeof(int));
|
||||
|
||||
if(!target) die("Memory error.");
|
||||
|
||||
memcpy(target, numbers, count * sizeof(int));
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
for(j = 0; j < count - 1; j++) {
|
||||
if(cmp(target[j], target[j+1]) > 0) {
|
||||
temp = target[j+1];
|
||||
target[j+1] = target[j];
|
||||
target[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
int sorted_order(int a, int b)
|
||||
{
|
||||
return a - b;
|
||||
}
|
||||
|
||||
int reverse_order(int a, int b)
|
||||
{
|
||||
return b - a;
|
||||
}
|
||||
|
||||
int strange_order(int a, int b)
|
||||
{
|
||||
if(a == 0 || b == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to test that we are sorting things correctly
|
||||
* by doing the sort and printing it out.
|
||||
*/
|
||||
void test_sorting(int *numbers, int count, compare_cb cmp)
|
||||
{
|
||||
int i = 0;
|
||||
int *sorted = bubble_sort(numbers, count, cmp);
|
||||
|
||||
if(!sorted) die("Failed to sort as requested.");
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%d ", sorted[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
free(sorted);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc < 2) die("USAGE: ex18 4 3 1 5 6");
|
||||
|
||||
int count = argc - 1;
|
||||
int i = 0;
|
||||
char **inputs = argv + 1;
|
||||
|
||||
int *numbers = malloc(count * sizeof(int));
|
||||
if(!numbers) die("Memory error.");
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
numbers[i] = atoi(inputs[i]);
|
||||
}
|
||||
|
||||
test_sorting(numbers, count, sorted_order);
|
||||
test_sorting(numbers, count, reverse_order);
|
||||
test_sorting(numbers, count, strange_order);
|
||||
|
||||
free(numbers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
225
oldstuff/lcthw-remnants-2/ex19.c
Normal file
225
oldstuff/lcthw-remnants-2/ex19.c
Normal file
@@ -0,0 +1,225 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "ex19.h"
|
||||
|
||||
|
||||
int Monster_attack(void *self, int damage)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Monster *monster = self;
|
||||
|
||||
printf("You attack %s!\n", monster->_(description));
|
||||
|
||||
monster->hit_points -= damage;
|
||||
|
||||
if(monster->hit_points > 0) {
|
||||
printf("It is still alive.\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("It is dead!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int Monster_init(void *self)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Monster *monster = self;
|
||||
monster->hit_points = 10;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Object MonsterProto = {
|
||||
.init = Monster_init,
|
||||
.attack = Monster_attack
|
||||
};
|
||||
|
||||
|
||||
void *Room_move(void *self, Direction direction)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Room *room = self;
|
||||
Room *next = NULL;
|
||||
|
||||
if(direction == NORTH && room->north) {
|
||||
printf("You go north, into:\n");
|
||||
next = room->north;
|
||||
} else if(direction == SOUTH && room->south) {
|
||||
printf("You go south, into:\n");
|
||||
next = room->south;
|
||||
} else if(direction == EAST && room->east) {
|
||||
printf("You go east, into:\n");
|
||||
next = room->east;
|
||||
} else if(direction == WEST && room->west) {
|
||||
printf("You go west, into:\n");
|
||||
next = room->west;
|
||||
} else {
|
||||
printf("You can't go that direction.");
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
if(next) {
|
||||
next->_(describe)(next);
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
int Room_attack(void *self, int damage)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Room *room = self;
|
||||
Monster *monster = room->bad_guy;
|
||||
|
||||
if(monster) {
|
||||
monster->_(attack)(monster, damage);
|
||||
return 1;
|
||||
} else {
|
||||
printf("You flail in the air at nothing. Idiot.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object RoomProto = {
|
||||
.move = Room_move,
|
||||
.attack = Room_attack
|
||||
};
|
||||
|
||||
|
||||
void *Map_move(void *self, Direction direction)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Map *map = self;
|
||||
Room *location = map->location;
|
||||
Room *next = NULL;
|
||||
|
||||
next = location->_(move)(location, direction);
|
||||
|
||||
if(next) {
|
||||
map->location = next;
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
int Map_attack(void *self, int damage)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Map *map = self;
|
||||
Room *location = map->location;
|
||||
|
||||
return location->_(attack)(location, damage);
|
||||
}
|
||||
|
||||
|
||||
int Map_init(void *self)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Map *map = self;
|
||||
|
||||
// make some rooms for a small map
|
||||
Room *hall = NEW(Room, "The great Hall");
|
||||
Room *throne = NEW(Room, "The throne room");
|
||||
Room *arena = NEW(Room, "The arena, with the minotaur");
|
||||
Room *kitchen = NEW(Room, "Kitchen, you have the knife now");
|
||||
|
||||
// put the bad guy in the arena
|
||||
arena->bad_guy = NEW(Monster, "The evil minotaur");
|
||||
|
||||
// setup the map rooms
|
||||
hall->north = throne;
|
||||
|
||||
throne->west = arena;
|
||||
throne->east = kitchen;
|
||||
throne->south = hall;
|
||||
|
||||
arena->east = throne;
|
||||
kitchen->west = throne;
|
||||
|
||||
// start the map and the characters off in the hall
|
||||
map->start = hall;
|
||||
map->location = hall;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Object MapProto = {
|
||||
.init = Map_init,
|
||||
.move = Map_move,
|
||||
.attack = Map_attack
|
||||
};
|
||||
|
||||
int process_input(Map *game)
|
||||
{
|
||||
assert(game != NULL);
|
||||
printf("\n> ");
|
||||
|
||||
char ch = getchar();
|
||||
getchar(); // eat ENTER
|
||||
|
||||
int damage = rand() % 4;
|
||||
|
||||
switch(ch) {
|
||||
case -1:
|
||||
printf("Giving up? You suck.\n");
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
game->_(move)(game, NORTH);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
game->_(move)(game, SOUTH);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
game->_(move)(game, EAST);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
game->_(move)(game, WEST);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
game->_(attack)(game, damage);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
printf("You can go:\n");
|
||||
if(game->location->north) printf("NORTH\n");
|
||||
if(game->location->south) printf("SOUTH\n");
|
||||
if(game->location->east) printf("EAST\n");
|
||||
if(game->location->west) printf("WEST\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("What?: %d\n", ch);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// simple way to setup the randomness
|
||||
srand(time(NULL));
|
||||
|
||||
// make our map to work with
|
||||
Map *game = NEW(Map, "The Hall of the Minotaur.");
|
||||
assert(game != NULL);
|
||||
|
||||
printf("You enter the ");
|
||||
game->location->_(describe)(game->location);
|
||||
|
||||
while(process_input(game)) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
118
oldstuff/lcthw-remnants-2/ex20.c
Normal file
118
oldstuff/lcthw-remnants-2/ex20.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "dbg.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void test_debug()
|
||||
{
|
||||
// notice you don't need the \n
|
||||
debug("I have Brown Hair.");
|
||||
|
||||
// passing in arguments like printf
|
||||
debug("I am %d years old.", 37);
|
||||
}
|
||||
|
||||
void test_log_err()
|
||||
{
|
||||
log_err("I believe everything is broken.");
|
||||
log_err("There are %d problems in %s.", 0, "space");
|
||||
}
|
||||
|
||||
void test_log_warn()
|
||||
{
|
||||
log_warn("You can safely ignore this.");
|
||||
log_warn("Maybe consider looking at: %s.", "/etc/passwd");
|
||||
}
|
||||
|
||||
void test_log_info()
|
||||
{
|
||||
log_info("Well I did something mundane.");
|
||||
log_info("It happened %f times today.", 1.3f);
|
||||
}
|
||||
|
||||
int test_check(char *file_name)
|
||||
{
|
||||
FILE *input = NULL;
|
||||
char *block = NULL;
|
||||
|
||||
block = malloc(100);
|
||||
check_mem(block); // should work
|
||||
|
||||
input = fopen(file_name, "r");
|
||||
check(input, "Failed to open %s.", file_name);
|
||||
|
||||
free(block);
|
||||
fclose(input);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(block) free(block);
|
||||
if(input) fclose(input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test_sentinel(int code)
|
||||
{
|
||||
char *temp = malloc(100);
|
||||
check_mem(temp);
|
||||
|
||||
switch(code) {
|
||||
case 1:
|
||||
log_info("It worked.");
|
||||
break;
|
||||
default:
|
||||
sentinel("I shouldn't run.");
|
||||
}
|
||||
|
||||
free(temp);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(temp) free(temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test_check_mem()
|
||||
{
|
||||
char *test = NULL;
|
||||
check_mem(test);
|
||||
|
||||
free(test);
|
||||
return 1;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test_check_debug()
|
||||
{
|
||||
int i = 0;
|
||||
check_debug(i != 0, "Oops, I was 0.");
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
check(argc == 2, "Need an argument.");
|
||||
|
||||
test_debug();
|
||||
test_log_err();
|
||||
test_log_warn();
|
||||
test_log_info();
|
||||
|
||||
check(test_check("ex20.c") == 0, "failed with ex20.c");
|
||||
check(test_check(argv[1]) == -1, "failed with argv");
|
||||
check(test_sentinel(1) == 0, "test_sentinel failed.");
|
||||
check(test_sentinel(100) == -1, "test_sentinel failed.");
|
||||
check(test_check_mem() == -1, "test_check_mem failed.");
|
||||
check(test_check_debug() == -1, "test_check_debug failed.");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return 1;
|
||||
}
|
||||
|
33
oldstuff/lcthw-remnants-2/ex22.c
Normal file
33
oldstuff/lcthw-remnants-2/ex22.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <stdio.h>
|
||||
#include "ex22.h"
|
||||
#include "dbg.h"
|
||||
|
||||
int THE_SIZE = 1000;
|
||||
|
||||
static int THE_AGE = 37;
|
||||
|
||||
int get_age()
|
||||
{
|
||||
return THE_AGE;
|
||||
}
|
||||
|
||||
void set_age(int age)
|
||||
{
|
||||
THE_AGE = age;
|
||||
}
|
||||
|
||||
|
||||
double update_ratio(double new_ratio)
|
||||
{
|
||||
static double ratio = 1.0;
|
||||
|
||||
double old_ratio = ratio;
|
||||
ratio = new_ratio;
|
||||
|
||||
return old_ratio;
|
||||
}
|
||||
|
||||
void print_size()
|
||||
{
|
||||
log_info("I think size is: %d", THE_SIZE);
|
||||
}
|
54
oldstuff/lcthw-remnants-2/ex22_main.c
Normal file
54
oldstuff/lcthw-remnants-2/ex22_main.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "ex22.h"
|
||||
#include "dbg.h"
|
||||
|
||||
const char *MY_NAME = "Zed A. Shaw";
|
||||
|
||||
void scope_demo(int count)
|
||||
{
|
||||
log_info("count is: %d", count);
|
||||
|
||||
if(count > 10) {
|
||||
int count = 100; // BAD! BUGS!
|
||||
|
||||
log_info("count in this scope is %d", count);
|
||||
}
|
||||
|
||||
log_info("count is at exit: %d", count);
|
||||
|
||||
count = 3000;
|
||||
|
||||
log_info("count after assign: %d", count);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// test out THE_AGE accessors
|
||||
log_info("My name: %s, age: %d", MY_NAME, get_age());
|
||||
|
||||
set_age(100);
|
||||
|
||||
log_info("My age is now: %d", get_age());
|
||||
|
||||
// test out THE_SIZE extern
|
||||
log_info("THE_SIZE is: %d", THE_SIZE);
|
||||
print_size();
|
||||
|
||||
THE_SIZE = 9;
|
||||
|
||||
log_info("THE_SIZE is now: %d", THE_SIZE);
|
||||
print_size();
|
||||
|
||||
// test the ration function static
|
||||
log_info("Ratio at first: %f", update_ratio(2.0));
|
||||
log_info("Ratio again: %f", update_ratio(10.0));
|
||||
log_info("Ratio once more: %f", update_ratio(300.0));
|
||||
|
||||
// test the scope demo
|
||||
int count = 4;
|
||||
scope_demo(count);
|
||||
scope_demo(count * 20);
|
||||
|
||||
log_info("count after calling scope_demo: %d", count);
|
||||
|
||||
return 0;
|
||||
}
|
109
oldstuff/lcthw-remnants-2/ex23.c
Normal file
109
oldstuff/lcthw-remnants-2/ex23.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "dbg.h"
|
||||
|
||||
int normal_copy(char *from, char *to, int count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
to[i] = from[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int duffs_device(char *from, char *to, int count)
|
||||
{
|
||||
{
|
||||
int n = (count + 7) / 8;
|
||||
debug("n=%d, (count %% 8)=%d", n, count % 8);
|
||||
|
||||
switch(count % 8) {
|
||||
case 0: do { *to++ = *from++;
|
||||
case 7: *to++ = *from++;
|
||||
case 6: *to++ = *from++;
|
||||
case 5: *to++ = *from++;
|
||||
case 4: *to++ = *from++;
|
||||
case 3: *to++ = *from++;
|
||||
case 2: *to++ = *from++;
|
||||
case 1: *to++ = *from++;
|
||||
} while(--n > 0);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int zeds_device(char *from, char *to, int count)
|
||||
{
|
||||
{
|
||||
int n = (count + 7) / 8;
|
||||
|
||||
switch(count % 8) {
|
||||
case 0:
|
||||
again: *to++ = *from++;
|
||||
case 7: *to++ = *from++;
|
||||
case 6: *to++ = *from++;
|
||||
case 5: *to++ = *from++;
|
||||
case 4: *to++ = *from++;
|
||||
case 3: *to++ = *from++;
|
||||
case 2: *to++ = *from++;
|
||||
case 1: *to++ = *from++;
|
||||
if(--n > 0) goto again;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int valid_copy(char *data, int count, char expects)
|
||||
{
|
||||
int i = 0;
|
||||
for(i = 0; i < count; i++) {
|
||||
if(data[i] != expects) {
|
||||
log_err("[%d] %c != %c", i, data[i], expects);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char from[1000] = {'a'};
|
||||
char to[1000] = {'c'};
|
||||
int rc = 0;
|
||||
|
||||
// setup the from to have some stuff
|
||||
memset(from, 'x', 1000);
|
||||
// set it to a failure mode
|
||||
memset(to, 'y', 1000);
|
||||
check(valid_copy(to, 1000, 'y'), "Not initialized right.");
|
||||
|
||||
// use normal copy to
|
||||
rc = normal_copy(from, to, 1000);
|
||||
check(rc == 1000, "Normal copy failed: %d", rc);
|
||||
check(valid_copy(to, 1000, 'x'), "Normal copy failed.");
|
||||
|
||||
// reset
|
||||
memset(to, 'y', 1000);
|
||||
|
||||
// duffs version
|
||||
rc = duffs_device(from, to, 1000);
|
||||
check(rc == 1000, "Duff's deice failed: %d", rc);
|
||||
check(valid_copy(to, 1000, 'x'), "Duff's deice failed copy.");
|
||||
|
||||
// reset
|
||||
memset(to, 'y', 1000);
|
||||
|
||||
// my version
|
||||
rc = zeds_device(from, to, 1000);
|
||||
check(rc == 1000, "Zed's device failed: %d", rc);
|
||||
check(valid_copy(to, 1000, 'x'), "Zed's device failed copy.");
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return 1;
|
||||
}
|
77
oldstuff/lcthw-remnants-2/ex24.c
Normal file
77
oldstuff/lcthw-remnants-2/ex24.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <stdio.h>
|
||||
#include "dbg.h"
|
||||
|
||||
#define MAX_DATA 100
|
||||
|
||||
typedef enum EyeColor {
|
||||
BLUE_EYES, GREEN_EYES, BROWN_EYES,
|
||||
BLACK_EYES, OTHER_EYES
|
||||
} EyeColor;
|
||||
|
||||
const char *EYE_COLOR_NAMES[] = {
|
||||
"Blue", "Green", "Brown", "Black", "Other"
|
||||
};
|
||||
|
||||
typedef struct Person {
|
||||
int age;
|
||||
char first_name[MAX_DATA];
|
||||
char last_name[MAX_DATA];
|
||||
EyeColor eyes;
|
||||
float income;
|
||||
} Person;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Person you = {.age = 0};
|
||||
int i = 0;
|
||||
int rc = -1;
|
||||
char *in = NULL;
|
||||
|
||||
printf("What's your First Name? ");
|
||||
in = fgets(you.first_name, MAX_DATA-1, stdin);
|
||||
check(in != NULL, "Failed to read first name.");
|
||||
|
||||
rc = sscanf(you.first_name, "%s", you.first_name);
|
||||
check(rc > 0, "Failed to strip first name.");
|
||||
|
||||
printf("What's your Last Name? ");
|
||||
in = fgets(you.last_name, MAX_DATA-1, stdin);
|
||||
check(in != NULL, "Failed to read last name.");
|
||||
|
||||
rc = sscanf(you.last_name, "%s", you.last_name);
|
||||
check(rc > 0, "Failed to strip last name.");
|
||||
|
||||
printf("How old are you? ");
|
||||
rc = fscanf(stdin, "%d", &you.age);
|
||||
check(rc > 0, "You have to enter a number.");
|
||||
|
||||
printf("What color are your eyes:\n");
|
||||
for(i = 0; i <= OTHER_EYES; i++) {
|
||||
printf("%d) %s\n", i+1, EYE_COLOR_NAMES[i]);
|
||||
}
|
||||
printf("> ");
|
||||
|
||||
int eyes = -1;
|
||||
rc = fscanf(stdin, "%d", &eyes);
|
||||
check(rc > 0, "You have to enter a number.");
|
||||
|
||||
you.eyes = eyes - 1;
|
||||
check(you.eyes <= OTHER_EYES && you.eyes >= 0, "Do it right, that's not an option.");
|
||||
|
||||
printf("How much do you make an hour? ");
|
||||
rc = fscanf(stdin, "%f", &you.income);
|
||||
check(rc > 0, "Enter a floating point number.");
|
||||
|
||||
printf("----- RESULTS -----\n");
|
||||
|
||||
printf("First Name: %s\n", you.first_name);
|
||||
printf("Last Name: %s\n", you.last_name);
|
||||
printf("Age: %d\n", you.age);
|
||||
printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]);
|
||||
printf("Income: %f\n", you.income);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
|
||||
return -1;
|
||||
}
|
134
oldstuff/lcthw-remnants-2/ex25.c
Normal file
134
oldstuff/lcthw-remnants-2/ex25.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/** WARNING: This code is fresh and potentially isn't correct yet. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "dbg.h"
|
||||
|
||||
#define MAX_DATA 100
|
||||
|
||||
int read_string(char **out_string, int max_buffer)
|
||||
{
|
||||
*out_string = calloc(1, max_buffer + 1);
|
||||
check_mem(*out_string);
|
||||
|
||||
char *result = fgets(*out_string, max_buffer, stdin);
|
||||
check(result != NULL, "Input error.");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(*out_string) free(*out_string);
|
||||
*out_string = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read_int(int *out_int)
|
||||
{
|
||||
char *input = NULL;
|
||||
int rc = read_string(&input, MAX_DATA);
|
||||
check(rc == 0, "Failed to read number.");
|
||||
|
||||
*out_int = atoi(input);
|
||||
|
||||
free(input);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(input) free(input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read_scan(const char *fmt, ...)
|
||||
{
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
int *out_int = NULL;
|
||||
char *out_char = NULL;
|
||||
char **out_string = NULL;
|
||||
int max_buffer = 0;
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
|
||||
for(i = 0; fmt[i] != '\0'; i++) {
|
||||
if(fmt[i] == '%') {
|
||||
i++;
|
||||
switch(fmt[i]) {
|
||||
case '\0':
|
||||
sentinel("Invalid format, you ended with %%.");
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
out_int = va_arg(argp, int *);
|
||||
rc = read_int(out_int);
|
||||
check(rc == 0, "Failed to read int.");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
out_char = va_arg(argp, char *);
|
||||
*out_char = fgetc(stdin);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
max_buffer = va_arg(argp, int);
|
||||
out_string = va_arg(argp, char **);
|
||||
rc = read_string(out_string, max_buffer);
|
||||
check(rc == 0, "Failed to read string.");
|
||||
break;
|
||||
|
||||
default:
|
||||
sentinel("Invalid format.");
|
||||
|
||||
}
|
||||
} else {
|
||||
fgetc(stdin);
|
||||
}
|
||||
|
||||
check(!feof(stdin) && !ferror(stdin), "Input error.");
|
||||
}
|
||||
|
||||
va_end(argp);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
va_end(argp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *first_name = NULL;
|
||||
char initial = ' ';
|
||||
char *last_name = NULL;
|
||||
int age = 0;
|
||||
|
||||
printf("What's your first name? ");
|
||||
int rc = read_scan("%s", MAX_DATA, &first_name);
|
||||
check(rc == 0, "Failed first name.");
|
||||
|
||||
printf("What's your initial? ");
|
||||
rc = read_scan("%c\n", &initial);
|
||||
check(rc == 0, "Failed initial.");
|
||||
|
||||
printf("What's your last name? ");
|
||||
rc = read_scan("%s", MAX_DATA, &last_name);
|
||||
check(rc == 0, "Failed last name.");
|
||||
|
||||
printf("How old are you? ");
|
||||
rc = read_scan("%d", &age);
|
||||
|
||||
printf("---- RESULTS ----\n");
|
||||
printf("First Name: %s", first_name);
|
||||
printf("Initial: '%c'\n", initial);
|
||||
printf("Last Name: %s", last_name);
|
||||
printf("Age: %d\n", age);
|
||||
|
||||
free(first_name);
|
||||
free(last_name);
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
74
oldstuff/lcthw-remnants-2/ex27.c
Normal file
74
oldstuff/lcthw-remnants-2/ex27.c
Normal file
@@ -0,0 +1,74 @@
|
||||
#undef NDEBUG
|
||||
#include "dbg.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* naive copy that assumes all inputs are always valid
|
||||
* taken from K&R C and cleaned up a bit;
|
||||
*/
|
||||
void copy(char to[], char from[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// while loop will not end if from isn't '\0' terminated
|
||||
while((to[i] = from[i]) != '\0') {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A safer version that checks for many common errors using the
|
||||
* length of each string to control the loops and termination.
|
||||
*/
|
||||
int safercopy(int from_len, char *from, int to_len, char *to)
|
||||
{
|
||||
assert(from != NULL && to != NULL && "from and to can't be NULL");
|
||||
int i = 0;
|
||||
int max = from_len > to_len - 1 ? to_len - 1 : from_len;
|
||||
|
||||
// to_len must have at least 1 byte
|
||||
if(from_len < 0 || to_len <= 0) return -1;
|
||||
|
||||
for(i = 0; i < max; i++) {
|
||||
to[i] = from[i];
|
||||
}
|
||||
|
||||
to[to_len - 1] = '\0';
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// careful to understand why we can get these sizes
|
||||
char from[] = "0123456789";
|
||||
int from_len = sizeof(from);
|
||||
|
||||
// notice that it's 7 chars + \0
|
||||
char to[] = "0123456";
|
||||
int to_len = sizeof(to);
|
||||
|
||||
debug("Copying '%s':%d to '%s':%d", from, from_len, to, to_len);
|
||||
|
||||
int rc = safercopy(from_len, from, to_len, to);
|
||||
check(rc > 0, "Failed to safercopy.");
|
||||
check(to[to_len - 1] == '\0', "String not terminated.");
|
||||
|
||||
debug("Result is '%s':%d", to, to_len);
|
||||
|
||||
// now try to break it
|
||||
rc = safercopy(from_len * -1, from, to_len, to);
|
||||
check(rc == -1, "safercopy should fail #1");
|
||||
check(to[to_len - 1] == '\0', "String not terminated.");
|
||||
|
||||
rc = safercopy(from_len, from, 0, to);
|
||||
check(rc == -1, "safercopy should fail #2");
|
||||
check(to[to_len - 1] == '\0', "String not terminated.");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return 1;
|
||||
}
|
1
oldstuff/lcthw-remnants-2/ex29/.gitignore
vendored
Normal file
1
oldstuff/lcthw-remnants-2/ex29/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tests/your_library_tests
|
0
oldstuff/lcthw-remnants-2/ex29/LICENSE
Normal file
0
oldstuff/lcthw-remnants-2/ex29/LICENSE
Normal file
59
oldstuff/lcthw-remnants-2/ex29/Makefile
Normal file
59
oldstuff/lcthw-remnants-2/ex29/Makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
|
||||
LDLIBS = -ldl $(OPTLIBS)
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
SOURCES = $(wildcard src/**/*.c src/*.c)
|
||||
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
|
||||
|
||||
TEST_SRC = $(wildcard tests/*_tests.c)
|
||||
TESTS = $(patsubst %.c,%,$(TEST_SRC))
|
||||
|
||||
LIBNAME = ex29
|
||||
TARGET = build/lib$(LIBNAME).a
|
||||
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
|
||||
|
||||
# The Target Build
|
||||
all: $(TARGET) $(SO_TARGET) tests
|
||||
|
||||
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
|
||||
dev: all
|
||||
|
||||
$(TARGET): CFLAGS += -fPIC
|
||||
$(TARGET): build $(OBJECTS)
|
||||
$(AR) rcs $@ $(OBJECTS)
|
||||
ranlib $@
|
||||
|
||||
$(SO_TARGET): $(TARGET) $(OBJECTS)
|
||||
$(CC) -shared -o $@ $(OBJECTS)
|
||||
|
||||
build:
|
||||
@mkdir -p build
|
||||
@mkdir -p bin
|
||||
|
||||
# The Unit Tests
|
||||
.PHONY: tests
|
||||
tests: LDLIBS += -l$(LIBNAME)
|
||||
tests: $(TESTS)
|
||||
sh ./tests/runtests.sh
|
||||
|
||||
valgrind:
|
||||
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
|
||||
|
||||
# The Cleaner
|
||||
clean:
|
||||
rm -rf build $(OBJECTS) $(TESTS)
|
||||
rm -f tests/tests.log
|
||||
find . -name "*.gc*" -exec rm {} \;
|
||||
rm -rf `find . -name "*.dSYM" -print`
|
||||
|
||||
# The Install
|
||||
install: all
|
||||
install -d $(DESTDIR)/$(PREFIX)/lib/
|
||||
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
|
||||
|
||||
# The Checker
|
||||
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
|
||||
check:
|
||||
@echo Files with potentially dangerous functions
|
||||
@egrep $(BADFUNCS) $(SOURCES) || true
|
0
oldstuff/lcthw-remnants-2/ex29/README.md
Normal file
0
oldstuff/lcthw-remnants-2/ex29/README.md
Normal file
30
oldstuff/lcthw-remnants-2/ex29/src/dbg.h
Normal file
30
oldstuff/lcthw-remnants-2/ex29/src/dbg.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __dbg_h__
|
||||
#define __dbg_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(M, ...)
|
||||
#else
|
||||
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||
|
||||
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
|
||||
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define check_mem(A) check((A), "Out of memory.")
|
||||
|
||||
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#endif
|
43
oldstuff/lcthw-remnants-2/ex29/src/ex29.c
Normal file
43
oldstuff/lcthw-remnants-2/ex29/src/ex29.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "dbg.h"
|
||||
|
||||
|
||||
int print_a_message(const char *msg)
|
||||
{
|
||||
printf("A STRING: %s\n", msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uppercase(const char *msg, int count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%c", toupper(msg[i]));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lowercase(const char *msg, int count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
printf("%c", tolower(msg[i]));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fail_on_purpose(const char *msg)
|
||||
{
|
||||
return 1;
|
||||
}
|
65
oldstuff/lcthw-remnants-2/ex29/tests/ex29_tests.c
Normal file
65
oldstuff/lcthw-remnants-2/ex29/tests/ex29_tests.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "minunit.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef int (*lib_function)(const char *data, int count);
|
||||
char *lib_file = "build/libex29.so";
|
||||
void *lib = NULL;
|
||||
|
||||
int check_function(const char *func_to_run, const char *data, int expected)
|
||||
{
|
||||
lib_function func = dlsym(lib, func_to_run);
|
||||
check(func != NULL, "Did not find %s function in the library %s: %s", func_to_run, lib_file, dlerror());
|
||||
|
||||
int rc = func(data, (int)strlen(data));
|
||||
check(rc == expected, "Function %s return %d for data: %s", func_to_run, rc, data);
|
||||
|
||||
return 1;
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *test_dlopen()
|
||||
{
|
||||
lib = dlopen(lib_file, RTLD_NOW);
|
||||
mu_assert(lib != NULL, "Failed to open the library to test.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_functions()
|
||||
{
|
||||
mu_assert(check_function("print_a_message", "Hello", 0), "print_a_message failed.");
|
||||
mu_assert(check_function("uppercase", "Hello", 0), "uppercase failed.");
|
||||
mu_assert(check_function("lowercase", "Hello", 0), "lowercase failed.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_failures()
|
||||
{
|
||||
mu_assert(check_function("fail_on_purpose", "Hello", 1), "fail_on_purpose should fail.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_dlclose()
|
||||
{
|
||||
int rc = dlclose(lib);
|
||||
mu_assert(rc == 0, "Failed to close lib.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
|
||||
mu_run_test(test_dlopen);
|
||||
mu_run_test(test_functions);
|
||||
mu_run_test(test_failures);
|
||||
mu_run_test(test_dlclose);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
38
oldstuff/lcthw-remnants-2/ex29/tests/minunit.h
Normal file
38
oldstuff/lcthw-remnants-2/ex29/tests/minunit.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#undef DNDEBUG
|
||||
#ifndef _minunit_h
|
||||
#define _minunit_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dbg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define mu_suite_start() char *message = NULL
|
||||
|
||||
#define mu_assert(test, message) if (!(test)) {\
|
||||
log_err(message); return message;\
|
||||
}\
|
||||
assertions_made++;
|
||||
#define mu_run_test(test) debug("\n-----%s", " " #test); \
|
||||
message = test(); tests_run++; if (message) return message;
|
||||
|
||||
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
|
||||
argc = argc; \
|
||||
argv = argv; \
|
||||
debug("----- RUNNING: %s", argv[0]);\
|
||||
printf("----\nRUNNING: %s\n", argv[0]);\
|
||||
char *result = name();\
|
||||
if (result != 0) {\
|
||||
printf("FAILED: %s\n", result);\
|
||||
}\
|
||||
else {\
|
||||
printf("ALL TESTS PASSED\n");\
|
||||
}\
|
||||
printf("Tests run: %d\n", tests_run);\
|
||||
printf("Assertions made: %d\n", assertions_made);\
|
||||
exit(result != 0);\
|
||||
}
|
||||
|
||||
int tests_run;
|
||||
int assertions_made;
|
||||
|
||||
#endif
|
19
oldstuff/lcthw-remnants-2/ex29/tests/runtests.sh
Normal file
19
oldstuff/lcthw-remnants-2/ex29/tests/runtests.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
echo "Running unit tests:"
|
||||
|
||||
for i in tests/*_tests
|
||||
do
|
||||
if test -f $i
|
||||
then
|
||||
if $VALGRIND ./$i 2>> tests/tests.log
|
||||
then
|
||||
echo $i PASS
|
||||
else
|
||||
echo "ERROR in test $i: here's tests/tests.log"
|
||||
echo "------"
|
||||
tail tests/tests.log
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
12
oldstuff/lcthw-remnants-2/ex3.c
Normal file
12
oldstuff/lcthw-remnants-2/ex3.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int age = 10;
|
||||
int height = 72;
|
||||
|
||||
printf("I am %d years old.\n", age);
|
||||
printf("I am %d inches tall.\n", height);
|
||||
|
||||
return 0;
|
||||
}
|
12
oldstuff/lcthw-remnants-2/ex31.c
Normal file
12
oldstuff/lcthw-remnants-2/ex31.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while(i < 100) {
|
||||
usleep(3000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
57
oldstuff/lcthw-remnants-2/ex35.c
Normal file
57
oldstuff/lcthw-remnants-2/ex35.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum {
|
||||
TYPE_INT,
|
||||
TYPE_FLOAT,
|
||||
TYPE_STRING,
|
||||
} VariantType;
|
||||
|
||||
struct Variant {
|
||||
VariantType type;
|
||||
union {
|
||||
int as_integer;
|
||||
float as_float;
|
||||
char *as_string;
|
||||
} data;
|
||||
};
|
||||
|
||||
typedef struct Variant Variant;
|
||||
|
||||
void Variant_print(Variant *var)
|
||||
{
|
||||
switch(var->type) {
|
||||
case TYPE_INT:
|
||||
printf("INT: %d\n", var->data.as_integer);
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
printf("FLOAT: %f\n", var->data.as_float);
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
printf("STRING: %s\n", var->data.as_string);
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN TYPE: %d", var->type);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Variant a_int = {.type = TYPE_INT, .data.as_integer = 100};
|
||||
Variant a_float = {.type = TYPE_FLOAT, .data.as_float = 100.34};
|
||||
Variant a_string = {.type = TYPE_STRING, .data.as_string = "YO DUDE!"};
|
||||
|
||||
Variant_print(&a_int);
|
||||
Variant_print(&a_float);
|
||||
Variant_print(&a_string);
|
||||
|
||||
// here's how you access them
|
||||
a_int.data.as_integer = 200;
|
||||
a_float.data.as_float = 2.345;
|
||||
a_string.data.as_string = "Hi there.";
|
||||
|
||||
Variant_print(&a_int);
|
||||
Variant_print(&a_float);
|
||||
Variant_print(&a_string);
|
||||
|
||||
return 0;
|
||||
}
|
12
oldstuff/lcthw-remnants-2/ex4.c
Normal file
12
oldstuff/lcthw-remnants-2/ex4.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int age = 10;
|
||||
int height = 72;
|
||||
|
||||
printf("I am %d years old.\n", age);
|
||||
printf("I am %d inches tall.\n", height);
|
||||
|
||||
return 0;
|
||||
}
|
12
oldstuff/lcthw-remnants-2/ex5.c
Normal file
12
oldstuff/lcthw-remnants-2/ex5.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* This is a comment. */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int distance = 100;
|
||||
|
||||
// this is also a comment
|
||||
printf("You are %d miles away.\n", distance);
|
||||
|
||||
return 0;
|
||||
}
|
22
oldstuff/lcthw-remnants-2/ex6.c
Normal file
22
oldstuff/lcthw-remnants-2/ex6.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int distance = 100;
|
||||
float power = 2.345f;
|
||||
double super_power = 56789.4532;
|
||||
char initial = 'A';
|
||||
char first_name[] = "Zed";
|
||||
char last_name[] = "Shaw";
|
||||
|
||||
printf("You are %d miles away.\n", distance);
|
||||
printf("You have %f levels of power.\n", power);
|
||||
printf("You have %f awesome super powers.\n", super_power);
|
||||
printf("I have na initial %c.\n", initial);
|
||||
printf("I have a first name %s.\n", first_name);
|
||||
printf("I have a last name %s.\n", last_name);
|
||||
printf("My whole name is %s %c. %s.\n",
|
||||
first_name, initial, last_name);
|
||||
|
||||
return 0;
|
||||
}
|
30
oldstuff/lcthw-remnants-2/ex7.c
Normal file
30
oldstuff/lcthw-remnants-2/ex7.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int bugs = 100;
|
||||
double bug_rate = 1.2;
|
||||
|
||||
printf("You have %d bugs at the imaginary rate of %f.\n",
|
||||
bugs, bug_rate);
|
||||
|
||||
long universe_of_defects = 1L * 1024L * 1024L * 1024L;
|
||||
printf("The entire universe has %ld bugs.\n",
|
||||
universe_of_defects);
|
||||
|
||||
double expected_bugs = bugs * bug_rate;
|
||||
printf("You are expected to have %f bugs.\n",
|
||||
expected_bugs);
|
||||
|
||||
double part_of_universe = expected_bugs / universe_of_defects;
|
||||
printf("That is only a %e portion of the universe.\n",
|
||||
part_of_universe);
|
||||
|
||||
// this makes no sense, just a demo of something weird
|
||||
char nul_byte = '\0';
|
||||
int care_percentage = bugs * nul_byte;
|
||||
printf("Which means you should care %d%%.\n",
|
||||
care_percentage);
|
||||
|
||||
return 0;
|
||||
}
|
36
oldstuff/lcthw-remnants-2/ex8.c
Normal file
36
oldstuff/lcthw-remnants-2/ex8.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int areas[] = {10, 12, 13, 14, 20};
|
||||
char name[] = "Zed";
|
||||
char full_name[] = {
|
||||
'Z', 'e', 'd',
|
||||
' ', 'A', '.', ' ',
|
||||
'S', 'h', 'a', 'w', '\0'
|
||||
};
|
||||
|
||||
// WARNING: On some systems you may have to change the
|
||||
// %ld in this code to a %u since it will use unsigned ints
|
||||
printf("The size of an int: %ld\n", sizeof(int));
|
||||
printf("The size of areas (int[]): %ld\n",
|
||||
sizeof(areas));
|
||||
printf("The first area is %d, the 2nd %d.\n",
|
||||
areas[0], areas[1]);
|
||||
|
||||
printf("The size of a char: %ld\n", sizeof(char));
|
||||
printf("The size of name (char[]): %ld\n",
|
||||
sizeof(name));
|
||||
printf("The number of chars: %ld\n",
|
||||
sizeof(name) / sizeof(char));
|
||||
|
||||
printf("The size of full_name (char[]): %ld\n",
|
||||
sizeof(full_name));
|
||||
printf("The number of chars: %ld\n",
|
||||
sizeof(full_name) / sizeof(char));
|
||||
|
||||
printf("name=\"%s\" and full_name=\"%s\"\n",
|
||||
name, full_name);
|
||||
|
||||
return 0;
|
||||
}
|
55
oldstuff/lcthw-remnants-2/ex9-ec.c
Normal file
55
oldstuff/lcthw-remnants-2/ex9-ec.c
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int numbers[4] = {0};
|
||||
char name[4] = {'a'};
|
||||
|
||||
// first, print them out raw
|
||||
printf("numbers: %d %d %d %d\n",
|
||||
numbers[0], numbers[1],
|
||||
numbers[2], numbers[3]);
|
||||
|
||||
printf("name each: %c %c %c %c\n",
|
||||
name[0], name[1],
|
||||
name[2], name[3]);
|
||||
|
||||
printf("name: %s\n", name);
|
||||
|
||||
// setup the numbers
|
||||
numbers[0] = 1;
|
||||
numbers[1] = 2;
|
||||
numbers[2] = 3;
|
||||
numbers[3] = 4;
|
||||
|
||||
// setup the name
|
||||
name[0] = 'Z';
|
||||
name[1] = 'e';
|
||||
name[2] = 'd';
|
||||
name[3] = '\0';
|
||||
|
||||
// then print them out initialized
|
||||
printf("numbers: %d %d %d %d\n",
|
||||
numbers[0], numbers[1],
|
||||
numbers[2], numbers[3]);
|
||||
|
||||
printf("name each: %c %c %c %c\n",
|
||||
name[0], name[1],
|
||||
name[2], name[3]);
|
||||
|
||||
// print the name like a string
|
||||
printf("name: %s\n", name);
|
||||
|
||||
// another way to use name;
|
||||
char *another = "Zed";
|
||||
|
||||
printf("another: %s\n", another);
|
||||
printf("another each: %c %c %c %c\n",
|
||||
another[0], another[1],
|
||||
another[2], another[3]);
|
||||
|
||||
printf("name length: %ld\n", sizeof(name));
|
||||
printf("name as int: %d\n", (int)(*name));
|
||||
|
||||
return 0;
|
||||
}
|
52
oldstuff/lcthw-remnants-2/ex9.c
Normal file
52
oldstuff/lcthw-remnants-2/ex9.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int numbers[4] = {0};
|
||||
char name[4] = {'a'};
|
||||
|
||||
// first, print them out raw
|
||||
printf("numbers: %d %d %d %d\n",
|
||||
numbers[0], numbers[1],
|
||||
numbers[2], numbers[3]);
|
||||
|
||||
printf("name each: %c %c %c %c\n",
|
||||
name[0], name[1],
|
||||
name[2], name[3]);
|
||||
|
||||
printf("name: %s\n", name);
|
||||
|
||||
// setup the numbers
|
||||
numbers[0] = 1;
|
||||
numbers[1] = 2;
|
||||
numbers[2] = 3;
|
||||
numbers[3] = 4;
|
||||
|
||||
// setup the name
|
||||
name[0] = 'Z';
|
||||
name[1] = 'e';
|
||||
name[2] = 'd';
|
||||
name[3] = '\0';
|
||||
|
||||
// then print them out initialized
|
||||
printf("numbers: %d %d %d %d\n",
|
||||
numbers[0], numbers[1],
|
||||
numbers[2], numbers[3]);
|
||||
|
||||
printf("name each: %c %c %c %c\n",
|
||||
name[0], name[1],
|
||||
name[2], name[3]);
|
||||
|
||||
// print the name like a string
|
||||
printf("name: %s\n", name);
|
||||
|
||||
// another way to use name;
|
||||
char *another = "Zed";
|
||||
|
||||
printf("another: %s\n", another);
|
||||
printf("another each: %c %c %c %c\n",
|
||||
another[0], another[1],
|
||||
another[2], another[3]);
|
||||
|
||||
return 0;
|
||||
}
|
41
oldstuff/lcthw-remnants-2/install-apr
Executable file
41
oldstuff/lcthw-remnants-2/install-apr
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# go somewhere safe
|
||||
cd /tmp
|
||||
|
||||
# get the source to base APR 1.4.6
|
||||
curl -L -O http://archive.apache.org/dist/apr/apr-1.4.6.tar.gz
|
||||
|
||||
# extract it and go into the source
|
||||
tar -xzvf apr-1.4.6.tar.gz
|
||||
cd apr-1.4.6
|
||||
|
||||
# configure, make, make install
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
# reset and cleanup
|
||||
cd /tmp
|
||||
rm -rf apr-1.4.6 apr-1.4.6.tar.gz
|
||||
|
||||
# do the same with apr-util
|
||||
curl -L -O http://archive.apache.org/dist/apr/apr-util-1.4.1.tar.gz
|
||||
|
||||
# extract
|
||||
tar -xzvf apr-util-1.4.1.tar.gz
|
||||
cd apr-util-1.4.1
|
||||
|
||||
# configure, make, make install
|
||||
./configure --with-apr=/usr/local/apr
|
||||
# you need that extra parameter to configure because
|
||||
# apr-util can't really find it because...who knows.
|
||||
|
||||
make
|
||||
sudo make install
|
||||
|
||||
#cleanup
|
||||
cd /tmp
|
||||
rm -rf apr-util-1.4.1* apr-1.4.6*
|
5
oldstuff/lcthw-remnants-2/liblcthw/.gitignore
vendored
Normal file
5
oldstuff/lcthw-remnants-2/liblcthw/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
tests/runtests
|
||||
tests/*_tests
|
||||
tests/**/*_tests
|
||||
bstrlib.c
|
||||
bstrlib.h
|
21
oldstuff/lcthw-remnants-2/liblcthw/LICENSE
Normal file
21
oldstuff/lcthw-remnants-2/liblcthw/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
Copyright (C) 2016 Dan Buch
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
76
oldstuff/lcthw-remnants-2/liblcthw/Makefile
Normal file
76
oldstuff/lcthw-remnants-2/liblcthw/Makefile
Normal file
@@ -0,0 +1,76 @@
|
||||
BSTRLIB_BASE_URL ?= https://raw.githubusercontent.com/websnarf/bstrlib/208b1f2a4dfc96b806ed499bd1909e87ec15981d
|
||||
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
|
||||
LDLIBS = -ldl $(OPTLIBS)
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
FIND ?= find
|
||||
CD ?= cd
|
||||
PATCH ?= patch
|
||||
INSTALL ?= install
|
||||
MKDIR ?= mkdir -p
|
||||
CURL ?= curl -sSL
|
||||
RANLIB ?= ranlib
|
||||
RUNTESTS ?= ./tests/runtests
|
||||
|
||||
SOURCES = $(wildcard src/**/*.c src/*.c)
|
||||
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
|
||||
|
||||
TEST_SRC = $(wildcard tests/**/*_tests.c tests/*_tests.c)
|
||||
TESTS = $(patsubst %.c,%,$(TEST_SRC))
|
||||
|
||||
LIBNAME = lcthw
|
||||
TARGET = build/lib$(LIBNAME).a
|
||||
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
|
||||
|
||||
all: $(TARGET) $(SO_TARGET) tests
|
||||
|
||||
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
|
||||
dev: all
|
||||
|
||||
$(TARGET): CFLAGS += -fPIC
|
||||
$(TARGET): build $(OBJECTS)
|
||||
$(AR) rcs $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
$(SO_TARGET): $(TARGET) $(OBJECTS)
|
||||
$(CC) -shared -o $@ $(OBJECTS)
|
||||
|
||||
build: bin src/lcthw/bstrlib.c src/lcthw/bstrlib.h
|
||||
@$(MKDIR) $@
|
||||
|
||||
bin:
|
||||
@$(MKDIR) $@
|
||||
|
||||
src/lcthw/bstrlib.c: src/lcthw/bstrlib.h
|
||||
$(CURL) -o $@ $(BSTRLIB_BASE_URL)/bstrlib.c
|
||||
$(CD) src/lcthw && $(PATCH) -p1 < bstrlib.patch
|
||||
|
||||
src/lcthw/bstrlib.h:
|
||||
$(CURL) -o $@ $(BSTRLIB_BASE_URL)/bstrlib.h
|
||||
|
||||
.PHONY: tests
|
||||
tests: LDLIBS += -static -l$(LIBNAME) -lbsd
|
||||
tests: $(RUNTESTS) $(TESTS)
|
||||
$(RUNTESTS) ./tests/lcthw
|
||||
|
||||
valgrind:
|
||||
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
|
||||
|
||||
clean:
|
||||
$(RM) -r build $(OBJECTS) $(TESTS)
|
||||
$(RM) tests/tests.log tests/runtests
|
||||
$(FIND) . -name "*.gc*" -exec rm {} \;
|
||||
$(RM) -r `find . -name "*.dSYM" -print`
|
||||
|
||||
distclean: clean
|
||||
$(RM) src/lcthw/bstrlib.c src/lcthw/bstrlib.h
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d $(DESTDIR)/$(PREFIX)/lib/
|
||||
$(INSTALL) $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
|
||||
|
||||
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
|
||||
check:
|
||||
@echo Files with potentially dangerous functions
|
||||
@egrep $(BADFUNCS) $(SOURCES) || true
|
0
oldstuff/lcthw-remnants-2/liblcthw/README.md
Normal file
0
oldstuff/lcthw-remnants-2/liblcthw/README.md
Normal file
12
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/bstrlib.patch
Normal file
12
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/bstrlib.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
--- a/bstrlib.c 2016-04-21 12:26:50.000000000 -0400
|
||||
+++ b/bstrlib.c 2016-04-21 12:27:59.000000000 -0400
|
||||
@@ -22,7 +22,8 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
-#include "bstrlib.h"
|
||||
+// PATCH to include adjacent bstrlib.h
|
||||
+#include <lcthw/bstrlib.h>
|
||||
|
||||
/* Optionally include a mechanism for debugging memory */
|
||||
|
116
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray.c
Normal file
116
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <lcthw/darray.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
DArray *DArray_create(size_t element_size, size_t initial_max)
|
||||
{
|
||||
DArray *array = malloc(sizeof(DArray));
|
||||
check_mem(array);
|
||||
array->max = initial_max;
|
||||
check(array->max > 0, "You must set an initial_max > 0.");
|
||||
|
||||
array->contents = calloc(initial_max, sizeof(void *));
|
||||
check_mem(array->contents);
|
||||
|
||||
array->end = 0;
|
||||
array->element_size = element_size;
|
||||
array->expand_rate = DEFAULT_EXPAND_RATE;
|
||||
|
||||
return array;
|
||||
|
||||
error:
|
||||
if(array) free(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DArray_clear(DArray *array)
|
||||
{
|
||||
int i = 0;
|
||||
if(array->element_size > 0) {
|
||||
for(i = 0; i < array->max; i++) {
|
||||
if(array->contents[i] != NULL) {
|
||||
free(array->contents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int DArray_resize(DArray *array, size_t newsize)
|
||||
{
|
||||
array->max = newsize;
|
||||
check(array->max > 0, "The newsize must be > 0.");
|
||||
|
||||
void *contents = realloc(array->contents, array->max * sizeof(void *));
|
||||
|
||||
check_mem(contents);
|
||||
|
||||
array->contents = contents;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DArray_expand(DArray *array)
|
||||
{
|
||||
size_t old_max = array->max;
|
||||
check(DArray_resize(array, array->max + array->expand_rate) == 0,
|
||||
"Failed to expand array to new size: %d",
|
||||
array->max + (int)array->expand_rate);
|
||||
|
||||
memset(array->contents + old_max, 0, array->expand_rate + 1);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DArray_contract(DArray *array)
|
||||
{
|
||||
int new_size = array->end < (int)array->expand_rate ? (int)array->expand_rate : array->end;
|
||||
|
||||
return DArray_resize(array, new_size + 1);
|
||||
}
|
||||
|
||||
|
||||
void DArray_destroy(DArray *array)
|
||||
{
|
||||
if(array) {
|
||||
if(array->contents) free(array->contents);
|
||||
free(array);
|
||||
}
|
||||
}
|
||||
|
||||
void DArray_clear_destroy(DArray *array)
|
||||
{
|
||||
DArray_clear(array);
|
||||
DArray_destroy(array);
|
||||
}
|
||||
|
||||
int DArray_push(DArray *array, void *el)
|
||||
{
|
||||
array->contents[array->end] = el;
|
||||
array->end++;
|
||||
|
||||
if(DArray_end(array) >= DArray_max(array)) {
|
||||
return DArray_expand(array);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *DArray_pop(DArray *array)
|
||||
{
|
||||
check(array->end - 1 >= 0, "Attempt to pop from empty array.");
|
||||
|
||||
void *el = DArray_remove(array, array->end - 1);
|
||||
array->end--;
|
||||
|
||||
if(DArray_end(array) > (int)array->expand_rate && DArray_end(array) % array->expand_rate) {
|
||||
DArray_contract(array);
|
||||
}
|
||||
|
||||
return el;
|
||||
error:
|
||||
return NULL;
|
||||
}
|
78
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray.h
Normal file
78
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef lcthw_DArray_h
|
||||
#define lcthw_DArray_h
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <lcthw/dbg.h>
|
||||
|
||||
typedef struct DArray {
|
||||
int end;
|
||||
int max;
|
||||
size_t element_size;
|
||||
size_t expand_rate;
|
||||
void **contents;
|
||||
} DArray;
|
||||
|
||||
DArray *DArray_create(size_t element_size, size_t initial_max);
|
||||
|
||||
void DArray_destroy(DArray *array);
|
||||
|
||||
void DArray_clear(DArray *array);
|
||||
|
||||
int DArray_expand(DArray *array);
|
||||
|
||||
int DArray_contract(DArray *array);
|
||||
|
||||
int DArray_push(DArray *array, void *el);
|
||||
|
||||
void *DArray_pop(DArray *array);
|
||||
|
||||
void DArray_clear_destroy(DArray *array);
|
||||
|
||||
#define DArray_last(A) ((A)->contents[(A)->end - 1])
|
||||
#define DArray_first(A) ((A)->contents[0])
|
||||
#define DArray_end(A) ((A)->end)
|
||||
#define DArray_count(A) DArray_end(A)
|
||||
#define DArray_max(A) ((A)->max)
|
||||
|
||||
#define DEFAULT_EXPAND_RATE 300
|
||||
|
||||
|
||||
static inline void DArray_set(DArray *array, int i, void *el)
|
||||
{
|
||||
check(i < array->max, "darray attempt to set past max");
|
||||
if(i > array->end) array->end = i;
|
||||
array->contents[i] = el;
|
||||
error:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void *DArray_get(DArray *array, int i)
|
||||
{
|
||||
check(i < array->max, "darray attempt to get past max");
|
||||
return array->contents[i];
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *DArray_remove(DArray *array, int i)
|
||||
{
|
||||
void *el = array->contents[i];
|
||||
|
||||
array->contents[i] = NULL;
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
static inline void *DArray_new(DArray *array)
|
||||
{
|
||||
check(array->element_size > 0, "Can't use DArray_new on 0 size darrays.");
|
||||
|
||||
return calloc(1, array->element_size);
|
||||
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define DArray_free(E) free((E))
|
||||
|
||||
#endif
|
19
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray_algos.c
Normal file
19
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray_algos.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <lcthw/darray_algos.h>
|
||||
#include <stdlib.h>
|
||||
#include <bsd/stdlib.h>
|
||||
|
||||
int DArray_qsort(DArray *array, DArray_compare cmp)
|
||||
{
|
||||
qsort(array->contents, DArray_count(array), sizeof(void *), cmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DArray_heapsort(DArray *array, DArray_compare cmp)
|
||||
{
|
||||
return heapsort(array->contents, DArray_count(array), sizeof(void *), cmp);
|
||||
}
|
||||
|
||||
int DArray_mergesort(DArray *array, DArray_compare cmp)
|
||||
{
|
||||
return mergesort(array->contents, DArray_count(array), sizeof(void *), cmp);
|
||||
}
|
14
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray_algos.h
Normal file
14
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/darray_algos.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef lcthw_DArray_algos_h
|
||||
#define lcthw_DArray_algos_h
|
||||
|
||||
#include <lcthw/darray.h>
|
||||
|
||||
typedef int (*DArray_compare)(const void *a, const void *b);
|
||||
|
||||
int DArray_qsort(DArray *array, DArray_compare cmp);
|
||||
|
||||
int DArray_heapsort(DArray *array, DArray_compare cmp);
|
||||
|
||||
int DArray_mergesort(DArray *array, DArray_compare cmp);
|
||||
|
||||
#endif
|
30
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/dbg.h
Normal file
30
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/dbg.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __dbg_h__
|
||||
#define __dbg_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(M, ...)
|
||||
#else
|
||||
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||
|
||||
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
|
||||
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#define check_mem(A) check((A), "Out of memory.")
|
||||
|
||||
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
|
||||
|
||||
#endif
|
244
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list.c
Normal file
244
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list.c
Normal file
@@ -0,0 +1,244 @@
|
||||
#include <lcthw/list.h>
|
||||
#include <lcthw/dbg.h>
|
||||
|
||||
List *List_create()
|
||||
{
|
||||
return calloc(1, sizeof(List));
|
||||
}
|
||||
|
||||
void List_destroy(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
if(cur->prev) {
|
||||
free(cur->prev);
|
||||
}
|
||||
}
|
||||
|
||||
free(list->last);
|
||||
free(list);
|
||||
}
|
||||
|
||||
|
||||
void List_clear(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
free(cur->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void List_clear_destroy(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
free(cur->value);
|
||||
if(cur->prev) {
|
||||
free(cur->prev);
|
||||
}
|
||||
}
|
||||
|
||||
free(list->last);
|
||||
free(list);
|
||||
}
|
||||
|
||||
|
||||
void List_push(List *list, void *value)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
ListNode *node = calloc(1, sizeof(ListNode));
|
||||
check_mem(node);
|
||||
|
||||
node->value = value;
|
||||
|
||||
if(list->last == NULL) {
|
||||
list->first = node;
|
||||
list->last = node;
|
||||
} else {
|
||||
list->last->next = node;
|
||||
node->prev = list->last;
|
||||
list->last = node;
|
||||
}
|
||||
|
||||
list->count++;
|
||||
|
||||
error:
|
||||
return;
|
||||
}
|
||||
|
||||
void *List_pop(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
ListNode *node = list->last;
|
||||
return node != NULL ? List_remove(list, node) : NULL;
|
||||
}
|
||||
|
||||
void List_unshift(List *list, void *value)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
ListNode *node = calloc(1, sizeof(ListNode));
|
||||
check_mem(node);
|
||||
|
||||
node->value = value;
|
||||
|
||||
if(list->first == NULL) {
|
||||
list->first = node;
|
||||
list->last = node;
|
||||
} else {
|
||||
node->next = list->first;
|
||||
list->first->prev = node;
|
||||
list->first = node;
|
||||
}
|
||||
|
||||
list->count++;
|
||||
|
||||
error:
|
||||
return;
|
||||
}
|
||||
|
||||
void *List_shift(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
ListNode *node = list->first;
|
||||
return node != NULL ? List_remove(list, node) : NULL;
|
||||
}
|
||||
|
||||
void *List_remove(List *list, ListNode *node)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
void *result = NULL;
|
||||
|
||||
check(list->first && list->last, "List is empty.");
|
||||
check(node, "node can't be NULL");
|
||||
|
||||
if(node == list->first && node == list->last) {
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
} else if(node == list->first) {
|
||||
list->first = node->next;
|
||||
check(list->first != NULL, "Invalid list, somehow got a first that is NULL.");
|
||||
list->first->prev = NULL;
|
||||
} else if(node == list->last) {
|
||||
list->last = node->prev;
|
||||
check(list->last != NULL, "Invalid list, somehow got a next that is NULL.");
|
||||
list->last->next = NULL;
|
||||
} else {
|
||||
ListNode *after = node->next;
|
||||
ListNode *before = node->prev;
|
||||
after->prev = before;
|
||||
before->next = after;
|
||||
}
|
||||
|
||||
list->count--;
|
||||
result = node->value;
|
||||
free(node);
|
||||
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
List *List_copy(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
List *out = List_create();
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
List_push(out, cur->value);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int List_split(List *list, void *split, List *a, List *b)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
check(list->first && list->last, "List is empty.");
|
||||
check(split, "split can't be NULL");
|
||||
|
||||
if(split == list->last->value || (split == list->first->value && split == list->last->value)) {
|
||||
(*a) = *List_copy(list);
|
||||
return 0;
|
||||
} else if(split == list->first->value) {
|
||||
(*b) = *List_copy(list);
|
||||
List_push(a, List_shift(b));
|
||||
return 0;
|
||||
} else {
|
||||
int past_split = 0;
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
if(past_split) {
|
||||
List_push(b, cur->value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(cur->value == split) {
|
||||
past_split = 1;
|
||||
}
|
||||
|
||||
List_push(a, cur->value);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void List_join(List *list, List *b)
|
||||
{
|
||||
List_validate(list);
|
||||
List_validate(b);
|
||||
|
||||
List *tail = List_copy(b);
|
||||
|
||||
list->last->next = tail->first;
|
||||
list->count += tail->count;
|
||||
free(tail);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void List_swap(ListNode *a, ListNode *b)
|
||||
{
|
||||
ListNode *tmp = a->next;
|
||||
a->next = b->next;
|
||||
b->next = tmp;
|
||||
tmp = a->prev;
|
||||
a->prev = b->prev;
|
||||
b->prev = tmp;
|
||||
}
|
||||
|
||||
|
||||
void List_dump(List *list)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
if(i > 0) {
|
||||
for(j = 0; j < (i*4); j++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("`");
|
||||
}
|
||||
printf("-> [%d] ListNode .value = %p (%s)\n", i, cur->value, (char *)cur->value);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
51
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list.h
Normal file
51
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef lcthw_List_h
|
||||
#define lcthw_List_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct ListNode;
|
||||
|
||||
typedef struct ListNode {
|
||||
struct ListNode *next;
|
||||
struct ListNode *prev;
|
||||
void *value;
|
||||
} ListNode;
|
||||
|
||||
typedef struct List {
|
||||
int count;
|
||||
ListNode *first;
|
||||
ListNode *last;
|
||||
} List;
|
||||
|
||||
List *List_create();
|
||||
void List_destroy(List *list);
|
||||
void List_clear(List *list);
|
||||
void List_clear_destroy(List *list);
|
||||
|
||||
#define List_count(A) ((A)->count)
|
||||
#define List_first(A) ((A)->first != NULL ? (A)->first->value : NULL)
|
||||
#define List_last(A) ((A)->last != NULL ? (A)->last->value : NULL)
|
||||
|
||||
void List_push(List *list, void *value);
|
||||
void *List_pop(List *list);
|
||||
|
||||
void List_unshift(List *list, void *value);
|
||||
void *List_shift(List *list);
|
||||
|
||||
void *List_remove(List *list, ListNode *node);
|
||||
|
||||
List *List_copy(List *list);
|
||||
int List_split(List *list, void *split, List *a, List *b);
|
||||
void List_join(List *list, List *b);
|
||||
void List_swap(ListNode *a, ListNode *b);
|
||||
void List_dump(List *list);
|
||||
|
||||
#define List_validate(A) (assert(A != NULL && List_count(A) > -1 &&\
|
||||
(List_count(A) > 0 && List_first(A) != NULL) && "invalid *List"))
|
||||
|
||||
#define LIST_FOREACH(L, F, N, C) ListNode *_node = NULL;\
|
||||
ListNode *C = NULL;\
|
||||
for(C = _node = L->F; _node != NULL; C = _node = _node->N)
|
||||
|
||||
#endif
|
87
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list_algos.c
Normal file
87
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list_algos.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <lcthw/list_algos.h>
|
||||
#include <lcthw/dbg.h>
|
||||
|
||||
int List_bubble_sort(List *list, List_compare cmp)
|
||||
{
|
||||
List_validate(list);
|
||||
|
||||
if(List_count(list) <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int swapped = 1;
|
||||
|
||||
while(swapped == 1) {
|
||||
swapped = 0;
|
||||
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
if(cur->next == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(cmp(cur->value, cur->next->value) > 0) {
|
||||
List_swap(cur, cur->next);
|
||||
swapped = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
List *List_merge(List *left, List *right, List_compare cmp)
|
||||
{
|
||||
List *result = List_create();
|
||||
|
||||
while(List_count(left) > 0 && List_count(right) > 0) {
|
||||
if(cmp(List_first(left), List_first(right)) <= 0) {
|
||||
List_push(result, List_shift(left));
|
||||
continue;
|
||||
}
|
||||
|
||||
List_push(result, List_shift(right));
|
||||
}
|
||||
|
||||
while(List_count(left) > 0) {
|
||||
List_push(result, List_shift(left));
|
||||
}
|
||||
|
||||
while(List_count(right) > 0) {
|
||||
List_push(result, List_shift(right));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
List *List_merge_sort(List *list, List_compare cmp)
|
||||
{
|
||||
if(List_count(list) <= 1) {
|
||||
return list;;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
List *left = List_create();
|
||||
List *right = List_create();
|
||||
|
||||
LIST_FOREACH(list, first, next, cur) {
|
||||
if(i % 2 == 0) {
|
||||
List_push(right, cur->value);
|
||||
} else {
|
||||
List_push(left, cur->value);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
List *sort_left = List_merge_sort(left, cmp);
|
||||
List *sort_right = List_merge_sort(right, cmp);
|
||||
|
||||
if(sort_left != left) {
|
||||
List_destroy(left);
|
||||
}
|
||||
|
||||
if(sort_right != right) {
|
||||
List_destroy(right);
|
||||
}
|
||||
|
||||
return List_merge(sort_left, sort_right, cmp);
|
||||
}
|
12
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list_algos.h
Normal file
12
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/list_algos.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef lcthw_List_algos_h
|
||||
#define lcthw_List_algos_h
|
||||
|
||||
#include <lcthw/list.h>
|
||||
|
||||
typedef int (*List_compare)(const void *a, const void *b);
|
||||
|
||||
int List_bubble_sort(List *list, List_compare cmp);
|
||||
|
||||
List *List_merge_sort(List *list, List_compare cmp);
|
||||
|
||||
#endif
|
140
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/radixmap.c
Normal file
140
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/radixmap.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Based on code by Andre Reinald then heavily modified by Zed A. Shaw
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <lcthw/radixmap.h>
|
||||
#include <lcthw/dbg.h>
|
||||
|
||||
RadixMap *RadixMap_create(size_t max)
|
||||
{
|
||||
RadixMap *map = calloc(sizeof(RadixMap), 1);
|
||||
check_mem(map);
|
||||
|
||||
map->contents = calloc(sizeof(RMElement), max + 1);
|
||||
check_mem(map->contents);
|
||||
|
||||
map->temp = calloc(sizeof(RMElement), max + 1);
|
||||
check_mem(map->temp);
|
||||
|
||||
map->max = max;
|
||||
map->end = 0;
|
||||
|
||||
return map;
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RadixMap_destroy(RadixMap *map)
|
||||
{
|
||||
if(map) {
|
||||
free(map->contents);
|
||||
free(map->temp);
|
||||
free(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ByteOf(x,y) (((uint8_t *)x)[y])
|
||||
|
||||
static inline void radix_sort(short offset, uint64_t max, uint64_t *source, uint64_t *dest)
|
||||
{
|
||||
uint64_t count[256] = {0};
|
||||
uint64_t *cp = NULL;
|
||||
uint64_t *sp = NULL;
|
||||
uint64_t *end = NULL;
|
||||
uint64_t s = 0;
|
||||
uint64_t c = 0;
|
||||
|
||||
// count occurences of every byte value
|
||||
for(sp = source, end = source + max; sp < end; sp++) {
|
||||
count[ByteOf(sp, offset)]++;
|
||||
}
|
||||
|
||||
// transform count into index by summing elements and storing into same array
|
||||
for(s = 0, cp = count, end = count + 256; cp < end; cp++) {
|
||||
c = *cp;
|
||||
*cp = s;
|
||||
s += c;
|
||||
}
|
||||
|
||||
// fill dest with the right values in the right place
|
||||
for(sp = source, end = source + max; sp < end; sp++) {
|
||||
cp = count + ByteOf(sp, offset);
|
||||
dest[*cp] = *sp;
|
||||
++(*cp);
|
||||
}
|
||||
}
|
||||
|
||||
void RadixMap_sort(RadixMap *map)
|
||||
{
|
||||
uint64_t *source = &map->contents[0].raw;
|
||||
uint64_t *temp = &map->temp[0].raw;
|
||||
|
||||
radix_sort(0, map->end, source, temp);
|
||||
radix_sort(1, map->end, temp, source);
|
||||
radix_sort(2, map->end, source, temp);
|
||||
radix_sort(3, map->end, temp, source);
|
||||
}
|
||||
|
||||
RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
|
||||
{
|
||||
int low = 0;
|
||||
int high = map->end - 1;
|
||||
RMElement *data = map->contents;
|
||||
|
||||
while(low <= high) {
|
||||
int middle = low + (high - low)/2;
|
||||
uint32_t key = data[middle].data.key;
|
||||
|
||||
if(to_find < key) {
|
||||
high = middle - 1;
|
||||
} else if(to_find > key) {
|
||||
low = middle + 1;
|
||||
} else {
|
||||
return &data[middle];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value)
|
||||
{
|
||||
check(key < UINT32_MAX, "Key can't be equal to UINT32_MAX.");
|
||||
|
||||
RMElement element = {.data = {.key = key, .value = value}};
|
||||
check(map->end + 1 < map->max, "RadixMap is full.");
|
||||
|
||||
map->contents[map->end++] = element;
|
||||
|
||||
RadixMap_sort(map);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int RadixMap_delete(RadixMap *map, RMElement *el)
|
||||
{
|
||||
check(map->end > 0, "There is nothing to delete.");
|
||||
check(el != NULL, "Can't delete a NULL element.");
|
||||
|
||||
el->data.key = UINT32_MAX;
|
||||
|
||||
if(map->end > 1) {
|
||||
// don't bother resorting a map of 1 length
|
||||
RadixMap_sort(map);
|
||||
}
|
||||
|
||||
map->end--;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
35
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/radixmap.h
Normal file
35
oldstuff/lcthw-remnants-2/liblcthw/src/lcthw/radixmap.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef lcthw_radixmap_h
|
||||
#define lcthw_radixmap_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union RMElement {
|
||||
uint64_t raw;
|
||||
struct {
|
||||
uint32_t key;
|
||||
uint32_t value;
|
||||
} data;
|
||||
} RMElement;
|
||||
|
||||
typedef struct RadixMap {
|
||||
size_t max;
|
||||
size_t end;
|
||||
uint32_t counter;
|
||||
RMElement *contents;
|
||||
RMElement *temp;
|
||||
} RadixMap;
|
||||
|
||||
|
||||
RadixMap *RadixMap_create(size_t max);
|
||||
|
||||
void RadixMap_destroy(RadixMap *map);
|
||||
|
||||
void RadixMap_sort(RadixMap *map);
|
||||
|
||||
RMElement *RadixMap_find(RadixMap *map, uint32_t key);
|
||||
|
||||
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value);
|
||||
|
||||
int RadixMap_delete(RadixMap *map, RMElement *el);
|
||||
|
||||
#endif
|
@@ -0,0 +1,55 @@
|
||||
#include "../minunit.h"
|
||||
#include <lcthw/bstrlib.h>
|
||||
|
||||
char *test_bfromcstr()
|
||||
{
|
||||
bstring b = bfromcstr("oh hai");
|
||||
mu_assert(b != NULL, "bstring is NULL.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_blk2bstr()
|
||||
{
|
||||
bstring b = blk2bstr("hats", 5);
|
||||
mu_assert(b != NULL, "bstring is NULL.");
|
||||
|
||||
b = blk2bstr(NULL, 42);
|
||||
mu_assert(b == NULL, "bstring is not NULL.");
|
||||
|
||||
b = blk2bstr("bats", -17);
|
||||
mu_assert(b == NULL, "bstring is not NULL.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_bstrcpy()
|
||||
{
|
||||
bstring b = bfromcstr("mats");
|
||||
mu_assert(bstrcpy(b) != NULL, "bstring is NULL.");
|
||||
|
||||
mu_assert(bstrcpy(NULL) == NULL, "bstring is not NULL.");
|
||||
|
||||
int orig_len = b->slen;
|
||||
b->slen = -1;
|
||||
mu_assert(bstrcpy(b) == NULL, "bstring is not NULL.");
|
||||
b->slen = orig_len;
|
||||
|
||||
b->data = NULL;
|
||||
mu_assert(bstrcpy(b) == NULL, "bstring is not NULL.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
|
||||
mu_run_test(test_bfromcstr);
|
||||
mu_run_test(test_blk2bstr);
|
||||
mu_run_test(test_bstrcpy);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
@@ -0,0 +1,78 @@
|
||||
#include "../minunit.h"
|
||||
#include <lcthw/darray_algos.h>
|
||||
|
||||
int testcmp(char **a, char **b)
|
||||
{
|
||||
return strcmp(*a, *b);
|
||||
}
|
||||
|
||||
DArray *create_words()
|
||||
{
|
||||
DArray *result = DArray_create(0, 5);
|
||||
char *words[] = {"asdfasfd", "werwar", "13234", "asdfasfd", "oioj"};
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < 5; i++) {
|
||||
DArray_push(result, words[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int is_sorted(DArray *array)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i = 0; i < DArray_count(array) - 1; i++) {
|
||||
if(strcmp(DArray_get(array, i), DArray_get(array, i+1)) > 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *run_sort_test(int (*func)(DArray *, DArray_compare), const char *name)
|
||||
{
|
||||
DArray *words = create_words();
|
||||
mu_assert(!is_sorted(words), "Words should start not sorted.");
|
||||
|
||||
name = name;
|
||||
debug("--- Testing %s sorting algorithm", name);
|
||||
int rc = func(words, (DArray_compare)testcmp);
|
||||
mu_assert(rc == 0, "sort failed");
|
||||
mu_assert(is_sorted(words), "didn't sort it");
|
||||
|
||||
DArray_destroy(words);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_qsort()
|
||||
{
|
||||
return run_sort_test(DArray_qsort, "qsort");
|
||||
}
|
||||
|
||||
char *test_heapsort()
|
||||
{
|
||||
return run_sort_test(DArray_heapsort, "heapsort");
|
||||
}
|
||||
|
||||
char *test_mergesort()
|
||||
{
|
||||
return run_sort_test(DArray_mergesort, "mergesort");
|
||||
}
|
||||
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
|
||||
mu_run_test(test_qsort);
|
||||
mu_run_test(test_heapsort);
|
||||
mu_run_test(test_mergesort);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
124
oldstuff/lcthw-remnants-2/liblcthw/tests/lcthw/darray_tests.c
Normal file
124
oldstuff/lcthw-remnants-2/liblcthw/tests/lcthw/darray_tests.c
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "../minunit.h"
|
||||
#include <lcthw/darray.h>
|
||||
|
||||
static DArray *array = NULL;
|
||||
static int *val1 = NULL;
|
||||
static int *val2 = NULL;
|
||||
|
||||
char *test_create()
|
||||
{
|
||||
array = DArray_create(sizeof(int), 100);
|
||||
mu_assert(array != NULL, "DArray_create failed.");
|
||||
mu_assert(array->contents != NULL, "contents are wrong in darray");
|
||||
mu_assert(array->end == 0, "end isn't at the right spot");
|
||||
mu_assert(array->element_size == sizeof(int), "element size is wrong.");
|
||||
mu_assert(array->max == 100, "wrong max length on initial size");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_destroy()
|
||||
{
|
||||
DArray_destroy(array);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_new()
|
||||
{
|
||||
val1 = DArray_new(array);
|
||||
mu_assert(val1 != NULL, "failed to make a new element");
|
||||
|
||||
val2 = DArray_new(array);
|
||||
mu_assert(val2 != NULL, "failed to make a new element");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_set()
|
||||
{
|
||||
DArray_set(array, 0, val1);
|
||||
DArray_set(array, 1, val2);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_get()
|
||||
{
|
||||
mu_assert(DArray_get(array, 0) == val1, "Wrong first value.");
|
||||
mu_assert(DArray_get(array, 1) == val2, "Wrong second value.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_remove()
|
||||
{
|
||||
int *val_check = DArray_remove(array, 0);
|
||||
mu_assert(val_check != NULL, "Should not get NULL.");
|
||||
mu_assert(*val_check == *val1, "Should get the first value.");
|
||||
mu_assert(DArray_get(array, 0) == NULL, "Should be gone.");
|
||||
DArray_free(val_check);
|
||||
|
||||
val_check = DArray_remove(array, 1);
|
||||
mu_assert(val_check != NULL, "Should not get NULL.");
|
||||
mu_assert(*val_check == *val2, "Should get the second value.");
|
||||
mu_assert(DArray_get(array, 1) == NULL, "Should be gone.");
|
||||
DArray_free(val_check);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_expand_contract()
|
||||
{
|
||||
int old_max = array->max;
|
||||
DArray_expand(array);
|
||||
mu_assert((unsigned int)array->max == old_max + array->expand_rate, "Wrong size after expand.");
|
||||
|
||||
DArray_contract(array);
|
||||
mu_assert((unsigned int)array->max == array->expand_rate + 1, "Should stay at the expand_rate at least.");
|
||||
|
||||
DArray_contract(array);
|
||||
mu_assert((unsigned int)array->max == array->expand_rate + 1, "Should stay at the expand_rate at least.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_push_pop()
|
||||
{
|
||||
int i = 0;
|
||||
for(i = 0; i < 1000; i++) {
|
||||
int *val = DArray_new(array);
|
||||
*val = i * 333;
|
||||
DArray_push(array, val);;
|
||||
}
|
||||
|
||||
mu_assert(array->max == 1201, "Wrong max size.");
|
||||
|
||||
for(i = 999; i >= 0; i--) {
|
||||
int *val = DArray_pop(array);
|
||||
mu_assert(val != NULL, "Shouldn't get a NULL.");
|
||||
mu_assert(*val == i * 333, "Wrong value.");
|
||||
DArray_free(val);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
|
||||
mu_run_test(test_create);
|
||||
mu_run_test(test_new);
|
||||
mu_run_test(test_set);
|
||||
mu_run_test(test_get);
|
||||
mu_run_test(test_remove);
|
||||
mu_run_test(test_expand_contract);
|
||||
mu_run_test(test_push_pop);
|
||||
mu_run_test(test_destroy);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
@@ -0,0 +1,91 @@
|
||||
#include "../minunit.h"
|
||||
#include <lcthw/list_algos.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
char *values[] = {"XXXX", "1234", "abcd", "xjvef", "NDSS"};
|
||||
#define NUM_VALUES 5
|
||||
|
||||
List *create_words()
|
||||
{
|
||||
int i = 0;
|
||||
List *words = List_create();
|
||||
|
||||
for(i = 0; i < NUM_VALUES; i++) {
|
||||
List_push(words, values[i]);
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
int is_sorted(List *words)
|
||||
{
|
||||
LIST_FOREACH(words, first, next, cur) {
|
||||
if(cur->next && strcmp(cur->value, cur->next->value) > 0) {
|
||||
debug("%s %s", (char *)cur->value, (char *)cur->next->value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *test_bubble_sort()
|
||||
{
|
||||
List *words = create_words();
|
||||
|
||||
// should work on a list that needs sorting
|
||||
int rc = List_bubble_sort(words, (List_compare)strcmp);
|
||||
mu_assert(rc == 0, "Bubble sort failed.");
|
||||
mu_assert(is_sorted(words), "Words are not sorted after bubble sort.");
|
||||
|
||||
// should work on an already sorted list
|
||||
rc = List_bubble_sort(words, (List_compare)strcmp);
|
||||
mu_assert(rc == 0, "Bubble sort of already sorted failed.");
|
||||
mu_assert(is_sorted(words), "Words should be sorted if already bubble sorted.");
|
||||
|
||||
List_destroy(words);
|
||||
|
||||
// should work on an empty list
|
||||
words = List_create();
|
||||
rc = List_bubble_sort(words, (List_compare)strcmp);
|
||||
mu_assert(rc == 0, "Bubble sort failed on empty list.");
|
||||
mu_assert(is_sorted(words), "Words should be sorted if empty.");
|
||||
|
||||
List_destroy(words);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_merge_sort()
|
||||
{
|
||||
List *words = create_words();
|
||||
|
||||
// should work on a list that needs sorting
|
||||
List *res = List_merge_sort(words, (List_compare)strcmp);
|
||||
mu_assert(List_count(res) == List_count(words), "Sorted list has different count.");
|
||||
mu_assert(is_sorted(res), "Words are not sorted after merge sort.");
|
||||
|
||||
List *res2 = List_merge_sort(res, (List_compare)strcmp);
|
||||
mu_assert(List_count(res2) == List_count(res), "Sorted list has different count.");
|
||||
mu_assert(is_sorted(res), "Should still be sorted after merge sort.");
|
||||
|
||||
List_destroy(res2);
|
||||
List_destroy(res);
|
||||
|
||||
List_destroy(words);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
|
||||
mu_run_test(test_bubble_sort);
|
||||
mu_run_test(test_merge_sort);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
205
oldstuff/lcthw-remnants-2/liblcthw/tests/lcthw/list_tests.c
Normal file
205
oldstuff/lcthw-remnants-2/liblcthw/tests/lcthw/list_tests.c
Normal file
@@ -0,0 +1,205 @@
|
||||
#include "../minunit.h"
|
||||
#include <lcthw/list.h>
|
||||
#include <assert.h>
|
||||
|
||||
static List *list = NULL;
|
||||
char *test1 = "test1 data";
|
||||
char *test2 = "test2 data";
|
||||
char *test3 = "test3 data";
|
||||
char *test4 = "test4 data";
|
||||
|
||||
|
||||
char *test_create()
|
||||
{
|
||||
list = List_create();
|
||||
mu_assert(list != NULL, "Failed to create list.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *test_destroy()
|
||||
{
|
||||
List_clear_destroy(list);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *test_push_pop()
|
||||
{
|
||||
List_push(list, test1);
|
||||
mu_assert(List_last(list) == test1, "Wrong last value.");
|
||||
|
||||
List_push(list, test2);
|
||||
mu_assert(List_last(list) == test2, "Wrong last value");
|
||||
|
||||
List_push(list, test3);
|
||||
mu_assert(List_last(list) == test3, "Wrong last value");
|
||||
mu_assert(List_count(list) == 3, "Wrong count on push.");
|
||||
|
||||
char *val = List_pop(list);
|
||||
mu_assert(val == test3, "Wrong value on pop.");
|
||||
|
||||
val = List_pop(list);
|
||||
mu_assert(val == test2, "Wrong value on pop.");
|
||||
|
||||
val = List_pop(list);
|
||||
mu_assert(val == test1, "Wrong value on pop.");
|
||||
mu_assert(List_count(list) == 0, "Wrong count after pop.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_unshift()
|
||||
{
|
||||
List_unshift(list, test1);
|
||||
mu_assert(List_first(list) == test1, "Wrong first value.");
|
||||
|
||||
List_unshift(list, test2);
|
||||
mu_assert(List_first(list) == test2, "Wrong first value.");
|
||||
|
||||
List_unshift(list, test3);
|
||||
mu_assert(List_first(list) == test3, "Wrong first value.");
|
||||
mu_assert(List_count(list) == 3, "Wrong count on unshift.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *test_remove()
|
||||
{
|
||||
// we only need to test the middle remove case since push/shift
|
||||
// already tests the other cases
|
||||
|
||||
char *val = List_remove(list, list->first->next);
|
||||
mu_assert(val == test2, "Wrong removed element.");
|
||||
mu_assert(List_count(list) == 2, "Wrong count after remove.");
|
||||
mu_assert(List_first(list) == test3, "Wrong first after remove.");
|
||||
mu_assert(List_last(list) == test1, "Wrong last after remove.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *test_shift()
|
||||
{
|
||||
mu_assert(List_count(list) != 0, "Wrong count before shift.");
|
||||
|
||||
char *val = List_shift(list);
|
||||
mu_assert(val == test3, "Wrong value on shift.");
|
||||
|
||||
val = List_shift(list);
|
||||
mu_assert(val == test1, "Wrong value on shift.");
|
||||
mu_assert(List_count(list) == 0, "Wrong count after shift.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *test_copy()
|
||||
{
|
||||
list = List_create();
|
||||
|
||||
mu_assert(List_count(list) == 0, "Wrong count before copy.");
|
||||
List_push(list, test1);
|
||||
List_push(list, test2);
|
||||
List_push(list, test3);
|
||||
List_push(list, test4);
|
||||
|
||||
mu_assert(List_count(list) == 4, "Wrong count after push.");
|
||||
|
||||
List *copy = List_copy(list);
|
||||
mu_assert(copy != list, "Copy and list have same address.");
|
||||
mu_assert(List_count(copy) == 4, "Copy has wrong count.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *test_split()
|
||||
{
|
||||
mu_assert(List_count(list) == 4, "Wrong count before split.");
|
||||
|
||||
List *a = List_create();
|
||||
List *b = List_create();
|
||||
List *tmp = List_copy(list);
|
||||
|
||||
int rc = -1;
|
||||
rc = List_split(tmp, test2, a, b);
|
||||
mu_assert(rc == 0, "Failed to split.");
|
||||
mu_assert(List_count(a) == 2, "List 'a' has wrong count.");
|
||||
mu_assert(List_count(b) == 2, "List 'b' has wrong count.");
|
||||
|
||||
List_destroy(a);
|
||||
List_destroy(b);
|
||||
|
||||
a = List_create();
|
||||
b = List_create();
|
||||
tmp = List_copy(list);
|
||||
|
||||
rc = List_split(tmp, test1, a, b);
|
||||
mu_assert(rc == 0, "Failed to split.");
|
||||
mu_assert(List_count(a) == 1, "List 'a' has wrong count.");
|
||||
mu_assert(List_count(b) == 3, "List 'b' has wrong count.");
|
||||
|
||||
List_destroy(a);
|
||||
List_destroy(b);
|
||||
|
||||
a = List_create();
|
||||
b = List_create();
|
||||
tmp = List_copy(list);
|
||||
|
||||
rc = List_split(tmp, test3, a, b);
|
||||
mu_assert(rc == 0, "Failed to split.");
|
||||
mu_assert(List_count(a) == 3, "List 'a' has wrong count.");
|
||||
mu_assert(List_count(b) == 1, "List 'b' has wrong count.");
|
||||
|
||||
List_destroy(a);
|
||||
List_destroy(b);
|
||||
|
||||
a = List_create();
|
||||
b = List_create();
|
||||
tmp = List_copy(list);
|
||||
|
||||
rc = List_split(tmp, test4, a, b);
|
||||
mu_assert(rc == 0, "Failed to split.");
|
||||
mu_assert(List_count(a) == 4, "List 'a' has wrong count.");
|
||||
mu_assert(List_count(b) == 0, "List 'b' has wrong count.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *test_join()
|
||||
{
|
||||
mu_assert(List_count(list) == 4, "Wrong count before join.");
|
||||
|
||||
List *b = List_create();
|
||||
List_push(b, test4);
|
||||
mu_assert(List_count(b) == 1, "List 'b' has wrong count.");
|
||||
|
||||
List_join(list, b);
|
||||
mu_assert(List_count(list) == 5, "Wrong count after join.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *all_tests() {
|
||||
mu_suite_start();
|
||||
|
||||
mu_run_test(test_create);
|
||||
mu_run_test(test_push_pop);
|
||||
mu_run_test(test_unshift);
|
||||
mu_run_test(test_remove);
|
||||
mu_run_test(test_shift);
|
||||
mu_run_test(test_destroy);
|
||||
mu_run_test(test_copy);
|
||||
mu_run_test(test_split);
|
||||
mu_run_test(test_join);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
105
oldstuff/lcthw-remnants-2/liblcthw/tests/lcthw/radixmap_tests.c
Normal file
105
oldstuff/lcthw-remnants-2/liblcthw/tests/lcthw/radixmap_tests.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "../minunit.h"
|
||||
#include <stdint.h>
|
||||
#include <lcthw/radixmap.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
static int make_random(RadixMap *map)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for(i = 0; i < map->max - 1; i++) {
|
||||
uint32_t key = (uint32_t)(rand() | (rand() << 16));
|
||||
check(RadixMap_add(map, key, i) == 0, "Failed to add key %u", key);
|
||||
}
|
||||
|
||||
return i;
|
||||
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_order(RadixMap *map)
|
||||
{
|
||||
RMElement d1, d2;
|
||||
unsigned int i = 0;
|
||||
|
||||
// only signal errors if any (should not be)
|
||||
for(i = 0; map->end > 0 && i < map->end-1; i++) {
|
||||
d1 = map->contents[i];
|
||||
d2 = map->contents[i+1];
|
||||
|
||||
if(d1.data.key > d2.data.key) {
|
||||
debug("FAIL:i=%u, key: %u, value: %u, equals max? %d\n", i, d1.data.key, d1.data.value,
|
||||
d2.data.key == UINT32_MAX);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_search(RadixMap *map)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
RMElement *d = NULL;
|
||||
RMElement *found = NULL;
|
||||
|
||||
for(i = map->end / 2; i < map->end; i++) {
|
||||
d = &map->contents[i];
|
||||
found = RadixMap_find(map, d->data.key);
|
||||
check(found != NULL, "Didn't find %u at %u.", d->data.key, i);
|
||||
check(found->data.key == d->data.key, "Got the wrong result: %p:%u looking for %u at %u",
|
||||
found, found->data.key, d->data.key, i);
|
||||
}
|
||||
|
||||
return 1;
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// test for big number of elements
|
||||
static char *test_operations()
|
||||
{
|
||||
size_t N = 200;
|
||||
|
||||
RadixMap *map = RadixMap_create(N);
|
||||
mu_assert(map != NULL, "Failed to make the map.");
|
||||
mu_assert(make_random(map), "Didn't make a random fake radix map.");
|
||||
|
||||
RadixMap_sort(map);
|
||||
mu_assert(check_order(map), "Failed to properly sort the RadixMap.");
|
||||
|
||||
mu_assert(test_search(map), "Failed the search test.");
|
||||
mu_assert(check_order(map), "RadixMap didn't stay sorted after search.");
|
||||
|
||||
while(map->end > 0) {
|
||||
RMElement *el = RadixMap_find(map, map->contents[map->end / 2].data.key);
|
||||
mu_assert(el != NULL, "Should get a result.");
|
||||
|
||||
size_t old_end = map->end;
|
||||
|
||||
mu_assert(RadixMap_delete(map, el) == 0, "Didn't delete it.");
|
||||
mu_assert(old_end - 1 == map->end, "Wrong size after delete.");
|
||||
|
||||
// test that the end is now the old value, but uint32 max so it trails off
|
||||
mu_assert(check_order(map), "RadixMap didn't stay sorted after delete.");
|
||||
}
|
||||
|
||||
RadixMap_destroy(map);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
srand(time(NULL));
|
||||
|
||||
mu_run_test(test_operations);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
38
oldstuff/lcthw-remnants-2/liblcthw/tests/minunit.h
Normal file
38
oldstuff/lcthw-remnants-2/liblcthw/tests/minunit.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#undef DNDEBUG
|
||||
#ifndef _minunit_h
|
||||
#define _minunit_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <lcthw/dbg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define mu_suite_start() char *message = NULL
|
||||
|
||||
#define mu_assert(test, message) if (!(test)) {\
|
||||
log_err(message); return message;\
|
||||
}\
|
||||
assertions_made++;
|
||||
#define mu_run_test(test) debug("\n-----%s", " " #test); \
|
||||
message = test(); tests_run++; if (message) return message;
|
||||
|
||||
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
|
||||
argc = argc; \
|
||||
argv = argv; \
|
||||
debug("----- RUNNING: %s", argv[0]);\
|
||||
printf("----\nRUNNING: %s\n", argv[0]);\
|
||||
char *result = name();\
|
||||
if (result != 0) {\
|
||||
printf("FAILED: %s\n", result);\
|
||||
}\
|
||||
else {\
|
||||
printf("ALL TESTS PASSED\n");\
|
||||
}\
|
||||
printf("Tests run: %d\n", tests_run);\
|
||||
printf("Assertions made: %d\n", assertions_made);\
|
||||
exit(result != 0);\
|
||||
}
|
||||
|
||||
int tests_run;
|
||||
int assertions_made;
|
||||
|
||||
#endif
|
107
oldstuff/lcthw-remnants-2/liblcthw/tests/runtests.c
Normal file
107
oldstuff/lcthw-remnants-2/liblcthw/tests/runtests.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <fnmatch.h>
|
||||
#include <lcthw/dbg.h>
|
||||
|
||||
int test_selector(const struct dirent *ep)
|
||||
{
|
||||
return fnmatch("*_tests", ep->d_name, 0) == 0;
|
||||
}
|
||||
|
||||
int run_tests_file(char *filename)
|
||||
{
|
||||
if(access(filename, R_OK | X_OK) == 0) {
|
||||
return system(filename);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int entcount = 0;
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
int ntests = 0;
|
||||
char *testsdir = NULL;
|
||||
char *valgrind = getenv("VALGRIND");
|
||||
struct dirent **namelist = NULL;
|
||||
struct dirent *ep = NULL;
|
||||
|
||||
if(argc > 1) {
|
||||
testsdir = argv[1];
|
||||
}
|
||||
|
||||
if(!testsdir) {
|
||||
testsdir = getenv("TESTS");
|
||||
}
|
||||
|
||||
if(!testsdir) {
|
||||
testsdir = "./tests";
|
||||
}
|
||||
|
||||
entcount = scandir((const char *)testsdir, &namelist, test_selector, alphasort);
|
||||
check(entcount > -1, "Failed to scan tests dir");
|
||||
|
||||
for(i = 0; i < entcount; i++) {
|
||||
ep = namelist[i];
|
||||
check(ep, "Dirent is missing.");
|
||||
|
||||
char filename[256];
|
||||
rc = sprintf(filename, "%s/%s", testsdir, ep->d_name);
|
||||
check(rc > -1, "Failed to build filename.");
|
||||
debug("Found filename '%s'", filename);
|
||||
|
||||
free(ep);
|
||||
|
||||
if(valgrind) {
|
||||
char command[1024];
|
||||
rc = sprintf(command, "%s %s", valgrind, filename);
|
||||
check(rc > -1, "Failed to build command with valgrind.");
|
||||
rc = run_tests_file(command);
|
||||
} else {
|
||||
rc = run_tests_file(filename);
|
||||
}
|
||||
|
||||
if(rc > 0) {
|
||||
debug("Skipping '%s'", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
ntests++;
|
||||
|
||||
if(rc == 0) {
|
||||
printf("%s PASS\n", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("ERROR in test %s", filename);
|
||||
if(access("tests/tests.log", R_OK) == 0) {
|
||||
printf(": here's tests/tests.log\n");
|
||||
printf("------\n");
|
||||
rc = system("tail tests/tests.log");
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("------\n");
|
||||
printf("Total of %d test file%s run.\n", ntests, ntests > 1 ? "s" : "");
|
||||
|
||||
if(namelist) {
|
||||
free(namelist);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(namelist) {
|
||||
free(namelist);
|
||||
}
|
||||
|
||||
return rc != 0 ? rc : 1;
|
||||
}
|
3
oldstuff/lcthw-remnants-2/list-exercises
Executable file
3
oldstuff/lcthw-remnants-2/list-exercises
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
grep -lE '^int main' *.c | sed 's/\.c//'
|
71
oldstuff/lcthw-remnants-2/object.c
Normal file
71
oldstuff/lcthw-remnants-2/object.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "object.h"
|
||||
#include <assert.h>
|
||||
|
||||
void Object_destroy(void *self)
|
||||
{
|
||||
Object *obj = self;
|
||||
|
||||
if(obj) {
|
||||
if(obj->description) free(obj->description);
|
||||
free(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void Object_describe(void *self)
|
||||
{
|
||||
assert(self != NULL);
|
||||
Object *obj = self;
|
||||
printf("%s.\n", obj->description);
|
||||
}
|
||||
|
||||
int Object_init(void *self)
|
||||
{
|
||||
// do nothing really
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *Object_move(void *self, Direction direction)
|
||||
{
|
||||
printf("You can't go that direction.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Object_attack(void *self, int damage)
|
||||
{
|
||||
printf("You can't attack that.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *Object_new(size_t size, Object proto, char *description)
|
||||
{
|
||||
assert(description != NULL);
|
||||
|
||||
// setup the default functions in case they aren't set
|
||||
if(!proto.init) proto.init = Object_init;
|
||||
if(!proto.describe) proto.describe = Object_describe;
|
||||
if(!proto.destroy) proto.destroy = Object_destroy;
|
||||
if(!proto.attack) proto.attack = Object_attack;
|
||||
if(!proto.move) proto.move = Object_move;
|
||||
|
||||
// this seems weird, but we can make a struct of one size,
|
||||
// then point a different pointer at it to "cast" it
|
||||
Object *el = calloc(1, size);
|
||||
assert(el != NULL);
|
||||
*el = proto;
|
||||
|
||||
// copy the description over
|
||||
el->description = strdup(description);
|
||||
|
||||
// initialize it with whatever init we were given
|
||||
if(!el->init(el)) {
|
||||
// looks like it didn't initialize properly
|
||||
el->destroy(el);
|
||||
return NULL;
|
||||
} else {
|
||||
// all done, we made an object of any type
|
||||
return el;
|
||||
}
|
||||
}
|
27
oldstuff/lcthw-remnants-2/object.h
Normal file
27
oldstuff/lcthw-remnants-2/object.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _object_h
|
||||
#define _object_h
|
||||
|
||||
typedef enum {
|
||||
NORTH, SOUTH, EAST, WEST
|
||||
} Direction;
|
||||
|
||||
typedef struct {
|
||||
char *description;
|
||||
int (*init)(void *self);
|
||||
void (*describe)(void *self);
|
||||
void (*destroy)(void *self);
|
||||
void *(*move)(void *self, Direction direction);
|
||||
int (*attack)(void *self, int damage);
|
||||
} Object;
|
||||
|
||||
int Object_init(void *self);
|
||||
void Object_destroy(void *self);
|
||||
void Object_describe(void *self);
|
||||
void *Object_move(void *self, Direction direction);
|
||||
int Object_attack(void *self, int damage);
|
||||
void *Object_new(size_t size, Object proto, char *description);
|
||||
|
||||
#define NEW(T, N) Object_new(sizeof(T), T##Proto, N)
|
||||
#define _(N) proto.N
|
||||
|
||||
#endif
|
47
oldstuff/lcthw-remnants-2/runtests
Executable file
47
oldstuff/lcthw-remnants-2/runtests
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
[[ $DEBUG ]] && set -x
|
||||
|
||||
test_ex17-ec() {
|
||||
local testdb=$(mktemp /var/tmp/XXXXXXX.dat)
|
||||
trap "rm ${testdb}" EXIT INT TERM
|
||||
./ex17-ec "${testdb}" c
|
||||
./ex17-ec "${testdb}" l &>/dev/null
|
||||
./ex17-ec "${testdb}" s 1 nancy pwnr@dungeon.info "Dark corner"
|
||||
./ex17-ec "${testdb}" s 2 fran eagleeye16@hotmail.com "Falcon's nest"
|
||||
./ex17-ec "${testdb}" l &>/dev/null
|
||||
./ex17-ec "${testdb}" d 1
|
||||
./ex17-ec "${testdb}" s 1 portia wanda@aeromar.mx "Fancy town"
|
||||
./ex17-ec "${testdb}" f nest &>/dev/null
|
||||
}
|
||||
|
||||
test_ex18() {
|
||||
local output=$(./ex18 4 1 7 3 2 0 8)
|
||||
[[ "${output}" =~ '0 1 2 3 4 7 8' ]]
|
||||
[[ "${output}" =~ '8 7 4 3 2 1 0' ]]
|
||||
[[ "${output}" =~ '3 4 2 7 1 0 8' ]]
|
||||
}
|
||||
|
||||
test_ex19() {
|
||||
printf "l\nn\nl\ne\nw\nw\nl\na\na\na\na\na\na\na\na\na\na\n" \
|
||||
| ./ex19 &>/dev/null
|
||||
printf "l\nl\nl\nl\na\na\nx\nq\nz\nn\n" | ./ex19 &>/dev/null
|
||||
for i in {0..20} ; do
|
||||
echo "${RANDOM}" | md5sum | ./ex19 &>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
for ex in $(./list-exercises) ; do
|
||||
func_name="test_${ex}"
|
||||
if type "${func_name}" &>/dev/null ; then
|
||||
echo -en "---> ${ex}: "
|
||||
"${func_name}"
|
||||
echo "OK"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
main "$@"
|
Reference in New Issue
Block a user