forked from dwery/coldsync
-
Notifications
You must be signed in to change notification settings - Fork 1
/
HACKING
129 lines (110 loc) · 5.75 KB
/
HACKING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
* * Guidelines for contributors, most important ones first: * *
$Id$
- Try to leave this code as clean as you wish you had found it.
- If you're in a rush to get something done, but something isn't quite
right, put an XXX comment (with explanation) next to it. Otherwise,
odds are you won't be able to easily find it and fix it next week;
certainly no one else will.
- Nobody likes to write documentation, but it _is_ important. If you
add a feature, at the very least add an item to the "TODO" file,
e.g., "Documentation: describe the `foo' keyword in pda{} blocks."
Better yet, write the documentation now, before you forget.
- Priorities: when you're deciding how to implement such-and-such
feature, remember that the cardinal sin in syncing is loss of data:
whatever you do, don't delete anything unless there's a backup
somewhere, or you're certain that it isn't needed.
The next issue is that things should be optimized for the
user. In particular, try to minimize total sync time. If you have to
choose between allocating a few Mb of memory for a cache, or making
the user wait another second for a sync to complete, choose the
former. Waiting is boring.
- As much as possible, if you add something, try to make it optional.
E.g., KDE and Gnome support would be cool, but not everyone is
running KDE or Gnome, so don't assume that they are available.
- As a corollary, don't force users to install your favorite tool,
library, or whatever: don't assume that everyone uses GNU make, or
Berkeley make, or bison and flex.
- Always compile with "-Wall -ansi -pedantic" (or the local equivalent
of a language lawyer looking over your shoulder). If you stick to
the rules, you're less likely to introduce some non-portability or a
memory leak.
- If you modify an existing struct, see if it has a "constructor" or
"destructor"-like function, and update them accordingly.. My
convention is that if you have a 'struct foo', then the constructor
will be named 'new_foo()', and the destructor will be named
'free_foo()'.
There might be other, "accessor" functions that manipulate the
struct. Make sure to update them as well, if necessary.
Hint: if you're changing the meaning of a field within a
struct, change its name (temporarily). That way, you'll get a
compilation error everywhere the old field is used. This forces you
to make sure each use of the field is updated to the new meaning.
- Don't name any files "errs.*". They'll get clobbered by "make
spotless".
- Remember: NUL (one ell) is the ASCII character \0. NULL (two ells)
is the pointer that always looks like 0. NULL is a bigger zero than
NUL.
- Portability: On some OSes, printf() checks to see whether the
argument to a %s is NULL. On others, it doesn't. Always check.
- Portability: uid_t, off_t, and other types vary widely across
systems. This can cause problems with printf(): under FreeBSD, off_t
is a long long, which means that it needs to be printed with %Ld.
Under Linux, on the other hand, off_t is a long, which means that it
needs to be printed with %ld. Hence,
printf("%Ld", my_off_t);
will barf under Linux, but
printf("%ld", my_off_t);
will complain under FreeBSD.
The best solution seems to be to cast the argument to the type
of the format: some systems have 16-bit UIDs, others have 32-bit
ones. But the following should work everywhere:
printf("%ld", (long) my_uid_t);
In the case of 'off_t', there is no good solution, since you can't
portably print a 'long long' (as far as I know), and casting an
'off_t' to 'long' will remove precision in the cases where it's a
'long long'. In this particular package, however, I don't expect any
files to be longer than a few Kb, to say nothing of 4Gb.
- I18N: when printing a message for the user's benefit, remember to
enclose the string in _(), so that it can be translated, and show up
in the user's native language.
This does not apply to debugging messages; those are assumed
to be temporary, and of interest mainly to the developer who wrote
that chunk of code, so they can be in the developer's native
language.
Function names should not be translated. by and large,
perror()'s argument need not be translated, since it's usually of
the form "<system call>" or "<function name>: <system call>".
- I18N: when printing an error message of the form "<function-name>:
<message>", print the function name as a separate argument, e.g.,
fprintf(stderr, _("%s: I'm unhappy!\n"),
"my_function");
instead of
fprintf(stderr, _("my_function: I'm unhappy!\n"));
Function names should not be translated into other languages,
so this rule reduces the number of strings that a translator needs
to deal with, especially with common error messages like "Out of
memory".
- I18N: to make things easy on the translator, every string that you
print should be at least one full sentence. Let's say that you want
to print "Can't read the 12th record". In some languages, this might
be better expressed as "Can't read record number 12" or "The 12th
record cannot be read". So don't write
fprintf(stderr, _("Can't read the "));
fprintf(stderr, somestruct->n);
fprintf(stderr, _("th record\n"));
Rather, write
fprintf(stderr, _("Can't read the %dth record\n"),
somestruct->n);
- When making changes to a file, respect the existing indentation
style.
- "if", "while", "for", etc. are not functions. So don't make them
look like functions. Use
if (foo)
and not
if( foo )
- In the "AUTHORS" file, when adding the name of a far-eastern
(Japanese, Chinese, Korean, ...) contributor, give the family name
in all capitals.
A lot of round-eyes (your humble author included) cannot
distinguish Japanese personal names from family names. This
convention helps reduce confusion on the author's part.