Programming in Plato’s Cave 181 Dennis never found the problem with his Makefile. He’s now stuck in a dead-end job where he has to wear a paper hat and maintains the sendmail configuration files for a large state university in the midwest. It’s a damn shame. Header Files C has these things called header files. They are files of definitions that are included in source files at compilation time. Like most things in Unix, they work reasonably well when there are one or two of them but quickly become unwieldy when you try to do anything serious. It is frequently difficult to calculate which header files to include in your source file. Header files are included by using the C preprocessor #include directive. This directive has two syntaxes: #include header1.h and: #include "header2.h" The difference between these two syntaxes is implementation dependent. This basically means that the implementation is free to do whatever the hell it wants. Let’s say Dennis has a friend named Joey who is also a novice Unix pro- grammer. Joey has a C program named foo.c that has some data structure definitions in foo.h, which lives in the same directory. Now, you probably know that “foo” is a popular name among computer programmers. It turns out that the systems programmer for Joey’s machine also made a file named foo.h and stored it in the default include file directory, /usr/include. Poor Joey goes to compile his foo.c program and is surprised to see multi- ple syntax errors. He is puzzled since the compiler generates a syntax error every time he mentions any of the data structures defined in foo.h. But the definitions in foo.h look okay. You and I probably know that the Joey probably has: #include foo.h in his C file instead of: #include "foo.h"
182 Programming but Joey doesn’t know that. Or maybe he is using quotes but is using a compiler with slightly different search rules for include files. The point is that Joey is hosed, and it’s probably not his fault. Having a large number of header files is a big pain. Unfortunately, this sit- uation occurs whenever you try to write a C program that does anything useful. Header files typically define data structures and many header files depend on data structures defined in other header files. You, as the pro- grammer, get the wonderful job of sorting out these dependencies and including the header files in the right order. Of course, the compiler will help you. If you get the order wrong, the com- piler will testily inform you that you have a syntax error. The compiler is a busy and important program and doesn’t have time to figure out the differ- ence between a missing data structure definition and a plain old mistyped word. In fact, if you make even a small omission, like a single semicolon, a C compiler tends to get so confused and annoyed that it bursts into tears and complains that it just can’t compile the rest of the file since the one missing semicolon has thrown it off so much. The poor compiler just can’t concentrate on the rest. In the compiler community, this phenomenon is known as “cascade errors,” which is compiler jargon for “I’ve fallen and I can’t get up.” The missing semicolon has thrown the compiler’s parser out of sync with respect to the program text. The compiler probably has such a hard time with syntax error because it’s based on yacc, which is a great tool for pro- ducing parsers for syntactically correct programs (the infrequent case), but a horrible tool for producing robust, error-detecting and -correcting pars- ers. Experienced C programmers know to ignore all but the first parse error from a compiler. Utility Programs and Man Pages Unix utilities are self-contained each is free to interpret its command-line arguments as it sees fit. This freedom is annoying instead of being able to learn a single set of conventions for command line arguments, you have to read a man page for each program to figure out how to use it. It’s a good thing the man pages are so well written. Take this following example. The “SYNOPSIS” sums it up nicely, don’t you think?
Previous Page Next Page