Move tons of stuff into oldstuff/

This commit is contained in:
2020-06-04 09:54:59 -04:00
parent 49038bb8ef
commit aa1345b6ed
213 changed files with 0 additions and 12 deletions

19
oldstuff/djtut/Pipfile Normal file
View File

@@ -0,0 +1,19 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
black = "*"
pytest = "*"
pytest-django = "*"
[packages]
Django = "<2.0"
psycopg2 = "<2.8"
[requires]
python_version = "3.7"
[pipenv]
allow_prereleases = true

248
oldstuff/djtut/Pipfile.lock generated Normal file
View File

@@ -0,0 +1,248 @@
{
"_meta": {
"hash": {
"sha256": "b34be6918d1424822217ca7656f0c09eae51b584a40c8a902cc0d589db10a1b8"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"django": {
"hashes": [
"sha256:014e3392058d94f40569206a24523ce254d55ad2f9f46c6550b0fe2e4f94cf3f",
"sha256:4200aefb6678019a0acf0005cd14cfce3a5e6b9b90d06145fcdd2e474ad4329c"
],
"index": "pypi",
"version": "==1.11.29"
},
"psycopg2": {
"hashes": [
"sha256:02445ebbb3a11a3fe8202c413d5e6faf38bb75b4e336203ee144ca2c46529f94",
"sha256:0e9873e60f98f0c52339abf8f0339d1e22bfe5aae0bcf7aabd40c055175035ec",
"sha256:1148a5eb29073280bf9057c7fc45468592c1bb75a28f6df1591adb93c8cb63d0",
"sha256:259a8324e109d4922b0fcd046e223e289830e2568d6f4132a3702439e5fd532b",
"sha256:28dffa9ed4595429e61bacac41d3f9671bb613d1442ff43bcbec63d4f73ed5e8",
"sha256:314a74302d4737a3865d40ea50e430ce1543c921ba10f39d562e807cfe2edf2a",
"sha256:36b60201b6d215d7658a71493fdf6bd5e60ad9a0cffed39906627ff9f4f3afd3",
"sha256:3f9d532bce54c4234161176ff3b8688ff337575ca441ea27597e112dfcd0ee0c",
"sha256:5d222983847b40af989ad96c07fc3f07e47925e463baa5de716be8f805b41d9b",
"sha256:6757a6d2fc58f7d8f5d471ad180a0bd7b4dd3c7d681f051504fbea7ae29c8d6f",
"sha256:6a0e0f1e74edb0ab57d89680e59e7bfefad2bfbdf7c80eb38304d897d43674bb",
"sha256:6ca703ccdf734e886a1cf53eb702261110f6a8b0ed74bcad15f1399f74d3f189",
"sha256:8513b953d8f443c446aa79a4cc8a898bd415fc5e29349054f03a7d696d495542",
"sha256:9262a5ce2038570cb81b4d6413720484cb1bc52c064b2f36228d735b1f98b794",
"sha256:97441f851d862a0c844d981cbee7ee62566c322ebb3d68f86d66aa99d483985b",
"sha256:a07feade155eb8e69b54dd6774cf6acf2d936660c61d8123b8b6b1f9247b67d6",
"sha256:a9b9c02c91b1e3ec1f1886b2d0a90a0ea07cc529cb7e6e472b556bc20ce658f3",
"sha256:ae88216f94728d691b945983140bf40d51a1ff6c7fe57def93949bf9339ed54a",
"sha256:b360ffd17659491f1a6ad7c928350e229c7b7bd83a2b922b6ee541245c7a776f",
"sha256:b4221957ceccf14b2abdabef42d806e791350be10e21b260d7c9ce49012cc19e",
"sha256:b90758e49d5e6b152a460d10b92f8a6ccf318fcc0ee814dcf53f3a6fc5328789",
"sha256:c669ea986190ed05fb289d0c100cc88064351f2b85177cbfd3564c4f4847d18c",
"sha256:d1b61999d15c79cf7f4f7cc9021477aef35277fc52452cf50fd13b713c84424d",
"sha256:de7bb043d1adaaf46e38d47e7a5f703bb3dab01376111e522b07d25e1a79c1e1",
"sha256:e393568e288d884b94d263f2669215197840d097c7e5b0acd1a51c1ea7d1aba8",
"sha256:ed7e0849337bd37d89f2c2b0216a0de863399ee5d363d31b1e5330a99044737b",
"sha256:f153f71c3164665d269a5d03c7fa76ba675c7a8de9dc09a4e2c2cdc9936a7b41",
"sha256:f1fb5a8427af099beb7f65093cbdb52e021b8e6dbdfaf020402a623f4181baf5",
"sha256:f36b333e9f86a2fba960c72b90c34be6ca71819e300f7b1fc3d2b0f0b2c546cd",
"sha256:f4526d078aedd5187d0508aa5f9a01eae6a48a470ed678406da94b4cd6524b7e"
],
"index": "pypi",
"version": "==2.7.7"
},
"pytz": {
"hashes": [
"sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
"sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
],
"version": "==2019.3"
}
},
"develop": {
"appdirs": {
"hashes": [
"sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
"sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
],
"version": "==1.4.3"
},
"attrs": {
"hashes": [
"sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
"sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
],
"version": "==19.3.0"
},
"black": {
"hashes": [
"sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b",
"sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"
],
"index": "pypi",
"version": "==19.10b0"
},
"click": {
"hashes": [
"sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
"sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
],
"version": "==7.1.1"
},
"importlib-metadata": {
"hashes": [
"sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302",
"sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"
],
"markers": "python_version < '3.8'",
"version": "==1.5.0"
},
"more-itertools": {
"hashes": [
"sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c",
"sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"
],
"version": "==8.2.0"
},
"packaging": {
"hashes": [
"sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
"sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
],
"version": "==20.3"
},
"pathspec": {
"hashes": [
"sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424",
"sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"
],
"version": "==0.7.0"
},
"pluggy": {
"hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
],
"version": "==0.13.1"
},
"py": {
"hashes": [
"sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa",
"sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"
],
"version": "==1.8.1"
},
"pyparsing": {
"hashes": [
"sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
"sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
],
"version": "==2.4.6"
},
"pytest": {
"hashes": [
"sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172",
"sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970"
],
"index": "pypi",
"version": "==5.4.1"
},
"pytest-django": {
"hashes": [
"sha256:456fa6854d04ee625d6bbb8b38ca2259e7040a6f93333bfe8bc8159b7e987203",
"sha256:489b904f695f9fb880ce591cf5a4979880afb467763b1f180c07574554bdfd26"
],
"index": "pypi",
"version": "==3.8.0"
},
"regex": {
"hashes": [
"sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431",
"sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242",
"sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1",
"sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d",
"sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045",
"sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b",
"sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400",
"sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa",
"sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0",
"sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69",
"sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74",
"sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb",
"sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26",
"sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5",
"sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2",
"sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce",
"sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab",
"sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e",
"sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70",
"sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc",
"sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"
],
"version": "==2020.2.20"
},
"six": {
"hashes": [
"sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
"sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
],
"version": "==1.14.0"
},
"toml": {
"hashes": [
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
],
"version": "==0.10.0"
},
"typed-ast": {
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"version": "==1.4.1"
},
"wcwidth": {
"hashes": [
"sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603",
"sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"
],
"version": "==0.1.8"
},
"zipp": {
"hashes": [
"sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
"sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
],
"version": "==3.1.0"
}
}
}

22
oldstuff/djtut/mysite/manage.py Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(sys.argv)

View File

View File

@@ -0,0 +1,66 @@
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = "rbkosjwn!o^)&kb-fr^3^+y60bbz^76f#jt_7a%n1pt8jjd%bv"
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = [
"polls.apps.PollsConfig",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "mysite.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "mysite.wsgi.application"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "mysite",
"USER": "mysite",
"HOST": "localhost",
"PORT": "5432",
"PASSWORD": "notsecurelol",
},
"test": {"ENGINE": "django.db.backends.sqlite3", "NAME": "test-mysite.sqlite3",},
}
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",},
]
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = "/static/"

View File

@@ -0,0 +1,7 @@
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url("^polls/", include("polls.urls")),
url("^admin/", admin.site.urls),
]

View File

