In V6, the C preprocessor is part of
cc, the compiler driver; see the
expand() function in
cc.c. The directory you linked to contains the source code to the two passes of the C compiler,
c1 (and their floating-point variants,
fc1), and the optional optimiser,
c2. The passes are driven by
cc, whose source code is available in the
As far as I can tell, the external preprocessor was introduced in V7.
In both cases, the preprocessor can be invoked using
cc -P. The V6 and V7
cc(1) manpages provide more detail. Dennis M. Ritchie’s The Development of the C Language paper gives this context:
Many other changes occurred around 1972-3, but the most important was the introduction of the preprocessor, partly at the urging of Alan Snyder, but also in recognition of the utility of the the file-inclusion mechanisms available in BCPL and PL/I. Its original version was exceedingly simple, and provided only included files and simple string replacements:
#define of parameterless macros. Soon thereafter, it was extended, mostly by Mike Lesk and then by John Reiser, to incorporate macros with arguments and conditional compilation. The preprocessor was originally considered an optional adjunct to the language itself. Indeed, for some years, it was not even invoked unless the source program contained a special signal at its beginning. This attitude persisted, and explains both the incomplete integration of the syntax of the preprocessor with the rest of the language and the imprecision of its description in early reference manuals.
The “special signal at its beginning” is
# as the very first character; this test can be seen in V5’s
cc.c (and in V6’s).
(I’m linking to Diomidis Spinellis’ Unix history repo because I’m familiar with it, but the repo you’ve found also has
cpptool is only provided for compatibility and you should invoke cc -E on those compilers instead, otherwise some expansions might not succeed properly.