Add 'lcthw-remnants/' from commit 'e172f73c8297b22a579c94558f0c171ca74a0e5c'
git-subtree-dir: lcthw-remnants git-subtree-mainline:4107485591
git-subtree-split:e172f73c82
This commit is contained in:
commit
f2380eef05
37
lcthw-remnants/.gitignore
vendored
Normal file
37
lcthw-remnants/.gitignore
vendored
Normal 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
22
lcthw-remnants/Makefile
Normal 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
2
lcthw-remnants/README.md
Normal 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.
|
39
lcthw-remnants/apr-install-script.sh
Executable file
39
lcthw-remnants/apr-install-script.sh
Executable 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*
|
10
lcthw-remnants/break-ex10.py
Normal file
10
lcthw-remnants/break-ex10.py
Normal 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)
|
11
lcthw-remnants/break-ex25.rb
Normal file
11
lcthw-remnants/break-ex25.rb
Normal 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
|
6
lcthw-remnants/check-for-iofunctions.sh
Executable file
6
lcthw-remnants/check-for-iofunctions.sh
Executable 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
40
lcthw-remnants/dbg.h
Normal 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
1
lcthw-remnants/devpkg/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
devpkg
|
16
lcthw-remnants/devpkg/Makefile
Normal file
16
lcthw-remnants/devpkg/Makefile
Normal 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
|
0
lcthw-remnants/devpkg/README
Normal file
0
lcthw-remnants/devpkg/README
Normal file
7
lcthw-remnants/devpkg/apr_errno_test.c
Normal file
7
lcthw-remnants/devpkg/apr_errno_test.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <apr_errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
2979
lcthw-remnants/devpkg/bstrlib.c
Normal file
2979
lcthw-remnants/devpkg/bstrlib.c
Normal file
File diff suppressed because it is too large
Load Diff
304
lcthw-remnants/devpkg/bstrlib.h
Normal file
304
lcthw-remnants/devpkg/bstrlib.h
Normal 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
|
175
lcthw-remnants/devpkg/commands.c
Normal file
175
lcthw-remnants/devpkg/commands.c
Normal 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;
|
||||||
|
}
|
32
lcthw-remnants/devpkg/commands.h
Normal file
32
lcthw-remnants/devpkg/commands.h
Normal 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
124
lcthw-remnants/devpkg/db.c
Normal 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;
|
||||||
|
}
|
13
lcthw-remnants/devpkg/db.h
Normal file
13
lcthw-remnants/devpkg/db.h
Normal 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
1
lcthw-remnants/devpkg/dbg.h
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../dbg.h
|
105
lcthw-remnants/devpkg/devpkg.c
Normal file
105
lcthw-remnants/devpkg/devpkg.c
Normal 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;
|
||||||
|
}
|
113
lcthw-remnants/devpkg/shell.c
Normal file
113
lcthw-remnants/devpkg/shell.c
Normal 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}
|
||||||
|
};
|
31
lcthw-remnants/devpkg/shell.h
Normal file
31
lcthw-remnants/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
|
13
lcthw-remnants/ex1.c
Normal file
13
lcthw-remnants/ex1.c
Normal 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
25
lcthw-remnants/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 = 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
41
lcthw-remnants/ex11.c
Normal 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
20
lcthw-remnants/ex12.c
Normal 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
62
lcthw-remnants/ex13.c
Normal 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
35
lcthw-remnants/ex14.c
Normal 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
89
lcthw-remnants/ex15.c
Normal 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
73
lcthw-remnants/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((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
239
lcthw-remnants/ex17-ec.c
Normal 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
201
lcthw-remnants/ex17-ec1.c
Normal 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
198
lcthw-remnants/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("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
115
lcthw-remnants/ex18.c
Normal 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
241
lcthw-remnants/ex19.c
Normal 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
54
lcthw-remnants/ex19.h
Normal 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
17
lcthw-remnants/ex19.mk
Normal 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
125
lcthw-remnants/ex20.c
Normal 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
124
lcthw-remnants/ex21.c
Normal 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
52
lcthw-remnants/ex22.c
Normal 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
18
lcthw-remnants/ex22.h
Normal 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
10
lcthw-remnants/ex22.mk
Normal 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
28
lcthw-remnants/ex22_ec1.c
Normal 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;
|
||||||
|
}
|
72
lcthw-remnants/ex22_main.c
Normal file
72
lcthw-remnants/ex22_main.c
Normal 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
113
lcthw-remnants/ex23.c
Normal 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
76
lcthw-remnants/ex24.c
Normal 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;
|
||||||
|
}
|
19
lcthw-remnants/ex24_iofunctions01.c
Normal file
19
lcthw-remnants/ex24_iofunctions01.c
Normal 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;
|
||||||
|
}
|
30
lcthw-remnants/ex24_iofunctions02.c
Normal file
30
lcthw-remnants/ex24_iofunctions02.c
Normal 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;
|
||||||
|
}
|
59
lcthw-remnants/ex24_iofunctions03.c
Normal file
59
lcthw-remnants/ex24_iofunctions03.c
Normal 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;
|
||||||
|
}
|
27
lcthw-remnants/ex24_iofunctions04.c
Normal file
27
lcthw-remnants/ex24_iofunctions04.c
Normal 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;
|
||||||
|
}
|
22
lcthw-remnants/ex24_iofunctions05.c
Normal file
22
lcthw-remnants/ex24_iofunctions05.c
Normal 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;
|
||||||
|
}
|
57
lcthw-remnants/ex24_iofunctions06.c
Normal file
57
lcthw-remnants/ex24_iofunctions06.c
Normal 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;
|
||||||
|
}
|
1
lcthw-remnants/ex25-fuzz-input
Normal file
1
lcthw-remnants/ex25-fuzz-input
Normal file
File diff suppressed because one or more lines are too long
135
lcthw-remnants/ex25.c
Normal file
135
lcthw-remnants/ex25.c
Normal 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
12
lcthw-remnants/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
lcthw-remnants/ex4.c
Normal file
12
lcthw-remnants/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;
|
||||||
|
}
|
20
lcthw-remnants/ex4.sh
Normal file
20
lcthw-remnants/ex4.sh
Normal 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
12
lcthw-remnants/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
lcthw-remnants/ex6.c
Normal file
22
lcthw-remnants/ex6.c
Normal 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
36
lcthw-remnants/ex7.c
Normal 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
58
lcthw-remnants/ex8.c
Normal 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
60
lcthw-remnants/ex9.c
Normal 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;
|
||||||
|
}
|
14
lcthw-remnants/iofunctions.txt
Normal file
14
lcthw-remnants/iofunctions.txt
Normal 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
91
lcthw-remnants/object.c
Normal 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
27
lcthw-remnants/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
|
35
lcthw-remnants/test.sh
Normal file
35
lcthw-remnants/test.sh
Normal 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
55
lcthw-remnants/test_ex17.sh
Executable 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
77
lcthw-remnants/test_ex19.sh
Executable 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
|
56
lcthw-remnants/test_ex24_iofunctions.sh
Executable file
56
lcthw-remnants/test_ex24_iofunctions.sh
Executable 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
|
Loading…
Reference in New Issue
Block a user