@@ -0,0 +1,16 @@
"""
WSGI config for mysite project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = get_wsgi_application()

View File

View File

@@ -0,0 +1,5 @@
from django.contrib import admin
from .models import Question
admin.site.register(Question)

View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = "polls"

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-03-14 01:39
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Choice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice_text', models.CharField(max_length=200)),
('votes', models.IntegerField(default=0)),
],
),
migrations.CreateModel(
name='Question',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question_text', models.CharField(max_length=200)),
('pub_date', models.DateTimeField(verbose_name='date published')),
],
),
migrations.AddField(
model_name='choice',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.Question'),
),
]

View File

@@ -0,0 +1,19 @@
import datetime
from django.utils import timezone
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

View File

@@ -0,0 +1,12 @@
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_mmessage }}</strong></p>{% endif %}
<form action="{% url "polls:vote" question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}"/>
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

View File

@@ -0,0 +1,9 @@
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="{% url "polls:detail" question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}

View File

@@ -0,0 +1,9 @@
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url "polls:detail" question.id %}">Vote again?</a>

View File

@@ -0,0 +1,11 @@
import datetime
from django.utils import timezone
from .models import Question
def test_was_published_recently_with_future_question():
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
assert not future_question.was_published_recently()

View File

@@ -0,0 +1,11 @@
from django.conf.urls import url
from . import views
app_name = "polls"
urlpatterns = [
url("^$", views.IndexView.as_view(), name="index"),
url("^(?P<pk>[0-9]+)/$", views.DetailView.as_view(), name="detail"),
url("^(?P<pk>[0-9]+)/results/$", views.ResultsView.as_view(), name="results",),
url("^(?P<question_id>[0-9]+)/vote/$", views.vote, name="vote"),
]

View File

@@ -0,0 +1,40 @@
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.views import generic
from .models import Choice, Question
class IndexView(generic.ListView):
template_name = "polls/index.html"
context_object_name = "latest_question_list"
def get_queryset(self):
return Question.objects.order_by("-pub_date")[:5]
class DetailView(generic.DetailView):
model = Question
template_name = "polls/detail.html"
class ResultsView(generic.DetailView):
model = Question
template_name = "polls/results.html"
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST["choice"])
except (KeyError, Choice.DoesNotExist):
return render(
request,
"polls/vote.html",
{"question": question, "error_message": "You didn't select a choice."},
)
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))

View File

@@ -0,0 +1,2 @@
[pytest]
DJANGO_SETTINGS_MODULE = mysite.settings

View File

@@ -0,0 +1,31 @@
package main
import (
"fmt"
"log"
"os"
farse "../.."
)
func main() {
fl := farse.New()
err := fl.AddKnown(
"-a", "-n", "-q", "-m",
"--azimuth", "--noodle", "--quince",
"whoop", "fizzle", "flim",
)
if err != nil {
log.Fatal(err)
}
fmt.Println("known:")
for key, tokType := range fl.Known() {
fmt.Printf(" %v: %s\n", key, tokType)
}
fmt.Println("scanned:")
for _, tok := range fl.Scan(os.Args) {
fmt.Printf(" %v: %s\n", tok.Value, tok.Type)
}
}

181
oldstuff/farse/farse.go Normal file
View File

@@ -0,0 +1,181 @@
package farse
import "fmt"
type TokenType int
const (
TokenLongFlag TokenType = iota
TokenShortFlag
TokenShortCompoundFlag
TokenIdentifier
TokenArgument
TokenInvalid
TokenSentinel
)
func (t TokenType) String() string {
switch t {
case TokenLongFlag:
return "long flag"
case TokenShortFlag:
return "short flag"
case TokenShortCompoundFlag:
return "short compound"
case TokenIdentifier:
return "identifier"
case TokenArgument:
return "argument"
case TokenInvalid:
return "invalid"
case TokenSentinel:
return "sentinel"
}
return "(x___x)"
}
type Token struct {
Value string
Type TokenType
}
type Farse struct {
known map[string]TokenType
}
func New() *Farse {
return &Farse{
known: map[string]TokenType{},
}
}
func (fl *Farse) Known() map[string]TokenType {
return fl.known
}
func (fl *Farse) AddKnown(knownStrings ...string) error {
for i, tok := range scan(knownStrings) {
if tok.Type == TokenShortCompoundFlag {
return fmt.Errorf("argument %d %q is invalid value for known identifier", i, tok.Value)
}
if len(tok.Value) == 0 {
return fmt.Errorf("argument %d is empty", i)
}
if len(tok.Value) == 1 && tok.Value == "-" {
return fmt.Errorf("argument %d %q is invalid value for known identifier", i, tok.Value)
}
if _, exists := fl.known[tok.Value]; exists {
return fmt.Errorf("argument %d %s conflicts with known", i, tok.Value)
}
fl.known[tok.Value] = tok.Type
}
return nil
}
func (fl *Farse) Scan(args []string) []*Token {
ret := []*Token{}
passedSentinel := false
for _, tok := range scan(args) {
if tok.Type == TokenSentinel {
ret = append(ret, tok)
passedSentinel = true
continue
}
if passedSentinel {
tok.Type = TokenArgument
ret = append(ret, tok)
continue
}
if tok.Type == TokenShortCompoundFlag {
ret = append(ret, fl.extractCompoundTokens(tok.Value)...)
continue
}
if tok.Type == TokenIdentifier {
if _, known := fl.known[tok.Value]; !known {
tok.Type = TokenArgument
}
ret = append(ret, tok)
}
}
return ret
}
func (fl *Farse) extractCompoundTokens(s string) []*Token {
ret := []*Token{}
for j, ch := range s {
last := j == (len(s) - 1)
if j == 0 && ch == '-' {
continue
}
sf := string(append([]rune("-"), ch))
if _, known := fl.known[sf]; known {
ret = append(ret, &Token{Value: sf, Type: TokenShortFlag})
if last {
return ret
}
if _, nextKnown := fl.known[string(append([]rune("-"), rune(s[j+1])))]; !nextKnown {
ret = append(ret, &Token{Value: s[j+1:], Type: TokenArgument})
return ret
}
}
}
return ret
}
func scan(sl []string) []*Token {
ret := []*Token{}
for _, s := range sl {
tok := scanToken(s)
if tok != nil {
ret = append(ret, tok)
}
}
return ret
}
func scanToken(s string) *Token {
switch len(s) {
case 0, 1:
return &Token{Value: s, Type: TokenIdentifier}
case 2:
if s == "--" {
return &Token{Value: s, Type: TokenSentinel}
}
if s[0] == '-' {
return &Token{Value: s, Type: TokenShortFlag}
}
default:
if s[0] == '-' {
if s[1] != '-' {
return &Token{Value: s, Type: TokenShortCompoundFlag}
}
return &Token{Value: s, Type: TokenLongFlag}
}
return &Token{Value: s, Type: TokenIdentifier}
}
return nil
}

98
oldstuff/graphy/grid.py Normal file
View File

@@ -0,0 +1,98 @@
import os
import sys
import time
from trie import Trie
DEBUG = os.environ.get('DEBUG', '') == '1'
def main():
dim = int(os.environ.get('DIM', '3'))
words_dat_file = os.environ.get('WORDS_DAT', 'words-en.dat')
edges = list(map(lambda s: s.strip(), sys.stdin.read().split()))
edge_map = {}
valid_words = Trie.from_dat_file(words_dat_file)
if len(edges) % dim != 0:
raise ValueError('edges length={!r} not divisible by dim={!r}'.format(
len(edges), dim))
for row in range(0, dim):
for col in range(0, dim):
idx = (row * dim) + col
if idx >= len(edges):
continue
edge_map[(row, col)] = Edge((row, col), edges[idx])
for (row, col), edge in edge_map.items():
for sibling in ((row, col - 1), (row, col + 1), (row - 1, col),
(row + 1, col), (row - 1, col - 1), (row - 1, col + 1),
(row + 1, col + 1), (row + 1, col - 1)):
debug('checking {!r} sibling {!r}'.format((row, col), sibling))
if edge_map.get(sibling) is not None:
edge.siblings.add(edge_map[sibling])
debug(' added sibling {!r} to {!r}'.format(sibling, edge))
for origin in sorted(edge_map.keys()):
for dest in sorted(edge_map.keys()):
if origin == dest:
continue
debug('getting paths from origin={!r} to dest={!r}'.format(
origin, dest))
for path in dfs_paths(edge_map, valid_words, origin, dest):
print(''.join(list(map(lambda e: edge_map[e].value, path))))
return 0
class Edge:
def __init__(self, id_, value, siblings=None):
self.id = id_
self.value = value
self.siblings = siblings if siblings is not None else set()
def __repr__(self):
return 'Edge({!r}, {!r}, siblings={!r})'.format(
self.id, self.value, set(map(lambda s: s.id, self.siblings)))
@property
def sibling_ids(self):
return set(map(lambda s: s.id, self.siblings))
def dfs_paths(edge_map, valid_words, origin, dest, path=None):
if path is None:
debug(' starting new path from {!r}'.format(origin))
path = [origin]
if origin == dest:
debug(' origin={!r} reached dest={!r}, yielding path'.format(
origin, dest))
if len(path) > 2 and len(path) < 17:
yield path
if ''.join(path) not in valid_words:
return
next_steps = edge_map[origin].sibling_ids - set(path)
if not next_steps:
return
debug(' origin={!r} dest={!r} checking next steps in {!r}'.format(
origin, dest, next_steps))
for next_step in edge_map[origin].sibling_ids - set(path):
yield from dfs_paths(edge_map, next_step, dest, path + [next_step])
def debug(msg):
if not DEBUG:
return
print(msg, file=sys.stderr)
if __name__ == '__main__':
sys.exit(main())

77
oldstuff/graphy/trie.py Normal file
View File

@@ -0,0 +1,77 @@
import os
import pickle
import sys
DEBUG = os.environ.get('DEBUG', '') == '1'
class Trie:
def __init__(self, value):
self.value = value
self.children = []
self.is_leaf = False
def add(self, value):
node = self
for ch in value:
child_matches = False
for child in node.children:
if child.value == value:
node = child
child_matches = True
break
if not child_matches:
to_add = Trie(value)
node.children.append(to_add)
node = to_add
node.is_leaf = True
def __contains__(self, search):
node = self
if not self.children:
return False
for ch in search:
found = False
for child in node.children:
if child.value == ch:
found = True
node = child
break
if not found:
return False
return True
def main():
words_file = os.environ.get('WORDS', 'words-en.txt')
words_dat_file = os.environ.get('WORDS_DAT', 'words-en.dat')
words_size_range = range(*(
map(lambda s: int(s),
os.environ.get('WORDS_SIZE_RANGE', '2-15').split('-'))))
valid_words = Trie('')
with open(words_file) as inwords:
debug('reading from {!r}'.format(words_file))
for word in inwords.read().split():
if len(word) not in words_size_range:
continue
debug('adding {!r} to valid words'.format(word))
valid_words.add(word)
with open(words_dat_file, 'wb') as outdat:
debug('writing valid words to {!r}'.format(words_dat_file))
pickle.dump(valid_words, outdat)
return 0
def debug(msg):
if not DEBUG:
return
print(msg, file=sys.stderr)
if __name__ == '__main__':
sys.exit(main())

90509
oldstuff/graphy/words-en.txt Normal file

File diff suppressed because it is too large Load Diff

38
oldstuff/kiddofun/quiz.rb Normal file
View File

@@ -0,0 +1,38 @@
def main
loop do
secret_number = rand(0..99)
hint_0 = secret_number - rand(0..49)
loop do
say "#{secret_number - hint_0} + #{hint_0} is", newline: false
print '?: '
begin
answer = Integer($stdin.readline.strip)
if answer == secret_number
say 'You got it!'
break
else
say 'That is so incorrect!'
end
rescue => e
$stderr.puts e
say 'NO, Human!'
end
end
say 'Do you want to play again? ', newline: false
print '[Y/n] '
if $stdin.readline.strip.downcase =~ /^n/
say 'Goodbye, Human!'
break
end
end
end
def say(msg, newline: true)
print msg
print "\n" if newline
system "say -v ralph #{msg.inspect}"
end
main

View File

@@ -0,0 +1,13 @@
package main
import (
"fmt"
)
func main() {
number := 43
fmt.Printf("%-2d - number\n", number)
fmt.Printf("%-2d - number tens place\n", number/10)
fmt.Printf("%-2d - number tens place multiplied by 10\n", (number/10)*10)
}

View File

@@ -0,0 +1,9 @@
number = Integer(ARGV.fetch(0))
divisor = Float(ARGV.fetch(1, 10.0))
raise 'Invalid divisor' unless divisor % 10 == 0
puts "#{number} - number"
puts "#{(Float(number) / divisor).round(0)} - number divided by #{divisor}"
puts "#{(Float(number) / divisor).round(0) * Integer(divisor)} - " \
"number divided by #{divisor}, multiplied by #{Integer(divisor)}"

6
oldstuff/lcthw-remnants-2/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
*.dat
ex*
!ex29
!ex*.c
devpkgzed
*.log

View File

@@ -0,0 +1,20 @@
FROM ubuntu:xenial
ENV DEBIAN_FRONTEND noninteractive
WORKDIR /app
RUN apt-get update -yq
RUN apt-get install -yq --no-install-recommends --no-install-suggests \
build-essential \
curl \
file \
gdb \
git \
man \
sudo \
vim-tiny \
zsh
RUN echo "kernel.yama.ptrace_scope = 0" > /etc/sysctl.d/10-ptrace.conf
CMD ["zsh", "-l"]

View File

@@ -0,0 +1,29 @@
SHELL = /bin/bash
CFLAGS = -Wall -g -DNDEBUG -fPIC
LDLIBS = -ldl
EXERCISES := $(shell ./list-exercises)
all: $(EXERCISES)
ex19: object.o
ex22_main: ex22.o
clean:
shopt -s nullglob ; \
$(RM) $(EXERCISES) *.o *.a
test:
@./runtests
exercises:
@echo $(EXERCISES)
.PHONY: docker-image
docker-image:
docker build -t meatballhat/lcthw:latest .
.PHONY: docker-run
docker-run:
docker run -it -v $(PWD):/app meatballhat/lcthw

View File

@@ -0,0 +1,3 @@
tests/runtests
tests/*_tests
tests/**/*_tests

View File

@@ -0,0 +1,21 @@
Copyright (C) 2016 Dan Buch
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,59 @@
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS = -ldl $(OPTLIBS)
PREFIX ?= /usr/local
SOURCES = $(wildcard src/**/*.c src/*.c)
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
TEST_SRC = $(wildcard tests/*_tests.c)
TESTS = $(patsubst %.c,%,$(TEST_SRC))
LIBNAME = YOUR_LIBRARY
TARGET = build/lib$(LIBNAME).a
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
$(AR) rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: LDLIBS += -static -l$(LIBNAME)
tests: ./tests/runtests $(TESTS)
./tests/runtests
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log tests/runtests
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions
@egrep $(BADFUNCS) $(SOURCES) || true

View File

@@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif

View File

@@ -0,0 +1,6 @@
#include "your_library.h"
int howmanyweasels()
{
return WEASELS;
}

View File

@@ -0,0 +1,8 @@
#ifndef _your_library_h
#define _your_library_h
#define WEASELS 23
int howmanyweasels();
#endif

View File

@@ -0,0 +1,38 @@
#undef DNDEBUG
#ifndef _minunit_h
#define _minunit_h
#include <stdio.h>
#include <dbg.h>
#include <stdlib.h>
#define mu_suite_start() char *message = NULL
#define mu_assert(test, message) if (!(test)) {\
log_err(message); return message;\
}\
assertions_made++;
#define mu_run_test(test) debug("\n-----%s", " " #test); \
message = test(); tests_run++; if (message) return message;
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
argc = argc; \
argv = argv; \
debug("----- RUNNING: %s", argv[0]);\
printf("----\nRUNNING: %s\n", argv[0]);\
char *result = name();\
if (result != 0) {\
printf("FAILED: %s\n", result);\
}\
else {\
printf("ALL TESTS PASSED\n");\
}\
printf("Tests run: %d\n", tests_run);\
printf("Assertions made: %d\n", assertions_made);\
exit(result != 0);\
}
int tests_run;
int assertions_made;
#endif

View File

@@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <fnmatch.h>
#include <dbg.h>
int test_selector(const struct dirent *ep)
{
return fnmatch("*_tests", ep->d_name, 0) == 0;
}
int run_tests_file(char *filename)
{
if(access(filename, R_OK | X_OK) == 0) {
return system(filename);
}
return -1;
}
int main(int argc, char *argv[])
{
int entcount = 0;
int rc = 0;
int i = 0;
int ntests = 0;
char *testsdir = NULL;
char *valgrind = getenv("VALGRIND");
struct dirent **namelist = NULL;
struct dirent *ep = NULL;
if(argc > 1) {
testsdir = argv[1];
}
if(!testsdir) {
testsdir = getenv("TESTS");
}
if(!testsdir) {
testsdir = "./tests";
}
entcount = scandir((const char *)testsdir, &namelist, test_selector, alphasort);
check(entcount > -1, "Failed to scan tests dir");
for(i = 0; i < entcount; i++) {
ep = namelist[i];
check(ep, "Dirent is missing.");
char filename[256];
rc = sprintf(filename, "%s/%s", testsdir, ep->d_name);
check(rc > -1, "Failed to build filename.");
debug("Found filename '%s'", filename);
free(ep);
if(valgrind) {
char command[1024];
rc = sprintf(command, "%s %s", valgrind, filename);
check(rc > -1, "Failed to build command with valgrind.");
rc = run_tests_file(command);
} else {
rc = run_tests_file(filename);
}
if(rc > 0) {
debug("Skipping '%s'", filename);
continue;
}
ntests++;
if(rc == 0) {
printf("%s PASS\n", filename);
continue;
}
printf("ERROR in test %s", filename);
if(access("tests/tests.log", R_OK) == 0) {
printf(": here's tests/tests.log\n");
printf("------\n");
rc = system("tail tests/tests.log");
} else {
printf("\n");
}
goto error;
}
printf("------\n");
printf("Total of %d test file%s run.\n", ntests, ntests > 1 ? "s" : "");
if(namelist) {
free(namelist);
}
return 0;
error:
if(namelist) {
free(namelist);
}
return rc != 0 ? rc : 1;
}

View File

@@ -0,0 +1,8 @@
#include <stdio.h>
#include "your_library.h"
int main()
{
printf("WEASELS: %d\n", howmanyweasels());
return 0;
}

View File

@@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif

View File

@@ -0,0 +1,2 @@
bstrlib.*
devpkg

View File

@@ -0,0 +1,30 @@
BSTRLIB_BASE_URL ?= https://raw.githubusercontent.com/websnarf/bstrlib/208b1f2a4dfc96b806ed499bd1909e87ec15981d
PREFIX ?= /usr/local
CFLAGS = -g -Wall -I${PREFIX}/apr/include/apr-1 -I${PREFIX}/apr/include/apr-util-1
LDFLAGS = -L${PREFIX}/apr/lib
LDLIBS = -lapr-1 -pthread -laprutil-1
all: devpkg
devpkg: bstrlib.o db.o shell.o commands.o
prebuild:
sudo mkdir -p /etc/ld.so.conf.d
echo $(DESTDIR)/$(PREFIX)/lib | sudo tee /etc/ld.so.conf.d/devpkg.conf
sudo ldconfig
install: all
install -d $(DESTDIR)/$(PREFIX)/bin/
install devpkg $(DESTDIR)/$(PREFIX)/bin/
clean:
$(RM) *.o
$(RM) devpkg
$(RM) *.dSYM
$(RM) bstrlib.c bstrlib.h
bstrlib.c: bstrlib.h
curl -sSLO $(BSTRLIB_BASE_URL)/bstrlib.c
bstrlib.h:
curl -sSLO $(BSTRLIB_BASE_URL)/bstrlib.h

View File

@@ -0,0 +1,47 @@
# `devpkg`
This is a thingy that downloads, builds, and installs stuff!
## usage
Before you can do the fun part, you need to initialize the bits:
``` bash
devpkg -S
```
Install something via URL:
``` bash
devpkg -I http://example.org/foo.tar.bz2
```
Install something via URL with custom arguments for configure, make, and
install:
``` bash
devpkg -I http://example.org/foo.tar.bz2 -c '--no-flair' -m 'CFLAGS+=-Wall' -i '-n'
```
Perform a fetch *only* without building or installing:
``` bash
devpkg -F http://example.org/foo.tar.bz2
```
Perform a build *only* without installing:
``` bash
devpkg -B http://example.org/foo.tar.bz2
```
List the stuff that's been installed:
``` bash
devpkg -L
```
<!--
vim:filetype=markdown
-->

View File

@@ -0,0 +1,174 @@
#include <apr_uri.h>
#include <apr_fnmatch.h>
#include <unistd.h>
#include "commands.h"
#include "dbg.h"
#include "bstrlib.h"
#include "db.h"
#include "shell.h"
int Command_depends(apr_pool_t *p, const char *path)
{
FILE *in = NULL;
bstring line = NULL;
in = fopen(path, "r");
check(in != NULL, "Failed to open downloaded depends: %s", path);
for(line = bgets((bNgetc)fgetc, in, '\n'); line != NULL;
line = bgets((bNgetc)fgetc, in, '\n'))
{
btrimws(line);
log_info("Processing depends: %s", bdata(line));
int rc = Command_install(p, bdata(line), NULL, NULL, NULL);
check(rc == 0, "Failed to install: %s", bdata(line));
bdestroy(line);
}
fclose(in);
return 0;
error:
if(line) bdestroy(line);
if(in) fclose(in);
return -1;
}
int Command_fetch(apr_pool_t *p, const char *url, int fetch_only)
{
apr_uri_t info = {.port = 0};
int rc = 0;
const char *depends_file = NULL;
apr_status_t rv = apr_uri_parse(p, url, &info);
check(rv == APR_SUCCESS, "Failed to parse URL: %s", url);
if(apr_fnmatch(GIT_PAT, info.path, 0) == APR_SUCCESS) {
rc = Shell_exec(GIT_SH, "URL", url, NULL);
check(rc == 0, "git failed.");
} else if(apr_fnmatch(DEPEND_PAT, info.path, 0) == APR_SUCCESS) {
check(!fetch_only, "No point in fetching a DEPENDS file.");
if(info.scheme) {
depends_file = DEPENDS_PATH;
rc = Shell_exec(CURL_SH, "URL", url, "TARGET", depends_file, NULL);
check(rc == 0, "Curl failed.");
} else {
depends_file = info.path;
}
// recursively process the devpkg list
log_info("Building according to DEPENDS: %s", url);
rv = Command_depends(p, depends_file);
check(rv == 0, "Failed to process the DEPENDS: %s", url);
// this indicates that nothing needs to be done
return 0;
} else if(apr_fnmatch(TAR_GZ_PAT, info.path, 0) == APR_SUCCESS) {
if(info.scheme) {
rc = Shell_exec(CURL_SH,
"URL", url,
"TARGET", TAR_GZ_SRC, NULL);
check(rc == 0, "Failed to curl source: %s", url);
}
rv = apr_dir_make_recursive(BUILD_DIR,
APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
check(rv == APR_SUCCESS, "Failed to make directory %s", BUILD_DIR);
rc = Shell_exec(TAR_SH, "FILE", TAR_GZ_SRC, NULL);
check(rc == 0, "Failed to untar %s", TAR_GZ_SRC);
} else if(apr_fnmatch(TAR_BZ2_PAT, info.path, 0) == APR_SUCCESS) {
if(info.scheme) {
rc = Shell_exec(CURL_SH, "URL", url, "TARGET", TAR_BZ2_SRC, NULL);
check(rc == 0, "Curl failed.");
}
apr_status_t rc = apr_dir_make_recursive(BUILD_DIR,
APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
check(rc == 0, "Failed to make directory %s", BUILD_DIR);
rc = Shell_exec(TAR_SH, "FILE", TAR_BZ2_SRC, NULL);
check(rc == 0, "Failed to untar %s", TAR_BZ2_SRC);
} else {
sentinel("Don't know how to handle %s", url);
}
// indicates that an install needs to actually run
return 1;
error:
return -1;
}
int Command_build(apr_pool_t *p, const char *url, const char *configure_opts,
const char *make_opts, const char *install_opts)
{
int rc = 0;
check(access(BUILD_DIR, X_OK | R_OK | W_OK) == 0,
"Build directory doesn't exist: %s", BUILD_DIR);
// actually do an install
if(access(CONFIG_SCRIPT, X_OK) == 0) {
log_info("Has a configure script, running it.");
rc = Shell_exec(CONFIGURE_SH, "OPTS", configure_opts, NULL);
check(rc == 0, "Failed to configure");
}
rc = Shell_exec(MAKE_SH, "OPTS", make_opts, NULL);
check(rc == 0, "Failed to build.");
rc = Shell_exec(INSTALL_SH,
"TARGET", install_opts ? install_opts : "install",
NULL);
check(rc == 0, "Failed to install.");
rc = Shell_exec(CLEANUP_SH, NULL);
check(rc == 0, "Failed to cleanup after build.");
rc = DB_update(url);
check(rc == 0, "Failed to add this package to the database.");
return 0;
error:
return -1;
}
int Command_install(apr_pool_t *p, const char *url, const char *configure_opts,
const char *make_opts, const char *install_opts)
{
int rc = 0;
check(Shell_exec(CLEANUP_SH, NULL) == 0, "Failed to cleanup before building.");
rc = DB_find(url);
check(rc != -1, "Error checking the install database.");
if(rc == 1) {
log_info("Package %s already installed.", url);
return 0;
}
rc = Command_fetch(p, url, 0);
if(rc == 1) {
rc = Command_build(p, url, configure_opts, make_opts, install_opts);
check(rc == 0, "Failed to build: %s", url);
} else if(rc == 0) {
// no install needed
log_info("Depends successfully installed: %s", url);
} else {
// had an error
sentinel("Install failed: %s", url);
}
Shell_exec(CLEANUP_SH, NULL);
return 0;
error:
Shell_exec(CLEANUP_SH, NULL);
return -1;
}

View File

@@ -0,0 +1,31 @@
#ifndef _commands_h
#define _commands_h
#include <apr_pools.h>
#define DEPENDS_PATH "/tmp/DEPENDS"
#define TAR_GZ_SRC "/tmp/pkg-src.tar.gz"
#define TAR_BZ2_SRC "/tmp/pkg-src.tar.bz2"
#define BUILD_DIR "/tmp/pkg-build"
#define GIT_PAT "*.git"
#define DEPEND_PAT "*DEPENDS"
#define TAR_GZ_PAT "*.tar.gz"
#define TAR_BZ2_PAT "*.tar.bz2"
#define CONFIG_SCRIPT "/tmp/pkg-build/configure"
enum CommandType {
COMMAND_NONE, COMMAND_INSTALL, COMMAND_LIST, COMMAND_FETCH,
COMMAND_INIT, COMMAND_BUILD
};
int Command_fetch(apr_pool_t *p, const char *url, int fetch_only);
int Command_install(apr_pool_t *p, const char *url, const char *configure_opts,
const char *make_opts, const char *install_opts);
int Command_depends(apr_pool_t *p, const char *path);
int Command_build(apr_pool_t *p, const char *url, const char *configure_opts,
const char *make_opts, const char *install_opts);
#endif

View File

@@ -0,0 +1,125 @@
#include <unistd.h>
#include <apr_errno.h>
#include <apr_file_io.h>
#include "db.h"
#include "bstrlib.h"
#include "dbg.h"
static FILE *DB_open(const char *path, const char *mode)
{
return fopen(path, mode);
}
static void DB_close(FILE *db)
{
fclose(db);
}
static bstring DB_load()
{
FILE *db = NULL;
bstring data = NULL;
db = DB_open(DB_FILE, "r");
check(db, "Failed to open database: %s", DB_FILE);
data = bread((bNread)fread, db);
check(data, "Failed to read from db file: %s", DB_FILE);
DB_close(db);
return data;
error:
if(db) DB_close(db);
if(data) bdestroy(data);
return NULL;
}
int DB_update(const char *url)
{
if(DB_find(url)) {
log_info("Already recorded as installed: %s", url);
}
FILE *db = DB_open(DB_FILE, "a+");
check(db, "Failed to open DB file: %s", DB_FILE);
bstring line = bfromcstr(url);
bconchar(line, '\n');
int rc = fwrite(line->data, blength(line), 1, db);
check(rc == 1, "Failed to append to the db.");
return 0;
error:
if(db) DB_close(db);
return -1;
}
int DB_find(const char *url)
{
bstring data = NULL;
bstring line = bfromcstr(url);
int res = -1;
data = DB_load();
check(data, "Failed to load: %s", DB_FILE);
if(binstr(data, 0, line) == BSTR_ERR) {
res = 0;
} else {
res = 1;
}
error: // fallthrough
if(data) bdestroy(data);
if(line) bdestroy(line);
return res;
}
int DB_init()
{
apr_pool_t *p = NULL;
apr_pool_initialize();
apr_pool_create(&p, NULL);
if(access(DB_DIR, W_OK | X_OK) == -1) {
apr_status_t rc = apr_dir_make_recursive(DB_DIR,
APR_UREAD | APR_UWRITE | APR_UEXECUTE |
APR_GREAD | APR_GWRITE | APR_GEXECUTE, p);
check(rc == APR_SUCCESS, "Failed to make database dir: %s", DB_DIR);
}
if(access(DB_FILE, W_OK) == -1) {
FILE *db = DB_open(DB_FILE, "w");
check(db, "Cannot open database: %s", DB_FILE);
DB_close(db);
}
apr_pool_destroy(p);
return 0;
error:
apr_pool_destroy(p);
return -1;
}
int DB_list()
{
bstring data = DB_load();
check(data, "Failed to read load: %s", DB_FILE);
printf("%s", bdata(data));
bdestroy(data);
return 0;
error:
return -1;
}

View File

@@ -0,0 +1,12 @@
#ifndef _db_h
#define _db_h
#define DB_FILE "/usr/local/.devpkg/db"
#define DB_DIR "/usr/local/.devpkg"
int DB_init();
int DB_list();
int DB_update(const char *url);
int DB_find(const char *url);
#endif

View File

@@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif

View File

@@ -0,0 +1,104 @@
#include <stdio.h>
#include <apr_general.h>
#include <apr_getopt.h>
#include <apr_strings.h>
#include <apr_lib.h>
#include "dbg.h"
#include "db.h"
#include "commands.h"
int main(int argc, const char const *argv[])
{
apr_pool_t *p = NULL;
apr_pool_initialize();
apr_pool_create(&p, NULL);
apr_getopt_t *opt;
apr_status_t rv;
char ch = '\0';
const char *optarg = NULL;
const char *config_opts = NULL;
const char *install_opts = NULL;
const char *make_opts = NULL;
const char *url = NULL;
enum CommandType request = COMMAND_NONE;
rv = apr_getopt_init(&opt, p, argc, argv);
while(apr_getopt(opt, "I:Lc:m:i:d:SF:B:", &ch, &optarg) == APR_SUCCESS) {
switch(ch) {
case 'I':
request = COMMAND_INSTALL;
url = optarg;
break;
case 'L':
request = COMMAND_LIST;
break;
case 'c':
config_opts = optarg;
break;
case 'm':
make_opts = optarg;
break;
case 'i':
install_opts = optarg;
break;
case 'S':
request = COMMAND_INIT;
break;
case 'F':
request = COMMAND_FETCH;
url = optarg;
break;
case 'B':
request = COMMAND_BUILD;
url = optarg;
break;
}
}
switch(request) {
case COMMAND_INSTALL:
check(url, "You must at least give a URL.");
Command_install(p, url, config_opts, make_opts, install_opts);
break;
case COMMAND_LIST:
DB_list();
break;
case COMMAND_FETCH:
check(url != NULL, "You must give a URL.");
Command_fetch(p, url, 1);
log_info("Downloaded to %s and in /tmp/", BUILD_DIR);
break;
case COMMAND_BUILD:
check(url, "You must at least give a URL.");
Command_build(p, url, config_opts, make_opts, install_opts);
break;
case COMMAND_INIT:
rv = DB_init();
check(rv == 0, "Failed to make the database.");
break;
default:
sentinel("Invalid command given.");
}
return 0;
error:
return 1;
}

View File

@@ -0,0 +1,120 @@
#include "shell.h"
#include "dbg.h"
#include <stdarg.h>
int Shell_exec(Shell template, ...)
{
apr_pool_t *p = NULL;
int rc = -1;
apr_status_t rv = APR_SUCCESS;
va_list argp;
const char *key = NULL;
const char *arg = NULL;
int i = 0;
rv = apr_pool_create(&p, NULL);
check(rv == APR_SUCCESS, "Failed to create pool.");
va_start(argp, template);
for(key = va_arg(argp, const char *);
key != NULL;
key = va_arg(argp, const char *))
{
arg = va_arg(argp, const char *);
for(i = 0; template.args[i] != NULL; i++) {
if(strcmp(template.args[i], key) == 0) {
template.args[i] = arg;
break; // found it
}
}
}
rc = Shell_run(p, &template);
apr_pool_destroy(p);
va_end(argp);
return rc;
error:
if(p) {
apr_pool_destroy(p);
}
return rc;
}
int Shell_run(apr_pool_t *p, Shell *cmd)
{
apr_procattr_t *attr;
apr_status_t rv;
apr_proc_t newproc;
rv = apr_procattr_create(&attr, p);
check(rv == APR_SUCCESS, "Failed to create proc attr.");
rv = apr_procattr_io_set(attr, APR_NO_PIPE, APR_NO_PIPE, APR_NO_PIPE);
check(rv == APR_SUCCESS, "Failed to set IO of command.");
rv = apr_procattr_dir_set(attr, cmd->dir);
check(rv == APR_SUCCESS, "Failed to set root to %s", cmd->dir);
rv = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
check(rv == APR_SUCCESS, "Failed to set cmd type.");
rv = apr_proc_create(&newproc, cmd->exe, cmd->args, NULL, attr, p);
check(rv == APR_SUCCESS, "Failed to run command.");
rv = apr_proc_wait(&newproc, &cmd->exit_code, &cmd->exit_why, APR_WAIT);
check(rv == APR_CHILD_DONE, "Failed to wait.");
check(cmd->exit_code == 0, "%s exited badly.", cmd->exe);
check(cmd->exit_why == APR_PROC_EXIT, "%s was killed or crashed", cmd->exe);
return 0;
error:
return -1;
}
Shell CLEANUP_SH = {
.exe = "rm",
.dir = "/tmp",
.args = {"rm", "-rf", "/tmp/pkg-build", "/tmp/pkg-src.tar.gz",
"/tmp/pkg-src.tar.bz2", "/tmp/DEPENDS", NULL}
};
Shell GIT_SH = {
.dir = "/tmp",
.exe = "git",
.args = {"git", "clone", "URL", "pkg-build", NULL}
};
Shell TAR_SH = {
.dir = "/tmp/pkg-build",
.exe = "tar",
.args = {"tar", "-xzf", "FILE", "--strip-components", "1", NULL}
};
Shell CURL_SH = {
.dir = "/tmp",
.exe = "curl",
.args = {"curl", "-L", "-o", "TARGET", "URL", NULL}
};
Shell CONFIGURE_SH = {
.exe = "./configure",
.dir = "/tmp/pkg-build",
.args = {"configure", "OPTS", NULL},
};
Shell MAKE_SH = {
.exe = "make",
.dir = "/tmp/pkg-build",
.args = {"make", "OPTS", NULL}
};
Shell INSTALL_SH = {
.exe = "sudo",
.dir = "/tmp/pkg-build",
.args = {"sudo", "make", "TARGET", NULL}
};

View File

@@ -0,0 +1,31 @@
#ifndef _shell_h
#define _shell_h
#define MAX_COMMAND_ARGS 100
#include <apr_thread_proc.h>
typedef struct Shell {
const char *dir;
const char *exe;
apr_procattr_t *attr;
apr_proc_t proc;
apr_exit_why_e exit_why;
int exit_code;
const char *args[MAX_COMMAND_ARGS];
} Shell;
int Shell_run(apr_pool_t *p, Shell *cmd);
int Shell_exec(Shell cmd, ...);
extern Shell CLEANUP_SH;
extern Shell GIT_SH;
extern Shell TAR_SH;
extern Shell CURL_SH;
extern Shell CONFIGURE_SH;
extern Shell MAKE_SH;
extern Shell INSTALL_SH;
#endif

View File

@@ -0,0 +1,8 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
puts("Hello world.");
return 0;
}

View File

@@ -0,0 +1,25 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
// go through each string in argv
// why am I skipping argv[0];
for(i = 1; i < argc; i++) {
printf("arg %d: %s\n", i, argv[i]);
}
// let's make our own array of strings
char *states[] = {
"California", "Oregon",
"Washington", "Texas"
};
int num_states = 4;
for(i = 0; i < num_states; i++) {
printf("state %d: %s\n", i, states[i]);
}
return 0;
}

View File

@@ -0,0 +1,27 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
// go through each string in argv
int i = 0;
while(i < argc) {
printf("arg %d: %s\n", i, argv[i]);
i++;
}
// let's make our own array of strings
char *states[] = {
"California", "Oregon",
"Washington", "Texas"
};
int num_states = 4;
i = 0; // watch for this
while(i < num_states) {
printf("state %d: %s\n", i, states[i]);
i++;
}
return 0;
}

View File

@@ -0,0 +1,21 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
if(argc == 1) {
printf("You only have one argument. You suck.\n");
} else if(argc > 1 && argc < 4) {
printf("Here's your arguments:\n");
for(i = 0; i < argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
} else {
printf("You have too many arguments. You suck.\n");
}
return 0;
}

View File

@@ -0,0 +1,55 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("ERROR: You need one argument.\n");
// this is how you abort a program
return 1;
}
int i = 0;
for(i = 0; argv[1][i] != '\0'; i++) {
char letter = argv[1][i];
switch(letter) {
case 'a':
case 'A':
printf("%d: 'A'\n", i);
break;
case 'e':
case 'E':
printf("%d: 'E'\n", i);
break;
case 'i':
case 'I':
printf("%d: 'I'\n", i);
break;
case 'o':
case 'O':
printf("%d: 'O'\n", i);
break;
case 'u':
case 'U':
printf("%d: 'U'\n", i);
break;
case 'y':
case 'Y':
if(i > 2) {
// it's only sometimes y
printf("%d: 'Y'\n", i);
}
break;
default:
printf("%d: %c is not a vowel\n", i, letter);
}
}
return 0;
}

View File

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

View File

@@ -0,0 +1,54 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
// create two arrays we care about
int ages[] = {23, 43, 12, 89, 2};
char *names[] = {
"Alan", "Frank",
"Mary", "John", "Lisa"
};
// safely get the size of ages
int count = sizeof(ages) / sizeof(int);
int i = 0;
// first way using indexing
for(i = 0; i < count; i++) {
printf("%s has %d years alive.\n",
names[i], ages[i]);
}
printf("---\n");
// setup the pointers to the start of the arrays
int *cur_age = ages;
char **cur_name = names;
// second way using pointers
for(i = 0; i < count; i++) {
printf("%s is %d years old.\n",
*(cur_name+i), *(cur_age+i));
}
printf("---\n");
// third way, pointers are just arrays
for(i = 0; i < count; i++) {
printf("%s is %d years old again.\n",
cur_name[i], cur_age[i]);
}
printf("---\n");
// fourth way with pointers in a stupid complex way
for(cur_name = names, cur_age = ages;
(cur_age - ages) < count;
cur_name++, cur_age++)
{
printf("%s lived %d years so far.\n",
*cur_name, *cur_age);
}
return 0;
}

View File

@@ -0,0 +1,73 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char *name;
int age;
int height;
int weight;
};
struct Person *Person_create(char *name, int age, int height, int weight)
{
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->name = strdup(name);
who->age = age;
who->height = height;
who->weight = weight;
return who;
}
void Person_destroy(struct Person *who)
{
assert(who != NULL);
free(who->name);
free(who);
}
void Person_print(struct Person *who)
{
printf("Name: %s\n", who->name);
printf("\tAge: %d\n", who->age);
printf("\tHeight: %d\n", who->height);
printf("\tWeight: %d\n", who->weight);
}
int main(int argc, char *argv[])
{
// make two people structures
struct Person *joe = Person_create(
"Joe Alex", 32, 64, 140);
struct Person *frank = Person_create(
"Frank Blank", 20, 72, 180);
// print them out and where they are in memory
printf("Joe is at memory location %p:\n", joe);
Person_print(joe);
printf("Frank is at memory location %p:\n", frank);
Person_print(frank);
// make everyone age 20 years and print them again
joe->age += 20;
joe->height -= 2;
joe->weight += 40;
Person_print(joe);
frank->age += 20;
frank->weight += 20;
Person_print(frank);
// destroy them both so we clean up
Person_destroy(joe);
Person_destroy(frank);
return 0;
}

View File

@@ -0,0 +1,234 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <libgen.h>
#define MAX_DATA 512
#define MAX_ROWS 100
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
char street[MAX_DATA];
};
struct Database {
struct Address rows[MAX_ROWS];
};
struct Connection {
FILE *file;
struct Database *db;
};
void Database_close(struct Connection *conn);
void die(const char *message, struct Connection *conn)
{
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
Database_close(conn);
exit(1);
}
void Address_print(struct Address *addr)
{
printf("%d %s %s \"%s\"\n",
addr->id, addr->name, addr->email, addr->street);
}
void Database_load(struct Connection *conn)
{
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
if(rc != 1) die("Failed to load database.", conn);
}
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if(!conn) die("Memory error", conn);
conn->db = malloc(sizeof(struct Database));
if(!conn->db) die("Memory error", conn);
if(mode == 'c') {
conn->file = fopen(filename, "w");
} else {
conn->file = fopen(filename, "r+");
if(conn->file) {
Database_load(conn);
}
}
if(!conn->file) die("Failed to open the file", conn);
return conn;
}
void Database_close(struct Connection *conn)
{
if(conn) {
if(conn->file) fclose(conn->file);
if(conn->db) free(conn->db);
free(conn);
}
}
void Database_write(struct Connection *conn)
{
rewind(conn->file);
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
if(rc != 1) die("Failed to write database.", conn);
rc = fflush(conn->file);
if(rc == -1) die("Connot flush database.", conn);
}
void Database_create(struct Connection *conn)
{
int i = 0;
for(i = 0; i < MAX_ROWS; i++) {
// make a prototype to initialize it
struct Address addr = {.id = i, .set = 0};
// then just assign it
conn->db->rows[i] = addr;
}
}
void Database_set(struct Connection *conn, int id, const char *name,
const char *email, const char *street)
{
struct Address *addr = &conn->db->rows[id];
if(addr->set) die("Already set, delete it first", conn);
addr->set = 1;
// WARNING: bug, read the "How To Break It" and fix this
char *res = strncpy(addr->name, name, MAX_DATA);
// demonstrate the strncpy bug
if(!res) die("Name copy failed", conn);
res = strncpy(addr->email, email, MAX_DATA);
if(!res) die("Email copy failed", conn);
res = strncpy(addr->street, street, MAX_DATA);
if(!res) die("Street copy failed", conn);
}
void Database_get(struct Connection *conn, int id)
{
struct Address *addr = &conn->db->rows[id];
if(addr->set) {
Address_print(addr);
} else {
die("ID is not set", conn);
}
}
void Database_delete(struct Connection *conn, int id)
{
struct Address addr = {.id = id, .set = 0};
conn->db->rows[id] = addr;
}
void Database_list(struct Connection *conn)
{
int i = 0;
struct Database *db = conn->db;
for(i = 0; i < MAX_ROWS; i++) {
struct Address *cur = &db->rows[i];
if(cur->set) {
Address_print(cur);
}
}
}
void Database_find(struct Connection *conn, char *search)
{
int i = 0;
struct Database *db = conn->db;
for(i = 0; i < MAX_ROWS; i++) {
struct Address *cur = &db->rows[i];
if(cur->set) {
if(strstr(cur->email, search) != NULL ||
strstr(cur->name, search) != NULL ||
strstr(cur->street, search) != NULL) {
Address_print(cur);
}
}
}
}
int main(int argc, char *argv[])
{
char usage[64];
sprintf(usage, "USAGE: %s <dbfile> <action> [action params]", basename(argv[0]));
if(argc < 3) die(usage, NULL);
char *filename = argv[1];
char action = argv[2][0];
struct Connection *conn = Database_open(filename, action);
int id = 0;
if(argc > 3) id = atoi(argv[3]);
if(id >= MAX_ROWS) die("There's not that many records.", conn);
switch(action) {
case 'c':
Database_create(conn);
Database_write(conn);
break;
case 'g':
if(argc != 4) die("Need an id to get", conn);
Database_get(conn, id);
break;
case 's':
if(argc != 7) die("Need id, name, email, and street to set", conn);
Database_set(conn, id, argv[4], argv[5], argv[6]);
Database_write(conn);
break;
case 'd':
if(argc != 4) die("Need id to delete", conn);
Database_delete(conn, id);
Database_write(conn);
break;
case 'f':
if(argc != 4) die("Need something to find", conn);
Database_find(conn, argv[3]);
break;
case 'l':
Database_list(conn);
break;
default:
die("Invalid action, only: c=create, g=get, s=set, d=del, l=list, f=find", conn);
}
Database_close(conn);
return 0;
}

View File

@@ -0,0 +1,86 @@
#include <stdio.h>
#include <stdlib.h>
#define MAX_STACK 1024
#define STACK_SENTINEL -1
struct Stack {
int l[MAX_STACK];
};
struct Stack *Stack_create()
{
struct Stack *s = malloc(sizeof(struct Stack));
if(!s) { return NULL; }
int i = 0;
for(i = 0; i < MAX_STACK; i++) {
s->l[i] = STACK_SENTINEL;
}
return s;
}
int Stack_push(struct Stack *s, int v)
{
if(v <= STACK_SENTINEL) {
return STACK_SENTINEL;
}
int i = 0;
for(i = 0; i < MAX_STACK; i++) {
if(s->l[i] == STACK_SENTINEL) {
s->l[i] = v;
return i;
}
}
return STACK_SENTINEL;
}
int Stack_pop(struct Stack *s)
{
int i = 0;
int v = 0;
for(i = 0; i < MAX_STACK; i++) {
if(s->l[i] == STACK_SENTINEL) {
v = s->l[i-1];
s->l[i-1] = STACK_SENTINEL;
return v;
}
}
return STACK_SENTINEL;
}
int Stack_size(struct Stack *s)
{
int i = 0;
for(i = 0; i < MAX_STACK; i++) {
if(s->l[i] == STACK_SENTINEL) {
return i;
}
}
return STACK_SENTINEL;
}
int main(int argc, char *argv[])
{
struct Stack *s = Stack_create();
printf("size: %d\n", Stack_size(s));
Stack_push(s, 10);
Stack_push(s, 20);
Stack_push(s, 40);
printf("size: %d\n", Stack_size(s));
printf("pop: %d\n", Stack_pop(s));
printf("pop: %d\n", Stack_pop(s));
printf("size: %d\n", Stack_size(s));
printf("pop: %d\n", Stack_pop(s));
printf("pop: %d\n", Stack_pop(s));
return 0;
}

View File

@@ -0,0 +1,198 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_DATA 512
#define MAX_ROWS 100
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};
struct Database {
struct Address rows[MAX_ROWS];
};
struct Connection {
FILE *file;
struct Database *db;
};
void die(const char *message)
{
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}
void Address_print(struct Address *addr)
{
printf("%d %s %s\n",
addr->id, addr->name, addr->email);
}
void Database_load(struct Connection *conn)
{
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
if(rc != 1) die("Failed to load database.");
}
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if(!conn) die("Memory error");
conn->db = malloc(sizeof(struct Database));
if(!conn->db) die("Memory error");
if(mode == 'c') {
conn->file = fopen(filename, "w");
} else {
conn->file = fopen(filename, "r+");
if(conn->file) {
Database_load(conn);
}
}
if(!conn->file) die("Failed to open the file");
return conn;
}
void Database_close(struct Connection *conn)
{
if(conn) {
if(conn->file) fclose(conn->file);
if(conn->db) free(conn->db);
free(conn);
}
}
void Database_write(struct Connection *conn)
{
rewind(conn->file);
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
if(rc != 1) die("Failed to write database.");
rc = fflush(conn->file);
if(rc == -1) die("Connot flush database.");
}
void Database_create(struct Connection *conn)
{
int i = 0;
for(i = 0; i < MAX_ROWS; i++) {
// make a prototype to initialize it
struct Address addr = {.id = i, .set = 0};
// then just assign it
conn->db->rows[i] = addr;
}
}
void Database_set(struct Connection *conn, int id, const char *name, const char *email)
{
struct Address *addr = &conn->db->rows[id];
if(addr->set) die("Already set, delete it first");
addr->set = 1;
// WARNING: bug, read the "How To Break It" and fix this
char *res = strncpy(addr->name, name, MAX_DATA);
// demonstrate the strncpy bug
if(!res) die("Name copy failed");
res = strncpy(addr->email, email, MAX_DATA);
if(!res) die("Email copy failed");
}
void Database_get(struct Connection *conn, int id)
{
struct Address *addr = &conn->db->rows[id];
if(addr->set) {
Address_print(addr);
} else {
die("ID is not set");
}
}
void Database_delete(struct Connection *conn, int id)
{
struct Address addr = {.id = id, .set = 0};
conn->db->rows[id] = addr;
}
void Database_list(struct Connection *conn)
{
int i = 0;
struct Database *db = conn->db;
for(i = 0; i < MAX_ROWS; i++) {
struct Address *cur = &db->rows[i];
if(cur->set) {
Address_print(cur);
}
}
}
int main(int argc, char *argv[])
{
if(argc < 3) die("USAGE: ex17 <dbfile> <action> [action params]");
char *filename = argv[1];
char action = argv[2][0];
struct Connection *conn = Database_open(filename, action);
int id = 0;
if(argc > 3) id = atoi(argv[3]);
if(id >= MAX_ROWS) die("There's not that many records.");
switch(action) {
case 'c':
Database_create(conn);
Database_write(conn);
break;
case 'g':
if(argc != 4) die("Need an id to get");
Database_get(conn, id);
break;
case 's':
if(argc != 6) die("Need id, name, email to set");
Database_set(conn, id, argv[4], argv[5]);
Database_write(conn);
break;
case 'd':
if(argc != 4) die("Need id to delete");
Database_delete(conn, id);
Database_write(conn);
break;
case 'l':
Database_list(conn);
break;
default:
die("Invalid action, only: c=create, g=get, s=set, d=del, l=list");
}
Database_close(conn);
return 0;
}

View File

@@ -0,0 +1,119 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
/** Our old friend die from ex17. */
void die(const char *message)
{
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}
// a typedef creates a fake type, in this
// case for a function pointer
typedef int (*compare_cb)(int a, int b);
/**
* A classic bubble sort function that uses the
* compare_cb to do the sorting.
*/
int *bubble_sort(int *numbers, int count, compare_cb cmp)
{
int temp = 0;
int i = 0;
int j = 0;
int *target = malloc(count * sizeof(int));
if(!target) die("Memory error.");
memcpy(target, numbers, count * sizeof(int));
for(i = 0; i < count; i++) {
for(j = 0; j < count - 1; j++) {
if(cmp(target[j], target[j+1]) > 0) {
temp = target[j+1];
target[j+1] = target[j];
target[j] = temp;
}
}
}
return target;
}
int sorted_order(int a, int b)
{
return a - b;
}
int reverse_order(int a, int b)
{
return b - a;
}
int strange_order(int a, int b)
{
if(a == 0 || b == 0) {
return 0;
} else {
return a % b;
}
}
/**
* Used to test that we are sorting things correctly
* by doing the sort and printing it out.
*/
void test_sorting(int *numbers, int count, compare_cb cmp)
{
int i = 0;
int *sorted = bubble_sort(numbers, count, cmp);
if(!sorted) die("Failed to sort as requested.");
for(i = 0; i < count; i++) {
printf("%d ", sorted[i]);
}
printf("\n");
free(sorted);
unsigned char *data = (unsigned char *)cmp;
for(i = 0; i < 25; i++) {
printf("%02x:", data[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
if(argc < 2) die("USAGE: ex18 4 3 1 5 6");
int count = argc - 1;
int i = 0;
char **inputs = argv + 1;
int *numbers = malloc(count * sizeof(int));
if(!numbers) die("Memory error.");
for(i = 0; i < count; i++) {
numbers[i] = atoi(inputs[i]);
}
test_sorting(numbers, count, sorted_order);
test_sorting(numbers, count, reverse_order);
test_sorting(numbers, count, strange_order);
free(numbers);
return 0;
}

View File

@@ -0,0 +1,111 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
/** Our old friend die from ex17. */
void die(const char *message)
{
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}
// a typedef creates a fake type, in this
// case for a function pointer
typedef int (*compare_cb)(int a, int b);
/**
* A classic bubble sort function that uses the
* compare_cb to do the sorting.
*/
int *bubble_sort(int *numbers, int count, compare_cb cmp)
{
int temp = 0;
int i = 0;
int j = 0;
int *target = malloc(count * sizeof(int));
if(!target) die("Memory error.");
memcpy(target, numbers, count * sizeof(int));
for(i = 0; i < count; i++) {
for(j = 0; j < count - 1; j++) {
if(cmp(target[j], target[j+1]) > 0) {
temp = target[j+1];
target[j+1] = target[j];
target[j] = temp;
}
}
}
return target;
}
int sorted_order(int a, int b)
{
return a - b;
}
int reverse_order(int a, int b)
{
return b - a;
}
int strange_order(int a, int b)
{
if(a == 0 || b == 0) {
return 0;
} else {
return a % b;
}
}
/**
* Used to test that we are sorting things correctly
* by doing the sort and printing it out.
*/
void test_sorting(int *numbers, int count, compare_cb cmp)
{
int i = 0;
int *sorted = bubble_sort(numbers, count, cmp);
if(!sorted) die("Failed to sort as requested.");
for(i = 0; i < count; i++) {
printf("%d ", sorted[i]);
}
printf("\n");
free(sorted);
}
int main(int argc, char *argv[])
{
if(argc < 2) die("USAGE: ex18 4 3 1 5 6");
int count = argc - 1;
int i = 0;
char **inputs = argv + 1;
int *numbers = malloc(count * sizeof(int));
if(!numbers) die("Memory error.");
for(i = 0; i < count; i++) {
numbers[i] = atoi(inputs[i]);
}
test_sorting(numbers, count, sorted_order);
test_sorting(numbers, count, reverse_order);
test_sorting(numbers, count, strange_order);
free(numbers);
return 0;
}

View File

@@ -0,0 +1,225 @@
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include "ex19.h"
int Monster_attack(void *self, int damage)
{
assert(self != NULL);
Monster *monster = self;
printf("You attack %s!\n", monster->_(description));
monster->hit_points -= damage;
if(monster->hit_points > 0) {
printf("It is still alive.\n");
return 0;
} else {
printf("It is dead!\n");
return 1;
}
}
int Monster_init(void *self)
{
assert(self != NULL);
Monster *monster = self;
monster->hit_points = 10;
return 1;
}
Object MonsterProto = {
.init = Monster_init,
.attack = Monster_attack
};
void *Room_move(void *self, Direction direction)
{
assert(self != NULL);
Room *room = self;
Room *next = NULL;
if(direction == NORTH && room->north) {
printf("You go north, into:\n");
next = room->north;
} else if(direction == SOUTH && room->south) {
printf("You go south, into:\n");
next = room->south;
} else if(direction == EAST && room->east) {
printf("You go east, into:\n");
next = room->east;
} else if(direction == WEST && room->west) {
printf("You go west, into:\n");
next = room->west;
} else {
printf("You can't go that direction.");
next = NULL;
}
if(next) {
next->_(describe)(next);
}
return next;
}
int Room_attack(void *self, int damage)
{
assert(self != NULL);
Room *room = self;
Monster *monster = room->bad_guy;
if(monster) {
monster->_(attack)(monster, damage);
return 1;
} else {
printf("You flail in the air at nothing. Idiot.\n");
return 0;
}
}
Object RoomProto = {
.move = Room_move,
.attack = Room_attack
};
void *Map_move(void *self, Direction direction)
{
assert(self != NULL);
Map *map = self;
Room *location = map->location;
Room *next = NULL;
next = location->_(move)(location, direction);
if(next) {
map->location = next;
}
return next;
}
int Map_attack(void *self, int damage)
{
assert(self != NULL);
Map *map = self;
Room *location = map->location;
return location->_(attack)(location, damage);
}
int Map_init(void *self)
{
assert(self != NULL);
Map *map = self;
// make some rooms for a small map
Room *hall = NEW(Room, "The great Hall");
Room *throne = NEW(Room, "The throne room");
Room *arena = NEW(Room, "The arena, with the minotaur");
Room *kitchen = NEW(Room, "Kitchen, you have the knife now");
// put the bad guy in the arena
arena->bad_guy = NEW(Monster, "The evil minotaur");
// setup the map rooms
hall->north = throne;
throne->west = arena;
throne->east = kitchen;
throne->south = hall;
arena->east = throne;
kitchen->west = throne;
// start the map and the characters off in the hall
map->start = hall;
map->location = hall;
return 1;
}
Object MapProto = {
.init = Map_init,
.move = Map_move,
.attack = Map_attack
};
int process_input(Map *game)
{
assert(game != NULL);
printf("\n> ");
char ch = getchar();
getchar(); // eat ENTER
int damage = rand() % 4;
switch(ch) {
case -1:
printf("Giving up? You suck.\n");
return 0;
break;
case 'n':
game->_(move)(game, NORTH);
break;
case 's':
game->_(move)(game, SOUTH);
break;
case 'e':
game->_(move)(game, EAST);
break;
case 'w':
game->_(move)(game, WEST);
break;
case 'a':
game->_(attack)(game, damage);
break;
case 'l':
printf("You can go:\n");
if(game->location->north) printf("NORTH\n");
if(game->location->south) printf("SOUTH\n");
if(game->location->east) printf("EAST\n");
if(game->location->west) printf("WEST\n");
break;
default:
printf("What?: %d\n", ch);
}
return 1;
}
int main(int argc, char *argv[])
{
// simple way to setup the randomness
srand(time(NULL));
// make our map to work with
Map *game = NEW(Map, "The Hall of the Minotaur.");
assert(game != NULL);
printf("You enter the ");
game->location->_(describe)(game->location);
while(process_input(game)) {
}
return 0;
}

View File

@@ -0,0 +1,118 @@
#include "dbg.h"
#include <stdlib.h>
#include <stdio.h>
void test_debug()
{
// notice you don't need the \n
debug("I have Brown Hair.");
// passing in arguments like printf
debug("I am %d years old.", 37);
}
void test_log_err()
{
log_err("I believe everything is broken.");
log_err("There are %d problems in %s.", 0, "space");
}
void test_log_warn()
{
log_warn("You can safely ignore this.");
log_warn("Maybe consider looking at: %s.", "/etc/passwd");
}
void test_log_info()
{
log_info("Well I did something mundane.");
log_info("It happened %f times today.", 1.3f);
}
int test_check(char *file_name)
{
FILE *input = NULL;
char *block = NULL;
block = malloc(100);
check_mem(block); // should work
input = fopen(file_name, "r");
check(input, "Failed to open %s.", file_name);
free(block);
fclose(input);
return 0;
error:
if(block) free(block);
if(input) fclose(input);
return -1;
}
int test_sentinel(int code)
{
char *temp = malloc(100);
check_mem(temp);
switch(code) {
case 1:
log_info("It worked.");
break;
default:
sentinel("I shouldn't run.");
}
free(temp);
return 0;
error:
if(temp) free(temp);
return -1;
}
int test_check_mem()
{
char *test = NULL;
check_mem(test);
free(test);
return 1;
error:
return -1;
}
int test_check_debug()
{
int i = 0;
check_debug(i != 0, "Oops, I was 0.");
return 0;
error:
return -1;
}
int main(int argc, char *argv[])
{
check(argc == 2, "Need an argument.");
test_debug();
test_log_err();
test_log_warn();
test_log_info();
check(test_check("ex20.c") == 0, "failed with ex20.c");
check(test_check(argv[1]) == -1, "failed with argv");
check(test_sentinel(1) == 0, "test_sentinel failed.");
check(test_sentinel(100) == -1, "test_sentinel failed.");
check(test_check_mem() == -1, "test_check_mem failed.");
check(test_check_debug() == -1, "test_check_debug failed.");
return 0;
error:
return 1;
}

View File

@@ -0,0 +1,33 @@
#include <stdio.h>
#include "ex22.h"
#include "dbg.h"
int THE_SIZE = 1000;
static int THE_AGE = 37;
int get_age()
{
return THE_AGE;
}
void set_age(int age)
{
THE_AGE = age;
}
double update_ratio(double new_ratio)
{
static double ratio = 1.0;
double old_ratio = ratio;
ratio = new_ratio;
return old_ratio;
}
void print_size()
{
log_info("I think size is: %d", THE_SIZE);
}

View File

@@ -0,0 +1,54 @@
#include "ex22.h"
#include "dbg.h"
const char *MY_NAME = "Zed A. Shaw";
void scope_demo(int count)
{
log_info("count is: %d", count);
if(count > 10) {
int count = 100; // BAD! BUGS!
log_info("count in this scope is %d", count);
}
log_info("count is at exit: %d", count);
count = 3000;
log_info("count after assign: %d", count);
}
int main(int argc, char *argv[])
{
// test out THE_AGE accessors
log_info("My name: %s, age: %d", MY_NAME, get_age());
set_age(100);
log_info("My age is now: %d", get_age());
// test out THE_SIZE extern
log_info("THE_SIZE is: %d", THE_SIZE);
print_size();
THE_SIZE = 9;
log_info("THE_SIZE is now: %d", THE_SIZE);
print_size();
// test the ration function static
log_info("Ratio at first: %f", update_ratio(2.0));
log_info("Ratio again: %f", update_ratio(10.0));
log_info("Ratio once more: %f", update_ratio(300.0));
// test the scope demo
int count = 4;
scope_demo(count);
scope_demo(count * 20);
log_info("count after calling scope_demo: %d", count);
return 0;
}

View File

@@ -0,0 +1,109 @@
#include <stdio.h>
#include <string.h>
#include "dbg.h"
int normal_copy(char *from, char *to, int count)
{
int i = 0;
for(i = 0; i < count; i++) {
to[i] = from[i];
}
return i;
}
int duffs_device(char *from, char *to, int count)
{
{
int n = (count + 7) / 8;
debug("n=%d, (count %% 8)=%d", n, count % 8);
switch(count % 8) {
case 0: do { *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
} while(--n > 0);
}
}
return count;
}
int zeds_device(char *from, char *to, int count)
{
{
int n = (count + 7) / 8;
switch(count % 8) {
case 0:
again: *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
if(--n > 0) goto again;
}
}
return count;
}
int valid_copy(char *data, int count, char expects)
{
int i = 0;
for(i = 0; i < count; i++) {
if(data[i] != expects) {
log_err("[%d] %c != %c", i, data[i], expects);
return 0;
}
}
return 1;
}
int main(int argc, char *argv[])
{
char from[1000] = {'a'};
char to[1000] = {'c'};
int rc = 0;
// setup the from to have some stuff
memset(from, 'x', 1000);
// set it to a failure mode
memset(to, 'y', 1000);
check(valid_copy(to, 1000, 'y'), "Not initialized right.");
// use normal copy to
rc = normal_copy(from, to, 1000);
check(rc == 1000, "Normal copy failed: %d", rc);
check(valid_copy(to, 1000, 'x'), "Normal copy failed.");
// reset
memset(to, 'y', 1000);
// duffs version
rc = duffs_device(from, to, 1000);
check(rc == 1000, "Duff's deice failed: %d", rc);
check(valid_copy(to, 1000, 'x'), "Duff's deice failed copy.");
// reset
memset(to, 'y', 1000);
// my version
rc = zeds_device(from, to, 1000);
check(rc == 1000, "Zed's device failed: %d", rc);
check(valid_copy(to, 1000, 'x'), "Zed's device failed copy.");
return 0;
error:
return 1;
}

View File

@@ -0,0 +1,77 @@
#include <stdio.h>
#include "dbg.h"
#define MAX_DATA 100
typedef enum EyeColor {
BLUE_EYES, GREEN_EYES, BROWN_EYES,
BLACK_EYES, OTHER_EYES
} EyeColor;
const char *EYE_COLOR_NAMES[] = {
"Blue", "Green", "Brown", "Black", "Other"
};
typedef struct Person {
int age;
char first_name[MAX_DATA];
char last_name[MAX_DATA];
EyeColor eyes;
float income;
} Person;
int main(int argc, char *argv[])
{
Person you = {.age = 0};
int i = 0;
int rc = -1;
char *in = NULL;
printf("What's your First Name? ");
in = fgets(you.first_name, MAX_DATA-1, stdin);
check(in != NULL, "Failed to read first name.");
rc = sscanf(you.first_name, "%s", you.first_name);
check(rc > 0, "Failed to strip first name.");
printf("What's your Last Name? ");
in = fgets(you.last_name, MAX_DATA-1, stdin);
check(in != NULL, "Failed to read last name.");
rc = sscanf(you.last_name, "%s", you.last_name);
check(rc > 0, "Failed to strip last name.");
printf("How old are you? ");
rc = fscanf(stdin, "%d", &you.age);
check(rc > 0, "You have to enter a number.");
printf("What color are your eyes:\n");
for(i = 0; i <= OTHER_EYES; i++) {
printf("%d) %s\n", i+1, EYE_COLOR_NAMES[i]);
}
printf("> ");
int eyes = -1;
rc = fscanf(stdin, "%d", &eyes);
check(rc > 0, "You have to enter a number.");
you.eyes = eyes - 1;
check(you.eyes <= OTHER_EYES && you.eyes >= 0, "Do it right, that's not an option.");
printf("How much do you make an hour? ");
rc = fscanf(stdin, "%f", &you.income);
check(rc > 0, "Enter a floating point number.");
printf("----- RESULTS -----\n");
printf("First Name: %s\n", you.first_name);
printf("Last Name: %s\n", you.last_name);
printf("Age: %d\n", you.age);
printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]);
printf("Income: %f\n", you.income);
return 0;
error:
return -1;
}

View File

@@ -0,0 +1,134 @@
/** WARNING: This code is fresh and potentially isn't correct yet. */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "dbg.h"
#define MAX_DATA 100
int read_string(char **out_string, int max_buffer)
{
*out_string = calloc(1, max_buffer + 1);
check_mem(*out_string);
char *result = fgets(*out_string, max_buffer, stdin);
check(result != NULL, "Input error.");
return 0;
error:
if(*out_string) free(*out_string);
*out_string = NULL;
return -1;
}
int read_int(int *out_int)
{
char *input = NULL;
int rc = read_string(&input, MAX_DATA);
check(rc == 0, "Failed to read number.");
*out_int = atoi(input);
free(input);
return 0;
error:
if(input) free(input);
return -1;
}
int read_scan(const char *fmt, ...)
{
int i = 0;
int rc = 0;
int *out_int = NULL;
char *out_char = NULL;
char **out_string = NULL;
int max_buffer = 0;
va_list argp;
va_start(argp, fmt);
for(i = 0; fmt[i] != '\0'; i++) {
if(fmt[i] == '%') {
i++;
switch(fmt[i]) {
case '\0':
sentinel("Invalid format, you ended with %%.");
break;
case 'd':
out_int = va_arg(argp, int *);
rc = read_int(out_int);
check(rc == 0, "Failed to read int.");
break;
case 'c':
out_char = va_arg(argp, char *);
*out_char = fgetc(stdin);
break;
case 's':
max_buffer = va_arg(argp, int);
out_string = va_arg(argp, char **);
rc = read_string(out_string, max_buffer);
check(rc == 0, "Failed to read string.");
break;
default:
sentinel("Invalid format.");
}
} else {
fgetc(stdin);
}
check(!feof(stdin) && !ferror(stdin), "Input error.");
}
va_end(argp);
return 0;
error:
va_end(argp);
return -1;
}
int main(int argc, char *argv[])
{
char *first_name = NULL;
char initial = ' ';
char *last_name = NULL;
int age = 0;
printf("What's your first name? ");
int rc = read_scan("%s", MAX_DATA, &first_name);
check(rc == 0, "Failed first name.");
printf("What's your initial? ");
rc = read_scan("%c\n", &initial);
check(rc == 0, "Failed initial.");
printf("What's your last name? ");
rc = read_scan("%s", MAX_DATA, &last_name);
check(rc == 0, "Failed last name.");
printf("How old are you? ");
rc = read_scan("%d", &age);
printf("---- RESULTS ----\n");
printf("First Name: %s", first_name);
printf("Initial: '%c'\n", initial);
printf("Last Name: %s", last_name);
printf("Age: %d\n", age);
free(first_name);
free(last_name);
return 0;
error:
return -1;
}

View File

@@ -0,0 +1,74 @@
#undef NDEBUG
#include "dbg.h"
#include <stdio.h>
#include <assert.h>
/*
* naive copy that assumes all inputs are always valid
* taken from K&R C and cleaned up a bit;
*/
void copy(char to[], char from[])
{
int i = 0;
// while loop will not end if from isn't '\0' terminated
while((to[i] = from[i]) != '\0') {
++i;
}
}
/*
* A safer version that checks for many common errors using the
* length of each string to control the loops and termination.
*/
int safercopy(int from_len, char *from, int to_len, char *to)
{
assert(from != NULL && to != NULL && "from and to can't be NULL");
int i = 0;
int max = from_len > to_len - 1 ? to_len - 1 : from_len;
// to_len must have at least 1 byte
if(from_len < 0 || to_len <= 0) return -1;
for(i = 0; i < max; i++) {
to[i] = from[i];
}
to[to_len - 1] = '\0';
return i;
}
int main(int argc, char *argv[])
{
// careful to understand why we can get these sizes
char from[] = "0123456789";
int from_len = sizeof(from);
// notice that it's 7 chars + \0
char to[] = "0123456";
int to_len = sizeof(to);
debug("Copying '%s':%d to '%s':%d", from, from_len, to, to_len);
int rc = safercopy(from_len, from, to_len, to);
check(rc > 0, "Failed to safercopy.");
check(to[to_len - 1] == '\0', "String not terminated.");
debug("Result is '%s':%d", to, to_len);
// now try to break it
rc = safercopy(from_len * -1, from, to_len, to);
check(rc == -1, "safercopy should fail #1");
check(to[to_len - 1] == '\0', "String not terminated.");
rc = safercopy(from_len, from, 0, to);
check(rc == -1, "safercopy should fail #2");
check(to[to_len - 1] == '\0', "String not terminated.");
return 0;
error:
return 1;
}

View File

@@ -0,0 +1 @@
tests/your_library_tests

View File

View File

@@ -0,0 +1,59 @@
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS = -ldl $(OPTLIBS)
PREFIX ?= /usr/local
SOURCES = $(wildcard src/**/*.c src/*.c)
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
TEST_SRC = $(wildcard tests/*_tests.c)
TESTS = $(patsubst %.c,%,$(TEST_SRC))
LIBNAME = ex29
TARGET = build/lib$(LIBNAME).a
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
$(AR) rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: LDLIBS += -l$(LIBNAME)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions
@egrep $(BADFUNCS) $(SOURCES) || true

View File

View File

@@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif

View File

@@ -0,0 +1,43 @@
#include <stdio.h>
#include <ctype.h>
#include "dbg.h"
int print_a_message(const char *msg)
{
printf("A STRING: %s\n", msg);
return 0;
}
int uppercase(const char *msg, int count)
{
int i = 0;
for(i = 0; i < count; i++) {
printf("%c", toupper(msg[i]));
}
printf("\n");
return 0;
}
int lowercase(const char *msg, int count)
{
int i = 0;
for(i = 0; i < count; i++) {
printf("%c", tolower(msg[i]));
}
printf("\n");
return 0;
}
int fail_on_purpose(const char *msg)
{
return 1;
}

View File

@@ -0,0 +1,65 @@
#include "minunit.h"
#include <dlfcn.h>
typedef int (*lib_function)(const char *data, int count);
char *lib_file = "build/libex29.so";
void *lib = NULL;
int check_function(const char *func_to_run, const char *data, int expected)
{
lib_function func = dlsym(lib, func_to_run);
check(func != NULL, "Did not find %s function in the library %s: %s", func_to_run, lib_file, dlerror());
int rc = func(data, (int)strlen(data));
check(rc == expected, "Function %s return %d for data: %s", func_to_run, rc, data);
return 1;
error:
return 0;
}
char *test_dlopen()
{
lib = dlopen(lib_file, RTLD_NOW);
mu_assert(lib != NULL, "Failed to open the library to test.");
return NULL;
}
char *test_functions()
{
mu_assert(check_function("print_a_message", "Hello", 0), "print_a_message failed.");
mu_assert(check_function("uppercase", "Hello", 0), "uppercase failed.");
mu_assert(check_function("lowercase", "Hello", 0), "lowercase failed.");
return NULL;
}
char *test_failures()
{
mu_assert(check_function("fail_on_purpose", "Hello", 1), "fail_on_purpose should fail.");
return NULL;
}
char *test_dlclose()
{
int rc = dlclose(lib);
mu_assert(rc == 0, "Failed to close lib.");
return NULL;
}
char *all_tests()
{
mu_suite_start();
mu_run_test(test_dlopen);
mu_run_test(test_functions);
mu_run_test(test_failures);
mu_run_test(test_dlclose);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,38 @@
#undef DNDEBUG
#ifndef _minunit_h
#define _minunit_h
#include <stdio.h>
#include <dbg.h>
#include <stdlib.h>
#define mu_suite_start() char *message = NULL
#define mu_assert(test, message) if (!(test)) {\
log_err(message); return message;\
}\
assertions_made++;
#define mu_run_test(test) debug("\n-----%s", " " #test); \
message = test(); tests_run++; if (message) return message;
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
argc = argc; \
argv = argv; \
debug("----- RUNNING: %s", argv[0]);\
printf("----\nRUNNING: %s\n", argv[0]);\
char *result = name();\
if (result != 0) {\
printf("FAILED: %s\n", result);\
}\
else {\
printf("ALL TESTS PASSED\n");\
}\
printf("Tests run: %d\n", tests_run);\
printf("Assertions made: %d\n", assertions_made);\
exit(result != 0);\
}
int tests_run;
int assertions_made;
#endif

View File

@@ -0,0 +1,19 @@
echo "Running unit tests:"
for i in tests/*_tests
do
if test -f $i
then
if $VALGRIND ./$i 2>> tests/tests.log
then
echo $i PASS
else
echo "ERROR in test $i: here's tests/tests.log"
echo "------"
tail tests/tests.log
exit 1
fi
fi
done
echo ""

View File

@@ -0,0 +1,12 @@
#include <stdio.h>
int main()
{
int age = 10;
int height = 72;
printf("I am %d years old.\n", age);
printf("I am %d inches tall.\n", height);
return 0;
}

View File

@@ -0,0 +1,12 @@
#include <unistd.h>
int main(int argc, char *argv[])
{
int i = 0;
while(i < 100) {
usleep(3000);
}
return 0;
}

View File

@@ -0,0 +1,57 @@
#include <stdio.h>
typedef enum {
TYPE_INT,
TYPE_FLOAT,
TYPE_STRING,
} VariantType;
struct Variant {
VariantType type;
union {
int as_integer;
float as_float;
char *as_string;
} data;
};
typedef struct Variant Variant;
void Variant_print(Variant *var)
{
switch(var->type) {
case TYPE_INT:
printf("INT: %d\n", var->data.as_integer);
break;
case TYPE_FLOAT:
printf("FLOAT: %f\n", var->data.as_float);
break;
case TYPE_STRING:
printf("STRING: %s\n", var->data.as_string);
break;
default:
printf("UNKNOWN TYPE: %d", var->type);
}
}
int main(int argc, char *argv[])
{
Variant a_int = {.type = TYPE_INT, .data.as_integer = 100};
Variant a_float = {.type = TYPE_FLOAT, .data.as_float = 100.34};
Variant a_string = {.type = TYPE_STRING, .data.as_string = "YO DUDE!"};
Variant_print(&a_int);
Variant_print(&a_float);
Variant_print(&a_string);
// here's how you access them
a_int.data.as_integer = 200;
a_float.data.as_float = 2.345;
a_string.data.as_string = "Hi there.";
Variant_print(&a_int);
Variant_print(&a_float);
Variant_print(&a_string);
return 0;
}

View File

@@ -0,0 +1,12 @@
#include <stdio.h>
int main()
{
int age = 10;
int height = 72;
printf("I am %d years old.\n", age);
printf("I am %d inches tall.\n", height);
return 0;
}

View File

@@ -0,0 +1,12 @@
#include <stdio.h>
/* This is a comment. */
int main(int argc, char *argv[])
{
int distance = 100;
// this is also a comment
printf("You are %d miles away.\n", distance);
return 0;
}

View File

@@ -0,0 +1,22 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int distance = 100;
float power = 2.345f;
double super_power = 56789.4532;
char initial = 'A';
char first_name[] = "Zed";
char last_name[] = "Shaw";
printf("You are %d miles away.\n", distance);
printf("You have %f levels of power.\n", power);
printf("You have %f awesome super powers.\n", super_power);
printf("I have na initial %c.\n", initial);
printf("I have a first name %s.\n", first_name);
printf("I have a last name %s.\n", last_name);
printf("My whole name is %s %c. %s.\n",
first_name, initial, last_name);
return 0;
}

View File

@@ -0,0 +1,30 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int bugs = 100;
double bug_rate = 1.2;
printf("You have %d bugs at the imaginary rate of %f.\n",
bugs, bug_rate);
long universe_of_defects = 1L * 1024L * 1024L * 1024L;
printf("The entire universe has %ld bugs.\n",
universe_of_defects);
double expected_bugs = bugs * bug_rate;
printf("You are expected to have %f bugs.\n",
expected_bugs);
double part_of_universe = expected_bugs / universe_of_defects;
printf("That is only a %e portion of the universe.\n",
part_of_universe);
// this makes no sense, just a demo of something weird
char nul_byte = '\0';
int care_percentage = bugs * nul_byte;
printf("Which means you should care %d%%.\n",
care_percentage);
return 0;
}

View File

@@ -0,0 +1,36 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int areas[] = {10, 12, 13, 14, 20};
char name[] = "Zed";
char full_name[] = {
'Z', 'e', 'd',
' ', 'A', '.', ' ',
'S', 'h', 'a', 'w', '\0'
};
// WARNING: On some systems you may have to change the
// %ld in this code to a %u since it will use unsigned ints
printf("The size of an int: %ld\n", sizeof(int));
printf("The size of areas (int[]): %ld\n",
sizeof(areas));
printf("The first area is %d, the 2nd %d.\n",
areas[0], areas[1]);
printf("The size of a char: %ld\n", sizeof(char));
printf("The size of name (char[]): %ld\n",
sizeof(name));
printf("The number of chars: %ld\n",
sizeof(name) / sizeof(char));
printf("The size of full_name (char[]): %ld\n",
sizeof(full_name));
printf("The number of chars: %ld\n",
sizeof(full_name) / sizeof(char));
printf("name=\"%s\" and full_name=\"%s\"\n",
name, full_name);
return 0;
}

View File

@@ -0,0 +1,55 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int numbers[4] = {0};
char name[4] = {'a'};
// first, print them out raw
printf("numbers: %d %d %d %d\n",
numbers[0], numbers[1],
numbers[2], numbers[3]);
printf("name each: %c %c %c %c\n",
name[0], name[1],
name[2], name[3]);
printf("name: %s\n", name);
// setup the numbers
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
// setup the name
name[0] = 'Z';
name[1] = 'e';
name[2] = 'd';
name[3] = '\0';
// then print them out initialized
printf("numbers: %d %d %d %d\n",
numbers[0], numbers[1],
numbers[2], numbers[3]);
printf("name each: %c %c %c %c\n",
name[0], name[1],
name[2], name[3]);
// print the name like a string
printf("name: %s\n", name);
// another way to use name;
char *another = "Zed";
printf("another: %s\n", another);
printf("another each: %c %c %c %c\n",
another[0], another[1],
another[2], another[3]);
printf("name length: %ld\n", sizeof(name));
printf("name as int: %d\n", (int)(*name));
return 0;
}

View File

@@ -0,0 +1,52 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int numbers[4] = {0};
char name[4] = {'a'};
// first, print them out raw
printf("numbers: %d %d %d %d\n",
numbers[0], numbers[1],
numbers[2], numbers[3]);
printf("name each: %c %c %c %c\n",
name[0], name[1],
name[2], name[3]);
printf("name: %s\n", name);
// setup the numbers
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
// setup the name
name[0] = 'Z';
name[1] = 'e';
name[2] = 'd';
name[3] = '\0';
// then print them out initialized
printf("numbers: %d %d %d %d\n",
numbers[0], numbers[1],
numbers[2], numbers[3]);
printf("name each: %c %c %c %c\n",
name[0], name[1],
name[2], name[3]);
// print the name like a string
printf("name: %s\n", name);
// another way to use name;
char *another = "Zed";
printf("another: %s\n", another);
printf("another each: %c %c %c %c\n",
another[0], another[1],
another[2], another[3]);
return 0;
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -e
# go somewhere safe
cd /tmp
# get the source to base APR 1.4.6
curl -L -O http://archive.apache.org/dist/apr/apr-1.4.6.tar.gz
# extract it and go into the source
tar -xzvf apr-1.4.6.tar.gz
cd apr-1.4.6
# configure, make, make install
./configure
make
sudo make install
# reset and cleanup
cd /tmp
rm -rf apr-1.4.6 apr-1.4.6.tar.gz
# do the same with apr-util
curl -L -O http://archive.apache.org/dist/apr/apr-util-1.4.1.tar.gz
# extract
tar -xzvf apr-util-1.4.1.tar.gz
cd apr-util-1.4.1
# configure, make, make install
./configure --with-apr=/usr/local/apr
# you need that extra parameter to configure because
# apr-util can't really find it because...who knows.
make
sudo make install
#cleanup
cd /tmp
rm -rf apr-util-1.4.1* apr-1.4.6*

View File

@@ -0,0 +1,5 @@
tests/runtests
tests/*_tests
tests/**/*_tests
bstrlib.c
bstrlib.h

View File

@@ -0,0 +1,21 @@
Copyright (C) 2016 Dan Buch
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,76 @@
BSTRLIB_BASE_URL ?= https://raw.githubusercontent.com/websnarf/bstrlib/208b1f2a4dfc96b806ed499bd1909e87ec15981d
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS = -ldl $(OPTLIBS)
PREFIX ?= /usr/local
FIND ?= find
CD ?= cd
PATCH ?= patch
INSTALL ?= install
MKDIR ?= mkdir -p
CURL ?= curl -sSL
RANLIB ?= ranlib
RUNTESTS ?= ./tests/runtests
SOURCES = $(wildcard src/**/*.c src/*.c)
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
TEST_SRC = $(wildcard tests/**/*_tests.c tests/*_tests.c)
TESTS = $(patsubst %.c,%,$(TEST_SRC))
LIBNAME = lcthw
TARGET = build/lib$(LIBNAME).a
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
$(AR) rcs $@ $(OBJECTS)
$(RANLIB) $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build: bin src/lcthw/bstrlib.c src/lcthw/bstrlib.h
@$(MKDIR) $@
bin:
@$(MKDIR) $@
src/lcthw/bstrlib.c: src/lcthw/bstrlib.h
$(CURL) -o $@ $(BSTRLIB_BASE_URL)/bstrlib.c
$(CD) src/lcthw && $(PATCH) -p1 < bstrlib.patch
src/lcthw/bstrlib.h:
$(CURL) -o $@ $(BSTRLIB_BASE_URL)/bstrlib.h
.PHONY: tests
tests: LDLIBS += -static -l$(LIBNAME) -lbsd
tests: $(RUNTESTS) $(TESTS)
$(RUNTESTS) ./tests/lcthw
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
clean:
$(RM) -r build $(OBJECTS) $(TESTS)
$(RM) tests/tests.log tests/runtests
$(FIND) . -name "*.gc*" -exec rm {} \;
$(RM) -r `find . -name "*.dSYM" -print`
distclean: clean
$(RM) src/lcthw/bstrlib.c src/lcthw/bstrlib.h
install: all
$(INSTALL) -d $(DESTDIR)/$(PREFIX)/lib/
$(INSTALL) $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions
@egrep $(BADFUNCS) $(SOURCES) || true

View File

@@ -0,0 +1,12 @@
--- a/bstrlib.c 2016-04-21 12:26:50.000000000 -0400
+++ b/bstrlib.c 2016-04-21 12:27:59.000000000 -0400
@@ -22,7 +22,8 @@
#include <string.h>
#include <ctype.h>
#include <limits.h>
-#include "bstrlib.h"
+// PATCH to include adjacent bstrlib.h
+#include <lcthw/bstrlib.h>
/* Optionally include a mechanism for debugging memory */

View File

@@ -0,0 +1,116 @@
#include <lcthw/darray.h>
#include <assert.h>
DArray *DArray_create(size_t element_size, size_t initial_max)
{
DArray *array = malloc(sizeof(DArray));
check_mem(array);
array->max = initial_max;
check(array->max > 0, "You must set an initial_max > 0.");
array->contents = calloc(initial_max, sizeof(void *));
check_mem(array->contents);
array->end = 0;
array->element_size = element_size;
array->expand_rate = DEFAULT_EXPAND_RATE;
return array;
error:
if(array) free(array);
return NULL;
}
void DArray_clear(DArray *array)
{
int i = 0;
if(array->element_size > 0) {
for(i = 0; i < array->max; i++) {
if(array->contents[i] != NULL) {
free(array->contents[i]);
}
}
}
}
static inline int DArray_resize(DArray *array, size_t newsize)
{
array->max = newsize;
check(array->max > 0, "The newsize must be > 0.");
void *contents = realloc(array->contents, array->max * sizeof(void *));
check_mem(contents);
array->contents = contents;
return 0;
error:
return -1;
}
int DArray_expand(DArray *array)
{
size_t old_max = array->max;
check(DArray_resize(array, array->max + array->expand_rate) == 0,
"Failed to expand array to new size: %d",
array->max + (int)array->expand_rate);
memset(array->contents + old_max, 0, array->expand_rate + 1);
return 0;
error:
return -1;
}
int DArray_contract(DArray *array)
{
int new_size = array->end < (int)array->expand_rate ? (int)array->expand_rate : array->end;
return DArray_resize(array, new_size + 1);
}
void DArray_destroy(DArray *array)
{
if(array) {
if(array->contents) free(array->contents);
free(array);
}
}
void DArray_clear_destroy(DArray *array)
{
DArray_clear(array);
DArray_destroy(array);
}
int DArray_push(DArray *array, void *el)
{
array->contents[array->end] = el;
array->end++;
if(DArray_end(array) >= DArray_max(array)) {
return DArray_expand(array);
} else {
return 0;
}
}
void *DArray_pop(DArray *array)
{
check(array->end - 1 >= 0, "Attempt to pop from empty array.");
void *el = DArray_remove(array, array->end - 1);
array->end--;
if(DArray_end(array) > (int)array->expand_rate && DArray_end(array) % array->expand_rate) {
DArray_contract(array);
}
return el;
error:
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More