From ec15bdbcb9bac355b7b67e97ec9cb87b65603c92 Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Tue, 13 Dec 2022 18:44:29 +0100 Subject: [PATCH] initial commit --- .gitignore | 6 +++ calc.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++ getcomments.pl | 85 ++++++++++++++++++++++++++++++++++ makefile | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ skel.c | 68 +++++++++++++++++++++++++++ 5 files changed, 397 insertions(+) create mode 100644 .gitignore create mode 100644 calc.c create mode 100644 getcomments.pl create mode 100644 makefile create mode 100644 skel.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d72a45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.d +*.ld +*.exe +*.log +*.o +.targets diff --git a/calc.c b/calc.c new file mode 100644 index 0000000..f5d9cfd --- /dev/null +++ b/calc.c @@ -0,0 +1,117 @@ +/* depend: */ +/* cflags: */ +/* linker: */ + +#include +#include +#include +#include +#include +#include + +/* constants */ + +//#define BUFFER_SIZE 4096 +#define BUFFER_SIZE 256 + +/* macros */ + +#define CEIL(x, y) (((x) + (y) - 1) / (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +/* verbose */ + +#define ERROR 0 +#define WARNING 1 +#define INFO 2 +#define DEBUG 3 + +#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0) + +/* gobal variables */ + +char *progname = NULL; +int verbose = 0; + +/* help function */ + +void usage (int ret) +{ + FILE *fd = ret ? stderr : stdout; + fprintf (fd, "usage: %s\n", progname); + fprintf (fd, " -h : help message\n"); + fprintf (fd, " -v : verbose level (%d)\n", verbose); + + exit (ret); +} + +/* main function */ + +int main (int argc, char *argv[]) +{ + char buffer[BUFFER_SIZE + 1] = {0}; + char *pt = buffer; + int i, j = 0, n; + + progname = argv[0]; + + int c; + while ((c = getopt(argc, argv, "hv:")) != EOF) { + switch (c) { + case 'v': + verbose = atoi (optarg); + break; + case 'h': + VERBOSE (INFO, usage (0)); + break; + default: + VERBOSE (ERROR, usage (1)); + } + } + if (argc - optind != 0) { + VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, argv[optind])); + VERBOSE (ERROR, usage (1)); + } + + /* read from input stream */ + while ((n = read (STDIN_FILENO, pt, BUFFER_SIZE - (pt - buffer))) != 0) { + VERBOSE (DEBUG, fprintf (stdout, "read %d bytes\n", n)); + n += (pt - buffer); + + /* look for end of line */ + for (i = 0, j = 0; i < n; i++) { + if (buffer[i] == '\n') { + buffer[i] = 0; + VERBOSE (DEBUG, fprintf (stdout, "line(%d): %s\n", j, buffer + j)); + j = i + 1; + } + } + + /* keep remainding */ + if (j < n) { + for (i = 0; i < n - j; i++) { + buffer[i] = buffer[i + j]; + } + pt = buffer + n - j; + for (i = n - j; i < BUFFER_SIZE; i++) { + buffer[i] = 0; + } + } + } + + /* check that nothing is left behind */ + + VERBOSE (DEBUG, fprintf (stdout, "last\n")); + VERBOSE (DEBUG, fprintf (stdout, "line(%d): %s\n", j, buffer + j)); + + return 0; +} + +// test: calc.exe -h +// test: calc.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }' +// test: calc.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }' +// test: calc.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }' +// test: echo "foo\nbar\nfoobar" | calc.exe -v3 + +/* vim: set ts=4 sw=4 et: */ diff --git a/getcomments.pl b/getcomments.pl new file mode 100644 index 0000000..47edf67 --- /dev/null +++ b/getcomments.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl + +use strict; + +# default value +my $format = "%"; +my $pattern = ""; + +# help message +sub usage() { + + print <) { + my $cmt; + + # process c++ comments + ($cmt, $_) = m{//\s*(.*?)\s*$()} if (m{//} && !m{/\*.*//}); + + # process standard c comments + ($cmt, $_) = m{^.*?/\*\s*(.*?)\s*\*/(.*)}s if (m{/\*.*\*/}s); + + push(@comments, $cmt) if ($cmt); + + # empty buffer if no comment is present + undef($_) if (!m{/[/*]}); + } + + # close file + close (IN); + + # display comment blocks + foreach my $block (@comments) { + if (($block) = ($block =~ /$pattern(.*)/s)) { + ($_ = $format) =~ s/%/$block/gs; + print "$_\n"; + } + } +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..40cfde7 --- /dev/null +++ b/makefile @@ -0,0 +1,121 @@ +# Default flags + +CC = gcc + +INCLUDES = -I../debug -D__MEMORY_ALLOCATION__ +OFLAGS = -O4 -Os +#OFLAGS = -O4 -ffast-math -finline-functions +#OFLAGS = -O4 -finline-functions +#OFLAGS += -mtune=pentium3 -mmmx -msse -msse2 -m3dnow +#OFLAGS += -minline-all-stringops -fsingle-precision-constant +#OFLAGS += -malign-double +CFLAGS += -W -Wall -Wextra -g +CFLAGS += -std=c99 -D_XOPEN_SOURCE=500 +CFLAGS += $(OFLAGS) $(INCLUDES) +LDFLAGS += -g + +# Targets + +ALLEXE = +ALLEXE += calc +ALLEXE += skel + +SHELL = bash + +MAKE = mingw32-make +MAKEFLAGS += -s + +# Functions + +TITLE = echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t" +PASS = echo -e "\033[1;32m$(strip $(1))\033[0;0m" +WARN = echo -e "\033[1;33m$(strip $(1))\033[0;0m" +FAIL = echo -e "\033[1;31m$(strip $(1))\033[0;0m" + +MKDIR = mkdir -p $(1) && chmod a+rx,go-w $(1) + +INSTALL = test -d `dirname $(2)` || $(call MKDIR, `dirname $(2)`) && cp -pa $(1) $(2) && chmod a+rX,go-w $(2) + +VALID = $(call TITLE, $(1)) && $(2) && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; } + +## Generic rules + +all: depends + $(MAKE) $(ALLEXE:%=%.exe) + +alltests: all + $(MAKE) $(addprefix test_,$(ALLEXE:%.exe=%)) + +depends: $(patsubst %.c, %.d, $(wildcard *.c)) $(patsubst %, %.ld, $(ALLEXE)) + +count: + wc $(wildcard *.c *.h) $(MAKEFILE_LIST) + +clean: + $(call TITLE, "Cleaning") + touch clean + rm -f clean $(wildcard *.d *.ld *.log *.o *.test *~ .exec_*) + $(call PASS, SUCCESS) + +purge: clean + $(call TITLE, "Purging") + touch purge + rm -f purge $(ALLEXE) $(shell [ -f .targets ] && { cat .targets | sort | uniq; echo .targets; }) + $(call PASS, SUCCESS) + +## Main rules + +include $(wildcard *.d) +include $(wildcard *.ld) + +%.test: %.c + $(call TITLE, "Building $@") +# awk '/\/\* *test:.*\*\// { sub(/^.*\/\* *test: */, ""); sub(/ *\*\/.*$$/, ""); print }' $< > $@ + ./getcomments.pl -p='test:\s' -f='%' $< > $@ + $(call PASS, SUCCESS) + +test_%: %.test %.exe + IFS=$$'\n'; RC=0; \ + for test in `cat $< | sed 's,${<:.test=.exe},./${<:.test=.exe},g'`; do \ + echo "=== $$test ==="; \ + eval $(VALGRIND) $$test; \ + [ $$? -eq 0 ] && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || { echo -e "\033[1;31mFAILED\033[0;0m"; RC=1; }; \ + done; \ + test "$$RC" -ne 1 + +valgrind_%: % + VALGRIND="valgrind -v --leak-check=full --show-reachable=yes --log-fd=2"; \ + export VALGRIND; \ + $(MAKE) test_$< + +%.d: %.c + $(call TITLE, "Building $@") + $(CC) $(INCLUDES) -MM $< -o $@~ + echo ${<:.c=.o}: $(shell ./getcomments.pl -p='depend:\s' -f='%' $<) >> $@~ + mv $@~ $@ + $(call PASS, SUCCESS) + +%.ld: %.c + $(call TITLE, "Building $@") + echo ${<:.c=.exe}: $(shell ./getcomments.pl -p='linker:\s' -f='%' $< | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') >> $@ + $(call PASS, SUCCESS) + +%.o: %.c + $(call TITLE, "Building $@") + $(CC) $(CFLAGS) $(INCLUDES) $(shell ./getcomments.pl -p='cflags:\s' -f='%' $<) -c $< -o $@ + $(call PASS, SUCCESS) + + +%.exe: %.o %.d + $(call TITLE, "Building $@") + $(CC) $(LDFLAGS) $(shell ./getcomments.pl -p='linker:\s' -f='%' ${<:.o=.c}) $< -o $@ + $(call PASS, SUCCESS) + +## Phony + +.PHONY: clean count purge + +## Precious + +.PRECIOUS: %.d %.o diff --git a/skel.c b/skel.c new file mode 100644 index 0000000..2219fca --- /dev/null +++ b/skel.c @@ -0,0 +1,68 @@ +/* depend: */ +/* cflags: */ +/* linker: */ + +#include +#include +#include +#include +#include + +/* macros */ + +#define CEIL(x, y) (((x) + (y) - 1) / (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0) + +/* gobal variables */ + +char *progname = NULL; +int verbose = 0; + +/* help function */ + +void usage (int ret) +{ + FILE *fd = ret ? stderr : stdout; + fprintf (fd, "usage: %s\n", progname); + fprintf (fd, " -h : help message\n"); + fprintf (fd, " -v : verbose level (%d)\n", verbose); + + exit (ret); +} + +/* main function */ + +int main (int argc, char *argv[]) +{ + + progname = argv[0]; + + int c; + while ((c = getopt(argc, argv, "hv:")) != EOF) { + switch (c) { + case 'v': + verbose = atoi (optarg); + break; + case 'h': + default: + usage (c != 'h'); + } + } + if (argc - optind != 0) { + fprintf (stderr, "%s: invalid option -- %s\n", progname, argv[optind]); + usage (1); + } + + printf ("work in progress...\n"); + + return 0; +} + +// test: skel.exe -h +// test: skel.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }' +// test: skel.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }' +// test: skel.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }' + +/* vim: set ts=4 sw=4 et */ -- 2.30.2