Add 'lcthw-remnants/' from commit 'e172f73c8297b22a579c94558f0c171ca74a0e5c'

git-subtree-dir: lcthw-remnants
git-subtree-mainline: 4107485591
git-subtree-split: e172f73c82
This commit is contained in:
Dan Buch 2013-01-09 23:42:19 -05:00
commit f2380eef05
69 changed files with 7046 additions and 0 deletions

37
lcthw-remnants/.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
*.dat
ex1
ex10
ex11
ex12
ex13
ex14
ex15
ex16
ex17
ex17-*
!ex17-*.c
ex18
ex19
ex20
ex21
ex22_ec1
ex22_main
ex23
ex24
ex24_iofunctions01
ex24_iofunctions02
ex24_iofunctions03
ex24_iofunctions04
ex24_iofunctions05
ex24_iofunctions06
ex25
ex3
ex4
ex5
ex6
ex7
ex8
ex9
.exrc
.rvmrc
valgrind-*

22
lcthw-remnants/Makefile Normal file
View File

@ -0,0 +1,22 @@
CFLAGS += -Wall -Wextra -pedantic -std=gnu99 -g -DNDEBUG
EXERCISES = $(patsubst %.c,%,$(shell ls ex*.c | egrep -v "ex(19|22)"))
all: $(EXERCISES)
$(MAKE) -f ex19.mk
$(MAKE) -f ex22.mk
test: all
$(MAKE) -f ex19.mk test
./test_ex24_iofunctions.sh
clean:
rm -f $(EXERCISES)
$(MAKE) -f ex19.mk clean
$(MAKE) -f ex22.mk clean
.PHONY: all test clean

2
lcthw-remnants/README.md Normal file
View File

@ -0,0 +1,2 @@
Zed asked for folks to work through <a href="http://c.learncodethehardway.org/">
<q>Learn C The Hard Way</q></a> and provide feedback, so that's what I'm doing.

View File

@ -0,0 +1,39 @@
#!/bin/bash
set -e
# go somewhere safe
cd /tmp
# get the source to base APR 1.4.5
curl -L -O http://download.nextag.com/apache/apr/apr-1.4.5.tar.gz
# extract it and go into the source
tar -xzvf apr-1.4.5.tar.gz
cd apr-1.4.5
# configure, make, make install
./configure
make
sudo make install
# reset
cd /tmp
# do the same with apr-util
curl -L -O http://download.nextag.com/apache/apr/apr-util-1.3.12.tar.gz
# extract
tar -xzvf apr-util-1.3.12.tar.gz
cd apr-util-1.3.12
# 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 -rvf apr-util-1.3.12* apr-1.4.5*

View File

@ -0,0 +1,10 @@
from __future__ import print_function
import os
import sys
argc = int(sys.argv[1]) if sys.argv[1:] else 23694
command = "valgrind ./ex10 " + " ".join(map(str, range(argc)))
print("command = {0}".format(command))
os.system(command)

View File

@ -0,0 +1,11 @@
def main
ex25 = IO.popen("./ex25", "w+")
ex25.write("z" * 10000)
ex25.flush
puts ex25.readlines.join("\n")
end
if $0 == __FILE__
main
end

View File

@ -0,0 +1,6 @@
#!/bin/bash
for func in $(cat iofunctions.txt)
do
echo "$func: $(grep "$func" *.c | wc -l)"
done

40
lcthw-remnants/dbg.h Normal file
View File

