Update README.md
[pp.git] / README.md
blobdfd82b4885d09b0e8158e46a9781dbd89aafb8be
1 # pp (prepend)
3 The **pp** (prepend) utility takes the content of the file named by the *source* operand and inserts or prepends it
4 above the first line of the file named by the *target* operand. The file operands are processed in command-line order.
5 If the *source* file is a single dash (‘-’) or absent, **pp** reads from the standard input.
7 So, essentially, if I have a CSV file without a header and I want to quickly insert the header from a file, I
8 would run:
10 ```sh
11 $ pp header.txt spreadsheet.csv
12 ```
14 and it would be functionally equivalent to
16 ```sh
17 $ cat header.txt spreadsheet.csv > temp
18 $ mv temp spreadsheet.csv
19 ```
21 ## Features
22 * Quality
23     * Compiled with security hardening flags
24     * Static analysis integrated using clang's `scan-build` using checkers `alpha.security`, `alpha.core.CastSize`,
25     `alpha.core.CastToStruct`, `alpha.core.IdenticalExpr`, `alpha.core.PointerArithm`, `alpha.core.PointerSub`,
26     `alpha.core.SizeofPtr`, `alpha.core.TestAfterDivZero`, `alpha.unix`
27     * Test harness
28     * Follows [FreeBSD coding style](https://www.freebsd.org/cgi/man.cgi?query=style&sektion=9)
29 * Portable
30     * C99 compliant
31     * Self-contained, no external dependencies
32     * Easy to compile (needs clang >= 11.0) and uses POSIX make
34 ## Build dependencies
35 The only dependency is the toolchain needed to build the program using the Makefile, which is `clang` >= 11.0. That's
36 because the security flags used to build the executable are specific to clang.
38 If you want to build it with GCC and have equivalent security flags you can change the `CFLAGS` and `LDFLAGS` to the
39 following
41 ```
42 CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic \
43     -Wformat=2 -Wformat-overflow=2 -Wformat-truncation=2 -Wformat-security \
44     -Wnull-dereference -Wstack-protector -Wtrampolines -Walloca -Wvla \
45     -Warray-bounds=2 -Wimplicit-fallthrough=3 -Wtraditional-conversion \
46     -Wshift-overflow=2 -Wcast-qual -Wstringop-overflow=4 -Wconversion \
47     -Warith-conversion -Wlogical-op -Wduplicated-cond -Wduplicated-branches \
48     -Wformat-signedness -Wshadow -Wstrict-overflow=4 -Wundef \
49     -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wstack-usage=1000000 \
50     -Wcast-align=strict \
51     -D_FORTIFY_SOURCE=2 \
52     -fstack-protector-strong -fstack-clash-protection -fPIE
54 LDFLAGS = -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack \
55     -Wl,-z,separate-code
56 ```
58 Otherwise you can just remove the security flags and compile it with
59 ```
60 CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic
61 LDFLAGS =
62 ```
64 ## Installation
65 Clone this repository then
67 ```sh
68 $ make PREFIX=/usr install
69 ```
71 This will install the compiled binary under `PREFIX` (`/usr/bin`) in this case, if not specified `PREFIX` will default
72 to `/usr/local`. For staged installs, `DESTDIR` is also supported. As the binary does not have any dependency (other
73 than clang) it does not have to be installed before use.
75 ## Usage
76 Using **pp** is quite simple, you just specify the *source* file and *target* file
77 ```sh
78 $ pp source target
79 ```
80 The source file however, can be omitted, in this case the program takes the input from the standard input until `EOF` or
81 `^D` is reached
82 ```sh
83 $ pp target
84 ```
85 this behavior can also be achieved by using ‘-’ as *source* file
86 ```sh
87 $ pp - target
88 ```
90 ## Compilation
91 In order to build on any Unix-like system, simply run `make`. Since the binary does not have any dependencies, it can
92 just be copied into your `PATH`.
94 ### Test suite
95 The test suite consists of a POSIX shell script called `harness.sh` contained in the `test` folder. It's output is
96 similar to [googletest](https://github.com/google/googletest)'s and it can be invoked with `make test` which, if
97 everything is working should output something similar to
98 ```
99 ./test/harness.sh
100 [----------] Test environment set-up.
101 [==========] Running 7 test cases.
102 [ RUN      ] empty_source
103 [       OK ] empty_source
104 [ RUN      ] empty_destination
105 [       OK ] empty_destination
106 [ RUN      ] trivial_test
107 [       OK ] trivial_test
108 [ RUN      ] stdin_source
109 [       OK ] stdin_source
110 [ RUN      ] utf8_source
111 [       OK ] utf8_source
112 [ RUN      ] filename_dash
113 [       OK ] filename_dash
114 [ RUN      ] opt_source
115 [       OK ] opt_source
116 [==========] 7 test cases ran.
117 [  PASSED  ] 7 tests.
118 [  FAILED  ] 0 tests.
119 [----------] Test environment teardown.
122 ### Static analysis
123 Static analysis on the code base is done by using clang's static analyzer run through `scan-build.sh` which wraps the
124 `scan-build` utility. The checkers used are part of the
125 [Experimental Checkers](https://releases.llvm.org/12.0.0/tools/clang/docs/analyzer/checkers.html#alpha-checkers)
126 (aka *alpha* checkers):
127 * `alpha.security`
128 * `alpha.core.CastSize`
129 * `alpha.core.CastToStruct`
130 * `alpha.core.IdenticalExpr`
131 * `alpha.core.PointerArithm`
132 * `alpha.core.PointerSub`
133 * `alpha.core.SizeofPtr`
134 * `alpha.core.TestAfterDivZero`
135 * `alpha.unix`