Annotation of OpenXM_contrib/gnuplot/CodeStyle, Revision 1.1.1.2
1.1.1.2 ! maekawa 1: $Id: CodeStyle,v 1.5 1998/11/20 22:20:20 lhecking Exp $
1.1 maekawa 2:
3: The following things have be observed when writing new code for gnuplot:
4: (this file is currently under construction) Some of the following is
5: just personal bug-bears, so dont take any offense if something I
6: moan about is something you think is good style...
7:
8:
9:
10: MISSING FUNCTIONS, AND FUNCTIONS TO BE AVOIDED
11: ----------------------------------------------
12: The following functions may not be used, since they are not present on all
13: systems (though the substitute functions might be defined to exactly these
14: functions)
15:
16: function use instead
17:
18: bcopy memcpy
19: bzero memset
20: index strchr
21: rindex strrchr
22: strncasecmp strnicmp
23:
24:
25:
26: The number of macros for conditional compilation is getting a little
27: extreme! I (personally) think it's better to make the conditionally-compiled
28: code 'feature-based' rather than 'compiler-based'. I think this is particularly
29: true for the many DOS compilers. The sort of thing I am thinking of is,
30: for example, whether to disable hidden3d stuff, or whether to store
31: data points as float rather than double to save space. Rather than having
32: a long list of compilers or OS's which use one or the other, add macros
33: such as SMALLMEMORY or NOHIDDENSTUFF and define these in the makefiles.
34: Perhaps a sensible guideline for choice of such macros is to arrange
35: things so that the smallest number of ports are affected. For example,
36: if we only compiled the hidden stuff if HIDDENSTUFF was defined, most
37: makefiles would have to be updated. But if instead it is being disabled
38: for a few machines, only those makefiles have to explicitly define
39: NOHIDDENSTUFF.
40:
41: Perhaps a good guideline would be that gnuplot should build cleanly
42: with most available features if no macros are defined on an ANSI C compiler
43: on a 'typical' (POSIX, say) unix machine.
44:
45: For example, I myself have broken this rule by requiring the macro
46: HAVE_LOCALE in order to support setlocale() - this feature is available
47: with ANSI compilers, and so setlocale() calls should be enabled by default,
48: and disabled only if NO_LOCALE is defined at compile time. Does this
49: sound reasonable? For example, there was some code in fit.c that would
50: prefer to use tempnam() if it is available, but falls back to ANSI fn
51: tmpnam() if necessary. The way it was done, tempnam() was the default,
52: and there was a list of those systems that had to use tmpnam().
53: But the trouble was that a new one had to be added to the list every
54: few weeks as new machines were discovered. The current scheme is
55: that tmpnam() is used unless feature HAVE_TEMPNAM is enabled.
56:
57:
58:
59: On a related note... if one particular machine does doesn't provide
60: a standard-ish function, but the same functionality can be
61: acheived, it would be preferable to implement the standardish
62: function in a os-specific source file, so that the core code can
63: simply invoke the function without any conditionals, and the OS-specific
64: files provide the missing functions. For example, in fit.c (at the
65: time of writing) where a temporary file is needed, there is some
66: inline code for DOS, OS2, AMIGA, etc to create temporary files,
67: otherwise tempnam() is used. I think I'd rather have tempnam()
68: implemented as a function in dos.c for example, then the fit code
69: would not need to have any conditional code other than HAVE_TEMPNAM
70:
71:
72:
73: Also, think generic where possible... I once noticed that popen()
74: had been implemented for atari or similar using temporary files
75: and system() call. It seems to me that this could easily be done
76: as a generic solution, so that DOS ports, for example, could also
77: benefit.
78:
79:
80:
81:
82: FUNCTION PROTOTYPES
83: -------------------
84:
85: Function prototypes are mandatory, even for local functions that are
86: declared before use. This is necessary for a clean compile on
87: some machines. gcc -Wstrict-prototypes is recommended.
88: However, to make the code compilable on pre-ANSI style compilers,
89: prototypes have to be enclosed in a special macro, e.g.
90:
91: int strcmp __PROTO((char *s, char *t)); /* note the double ()'s */
92:
93: Function definitions, on the other hand, must be done in
94: k&r style (which ANSI compilers accept).
95:
96: int strcmp(s,t)
97: char *s, *t;
98: {
99: ...
100: }
101:
102: While compilers do not require that explicit declarations be
103: given for integer arguments, we do !
104:
105:
106:
107: If a function has an argument which has a default promotion (char, short,
108: float), this could cause problems with some strict ANSI conforming compilers.
109: In this case an alternate function header must be used, e.g.
110:
111: #ifdef PROTOTYPES
112: char *foo(char s)
113: #else
114: char *foo(s)
115: char s;
116: #endif
117:
118: but since there's no benefit from using a character as parameter, may
119: as well use the int ie.
120: char *foo(s)
121: int s;
122:
123: gcc -Wtraditional might help with this.
124: [char parameters should be avoided. int can safely be used in this case.]
125:
126:
127:
128: While ANSI compilers can use prototypes for implicit typecasts, k&r
129: compilers do not have this information. Avoid relying on implicit
130: conversions of function parameters. gcc -Wconversion helps with this.
131: There are many signed/unsigned warnings, but look out for other
132: ones which may be more serious, in particular integer to float and
133: vice versa. Placing casts is necessary in this case for correct
134: code on non-ansi compilers.
135:
136: [we will definitely give up k&r support in the near future, but
137: since existing code seems to work with k&r, we're sticking
138: with it.
139: ]
140:
141:
142:
143:
144: INTEGER SIZE
145: ------------
146:
147: Large integer constant expression have to be explicitly cast to long, even
148: if the result is assigned to a long variable.
149:
150: long t=60*60*24;
151: results in a overflow on 16 bit compilers, even though the result fits into
152: the long variable.
153:
154: Correct: long t=60l*60l*24l;
155:
156:
157:
158: Similarly, though not particularly important, ANSI and k&r compilers
159: treat integer constants > MAX_INT differently. If you mean an
160: unsigned integer constant, say so.
161:
162:
163:
164:
165: Please avoid duplicating large sections of code - make the effort
166: to make a function or macro out of the common code.
167:
168:
169: min(a,b), max(a,b), MIN(a,b), MAX(a,b) are all predefined by some
170: compilers. I am now using GPMIN() and GPMAX() [wot a pain !]
171:
172:
173: Avoid putting directories into #includes - eg #include "term/file.h"
174: is to be avoided. Instead, #include "file.h" and use -Iterm on the
175: compile line.
176:
177:
178: coordval is typedef-ed to either double or float - it is almost always
179: double, but please take care not to mix coordval's with doubles.
180:
181:
182:
183:
184:
185: LAYOUT AND INDENTATION
186: ----------------------
187:
188: The code layout is getting into a bit of a mess, due to mixed
189: conventions. IMHO the only useful style is one tab stop per
190: indent. This way, anyone can set their editor to display
191: with their preferred spacing. More importantly, one has to
192: delete only one tab to outdent once more : this makes it so much
193: easier to ensure alignment even if the opening brace is
194: off the top of the screen.
195: Much of the code seems to assume tab=8, and uses 4 spaces,
196: then one tab, then tab+4, then 2tab, ... On an entirely
197: personal note, this breaks my folding editor :-(
198:
199: I think vi does this by default. If using vi, please try
200: putting set ts=4 into your ~/.exrc file.
201:
202:
203: Unfortunately, gnu indent does not seem to recognise this
204: as a layout style. If it did, I'd have run all sources
205: through it long ago. [GNU indent -kr -cp0 -l100 -lps comes
206: pretty close, though. I need very little manual editing after
207: running this, mostly for long (> 80 cols) lines. -Lars]
208:
209:
210:
211: Please use lots of vertical whitespace between unrelated
212: blocks of code in functions. And it should not be need to
213: be said, but I'll say it anyway... please put in lots of
214: comments describing blocks of code. Many people maintain and
215: contribute to this code.
216:
217:
218: The functions in plot?d.c and graph*.c are sometimes very long.
219: This isn't really a problem, since there's a lot of semi-independent
220: things to be done in sequence. However, I do object to the
221: practise of having all variables declared at the top of
222: such functions. Please keep the scope of temporary variables
223: as local as possible, particularly in these long functions.
224: The main reason is for ease of maintenance : many people
225: make modifications to small parts of code without fully
226: understanding in exacting detail the surrounding code.
227:
228:
229: In case you were wondering, lines of the form /*{{{ comment */
230: and /*}}}*/ are markers left by my folding editor when I am forced
231: to fold up particularly long functions when trying to understand the
232: logic. I tend to leave these markers in when I finally figure it out,
233: though perhaps I should not.
234:
235:
236: Source code is intended to be read and maintained by humans. As such,
237: readability is prefered over elegance. Please separate all operators
238: from operands with a space, ie. instead of x+=3, use x += 3. The former
239: is not only less readable, it may also break older compilers! This rule
240: should also be followed for simple assignments, ie. in for (;;) loops.
241: Unary operators should be writen as usual, ie i++.
242:
243:
244: [more to come]
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>