@ -0,0 +1,40 @@
#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__, __FUNCTION__, ##__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__, __FUNCTION__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) \
fprintf(stderr, "[WARN] (%s:%d:[%s]: errno: %s) " M "\n", \
__FILE__, __LINE__, __FUNCTION__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) \
fprintf(stderr, "[INFO] (%s:%d:[%s]: errno: %s) " M "\n", \
__FILE__, __LINE__, __FUNCTION__, clean_errno(), ##__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

1
lcthw-remnants/devpkg/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
devpkg

View File

@ -0,0 +1,16 @@
PREFIX?=/usr/local
CFLAGS=-g -Wall -I${PREFIX}/apr/include/apr-1 -D_LARGEFILE64_SOURCE
LDFLAGS=-L${PREFIX}/apr/lib -lapr-1 -pthread -laprutil-1
all: devpkg
devpkg: bstrlib.o db.o shell.o commands.o
install: all
install -d $(DESTDIR)/$(PREFIX)/bin/
install devpkg $(DESTDIR)/$(PREFIX)/bin/
clean:
rm -f *.o
rm -f devpkg
rm -rf *.dSYM

View File

View File

@ -0,0 +1,7 @@
#include <apr_errno.h>
int main(int argc, char *argv[])
{
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,304 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
* for details on usage and license.
*/
/*
* bstrlib.h
*
* This file is the header file for the core module for implementing the
* bstring functions.
*/
#ifndef BSTRLIB_INCLUDE
#define BSTRLIB_INCLUDE
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
# if defined (__TURBOC__) && !defined (__BORLANDC__)
# define BSTRLIB_NOVSNP
# endif
#endif
#define BSTR_ERR (-1)
#define BSTR_OK (0)
#define BSTR_BS_BUFF_LENGTH_GET (0)
typedef struct tagbstring * bstring;
typedef const struct tagbstring * const_bstring;
/* Copy functions */
#define cstr2bstr bfromcstr
extern bstring bfromcstr (const char * str);
extern bstring bfromcstralloc (int mlen, const char * str);
extern bstring blk2bstr (const void * blk, int len);
extern char * bstr2cstr (const_bstring s, char z);
extern int bcstrfree (char * s);
extern bstring bstrcpy (const_bstring b1);
extern int bassign (bstring a, const_bstring b);
extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
extern int bassigncstr (bstring a, const char * str);
extern int bassignblk (bstring a, const void * s, int len);
/* Destroy function */
extern int bdestroy (bstring b);
/* Space allocation hinting functions */
extern int balloc (bstring s, int len);
extern int ballocmin (bstring b, int len);
/* Substring extraction */
extern bstring bmidstr (const_bstring b, int left, int len);
/* Various standard manipulations */
extern int bconcat (bstring b0, const_bstring b1);
extern int bconchar (bstring b0, char c);
extern int bcatcstr (bstring b, const char * s);
extern int bcatblk (bstring b, const void * s, int len);
extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
extern int bdelete (bstring s1, int pos, int len);
extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
extern int btrunc (bstring b, int n);
/* Scan/search functions */
extern int bstricmp (const_bstring b0, const_bstring b1);
extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
extern int biseqcaseless (const_bstring b0, const_bstring b1);
extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
extern int biseq (const_bstring b0, const_bstring b1);
extern int bisstemeqblk (const_bstring b0, const void * blk, int len);
extern int biseqcstr (const_bstring b, const char * s);
extern int biseqcstrcaseless (const_bstring b, const char * s);
extern int bstrcmp (const_bstring b0, const_bstring b1);
extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
extern int binstr (const_bstring s1, int pos, const_bstring s2);
extern int binstrr (const_bstring s1, int pos, const_bstring s2);
extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
extern int bstrchrp (const_bstring b, int c, int pos);
extern int bstrrchrp (const_bstring b, int c, int pos);
#define bstrchr(b,c) bstrchrp ((b), (c), 0)
#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1)
extern int binchr (const_bstring b0, int pos, const_bstring b1);
extern int binchrr (const_bstring b0, int pos, const_bstring b1);
extern int bninchr (const_bstring b0, int pos, const_bstring b1);
extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos);
extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos);
/* List of string container functions */
struct bstrList {
int qty, mlen;
bstring * entry;
};
extern struct bstrList * bstrListCreate (void);
extern int bstrListDestroy (struct bstrList * sl);
extern int bstrListAlloc (struct bstrList * sl, int msz);
extern int bstrListAllocMin (struct bstrList * sl, int msz);
/* String split and join functions */
extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar);
extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr);
extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr);
extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
/* Miscellaneous functions */
extern int bpattern (bstring b, int len);
extern int btoupper (bstring b);
extern int btolower (bstring b);
extern int bltrimws (bstring b);
extern int brtrimws (bstring b);
extern int btrimws (bstring b);
/* <*>printf format functions */
#if !defined (BSTRLIB_NOVSNP)
extern bstring bformat (const char * fmt, ...);
extern int bformata (bstring b, const char * fmt, ...);
extern int bassignformat (bstring b, const char * fmt, ...);
extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
#define bvformata(ret, b, fmt, lastarg) { \
bstring bstrtmp_b = (b); \
const char * bstrtmp_fmt = (fmt); \
int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
for (;;) { \
va_list bstrtmp_arglist; \
va_start (bstrtmp_arglist, lastarg); \
bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
va_end (bstrtmp_arglist); \
if (bstrtmp_r >= 0) { /* Everything went ok */ \
bstrtmp_r = BSTR_OK; \
break; \
} else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
bstrtmp_r = BSTR_ERR; \
break; \
} \
bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
} \
ret = bstrtmp_r; \
}
#endif
typedef int (*bNgetc) (void *parm);
typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm);
/* Input functions */
extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
extern bstring bread (bNread readPtr, void * parm);
extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
extern int breada (bstring b, bNread readPtr, void * parm);
/* Stream functions */
extern struct bStream * bsopen (bNread readPtr, void * parm);
extern void * bsclose (struct bStream * s);
extern int bsbufflength (struct bStream * s, int sz);
extern int bsreadln (bstring b, struct bStream * s, char terminator);
extern int bsreadlns (bstring r, struct bStream * s, const_bstring term);
extern int bsread (bstring b, struct bStream * s, int n);
extern int bsreadlna (bstring b, struct bStream * s, char terminator);
extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term);
extern int bsreada (bstring b, struct bStream * s, int n);
extern int bsunread (struct bStream * s, const_bstring b);
extern int bspeek (bstring r, const struct bStream * s);
extern int bssplitscb (struct bStream * s, const_bstring splitStr,
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
extern int bseof (const struct bStream * s);
struct tagbstring {
int mlen;
int slen;
unsigned char * data;
};
/* Accessor macros */
#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen))
#define blength(b) (blengthe ((b), 0))
#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o))
#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0))
#define bdatae(b, e) (bdataofse (b, 0, e))
#define bdata(b) (bdataofs (b, 0))
#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e))
#define bchar(b, p) bchare ((b), (p), '\0')
/* Static constant string initialization macro */
#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
#if defined(_MSC_VER)
/* There are many versions of MSVC which emit __LINE__ as a non-constant. */
# define bsStatic(q) bsStaticMlen(q,-32)
#endif
#ifndef bsStatic
# define bsStatic(q) bsStaticMlen(q,-__LINE__)
#endif
/* Static constant block parameter pair */
#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1)
/* Reference building macros */
#define cstr2tbstr btfromcstr
#define btfromcstr(t,s) { \
(t).data = (unsigned char *) (s); \
(t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \
(t).mlen = -1; \
}
#define blk2tbstr(t,s,l) { \
(t).data = (unsigned char *) (s); \
(t).slen = l; \
(t).mlen = -1; \
}
#define btfromblk(t,s,l) blk2tbstr(t,s,l)
#define bmid2tbstr(t,b,p,l) { \
const_bstring bstrtmp_s = (b); \
if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \
int bstrtmp_left = (p); \
int bstrtmp_len = (l); \
if (bstrtmp_left < 0) { \
bstrtmp_len += bstrtmp_left; \
bstrtmp_left = 0; \
} \
if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \
bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \
if (bstrtmp_len <= 0) { \
(t).data = (unsigned char *)""; \
(t).slen = 0; \
} else { \
(t).data = bstrtmp_s->data + bstrtmp_left; \
(t).slen = bstrtmp_len; \
} \
} else { \
(t).data = (unsigned char *)""; \
(t).slen = 0; \
} \
(t).mlen = -__LINE__; \
}
#define btfromblkltrimws(t,s,l) { \
int bstrtmp_idx = 0, bstrtmp_len = (l); \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
} \
} \
(t).data = bstrtmp_s + bstrtmp_idx; \
(t).slen = bstrtmp_len - bstrtmp_idx; \
(t).mlen = -__LINE__; \
}
#define btfromblkrtrimws(t,s,l) { \
int bstrtmp_len = (l) - 1; \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_len >= 0; bstrtmp_len--) { \
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
} \
} \
(t).data = bstrtmp_s; \
(t).slen = bstrtmp_len + 1; \
(t).mlen = -__LINE__; \
}
#define btfromblktrimws(t,s,l) { \
int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
} \
for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
} \
} \
(t).data = bstrtmp_s + bstrtmp_idx; \
(t).slen = bstrtmp_len + 1 - bstrtmp_idx; \
(t).mlen = -__LINE__; \
}
/* Write protection macros */
#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; }
#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); }
#define biswriteprotected(t) ((t).mlen <= 0)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,175 @@
#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;
}

