|
|
1.1 root 1: # include "/usr/sys/param.h"
2:
3: /*
4: ** DEMO PROGRAM
5: **
6: ** This hunk of code does virtually nothing of use. Its main
7: ** purpose is to demonstrate the "official" ingres coding style.
8: **
9: ** This demonstrates comments. There should be a block comment
10: ** at the beginning of every file and/or procedure to explain
11: ** the function of the code. Important information to put here
12: ** includes the parameters of the routines, any options that the
13: ** user may specify, etc.
14: **
15: ** The first line of the comment should be a one-line description
16: ** of what's going on. The remainder should be more detailed.
17: ** Blank lines should seperate major points in the comments. In
18: ** general, ask yourself the question, "If I didn't know what this
19: ** code was, what it was for, how it fit in, etc., and if I didn't
20: ** even have the documentation for it, would these comments be
21: ** enough for me?"
22: **
23: ** Some general guidelines for the code:
24: **
25: ** - Commas and semicolons should always be followed by a space.
26: ** Binary operators should be surrounded on both sides by
27: ** spaces. Unary operators should be in direct contact
28: ** with the object that they act on, except for "sizeof",
29: ** which should be seperated by one space.
30: **
31: ** - Two statements should never go on the same line. This includes
32: ** such things as an if and the associated conditionally
33: ** executed statement.
34: ** In cases such as this, the second half of the if
35: ** should be indented one tab stop more than the if. For
36: ** example, use:
37: ** if (cond)
38: ** statement;
39: ** never:
40: ** if (cond) statement;
41: ** or:
42: ** if (cond)
43: ** statement;
44: **
45: ** - Braces ({}) should (almost) always be on a line by them-
46: ** selves. Exceptions are closing a do, and terminating
47: ** a struct definition or variable initialization. Braces
48: ** should start at the same indent as the statement with
49: ** which they bind, and code inside the braces should be
50: ** indented one stop further. For example, use:
51: ** while (cond)
52: ** {
53: ** code
54: ** }
55: ** and never:
56: ** while (cond)
57: ** {
58: ** code
59: ** }
60: ** or:
61: ** while (cond) {
62: ** code
63: ** }
64: ** or:
65: ** while (cond)
66: ** {
67: ** code
68: ** }
69: ** or anything else in that line. Braces which match
70: ** should always be at the same tab stop.
71: **
72: ** - Declarations should always have at least one tab between the
73: ** declaration part and the variable list part, but never
74: ** any tabs within the declaration part or the variable
75: ** list part. For example, in the line:
76: ** register int i, j;
77: ** There is a tab between the "int" and the "i", but a
78: ** space between "register" and "int", since together
79: ** these make up the declaration part.
80: **
81: ** - There should always be a space following a keyword (i.e.,
82: ** for, if, do, while, switch, and return), but never
83: ** between a function and the paren preceeding its
84: ** arguments. For example, use:
85: ** if (i == 0)
86: ** exit();
87: ** never:
88: ** if(i == 0)
89: ** exit ();
90: **
91: ** - Every case in a switch statement (including default) should
92: ** be preceeded by a blank line. The actual word "case" or
93: ** "default" should have the indent of the switch statement plus
94: ** two spaces. It should be followed by a space (not a
95: ** tab) and the case constant. Multiple case labels on
96: ** a single block of code should be on seperate lines, but
97: ** they should not be seperated by blank lines. The
98: ** switch statement should in general be used in place of
99: ** such constructs as:
100: ** if (i == 1)
101: ** code1;
102: ** else
103: ** if (i == 34)
104: ** code2;
105: ** else
106: ** if (i == -1643)
107: ** code3;
108: ** which can be more succinctly stated as:
109: ** switch (i)
110: ** {
111: **
112: ** case 1:
113: ** code1;
114: ** break;
115: **
116: ** case 34:
117: ** code2;
118: ** break;
119: **
120: ** case -1643:
121: ** code3;
122: ** break;
123: **
124: ** }
125: ** In point of fact the equivalent switch will compile
126: ** extremely efficiently. (Note that if you had some
127: ** instance where you could not use a case, e.g., checking
128: ** for i < 5, else check for j > 3, else whatever, then
129: ** the above ("if") code is in the correct style. However,
130: ** an acceptable alternate structure is to consider "else if"
131: ** as a primitive. Hence:
132: ** if (i < 5)
133: ** code1;
134: ** else if (j > 3)
135: ** code2;
136: ** else
137: ** code3;
138: ** is acceptable.
139: **
140: ** - Do statements must always be of the form:
141: ** do
142: ** {
143: ** code;
144: ** } while (cond);
145: ** even if "code" is only one line. This is done so that
146: ** it is clear that the "while" is with a do, rather than
147: ** a standalone "while" which is used for the side effects of
148: ** evaluation of the condition.
149: **
150: ** - Defined constants (defined with the # define feature) must
151: ** be entirely upper case. The exceptions to this are
152: ** compilation flags, which begin with a lower case "x",
153: ** and some sub-types for parser symbols. In any case,
154: ** the majority of the symbol is upper case.
155: **
156: ** - Global variables should begin with an upper case letter and
157: ** be otherwise all lower case. Local symbols should be
158: ** entirely lower case. Procedure names are all lower
159: ** case. The only exception to this is the trace routine
160: ** "tTf". You should avoid user non-local symbols (globals
161: ** or # define'd symbols) which are one character only;
162: ** it is impossible to distinguish them.
163: **
164: ** - # defines and # includes should have a space after the sharp
165: ** sign and be followed by a tab. In general, try to make
166: ** things line up. Use:
167: ** # define ARPA 25
168: ** # define MAXFIELDS 18
169: ** and not:
170: ** #define ARPA 25
171: ** #define MAXFIELDS 18
172: ** Conditional compilation statements should have as many
173: ** tabs as are necessary to bring the "ifdef",
174: ** "ifndef", or "endif" to the tab stop of the surrounding
175: ** code. The keyword ("ifdef" or "ifndef") should be
176: ** followed by a space and the conditional compilation
177: ** variable. Conditional compilation should be used
178: ** around all trace information, timing code, and code
179: ** which may vary from version to version of UNIX. See
180: ** the code below for an example of conditional compila-
181: ** tion use.
182: **
183: ** - A blank line should seperate the declarations and the code
184: ** in a procedure. Blank lines should also be used freely
185: ** between major subsections of your code. The major
186: ** subsections should also have a comment giving some idea
187: ** of what is about to occur.
188: **
189: ** - Use descriptive variable names, particularly for global var-
190: ** iables. "IEH3462" tells me nothing; nor does "R". On
191: ** the other hand, "Resultid" tells me quite a lot,
192: ** including what it might be, where I might go to see
193: ** how it is initialized, etc. Try not to use variables
194: ** for multiple purposes.
195: **
196: ** - It is quite possible to name a file "printr.c" and then
197: ** put the code for "destroydb" in it. Try to arrange
198: ** the names of your files so that given the name of a
199: ** routine, it is fairly easy to figure out which file
200: ** it is in.
201: **
202: ** - Sometimes it is really pretty much impossible to avoid doing
203: ** something which is not immediately obvious. In these
204: ** cases, put in a comment telling what you are doing and
205: ** why you are doing it.
206: **
207: ** - Try to write things that are clear, rather than things which
208: ** you think are easier to compile. I mean, who really
209: ** cares? For example, always declare temporary buffers
210: ** as local, rather than as global. This way you can
211: ** guarantee that you will never clobber the buffer in
212: ** another routine accidently when it still had useful
213: ** info in it.
214: **
215: ** Remember, it is easy to write incomprehensible code in
216: ** C. If you really get off on doing this, however, go get
217: ** a job programming in APL.
218: **
219: ** For efficiency reasons, you should always use register variables
220: ** when possible. A simple and extremely effective tip is to define
221: ** a register variable, and assign an oft-used parameter to it,
222: ** since it is particularly inefficient to reference a parameter.
223: ** Another particularly inefficient operation is referencing arrays
224: ** of structures. When possible, define a register pointer to the
225: ** structure, and then say:
226: ** struct xyz structure[MAX];
227: ** register struct xyz *p;
228: ** ...
229: ** for (i = 0; i < MAX; i++)
230: ** {
231: ** p = &structure[i];
232: ** p->x = p->y + p->z;
233: ** (diddle with p->???)
234: ** }
235: ** and not:
236: ** struct xyz structure[MAX];
237: ** ...
238: ** for (i = 0; i < MAX; i++)
239: ** {
240: ** Structure[i].x = Structure[i].y + Structure[i].z;
241: ** (diddle with Structure[i].???)
242: ** }
243: ** Remember, the nice things about register variables is that they
244: ** make your code smaller and they run faster. It is hard to
245: ** lose with registers. There are three restrictions which you
246: ** should be aware of on register variables, however. First,
247: ** The only types which may be registers are int's, char's,
248: ** and pointers. Second, there may only be three register
249: ** variables per subroutine. Third, you may not take the address
250: ** of a register variable (i.e., you may not say "&i" if i is
251: ** typed as a register variable).
252: */
253:
254:
255: # define XEQ1 5
256:
257: struct magic
258: {
259: char *name; /* name of symbol */
260: int type; /* type of symbol, defined in symbol.h */
261: int value; /* optional value. This is actually
262: * the value if it is type "integer",
263: * a pointer to the value if it is a
264: * string. */
265: };
266:
267: struct magic Stuff;
268:
269: main(argc, argv)
270: int argc;
271: char *argv[];
272: {
273: register struct magic *r;
274: register int i;
275: register int j;
276: int timebuf[2];
277: int status;
278:
279: /* Note that in the declarations of argc and argv above, all
280: * parameters to any function should be declared, even if they
281: * are of type int (which is the default). */
282:
283: r = &Stuff;
284: /* initialize random # generator */
285: time(timebuf);
286: srand(timebuf[1]);
287:
288: /* scan Stuff structure */
289: for (i = 0; i < XEQ1; i++)
290: {
291: # ifdef xTRACE
292: if (tTf(5, 13))
293: printf("switch on type %d\n", r->reltype);
294: # endif
295: switch (r->type)
296: {
297:
298: case 0:
299: case 1:
300: case 3:
301: /* initialize */
302: printf("hi\n");
303: break;
304:
305: case 2:
306: /* end of query */
307: printf("bye\n");
308: break;
309:
310: default:
311: /* be sure to print plenty of info on an error;
312: * "syserr("bad reltype");" would not have been
313: * sufficient */
314: syserr("bad type %d", r->type);
315:
316: }
317: }
318:
319: /* resist the temptation to say "} else {" */
320: if (i == 5)
321: {
322: i++;
323: j = 4;
324: }
325: else
326: i--;
327:
328: /* plot the results */
329: do
330: {
331: i = rand() & 017;
332: while (i--)
333: {
334: printf("*");
335: }
336: printf("\n");
337: } while (j--);
338:
339: /* wait for child processes to complete */
340: wait(&status);
341: /* end of run, print termination message and exit */
342: for (i = 0; i < 2; i++)
343: printf("bye ");
344: printf("\n");
345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.