No new tools are needed for this chapter. The toolchain from
f05/00
covers everything: gcc, make, valgrind.
Start from libtci
tci_printf extends libtci — the static library from
c01. Create a new
working directory and populate it with the c01 project as a starting
point. If you completed c01 yourself, copy your working directory:
cp -r ~/c01-practice ~/c02-practice
cd ~/c02-practiceIf you are starting fresh or want the reference version, clone the c01 companion repo and copy the solution:
git clone https://github.com/thecodingidiot-com/c01-the-toolkit.git
cp -r c01-the-toolkit/solution ~/c02-practice
cd ~/c02-practiceVerify the library still builds:
make reYou should see ar rcs libtci.a complete with no warnings. Twenty-nine
object files, one archive.
Add the tci_printf stub
Create tci_printf.c with a function that compiles but does nothing yet:
#include "libtci.h"
#include <stdarg.h>
#include <unistd.h>
int tci_printf(const char *fmt, ...)
{
(void)fmt;
return (0);
}Add tci_printf.c to SRCS in the Makefile:
SRCS = tci_memset.c tci_memcpy.c tci_memmove.c tci_memchr.c tci_bzero.c \
tci_isascii.c tci_isalpha.c tci_isdigit.c tci_isalnum.c \
tci_isspace.c tci_isupper.c tci_islower.c tci_isprint.c \
tci_toupper.c tci_tolower.c \
tci_strlen.c tci_strcpy.c tci_strncpy.c tci_strlcpy.c tci_strlcat.c \
tci_strcmp.c tci_strncmp.c tci_strchr.c tci_strrchr.c tci_strnstr.c \
tci_atoi.c \
tci_calloc.c tci_strdup.c tci_strndup.c \
tci_printf.cAdd the declaration to libtci.h:
int tci_printf(const char *fmt, ...);Run make re. Thirty object files, one archive, no warnings. The
stub compiles but prints nothing — that changes on the next page.
Get the tester
Clone the companion repo and copy test.sh into your working directory:
git clone https://github.com/thecodingidiot-com/c02-the-voice.git
cp c02-the-voice/test.sh ~/c02-practice/You will run bash test.sh at the end of each implementation page. Leave
the clone where it is — you only need to do this once.
What printf[1] does
printf(fmt, ...) writes formatted text to standard output and returns
the number of characters written. Internally, every C library printf
eventually calls write(1, buf, n) — the POSIX system call that sends
n bytes from buf to file descriptor 1. That is the only way to write
to standard output without going through another library function.
tci_printf will do the same. It reads fmt character by character. When
it encounters a % followed by a conversion specifier (d, s, x,
etc.), it reads the next argument from the variable argument list, converts
it to text, and writes the result. For every other character, it writes
the character directly. It counts every byte written and returns the total.
The next page covers the variadic argument mechanism before any format string logic is added.