View File

@ -0,0 +1,32 @@
#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

124
lcthw-remnants/devpkg/db.c Normal file
View File

@ -0,0 +1,124 @@
#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(const char *path)
{
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(DB_FILE);
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(DB_FILE);
check(data, "Failed to read load: %s", DB_FILE);
printf("%s", bdata(data));
bdestroy(data);
return 0;
error:
return -1;
}

View File

@ -0,0 +1,13 @@
#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

1
lcthw-remnants/devpkg/dbg.h Symbolic link
View File

@ -0,0 +1 @@
../dbg.h

View File

@ -0,0 +1,105 @@
#include <stdio.h>
#include <apr_general.h>
#include <apr_getopt.h>
#include <apr_strings.h>
#include <apr_lib.h>
#include <apr_strings.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;
}

View File

@ -0,0 +1,113 @@
#include "shell.h"
#include "dbg.h"
#include <stdarg.h>
int Shell_exec(Shell template, ...)
{
apr_pool_t *p = NULL;
apr_pool_create(&p, NULL);
va_list argp;
const char *key = NULL;
const char *arg = NULL;
int i = 0;
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
}
}
}
int rc = Shell_run(p, &template);
apr_pool_create(&p, NULL);
va_end(argp);
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}
};

View 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

13
lcthw-remnants/ex1.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
int main()
{
puts("Hello world.");
puts("Hello man.");
puts("Hello to you.");
puts("Hello woman.");
puts("Hello to the world of learning C the hard way, mkay?");
puts("yup.");
return 0;
}

25
lcthw-remnants/ex10.c Normal file
View 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 = 0; 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;
}

41
lcthw-remnants/ex11.c Normal file
View File

@ -0,0 +1,41 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i = 0;
while(i < argc) {
printf("arg %d: %s\n", i, argv[i]);
i++;
}
char *states[] = {
"California", "Oregon",
"Washington", "Texas"
};
int num_states = 4;
i = 0;
while(i < num_states) {
printf("state %d: %s\n", i, states[i]);
i++;
}
i = 0;
size_t l;
while(i < num_states) {
l = strlen((char *)&(argv[i]));
strncpy((char *)&(states[i]), (char *)&(argv[i]), l);
printf("copied %s into state %d\n", states[i], i);
i++;
}
i = 0;
while(i < num_states) {
printf("state %d: %s\n", i, states[i]);
i++;
}
return 0;
}

20
lcthw-remnants/ex12.c Normal file
View File

@ -0,0 +1,20 @@
#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;
}

62
lcthw-remnants/ex13.c Normal file
View File

@ -0,0 +1,62 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "ERROR: You must provide at least one argument.\n");
return 1;
}
int i;
int argn;
char letter;
int up_low_sep = (int)('a' - 'A');
int upper_floor = (int)'A';
int upper_ceil = (int)'Z';
for(argn = 1; argn < argc; argn++) {
for(i = 0; '\0' != (letter = argv[argn][i]); i++) {
int i_letter = (int)letter;
if (upper_floor < i_letter && i_letter < upper_ceil) {
letter = (char)(i_letter + up_low_sep);
}
switch(letter) {
case 'a':
printf("%d: 'a'\n", i);
break;
case 'e':
printf("%d: 'e'\n", i);
break;
case 'i':
printf("%d: 'i'\n", i);
break;
case 'o':
printf("%d: 'o'\n", i);
break;
case 'u':
printf("%d: 'u'\n", i);
break;
case 'y':
if (i > 2) {
printf("%d: 'Y'\n", i);
} else {
printf("%d: 'Y' isn't a vowel this time\n", i);
}
break;
default:
printf("%d: '%c' is not a vowel\n", i, letter);
}
}
}
return 0;
}

35
lcthw-remnants/ex14.c Normal file
View File

@ -0,0 +1,35 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void print_letters(char arg[], int nchars);
void print_arguments(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < argc; i++) {
print_letters(argv[i], strlen(argv[i]));
}
}
void print_letters(char arg[], int nchars)
{
int i = 0;
for (i = 0; i < nchars; i++) {
char ch = arg[i];
if(isalpha(ch) || isblank(ch)) {
printf("'%c' == %d ", ch, ch);
}
}
printf("\n");
}
int main(int argc, char *argv[])
{
print_arguments(argc, argv);
return 0;
}

89
lcthw-remnants/ex15.c Normal file
View File

@ -0,0 +1,89 @@
#include <stdio.h>
void print_with_array_indexing(int count, char **names, int *ages)
{
int i = 0;
// first way using indexing
while(i < count) {
printf("%s has %d years alive.\n",
names[i], ages[i]);
i++;
}
printf("---\n");
}
void print_with_pointer_arithmetic(int count, char **names, int *ages)
{
int i = 0;
// setup the pointers to the start of the arrays
int *cur_age = ages;
char **cur_name = names;
// second way using pointers
while(i < count) {
printf("%s is %d years old.\n",
*(cur_name+i), *(cur_age+i));
i++;
}
printf("---\n");
}
void print_with_pointers_as_arrays(int count, char **names, int *ages)
{
int i = 0;
int *cur_age = ages;
char **cur_name = names;
// third way, pointers are just arrays
while(i < count) {
printf("%s is %d years old again.\n",
cur_name[i], cur_age[i]);
i++;
}
printf("---\n");
}
void print_in_stupidly_complex_way(int count, char **names, int *ages)
{
int *cur_age = ages;
char **cur_name = names;
// fourth way with pointers in a stupid complex way
while((cur_age - ages) < count) {
printf("%s lived %d years so far.\n",
*cur_name++, *cur_age++);
}
printf("---\n");
}
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);
print_with_array_indexing(count, names, ages);
print_with_pointer_arithmetic(count, names, ages);
print_with_pointers_as_arrays(count, names, ages);
print_in_stupidly_complex_way(count, names, ages);
int i;
char **arg = argv;
for(i = 0; i < argc; i++) {
printf("argument %d is '%s' (address = %p)\n", i, *arg, (void *)arg);
arg++;
}
return 0;
}

