|
|
1.1 root 1: # include "/usr/sys/param.h"
2: # include <sccs.h>
3:
4: /*
5: ** CODE_CNVNTNS.C -- A Program to Display the INGRES Coding Style
6: **
7: ** This hunk of code does virtually nothing of use. Its main
8: ** purpose is to demonstrate the "official" ingres coding style.
9: **
10: ** This demonstrates comments. There should be a block comment
11: ** at the beginning of every file and/or procedure to explain
12: ** the function of the code. Important information to put here
13: ** includes the parameters of the routines, any options that the
14: ** user may specify, etc.
15: **
16: ** The first line of the comment should be a one-line description
17: ** of what's going on. The remainder should be more detailed.
18: ** Blank lines should separate major points in the comments. In
19: ** general, ask yourself the question, "If I didn't know what this
20: ** code was, what it was for, how it fit in, etc., and if I didn't
21: ** even have the documentation for it, would these comments be
22: ** enough for me?"
23: **
24: ** Some general guidelines for the code:
25: **
26: ** ***** GENERAL SYNTAX *****
27: **
28: ** - Commas and semicolons should always be followed by a space.
29: ** Binary operators should be surrounded on both sides by
30: ** spaces. Unary operators should be in direct contact
31: ** with the object that they act on, except for "sizeof",
32: ** which should be separated by one space.
33: **
34: ** - Two statements should never go on the same line. This includes
35: ** such things as an if and the associated conditionally
36: ** executed statement.
37: ** In cases such as this, the second half of the if
38: ** should be indented one tab stop more than the if. For
39: ** example, use:
40: ** if (cond)
41: ** statement;
42: ** never:
43: ** if (cond) statement;
44: ** or:
45: ** if (cond)
46: ** statement;
47: **
48: ** - Braces ({}) should (almost) always be on a line by them-
49: ** selves. Exceptions are closing a do, and terminating
50: ** a struct definition or variable initialization. Braces
51: ** should start at the same indent as the statement with
52: ** which they bind, and code inside the braces should be
53: ** indented one stop further. For example, use:
54: ** while (cond)
55: ** {
56: ** code
57: ** }
58: ** and never:
59: ** while (cond)
60: ** {
61: ** code
62: ** }
63: ** or:
64: ** while (cond) {
65: ** code
66: ** }
67: ** or:
68: ** while (cond)
69: ** {
70: ** code
71: ** }
72: ** or anything else in that line. Braces which match
73: ** should always be at the same tab stop.
74: **
75: ** - Do statements must always be of the form:
76: ** do
77: ** {
78: ** code;
79: ** } while (cond);
80: ** even if "code" is only one line. This is done so that
81: ** it is clear that the "while" is with a do, rather than
82: ** a standalone "while" which is used for the side effects of
83: ** evaluation of the condition.
84: **
85: ** - There should always be a space following a keyword (i.e.,
86: ** for, if, do, while, switch, and return), but never
87: ** between a function and the paren preceeding its
88: ** arguments. For example, use:
89: ** if (i == 0)
90: ** exit();
91: ** never:
92: ** if(i == 0)
93: ** exit ();
94: **
95: ** - Every case in a switch statement (including default) should
96: ** be preceeded by a blank line. The actual word "case" or
97: ** "default" should have the indent of the switch statement plus
98: ** two spaces. It should be followed by a space (not a
99: ** tab) and the case constant. Multiple case labels on
100: ** a single block of code should be on separate lines, but
101: ** they should not be separated by blank lines. The
102: ** switch statement should in general be used in place of
103: ** such constructs as:
104: ** if (i == 1)
105: ** code1;
106: ** else if (i == 34)
107: ** code2;
108: ** else if (i == -1643)
109: ** code3;
110: ** which can be more succinctly stated as:
111: ** switch (i)
112: ** {
113: ** case 1:
114: ** code1;
115: ** break;
116: **
117: ** case 34:
118: ** code2;
119: ** break;
120: **
121: ** case -1643:
122: ** code3;
123: ** break;
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: ** if (i < 5)
131: ** code1;
132: ** else
133: ** if (j > 3)
134: ** code2;
135: ** else
136: ** code3;
137: ** is acceptable.
138: **
139: ** - A blank line should separate the declarations and the code
140: ** in a procedure. Blank lines should also be used freely
141: ** between major subsections of your code. The major
142: ** subsections should also have a block comment giving
143: ** some idea of what is about to occur.
144: **
145: ** ***** PREPROCESSOR USAGE *****
146: **
147: ** - Fields of #defines and #includes should line up. Use:
148: ** # define ARPA 25
149: ** # define MAXFIELDS 18
150: ** and not:
151: ** #define ARPA 25
152: ** #define MAXFIELDS 18
153: ** Conditional compilation (#ifdef/#endif) should be used
154: ** around all trace information, timing code, and code
155: ** which may vary from version to version of UNIX. See
156: ** the code below for an example of conditional compila-
157: ** tion use.
158: **
159: ** ***** VARIABLES AND DECLARATIONS *****
160: **
161: ** - Defined constants (defined with the # define feature) must
162: ** be entirely upper case. The exceptions to this are
163: ** compilation flags, which begin with a lower case "x",
164: ** and some sub-types for parser symbols. In any case,
165: ** the majority of the symbol is upper case.
166: **
167: ** - Global variables should begin with an upper case letter and
168: ** be otherwise all lower case. Local symbols should be
169: ** entirely lower case. Procedure names are all lower
170: ** case. The only exception to this is the trace routine
171: ** "tTf". You should avoid user non-local symbols (globals
172: ** or # define'd symbols) which are one character only;
173: ** it is impossible to distinguish them. Capitalization
174: ** may be used freely inside global names so long as they
175: ** are primarily lower case; for example, "ProcName" is
176: ** an acceptable name (and preferred over either Proc_name
177: ** or Procname).
178: **
179: ** - Use descriptive variable names, particularly for global var-
180: ** iables. "IEH3462" tells me nothing; nor does "R". On
181: ** the other hand, "Resultid" tells me quite a lot,
182: ** including what it might be, where I might go to see
183: ** how it is initialized, etc. Try not to use variables
184: ** for multiple purposes. Variable names like "i" are
185: ** acceptable for loop indices & temporary storage
186: ** provided that the value does not have long-term
187: ** semantic value.
188: **
189: ** - When the storage structure or type of a variable is
190: ** important, always state it explicitly. In particular,
191: ** include "auto" if you are going to take the address
192: ** of something using the ampersand operator (so that
193: ** some wayward programmer doesn't change it to register),
194: ** and declare int parameters as int instead of letting
195: ** them default.
196: **
197: ** ***** GENERAL COMMENTS *****
198: **
199: ** - It is quite possible to name a file "printr.c" and then
200: ** put the code for "destroydb" in it. Try to arrange
201: ** the names of your files so that given the name of a
202: ** routine, it is fairly easy to figure out which file
203: ** it is in.
204: **
205: ** - Sometimes it is really pretty much impossible to avoid doing
206: ** something tricky. In these cases, put in a comment
207: ** telling what you are doing and why you are doing it.
208: **
209: ** - Try to write things that are clear and safe, rather than
210: ** things which you think are easier to compile. For
211: ** example, always declare temporary buffers as local,
212: ** rather than as global. This way you can another
213: ** routine accidently when it still had useful info
214: ** in it.
215: **
216: ** ***** COMMENTS *****
217: **
218: ** - The importance of comments cannot be overemphasised.
219: ** INGRES is primarily a research vehicle rather than
220: ** a program product. This means that there will be
221: ** many people pouring over your code, trying to
222: ** understand what you have done & modify it to do
223: ** other things. Try to make life easy for them &
224: ** maybe they will be nice to you someday.
225: **
226: ** - Try to keep an idea of the flow of your program. Put
227: ** block comments at the beginning of major segments,
228: ** and use one-line comments at less major junctures.
229: ** A person viewing your code at ten paces should be
230: ** able to tell where the major segments lay.
231: **
232: ** - The preferred format for block comments is to begin with
233: ** a line containing slash-star alone, followed by a
234: ** number of lines all beginning star-star containing
235: ** the comment, and terminating with a line containing
236: ** star-slash alone. Comments without the double-star
237: ** at the beginning of each line should be avoided,
238: ** since it makes the comments seemingly disappear into
239: ** the body of the code.
240: **
241: ** - The beginning of each routine should have a comment block
242: ** in parametric form as demonstrated below. The fields
243: ** "Parameters", "Returns", and "Side Effects" should
244: ** be considered mandatory. Mark parameters as being
245: ** (IN), (IN/OUT), or (OUT) parameters, depending on
246: ** whether the parameter is used only to transmit infor-
247: ** mation into the routine, in and out of the routine,
248: ** or only to return information; the default is (IN).
249: **
250: ** Remember, it is easy to write totally incomprehensible code in
251: ** C, but we don't go in for that sort of thing. It isn't too
252: ** much harder to write brilliantly clear code, and the code is
253: ** worth a lot more later.
254: **
255: ** For efficiency reasons, you should always use register variables
256: ** when possible. A simple and extremely effective tip is to define
257: ** a register variable, and assign an oft-used parameter to it,
258: ** since it is particularly inefficient to reference a parameter.
259: ** Another particularly inefficient operation is referencing arrays
260: ** of structures. When possible, define a register pointer to the
261: ** structure, and then say:
262: ** struct xyz structure[MAX];
263: ** register struct xyz *p;
264: ** ...
265: ** for (i = 0; i < MAX; i++)
266: ** {
267: ** p = &structure[i];
268: ** p->x = p->y + p->z;
269: ** (diddle with p->???)
270: ** }
271: ** and not:
272: ** struct xyz structure[MAX];
273: ** ...
274: ** for (i = 0; i < MAX; i++)
275: ** {
276: ** Structure[i].x = Structure[i].y + Structure[i].z;
277: ** (diddle with Structure[i].???)
278: ** }
279: ** Remember, the nice things about register variables is that they
280: ** make your code smaller and they run faster. It is hard to
281: ** lose with registers. There are three restrictions which you
282: ** should be aware of on register variables, however. First,
283: ** The only types which may be registers are int's, char's,
284: ** and pointers. Second, there may only be three register
285: ** variables per subroutine. Third, you may not take the address
286: ** of a register variable (i.e., you may not say "&i" if i is
287: ** typed as a register variable).
288: **
289: ** Usage:
290: ** example [flags] argument
291: **
292: ** Positional Parameters:
293: ** argument -- this gets echoed to the standard
294: ** output.
295: **
296: ** Flags:
297: ** -n -- don't put a newline at the end.
298: ** -x -- don't do anything.
299: ** -b -- echo it with a bell character.
300: **
301: ** Return Codes:
302: ** 0 -- successful
303: ** else -- failure
304: **
305: ** Defined Constants:
306: ** XEQ1 -- maximum number of simultaneous equijoins.
307: **
308: ** Compilation Flags:
309: ** xTRACE -- enable trace information
310: **
311: ** Trace Flags:
312: ** 5 -- general debug
313: ** 6 -- reserved for future use
314: **
315: ** Compilation Instructions:
316: ** cc -n example.c
317: ** mv a.out example
318: ** chmod 755 example
319: **
320: ** Notes:
321: ** These comments don't apply to the code at all,
322: ** since this is just an example program.
323: ** Also, it is wise to avoid this many comments
324: ** except at the head of main programs and
325: ** at the head of major modules. For example,
326: ** this sort of commenting is appropriate at
327: ** the top of ingres.c (system startup) and
328: ** view.c (virtual view subsystem), but not
329: ** in small utility routines, e.g., length.c.
330: ** This sort of routine should be limited to
331: ** "Parameters:", "Returns:", "Side Effects:",
332: ** and anything else that seems relevant in
333: ** that context.
334: ** A fairly large comment block should exist at the
335: ** top of modules [files] which contain many
336: ** procedures; this block should clarify why
337: ** the procedures are grouped together, that
338: ** is, their common purpose in life. A small
339: ** block should occur at the top of each
340: ** procedure explaining details of that proce-
341: ** dure.
342: ** Procedures should be on separate pages (use the
343: ** form feed character, control-L).
344: ** A program will help you generate this comment block.
345: ** In ex, go to the line where you want to insert
346: ** a block and say "so /mnt/ingres/comment". It
347: ** will ask you for a block type, e.g., "main"
348: ** for main program, "modfn" for a file which
349: ** contains only one function, "function" or
350: ** "procedure" for a procedure within a module,
351: ** "module" for a module header (e.g., as a
352: ** separate comment block for a major module
353: ** [check .../qrymod/view.c for an example] or
354: ** in header files.
355: ** SCCS should be considered an essential tool, if only
356: ** to maintain history fields.
357: **
358: ** Deficiencies:
359: ** It should handle pseudo tty's.
360: */
361:
362: /* the following macro is defined by <sccs.h> */
363: SCCSID(%W%); /* %W% is replaced by a version number by SCCS */
364:
365:
366:
367:
368:
369:
370: # define XEQ1 5
371:
372: struct magic
373: {
374: char *name; /* name of symbol */
375: int type; /* type of symbol, defined in symbol.h */
376: int value; /* optional value. This is actually
377: * the value if it is type "integer",
378: * a pointer to the value if it is a
379: * string. */
380: };
381:
382: struct magic Stuff;
383:
384: main(argc, argv)
385: int argc;
386: char *argv[];
387: {
388: register struct magic *r;
389: register int i;
390: register int j;
391: int timebuf[2];
392: auto int status;
393:
394: /*
395: ** Note that in the declarations of argc and argv above, all
396: ** parameters to any function should be declared, even if they
397: ** are of type int (which is the default).
398: */
399:
400: r = &Stuff;
401: /* initialize random # generator */
402: time(timebuf);
403: srand(timebuf[1]);
404:
405: /* scan Stuff structure */
406: for (i = 0; i < XEQ1; i++)
407: {
408: # ifdef xTRACE
409: if (tTf(5, 13))
410: printf("switch on type %d\n", r->reltype);
411: # endif
412: switch (r->type)
413: {
414:
415: case 0:
416: case 1:
417: case 3:
418: /* initialize */
419: printf("hi\n");
420: break;
421:
422: case 2:
423: /* end of query */
424: printf("bye\n");
425: break;
426:
427: default:
428: /*
429: ** be sure to print plenty of info on an error;
430: ** "syserr("bad reltype");" would not have been
431: ** sufficient. However, don't make syserr's
432: ** overly verbose; they take much space in the
433: ** object module, and it will probably be
434: ** necessary to look at the code anyway.
435: */
436: syserr("main: bad type %d", r->type);
437:
438: }
439: }
440:
441: /* resist the temptation to say "} else {" */
442: if (i == 5)
443: {
444: i++;
445: j = 4;
446: }
447: else
448: i--;
449:
450: /* plot the results */
451: do
452: {
453: i = rand() & 017;
454: plot(i);
455: } while (j--);
456:
457: /* wait for child processes to complete */
458: wait(&status);
459: /* end of run, print termination message and exit */
460: for (i = 0; i < 2; i++)
461: printf("bye ");
462: printf("\n");
463: }
464: /*
465: ** PLOT -- Plot a Bar-Graph
466: **
467: ** Does a simple plot on a terminal -- one line's worth.
468: **
469: ** Parameters:
470: ** n (IN) -- number of asterisks to plot
471: **
472: ** Returns:
473: ** none
474: **
475: ** Side Effects:
476: ** none
477: **
478: ** Deficiencies:
479: ** Should allow scaling.
480: */
481:
482: plot(n)
483: int n;
484: {
485: register int i;
486:
487: for (i = n; i-- > 0; )
488: {
489: printf("*");
490: }
491: printf("\n");
492: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.