Of course, this means that your build system needs to become more
complicated. If you use \man{make}{1}, then something like
\begin{prog}
- SOD = sod
- \\+
- .SUFFIXES: .sod .c .h \\
- .sod.c:; \$(SOD) -tc \$< \\
+ SOD = sod \\+
+
+ .SUFFIXES: .sod .c .h \\
+ .sod.c:; \$(SOD) -tc \$< \\
.sod.h:; \$(SOD) -th \$<
\end{prog}
ought to do the job.
The following is a simple Sod input file.
\begin{prog}
- /* -*-sod-*- */
- \\+
- code c : includes \{ \\
- \#include "greeter.h" \\
- \}
- \\+
- code h : includes \{ \\
- \#include <stdio.h> \\
- \#include <sod/sod.h> \\
- \}
- \\+
- class Greeter : SodObject \{ \\ \ind
- void greet(FILE *fp) \{ \\ \ind
- fputs("Hello, world!\textbackslash n", fp); \- \\
- \} \- \\
+ /* -*-sod-*- */ \\+
+
+ code c: includes \{ \\
+ \#include "greeter.h" \\
+ \} \\+
+
+ code h: includes \{ \\
+ \#include <stdio.h> \\
+ \#include <sod/sod.h> \\
+ \} \\+
+
+ class Greeter: SodObject \{ \\ \ind
+ void greet(FILE *fp) \{ \\ \ind
+ fputs("Hello, world!\textbackslash n", fp); \-\\
+ \} \-\\
\}
\end{prog}
-Save it as @"greeter.sod", and run
+Save it as @|greeter.sod|, and run
\begin{prog}
sod --gc --gh greeter
\end{prog}
-This will create files @"greeter.c" and @"greeter.h" in the current
+This will create files @|greeter.c| and @|greeter.h| in the current
directory. Here's how we might use such a simple thing.
\begin{prog}
- \#include "greeter.h"
- \\+
- int main(void) \\
- \{ \\ \ind
- SOD_DECL(Greeter, g);
- \\+
- Greeter_greet(g, stdout); \\
- return (0); \- \\
+ \#include "greeter.h" \\+
+
+ int main(void) \\
+ \{ \\ \ind
+ SOD_DECL(Greeter, g); \\+
+
+ Greeter_greet(g, stdout); \\
+ return (0); \-\\
\}
\end{prog}
Compare this to the traditional
\begin{prog}
- \#include <stdio.h>
- \\+
- int main(void) \\ \ind
+ \#include <stdio.h> \\+
+
+ int main(void) \\ \ind
\{ fputs("Hello, world@\\n", stdout); return (0); \}
\end{prog}
and I'm sure you'll appreciate the benefits of using Sod already -- mostly to
do with finger exercise. Trust me, it gets more useful.
-The @".sod" file was almost comprehensible. There are two important parts to
+The @|.sod| file was almost comprehensible. There are two important parts to
it (after the comment which tells Emacs how to cope with it).
-The first part consists of the two @"code" stanzas. Both of them define
-gobbets of raw C code to copy into output files. The first one, @"code~:
-c"~\ldots, says that
+The first part consists of the two @|code| stanzas. Both of them define
+gobbets of raw C code to copy into output files. The first one, @|code~:
+c|~\ldots, says that
\begin{prog}
\#include "greeter.h"
\end{prog}
needs to appear in the generated @|greeter.c| file; the second says that
\begin{prog}
- \#include <stdio.h> \\
+ \#include <stdio.h> \\
\#include <sod/sod.h>
\end{prog}
needs to appear in the header file @|greeter.h|. The generated C files need
-to get declarations for external types and functions (e.g., @"FILE" and
-@"fputs") from somewhere, and the generated @".c" file will need the
-declarations from the corresponding @".h" file. Sod takes a very simple
+to get declarations for external types and functions (e.g., @|FILE| and
+@|fputs|) from somewhere, and the generated @|.c| file will need the
+declarations from the corresponding @|.h| file. Sod takes a very simple
approach to all of this: it expects you, the programmer, to deal with it.
-The basic syntax for @"code" stanzas is
+The basic syntax for @|code| stanzas is
\begin{prog}
- code @<file-label> : @<section> \{ \\ \ind
- @<code> \- \\
+ code @<file-label>: @<section> \{ \\ \ind
+ @<code> \-\\
\}
\end{prog}
-The @<file-label> is either @"c" or @"h", and says which output file the code
+The @<file-label> is either @|c| or @|h|, and says which output file the code
wants to be written to. The @<section> is a name which explains where in the
-output file to place the code. The @"includes" section is the usual choice:
+output file to place the code. The @|includes| section is the usual choice:
it's the `right' place for @`\#include' directives and similar declarations.
The remaining part, the `meat' of the file, defines a class called
-@"greeter". The class can respond to a single message, named @"greet", and
+@|greeter|. The class can respond to a single message, named @|greet|, and
in response, it writes a traditional greeting to the file passed in with the
message.
\begin{prog}
struct Greeter__ilayout g_obj;
\end{prog}
-allocates space for an instance of class @"Greeter". We're not going to use
+allocates space for an instance of class @|Greeter|. We're not going to use
this space directly. Instead, we do this frightening looking thing.
\begin{prog}
Greeter *g = Greeter__class@->cls.init(\&g_obj);
\end{prog}
-Taking it slowly: @"Greeter__class" is a pointer to the object that
-represents our class @"Greeter". This object contains a member, named
-@"cls.init", which points to a function whose job is to turn uninitialized
+Taking it slowly: @|Greeter__class| is a pointer to the object that
+represents our class @|Greeter|. This object contains a member, named
+@|cls.init|, which points to a function whose job is to turn uninitialized
storage space into working instances of the class. It returns a pointer to
the instance, which we use in preference to grovelling about in the
-@"ilayout" structure.
+@|ilayout| structure.
Having done this, we `send the instance a message':
\begin{prog}
g@->_vt@->greeter.greet(g, stdout);
\end{prog}
This looks horrific, and seems to repeat itself quite unnecessarily. The
-first @"g" is the recipient of our `message'. The second is indeed a copy of
+first @|g| is the recipient of our `message'. The second is indeed a copy of
the first: we have to tell it who it is. (Sod doesn't extend C's syntax, so
this is the sort of thing we just have to put up with.) The lowercase
-@"greeter" is our class's `nickname': we didn't choose one explicitly, so Sod
+@|greeter| is our class's `nickname': we didn't choose one explicitly, so Sod
picked one by forcing the classname to lowercase.
%%%----- That's all, folks --------------------------------------------------