73
lcthw-remnants/ex16.c Normal file
View 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((char *)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", (void *)joe);
Person_print(joe);
printf("Frank is at memory location %p:\n", (void *)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;
}

239
lcthw-remnants/ex17-ec.c Normal file
View File

@ -0,0 +1,239 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define DEFAULT_MAX_DATA 512
#define DEFAULT_MAX_ROWS 100
struct Address {
int id;
int set;
char *name;
char *email;
};
struct Database {
size_t size;
int max_data;
int max_rows;
struct Address *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\n",
addr->id, addr->name, addr->email);
}
void Database_load(struct Connection *conn)
{
rewind(conn->file);
int rc = fread(&conn->db->max_rows, sizeof(int), 1, conn->file);
if(rc != 1) die("Failed to load database max_rows.", conn);
rc = fread(&conn->db->max_data, sizeof(int), 1, conn->file);
if(rc != 1) die("Failed to load database max_data.", conn);
rc = fread(conn->db->rows, sizeof(struct Address), conn->db->max_rows, conn->file);
if(rc != 1) die("Failed to load database rows.", conn);
}
struct Connection* Database_open(const char *filename, char mode, int max_rows)
{
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);
size_t rowsize = max_rows * sizeof(struct Address);
conn->db->size = rowsize;
conn->db->rows = malloc(rowsize);
if(!conn->db->rows) 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 != NULL) {
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->size, sizeof(size_t), 1, conn->file);
if(rc != 1) die("Failed to write database size.", conn);
rc = fwrite(&conn->db->max_rows, sizeof(int), 1, conn->file);
if(rc != 1) die("Failed to write database max_rows.", conn);
rc = fwrite(&conn->db->max_data, sizeof(int), 1, conn->file);
if(rc != 1) die("Failed to write database max_data.", conn);
rc = fwrite(conn->db->rows, conn->db->size, 1, conn->file);
if(rc != 1) die("Failed to write database rows.", conn);
rc = fflush(conn->file);
if(rc == -1) die("Cannot flush database.", conn);
}
void Database_create(struct Connection *conn, int max_rows, int max_data)
{
int i = 0;
conn->db->max_rows = max_rows;
conn->db->max_data = max_data;
for(i = 0; i < conn->db->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)
{
int max_data = conn->db->max_data;
struct Address *addr = &conn->db->rows[id];
if(addr->set) die("Already set, delete it first", conn);
addr->set = 1;
char *res = strncpy(addr->name, name, max_data);
if(!res) die("Name copy failed", conn);
addr->name[max_data - 1] = '\0';
res = strncpy(addr->email, email, max_data);
if(!res) die("Email copy failed", conn);
addr->email[max_data - 1] = '\0';
}
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 < conn->db->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>[:max_data,max_rows] [action params]", NULL);
char *filename = argv[1];
int max_data = DEFAULT_MAX_DATA;
int max_rows = DEFAULT_MAX_ROWS;
char action = argv[2][0];
if(':' == argv[2][1]) {
sscanf(argv[2], "%c:%d,%d", &action, &max_data, &max_rows);
}
struct Connection *conn = Database_open(filename, action, max_rows);
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, max_rows, max_data);
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 != 6) die("Need id, name, email to set", conn);
Database_set(conn, id, argv[4], argv[5]);
Database_write(conn);
break;
case 'd':
if(argc != 4) die("Need id to delete", conn);
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", conn);
}
Database_close(conn);
return 0;
}

201
lcthw-remnants/ex17-ec1.c Normal file
View File

@ -0,0 +1,201 @@
#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 Database_close(struct Connection *conn);
void die(struct Connection *conn, const char *message)
{
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\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(conn, "Failed to load database.");
}
struct Connection* Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if(!conn) die(NULL, "Memory error");
conn->db = malloc(sizeof(struct Database));
if(!conn->db) die(conn, "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(conn, "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(conn, "Failed to write database.");
rc = fflush(conn->file);
if(rc == -1) die(conn, "Cannot 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(conn, "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(conn, "Name copy failed");
res = strncpy(addr->email, email, MAX_DATA);
if(!res) die(conn, "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(conn, "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(NULL, "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(conn, "There's not that many records.");
switch(action) {
case 'c':
Database_create(conn);
Database_write(conn);
break;
case 'g':
if(argc != 4) die(conn, "Need an id to get");
Database_get(conn, id);
break;
case 's':
if(argc != 6) die(conn, "Need id, name, email to set");
Database_set(conn, id, argv[4], argv[5]);
Database_write(conn);
break;
case 'd':
if(argc != 4) die(conn, "Need id to delete");
Database_delete(conn, id);
Database_write(conn);
break;
case 'l':
Database_list(conn);
break;
default:
die(conn, "Invalid action, only: c=create, g=get, s=set, d=del, l=list");
}
Database_close(conn);
return 0;
}

198
lcthw-remnants/ex17.c Normal file
View 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("Cannot 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;
}

115
lcthw-remnants/ex18.c Normal file
View File

@ -0,0 +1,115 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
void die(const char *message)
{
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}
typedef int (*compare_cb)(int a, int b);
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;
}
}
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("%0x:", 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;
}

241
lcthw-remnants/ex19.c Normal file
View File

@ -0,0 +1,241 @@
#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);
assert(damage > -1);
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);
} else {
printf("mumble mumble.\n");
}
return next;
}
int Room_attack(void *self, int damage)
{
assert(self != NULL);
assert(damage > -1);
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;
} else {
map->location = location;
}
return next;
}
int Map_attack(void *self, int damage)
{
assert(self != NULL);
assert(damage > -1);
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 character 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)
{
printf("\n> ");
char ch = getchar();
int damage = rand() % 4;
switch(ch) {
case EOF:
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);
}
getchar(); // eat ENTER
return 1;
}
int main(int argc, char *argv[])
{
// simple way to setup randomness
srand(time(NULL));
// make our map to work with
Map *game = NEW(Map, "The Hall of the Minotaur.");
printf("You enter the ");
game->location->_(describe)(game->location);
while(process_input(game)) {
}
return 0;
}

54
lcthw-remnants/ex19.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef _ex19_h
#define _ex19_h
#include "object.h"
struct Monster {
Object proto;
int hit_points;
};
typedef struct Monster Monster;
int Monster_attack(void *self, int damage);
int Monster_init(void *self);
struct Room {
Object proto;
Monster *bad_guy;
struct Room *north;
struct Room *south;
struct Room *east;
struct Room *west;
};
typedef struct Room Room;
void *Room_move(void *self, Direction direction);
int Room_attack(void *self, int damage);
int Room_init(void *self);
struct Map {
Object proto;
Room *start;
Room *location;
};
typedef struct Map Map;
void *Map_move(void *self, Direction direction);
int Map_attack(void *self, int damage);
int Map_init(void *self);
#endif

17
lcthw-remnants/ex19.mk Normal file
View File

@ -0,0 +1,17 @@
CFLAGS := -Wall -g
all: ex19
ex19: object.o
test:
./test_ex19.sh
clean:
rm -f ex19 object.o
.PHONY: all test clean

125
lcthw-remnants/ex20.c Normal file
View File

@ -0,0 +1,125 @@
#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;
}

124
lcthw-remnants/ex21.c Normal file
View File

@ -0,0 +1,124 @@
#include <stdint.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("sizeof(int8_t) = %ld\n", sizeof(int8_t));
printf("sizeof(uint8_t) = %ld\n", sizeof(uint8_t));
printf("sizeof(int16_t) = %ld\n", sizeof(int16_t));
printf("sizeof(uint16_t) = %ld\n", sizeof(uint16_t));
printf("sizeof(int32_t) = %ld\n", sizeof(int32_t));
printf("sizeof(uint32_t) = %ld\n", sizeof(uint32_t));
#if defined(_M_X64) || defined(__amd64__)
printf("sizeof(int64_t) = %ld\n", sizeof(int64_t));
printf("sizeof(uint64_t) = %ld\n", sizeof(uint64_t));
#endif
printf("INT8_MAX = %d\n", INT8_MAX);
printf("INT16_MAX = %d\n", INT16_MAX);
printf("INT32_MAX = %d\n", INT32_MAX);
#if defined(_M_X64) || defined(__amd64__)
printf("INT64_MAX = %ld\n", INT64_MAX);
#endif
printf("INT8_MIN = %d\n", INT8_MIN);
printf("INT16_MIN = %d\n", INT16_MIN);
printf("INT32_MIN = %d\n", INT32_MIN);
#if defined(_M_X64) || defined(__amd64__)
printf("INT64_MIN = %ld\n", INT64_MIN);
#endif
printf("sizeof(int_least8_t) = %ld\n", sizeof(int_least8_t));
printf("sizeof(int_least16_t) = %ld\n", sizeof(int_least16_t));
printf("sizeof(int_least32_t) = %ld\n", sizeof(int_least32_t));
#if defined(_M_X64) || defined(__amd64__)
printf("sizeof(int_least64_t) = %ld\n", sizeof(int_least64_t));
#endif
printf("sizeof(uint_least8_t) = %ld\n", sizeof(uint_least8_t));
printf("sizeof(uint_least16_t) = %ld\n", sizeof(uint_least16_t));
printf("sizeof(uint_least32_t) = %ld\n", sizeof(uint_least32_t));
#if defined(_M_X64) || defined(__amd64__)
printf("sizeof(uint_least64_t) = %ld\n", sizeof(uint_least64_t));
#endif
printf("INT_LEAST8_MAX = %d\n", INT_LEAST8_MAX);
printf("INT_LEAST16_MAX = %d\n", INT_LEAST16_MAX);
printf("INT_LEAST32_MAX = %d\n", INT_LEAST32_MAX);
#if defined(_M_X64) || defined(__amd64__)
printf("INT_LEAST64_MAX = %ld\n", INT_LEAST64_MAX);
#endif
printf("INT_LEAST8_MIN = %d\n", INT_LEAST8_MIN);
printf("INT_LEAST16_MIN = %d\n", INT_LEAST16_MIN);
printf("INT_LEAST32_MIN = %d\n", INT_LEAST32_MIN);
#if defined(_M_X64) || defined(__amd64__)
printf("INT_LEAST64_MIN = %ld\n", INT_LEAST64_MIN);
#endif
printf("UINT_LEAST8_MAX = %d\n", UINT_LEAST8_MAX);
printf("UINT_LEAST16_MAX = %d\n", UINT_LEAST16_MAX);
printf("UINT_LEAST32_MAX = %d\n", UINT_LEAST32_MAX);
#if defined(_M_X64) || defined(__amd64__)
printf("UINT_LEAST64_MAX = %ld\n", UINT_LEAST64_MAX);
#endif
printf("sizeof(int_fast8_t) = %ld\n", sizeof(int_fast8_t));
printf("sizeof(int_fast16_t) = %ld\n", sizeof(int_fast16_t));
printf("sizeof(int_fast32_t) = %ld\n", sizeof(int_fast32_t));
#if defined(_M_X64) || defined(__amd64__)
printf("sizeof(int_fast64_t) = %ld\n", sizeof(int_fast64_t));
#endif
printf("sizeof(uint_fast8_t) = %ld\n", sizeof(uint_fast8_t));
printf("sizeof(uint_fast16_t) = %ld\n", sizeof(uint_fast16_t));
printf("sizeof(uint_fast32_t) = %ld\n", sizeof(uint_fast32_t));
#if defined(_M_X64) || defined(__amd64__)
printf("sizeof(uint_fast64_t) = %ld\n", sizeof(uint_fast64_t));
#endif
printf("INT_FAST8_MAX = %d\n", INT_FAST8_MAX);
printf("INT_FAST16_MAX = %ld\n", INT_FAST16_MAX);
printf("INT_FAST32_MAX = %ld\n", INT_FAST32_MAX);
#if defined(_M_X64) || defined(__amd64__)
printf("INT_FAST64_MAX = %ld\n", INT_FAST64_MAX);
#endif
printf("INT_FAST8_MAX = %d\n", INT_FAST8_MAX);
printf("INT_FAST16_MAX = %ld\n", INT_FAST16_MAX);
printf("INT_FAST32_MAX = %ld\n", INT_FAST32_MAX);
#if defined(_M_X64) || defined(__amd64__)
printf("INT_FAST64_MAX = %ld\n", INT_FAST64_MAX);
#endif
printf("INT_FAST8_MIN = %d\n", INT_FAST8_MIN);
printf("INT_FAST16_MIN = %ld\n", INT_FAST16_MIN);
printf("INT_FAST32_MIN = %ld\n", INT_FAST32_MIN);
#if defined(_M_X64) || defined(__amd64__)
printf("INT_FAST64_MIN = %ld\n", INT_FAST64_MIN);
#endif
printf("UINT_FAST8_MAX = %d\n", UINT_FAST8_MAX);
printf("UINT_FAST16_MAX = %ld\n", UINT_FAST16_MAX);
printf("UINT_FAST32_MAX = %ld\n", UINT_FAST32_MAX);
#if defined(_M_X64) || defined(__amd64__)
printf("UINT_FAST64_MAX = %ld\n", UINT_FAST64_MAX);
#endif
printf("sizeof(intptr_t) = %ld\n", sizeof(intptr_t));
printf("sizeof(uintptr_t) = %ld\n", sizeof(uintptr_t));
printf("INTPTR_MAX = %ld\n", INTPTR_MAX);
printf("INTPTR_MIN = %ld\n", INTPTR_MIN);
printf("UINTPTR_MAX = %ld\n", UINTPTR_MAX);
printf("sizeof(intmax_t) = %ld\n", sizeof(intmax_t));
printf("sizeof(uintmax_t) = %ld\n", sizeof(uintmax_t));
printf("INTMAX_MAX = %ld\n", INTMAX_MAX);
printf("INTMAX_MIN = %ld\n", INTMAX_MIN);
printf("UINTMAX_MAX = %ld\n", UINTMAX_MAX);
printf("PTRDIFF_MIN = %ld\n", PTRDIFF_MIN);
printf("PTRDIFF_MAX = %ld\n", PTRDIFF_MAX);
printf("SIZE_MAX = %ld\n", SIZE_MAX);
return 0;
}

52
lcthw-remnants/ex22.c Normal file
View File

@ -0,0 +1,52 @@
#include <stdio.h>
#include "ex22.h"
#include "dbg.h"
int THE_SIZE = 1000;
static int THE_AGE = 37;
int get_age()
{
return THE_AGE;
}
int *get_age_pointer()
{
return &THE_AGE;
}
void set_age(int age)
{
THE_AGE = age;
}
double *get_function_static(double to_add)
{
static double value = 1.0;
double old = value;
value = value + to_add;
return &value;
}
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);
}

18
lcthw-remnants/ex22.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _ex22_h
#define _ex22_h
// makes THE_SIZE in ex22.c available to other .c files
int THE_SIZE;
// gets and sets an internal static variable in ex22.c
int get_age();
int * get_age_pointer();
double * get_function_static(double);
void set_age(int age);
// updates a static variable that's inside update_ratio
double update_ratio(double ratio);
void print_size();
#endif

10
lcthw-remnants/ex22.mk Normal file
View File

@ -0,0 +1,10 @@
all: ex22_main ex22_ec1
ex22_main: ex22_main.o ex22.o
clean:
rm -f ex22_main ex22.o ex22_main.o ex22_ec1
.PHONY: all clean

28
lcthw-remnants/ex22_ec1.c Normal file
View File

@ -0,0 +1,28 @@
#include <stdio.h>
#include "dbg.h"
int pass_by_value(int n)
{
n = n + 2;
return n;
}
int pass_by_reference(int *n)
{
*n = *n + 8;
return *n;
}
int main(int argc, char *argv[])
{
int n = 2;
log_info("n = %d", n);
log_info("By value example: %d", pass_by_value(n));
log_info("n = %d", n);
log_info("By reference example: %d", pass_by_reference(&n));
log_info("n = %d", n);
return 0;
}

View File

@ -0,0 +1,72 @@
#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());
int new_age = 44;
log_info("Setting age directly to %d", new_age);
int *age = get_age_pointer();
*age = new_age;
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 ratio 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));
// accessing a function static
double *func_static_value = get_function_static(4.0);
log_info("get_function_static(4.0) = %.1f", *func_static_value);
double new_func_static_value = 8.0;
log_info("Setting the function static var directly to %.1f",
new_func_static_value);
*func_static_value = new_func_static_value;
log_info("get_function_static(4.0) = %.1f", *get_function_static(4.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;
}

113
lcthw-remnants/ex23.c Normal file
View File

@ -0,0 +1,113 @@
#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;
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 device failed: %d", rc);
check(valid_copy(to, 1000, 'x'), "Duff's device 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.");
log_info("DING!");
return 0;
error:
return 1;
}

76
lcthw-remnants/ex24.c Normal file
View File

@ -0,0 +1,76 @@
#include <stdlib.h>
#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;
char *in = NULL;
char tmp[MAX_DATA];
printf("What's your First Name? ");
in = fgets(you.first_name, MAX_DATA-1, stdin);
check(in != NULL, "Failed to read 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.");
printf("How old are you? ");
in = fgets(tmp, MAX_DATA-1, stdin);
check(in != NULL, "Failed to read age.");
you.age = atoi(tmp);
check(you.age != -1, "Failed to convert age to int.");
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;
in = fgets(tmp, MAX_DATA-1, stdin);
check(in != NULL, "Failed to read eye color selection.");
eyes = atoi(tmp);
check(eyes <= OTHER_EYES && eyes > 0, "Do it right, that's not an option.");
you.eyes = eyes - 1;
printf("How much do you make an hour? ");
in = fgets(tmp, MAX_DATA-1, stdin);
check(in != NULL, "Failed to read income.");
you.income = strtod(tmp, NULL);
check(you.income != -1, "Failed to convert income.");
printf("----- RESULTS -----\n");
printf("First Name: %s", you.first_name);
printf("Last Name: %s", 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;
}

View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include "dbg.h"
int main(int argc, char *argv[])
{
int a, b, rc;
char c;
printf("Reading from stdin: <a:number> <b:number> <c:letter>\n> ");
rc = fscanf(stdin, "%d %d %c", &a, &b, &c);
check(rc == 3, "Failed to read from stdin.");
printf("Read in: a=%d b=%d c=%c\n", a, b, c);
return 0;
error:
return 1;
}

View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include "dbg.h"
int main(int argc, char *argv[])
{
int a, b, rc;
char c;
char filename[1024 * 2];
FILE *fp;
printf("Provide filename from which to inputs\n> ");
rc = fscanf(stdin, "%s", filename);
check(rc == 1, "Failed to read filename");
fp = fopen(filename, "r");
check(fp != NULL, "Failed to open file %s", filename);
printf("Reading from file: <a:number> <b:number> <c:letter>\n");
rc = fscanf(fp, "%d %d %c", &a, &b, &c);
check(rc == 3, "Failed to read from \"%s\".", filename);
printf("Read in: a=%d b=%d c=%c\n", a, b, c);
rc = fclose(fp);
check(rc != EOF, "Failed to close file \"%s\"", filename);
return 0;
error:
return 1;
}

View File

@ -0,0 +1,59 @@
#include <stdio.h>
#include "dbg.h"
#define MAX_FILENAME 2048
int main(int argc, char *argv[])
{
int rc = -1;
char *filename;
int nchars = 0;
int nlines = 0;
int i;
long seekpos;
char c;
FILE *fp;
check(argc > 1, "You must provide a filename as arg 1");
filename = argv[1];
fp = fopen(filename, "r");
check(fp != NULL, "Failed to open \"%s\".", filename);
while((c = fgetc(fp)) != EOF) {
nchars++;
if (c == '\n') {
nlines++;
if (nlines % 10 == 0) {
printf("At line %d of \"%s\"\n", nlines, filename);
}
}
}
printf("\"%s\" contains %d chars\n", filename, nchars);
printf("Current position of \"%s\" is %ld\n", filename, ftell(fp));
printf("Writing out \"%s\" in reverse:\n", filename);
for (i = 0; i < nchars; i++) {
seekpos = (long)nchars - (i + 1);
rc = fseek(fp, seekpos, SEEK_SET);
check(rc != -1, "Failed to seek to %ld", seekpos);
c = fgetc(fp);
check(c != EOF, "Failed to read char at %ld", seekpos);
putc(c, stdout);
}
rewind(fp);
printf("\n\nRewound \"%s\" to position %ld\n", filename, ftell(fp));
rc = fclose(fp);
check(rc != -1, "Failed to close \"%s\".", filename);
return 1;
error:
return 0;
}

View File

@ -0,0 +1,27 @@
#define _GNU_SOURCE
#include <stdio.h>
#include "dbg.h"
int main(int argc, char *argv[])
{
int rc = -1;
printf("This should be visible, I think.\n");
rc = fcloseall();
check(rc == 0, "Failed to close all io streams.");
printf("I've used `fcloseall`, so this should not be visible, right?\n");
rc = fflush(stdout);
check(rc != EOF, "Failed to flush stdout.");
printf("Maybe we won't see anything after I explicitly `fflush(stdout)`?\n");
rc = fclose(stdout);
check(rc != EOF, "Failed to explicitly close stdout.");
printf("This had better not show up, right?\n");
return 0;
error:
return 1;
}

View File

@ -0,0 +1,22 @@
#include <stdio.h>
#include "dbg.h"
int main(int argc, char *argv[])
{
FILE *fp;
char *filename;
check(argc == 2, "You must provide a filename for redirecting stdout.");
filename = argv[1];
fp = freopen(filename, "w", stdout);
check(fp != NULL, "Failed to reopen stdout as \"%s\"", filename);
printf("This should be written to the file you specified!\n");
return 0;
error:
return 1;
}

View File

@ -0,0 +1,57 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include "dbg.h"
int main(int argc, char *argv[])
{
int fd;
int rc;
long lrc;
char *out;
char buffer[1024];
fpos_t pos;
FILE *instream;
FILE *outstream;
check(argc == 2, "You must provide a filename.");
fd = open(argv[1], O_RDWR | O_CREAT);
check(fd != -1, "Unable to open \"%s\" for reading and writing.", argv[1]);
rc = fchmod(fd, 0644);
check(rc != -1, "Failed to chmod \"%s\"", argv[1]);
outstream = fdopen(fd, "w");
check(outstream != NULL, "Unable to open an outstream.");
rc = fgetpos(outstream, &pos);
check(rc != -1, "Failed to get position of outstream.");
rc = fprintf(outstream, "It was written.");
check(rc > 0, "Failed to write to outstream.");
rc = fflush(outstream);
check(rc != EOF, "Failed to flush outstream.");
rc = fsetpos(outstream, &pos);
check(rc != -1, "Failed to set outstream back to old position.");
instream = fdopen(fd, "r");
check(instream != NULL, "Unable to open an instream.");
rewind(instream);
lrc = ftell(instream);
check(lrc == 0, "Failed to rewind instream.");
out = fgets(buffer, 1023, instream);
check(buffer != NULL, "Failed to read from instream.");
printf("Read this from instream: \"%s\"\n", buffer);
return 0;
error:
return 1;
}

File diff suppressed because one or more lines are too long

135
lcthw-remnants/ex25.c Normal file
View File

@ -0,0 +1,135 @@
#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);
check(rc == 0, "Failed 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;
}

12
lcthw-remnants/ex3.c Normal file
View 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
lcthw-remnants/ex4.c Normal file
View 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;
}

20
lcthw-remnants/ex4.sh Normal file
View File

@ -0,0 +1,20 @@
# 1) Download it (use wget if you don't have curl)
curl -O http://valgrind.org/downloads/valgrind-3.7.0.tar.bz2
# use md5sum to make sure it matches the one on the site
md5sum valgrind-3.7.0.tar.bz2
# 2) Unpack it.
tar -xjvf valgrind-3.7.0.tar.bz2
# cd into the newly created directory
cd valgrind-3.7.0
# 3) configure it
./configure
# 4) make it
make
# 5) install it (need root)
sudo make install

12
lcthw-remnants/ex5.c Normal file
View 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
lcthw-remnants/ex6.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int distance = 0xaf + 0747;
float power = 2.345f + 'Z' + 'A' + 'P';
double super_power = 56789.4532f;
char initial = 'A';
char first_name[] = "Zed";
char last_name[] = {'S', 'h', 'a', 'w', '\0'};
printf("You are %08d miles away.\n", distance);
printf("You have %.2f levels of power.\n", power);
printf("You have %.3f awesome super powers.\n", super_power);
printf("I have an 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;
}

36
lcthw-remnants/ex7.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int bugs = 100;
double bug_rate = 1.2;
printf("You have %d bugs imaginary rate of %f.\n",
bugs, bug_rate);
unsigned long universe_of_defects = 63.99999999999 * 32 * 1024 * 1024;
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);
puts("also...");
int nul = (int)nul_byte;
int *nul_ptr = &nul;
printf("char '\\0' = '%c', (int)'\\0' = '%d', &(int)'\\0' = '%n'.\n",
nul_byte, nul, nul_ptr);
return 0;
}

58
lcthw-remnants/ex8.c Normal file
View File

@ -0,0 +1,58 @@
#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 number of ints in areas: %ld\n",
sizeof(areas) / sizeof(int));
printf("The first area is %d, then 2nd %d.\n",
areas[0], areas[1]);
areas[0] = 100;
areas[2] = areas[1];
printf("Now the first area is %d and the 3rd area is %d.\n",
areas[0], areas[2]);
printf("The size of 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);
printf("name[0] is %c.\n", name[0]);
printf("full_name[7] is %c.\n", full_name[7]);
name[0] = 'X';
printf("Now name[0] is %c.\n", name[0]);
full_name[7] = 'T';
printf("Now full_name[7] is %c.\n", full_name[7]);
printf("name=\"%s\" and full_name=\"%s\"\n",
name, full_name);
areas[2] = name[0];
printf("First area is now name[0]: %%c=%c, %%d=%d.\n",
areas[2], areas[2]);
return 0;
}

60
lcthw-remnants/ex9.c Normal file
View File

@ -0,0 +1,60 @@
#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';
printf("%d\n", name[0]);
printf("%d\n", name[1]);
printf("%d\n", name[2]);
printf("%d\n", name[3]);
printf("name as int=%d\n", (int)*name);
// 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;
}

View File

@ -0,0 +1,14 @@
fscanf
fgets
fopen
freopen
fdopen
fclose
fcloseall
fgetpos
fseek
ftell
rewind
fprintf
fwrite
fread

91
lcthw-remnants/object.c Normal file
View File

@ -0,0 +1,91 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object.h"
#include <assert.h>
void Object_destroy(void *self)
{
assert(self != NULL);
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)
{
assert(self != NULL);
// do nothing really
return 1;
}
void *Object_move(void *self, Direction direction)
{
assert(self != NULL);
assert(direction);
printf("You can't go that direction.\n");
return NULL;
}
int Object_attack(void *self, int damage)
{
assert(self != NULL);
assert(damage);
printf("You can't attack that.\n");
return 0;
}
void *Object_new(size_t size, Object proto, char *description)
{
assert(size);
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(size, 1);
assert(el != NULL);
*el = proto;
// copy the description over
el->description = strdup(description);
assert(el->description != NULL);
// 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
assert(el != NULL);
return el;
}
}

27
lcthw-remnants/object.h Normal file
View 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

35
lcthw-remnants/test.sh Normal file
View File

@ -0,0 +1,35 @@
EXIT_CODE=0
ASSERT_COUNT=0
function assert_equal(){
if [[ $1 == $2 ]] ; then
echo -n "."
else
echo -n "F"
EXIT_CODE=1
fi
ASSERT_COUNT=$(expr $ASSERT_COUNT + 1)
}
function assert_not_equal(){
if [[ $1 != $2 ]] ; then
echo -n "."
else
echo -n "F"
EXIT_CODE=1
fi
ASSERT_COUNT=$(expr $ASSERT_COUNT + 1)
}
function test_finish(){
echo
if [ $EXIT_CODE -eq 0 ]; then
echo "PASS"
else
echo "FAIL"
fi
exit $EXIT_CODE
}

55
lcthw-remnants/test_ex17.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
source './test.sh'
prog=${1-'./ex17'}
test_db=db.$$.$RANDOM.dat
# ----------------------------------------------------------------------------
$prog 2>&1 >/dev/null
assert_equal $? 1
$prog $test_db c 2>&1 >/dev/null
assert_equal $? 0
$prog $test_db s 2>&1 >/dev/null
assert_equal $? 1
$prog $test_db s 1 ham ham@foo.bar
assert_equal $? 0
$prog $test_db s 2 derp derp@foo.bar
assert_equal $? 0
$prog $test_db s 3 herp herp@foo.bar
assert_equal $? 0
$prog $test_db s 4 zap zap@foo.bar
assert_equal $? 0
$prog $test_db l > $$.out
grep '1 ham ham@foo.bar' $$.out >/dev/null
assert_equal $? 0
$prog $test_db l > $$.out
grep '2 derp derp@foo.bar' $$.out >/dev/null
assert_equal $? 0
$prog $test_db l > $$.out
grep '3 herp herp@foo.bar' $$.out >/dev/null
assert_equal $? 0
$prog $test_db l > $$.out
grep '4 zap zap@foo.bar' $$.out >/dev/null
assert_equal $? 0
$prog $test_db g 1 > $$.out
grep '1 ham ham@foo.bar' $$.out >/dev/null
assert_equal $? 0
$prog $test_db d 1
$prog $test_db l > $$.out
grep 'ham@foo.bar' $$.out >/dev/null
assert_not_equal $? 0
# ----------------------------------------------------------------------------
rm -f $$.out
rm -f $test_db
test_finish

77
lcthw-remnants/test_ex19.sh Executable file
View File

@ -0,0 +1,77 @@
#!/bin/bash
EXIT_CODE=0
run_test()
{
echo -n " $1"
cat "$2" | ./ex19 >/dev/null
if [[ "$?" -eq "0" ]]
then
echo " ... OK"
else
echo " ... FAIL"
EXIT_CODE=1
fi
rm -f "$2"
}
tmp_01="`mktemp`"
cat > "$tmp_01" <<EOF
l
n
w
n
w
n
w
e
w
e
e
e
s
s
w
w
n
a
a
a
a
a
a
a
a
a
a
a
a
EOF
tmp_02="`mktemp`"
cat > "$tmp_02" <<EOF
l
a
a
a
a
a
n
hutesoahutesohas
999999999999
l
n
n
n
e
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
EOF
run_test '01' "$tmp_01"
run_test '02' "$tmp_02"
exit $EXIT_CODE

View File

@ -0,0 +1,56 @@
#!/bin/bash
EXIT_CODE=0
run_test()
{
echo -n " $1"
out_tmp="$(mktemp)"
./ex24_iofunctions$1 < "$2" > "$out_tmp"
diff_out="$(mktemp)"
diff -u "$3" "$out_tmp" > "$diff_out"
diff_count="$(cat "$diff_out" | wc -l)"
if [[ "$?" == "0" ]] && [[ "$diff_count" == "0" ]]
then
echo " ... OK"
else
echo " ... FAIL"
echo " diff count => $diff_count"
cat "$diff_out"
EXIT_CODE=1
fi
rm -f "$2" "$out_tmp" "$diff_out"
}
tmp_01="$(mktemp)"
cat > "$tmp_01" <<EOF
2 8 n
EOF
expected_01="$(mktemp)"
cat > "$expected_01" <<EOF
Reading from stdin: <a:number> <b:number> <c:letter>
> Read in: a=2 b=8 c=n
EOF
tmp_02="$(mktemp)"
tmp_02in="$(mktemp)"
cat > "$tmp_02in" <<EOF
1 4 a
EOF
cat > "$tmp_02" <<EOF
$tmp_02in
EOF
expected_02="$(mktemp)"
cat > "$expected_02" <<EOF
Provide filename from which to inputs
> Reading from file: <a:number> <b:number> <c:letter>
Read in: a=1 b=4 c=a
EOF
run_test '01' "$tmp_01" "$expected_01"
run_test '02' "$tmp_02" "$expected_02"
exit $EXIT_CODE