
                       GALACTICOMM CODING STANDARDS
                       ----------------------------
                                                              29 Jan 1992
                                                         rev. 22 Jan 1994

1. Galacticomm Software Development Values

     Galacticomm is, for good reason, a few years behind the leading edge of
coding standards and compiler capabilities.  Because we are in the unique
position of selling source code to hundreds of development sites, certain
considerations are paramount.

     Reliability.  As much as possible, the most direct and plain-vanilla
          approach available should always be used.  This minimizes the
          probability of:

         o   Compiler errors from one version of compiler to another
         o   Linker and protected mode loader errors
         o   Run-time problems due to varying run-time environments

     Clarity.  "The code never lies."  That is, nothing has higher
         accuracy in describing the function of a program than the code
         itself.  Therefore the code must be self-documenting to the
         greatest degree possible.  Comments should be used very
         sparingly to concisely capture the meaning of actions and data,
         the designer's intent, or other valuable information that is not
         present in the code itself.  Excessive comments or excessively
         detailed documentation is a heavy tax to pay for coding, which
         is already a costly undertaking.

     Cohesion.  A function should encode a set of actions that belong
         together, or "stick together".  The function and parameter names
         along with comments should allow people working with the code to
         (1) understand what the function does and how to use it
         (ignoring the internal workings) and (2) verify that the
         function does what it's supposed to (by scrutinizing the
         internal workings).  Code your functions in ways that are
         unlikely to produce bugs no matter how the functions might
         logically be expected to be used.

     Consistency.  Syntax outside of that demanded by the compiler is
         what coding standards are all about.  After the other
         considerations, consistency in code formatting and appearance is
         of tremendous help to customers and 3rd party developers.

1.1 Why Standardize?

     The benefits of all Galacticomm programmers using the same standards
for code design and layout are substantial.  We can read each others' code
more easily, without constantly being struck by unfamiliar formatting.  We
can make mods to each others' code, without creating a mishmosh of different
coding styles.  In addition, if we choose the "right" standard, our mutual
productivity can be enhanced.  Details like whether or not you always put
curly-braces around an if-clause, for example, have a significant impact on
the time it takes to change a programming construct, both during initial
development and later in the life-cycle of the program.

     The objections to code format standardization generally fall into one
of the following categories:

     "It takes time to learn the standards, that could be spent coding."
     "My way is better."
     "It's not that big of a deal."
     "Just use a pretty-printer program if you think it's so important!"

     It doesn't take very long to learn at all, since most of the standards
outlined here are ordinary common sense.  In the cases where an arbitrary
choice has been made, such as always putting spaces around a double-equals
(x == y), never around a single-equals (x=y), it is not all that hard to
remember and it quickly becomes second nature.  The central thing is that
there BE a standard, so that you don't have to stop and think, each line of
code you write, how it should best appear.  The time lost learning the
standard is very quickly recouped because bugs are reduced, code is reused
more, and more interchange with other programmers becomes possible.

     Your way may be better, but if it's different from other people's, you
will have a hard time reading their code and vice versa.  Your eyes get used
to seeing code laid out in a certain way after a while, and when you have to
deal with code in which the placement of braces, use of upper and lower
case, spacing conventions and so forth are different from yours, the
comprehension of every line is a battle.  Brain cells are in short enough
supply... the less you have to devote to deciphering the formatting of
someone else's code, the more you have available to understand what's really
important, which is its content and function.

     Formatting is definitely "not that big of a deal" when compared with
the issues of code architecture, flow, encapsulation, etc.  That's why it's
silly to let it interfere with the understanding of these larger issues.
Reading code in an unfamiliar format is like slogging through mud -- you
have to consciously dope out which brace goes with which, and whether
something is a comparison or an assignment, etc.  Reading code that looks
like what you are accustomed to, you barely notice that there is a format at
all -- you see straight through it, to the important aspects of what the
code actually does.

     Pretty-printers are not the solution, either.  Besides the fact that
pretty-printers are time-consuming to configure and use, there is an
inherent benefit in writing your actual code in a standardized way.  Your
thoughts become more organized, because the layout on the screen in front of
you is organized and can be read without conscious effort.  If another
programmer is working with you, he may be able to catch bugs that you
didn't, just by looking over your shoulder as you edit.  And, calling in a
"guru" to help with particularly knotty problems will not result in hostile
mutterings in your direction.


2. C Source

     The standards we adhere to are basically those of Kernighan and
Ritchie, with a few small extensions and updates.

2.01 Block Comment Header

     Each C source file should begin with a block comment of the form:

/***************************************************************************
 *                                                                         *
 *   FILENAME.C                                                            *
 *                                                                         *
 *   Copyright (C) 19xx-19xx GALACTICOMM, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   Brief description of the contents of the source file.                 *
 *                                                                         *
 *                                               - Author MM/DD/YY         *
 *                                                                         *
 ***************************************************************************/

2.02 '#include' Statements

     The first statement after the block comment in every file should be:

          #include "gcomm.h"

The file "gcomm.h" will contain all of our standard library function
prototypes, our #defines such as those for movmem() and setmem(), globally-
useful macros such as min() and max(), and any other symbols and
declarations that we make part of our "bag of tricks" over time.  In
addition, it contains most of the Borland header files needed for everyday
coding.

     The file "gcomm.h" will also #include the file "transit.h".  As you
develop, you will from time to time come up with symbols and/or function
prototypes that you feel should be included in "gcomm.h" -- but you will not
want to stop and wait for the code librarian to put them into "gcomm.h"
before you proceed, and you will also not want to just put them into the
source of the program you happen to be developing at the time, because then
it will be a pain in the neck to remember to remove them later, etc.  The
answer?  Put them in "transit.h".  Anything in your local copy of
"transit.h" is 'in transit' to "gcomm.h".  Once it is in "gcomm.h", you can
remove it from "transit.h" at your convenience.  Periodically you should go
through your "transit.h" and check to see if its contents have been put into
"gcomm.h".  If they have, delete them from "transit.h"; if not, demand to
know why not.

     After the #include "gcomm.h", put all of your other C header files to
be included in the compilation, in order from the most standard to the most
application-specific.  Most standard C header files are already included in
"gcomm.h", so check there first before adding standard headers to your
source.

     After these, put your application-specific files such as "majorbbs.h".
Put any specialized headers only shared by one or two source files, such as
"flash.h" or "message.h", at the very end of this list.

     Always use double-quotes rather than angle brackets to delimit the
included filename.

     Popping a '#include' into the middle of other declarations, or code,
is frowned upon.

2.03 Declarations and '#define' Statements

     After the '#include' statements should come all of the public data
declarations, external data declarations, structure declarations, and local
'#define' statements in the file.  Use whatever order seems clearest --
there is no need to put all of the structure declarations together, all of
the '#define' statements together, etc.  However, once the code starts,
there should be no further appearance of any of these four classes of
statements except in unusual circumstances.  The purpose of this is so that
when someone reading the code sees a reference to one of these things, he
knows that if it's in the file at all (as opposed to a header file), he can
find it toward the top:  if he hasn't found it by the time he reaches the
first actual function definition, it isn't there.

     All STATIC function prototypes should appear just before the first
function definition in your code.

     Within function definitions, all local declarations of variables and
structures should appear at the very top of the function, indented one tab
stop.  All static variables local to a function should appear last in this
list.  A blank line should separate these lines from the first line of
actual code.

2.04 All Caps for '#define' Constants

     Generally the only use of upper case in a C file (besides in comments
and quoted character strings) should be for constants defined via the
'#define' statement.  If the symbol defined in a '#define' statement takes
an argument list, though, the symbol may be in lower or upper case.  The
central rules are: always use upper case for CONSTANTS defined via
'#define'; use lower case for all normal non-preprocessor-related code text.

2.05 Data Declaration Comments

     Each variable declaration, and each element of each data structure
declaration, should have a short (25 to 40 byte) comment on it.  Except in
unusual cases, all comments should begin in column 36 and end in column 77:

int varname;                       /* comment text                         */

2.06 Order Functions 'Top Down'

     The order of arranging functions in a source file should be generally
from the highest-level functions to the lowest.  This is not an ironclad
rule, except that the function 'main()' should always appear first if it is
present.  Similarly, function groups in which some function acts as a kind
of master gateway to a group of subsidiary functions should generally have
the master function first, followed by its direct subsidiaries, followed by
subsidiaries of those subsidiaries, etc.

     Generally, a source file containing both public and private functions
should list the public functions first, then the private ones.

2.07 Code Comments

     The code should be clear and understandable by the very nature of its
design and architecture.  Also, by the appropriate choice of variable and
function names it should be as self-documenting as possible.  Therefore
there should be very few actual comments in the code itself.  Ideally, each
function should have just a one-liner comment.  Functions with special
considerations or especially complicated argument lists can have explanatory
text around them.  However, if you think that your code would not be clear
to a reasonably diligent reader, the solution is not to comment the unclear
aspects of the code.  The solution is to redesign that portion of the code,
so that it *is* clear.

2.08 Short Names

     In most cases, variable and function names should be no more than 8
characters.  This keeps the code from getting bulky and requiring a lot of
continuation lines.  Shorter names also take less time to read, and less
time to type.  They can be just as easy to understand and remember as long
names, if chosen well.  The name 'set_attribute()' is no more intrinsically
clear than 'setatr()', it takes longer to type (over and over!), and it is
much more likely to yield lines going over the 80-column boundary, which
makes them much harder to read.

     The use of the underscore character, in particular, should be avoided
whenever possible.

2.09 Indentation and Curly-Braces

     Use the K&R standard of tab stops every five columns.  More than this
leads to code walking off the right edge of the screen; less makes it hard
to tell, visually, which code sections line up with one another vertically.

     Indent the body of every if, else, do, for, and while block one tab
stop.  In a switch construct, keep each 'case' statement at the same indent
level as the 'switch' statement itself, but indent the code under each case
one tab stop.

     Each and every if, else, do, for, while, and switch should have a left
curly brace positioned at the end of the opening line of the construct (or
its continuation), and a right curly brace on a line by itself at the end of
the dependent code.  This rule most definitely applies even if there is only
one line of dependent code in the construct.  Also, dependent code should
never appear on the same line with the left curly brace.  The right curly
brace at the end of the dependent code should be at the same tab stop as its
parent keyword.

     In a series of if-else if-else if-...-else clauses, the initial 'if',
its corresponding right curly brace, each 'else', and each of their
corresponding right curly braces should all be at the same tab stop.

     The only time that a left curly brace should appear on a line by itself
is in column 1 at the start of a new function definition, right after the
function parameter declarations if any.

     Never put more than one statement on a single line: this leads to
time-wasting tradeoff analysis, and further time-wasting reformatting in the
event that the analysis is wrong, or becomes invalid in the light of later
developments.

2.10 Spaces

     Besides in comments and quoted character strings, there should be no
spaces anywhere in your code except:

     > as preprocessor statement delimiters
     > for indenting
     > after declarators such as 'char', 'int', 'struct', 'static', etc.
     > on either side of comparison operators (==, !=, >=, <=, <, and >)
     > on either side of binary logical operators (&& and ||)
     > after if, else, do, for, while, switch and corresponding close-parens
     > on either side of each ';' in 'for' statements
     > on either side of '?' and ':' in conditionals

     In particular, spaces should NOT appear around commas, or around any
arithmetic, boolean, or assignment operators.  The following are examples of
operators that should NOT have spaces on either side of them:

     +    -    *    /    <<   >>   &    |    ^    ~    !    ++   --   ->
     +=   -=   *=   /=   <<=  >>=  &=   |=   ^=   =

     A short piece of code with examples of where to use and not to use
spaces:

          #define P2TSIZ 5         /* power of 2 table size                */
          int powof2[P2TSIZ];      /* power of 2 table                     */

          void
          compow2(void)            /* compute powers of 2                  */
          {
               int i;

               for (i=0 ; i < P2TSIZ ; i++) {
                    powof2[i]=(i == 0 ? 1 : powof2[i-1]<<1);
               }
          }

     Note: it is especially important to maintain the distinction between
single-equals (assignment) and double-equals (equality comparison).  The
advantage here is that, once you are used to this standard, your eyes will
react to the appearance of a single-equals with spaces around it, or
double-equals without them, as an alarm situation requiring investigation.
This greatly cuts down on the class of bugs in which an intended comparison
is inadvertantly coded as an assignment.

2.11 80-Column Lines

     Source code lines should never contain characters beyond the 80th
column.  This keeps all code visible when scrolling through with a standard
text editor.

     If you have statements that require more than 80 columns, split them
across two or more lines.  There are no fixed rules determining where the
splits should occur -- just try to make the code as readable as possible.
This means lining up similar sub-clauses where possible, for example:

          if (sameas(usaptr->userid,esgptr->msg.to)
           || sameas(usaptr->userid,esgptr->msg.from)) {

     Where no similar sub-clauses exist, try to break lines at logical
boundaries, such as after commas, before '&&' and '||' operators, etc.  When
breaking on '&&' or '||', always put the operator at the start of the
continuation line, not at the end of the line being continued.  This helps
the reader more quickly identify the continuation line as such, and not as a
new statement in its own right.  Also, use a non-tab-stop column for the
start of continuation lines, as this helps further cue the reader to the
fact that the line is not a normal standalone statement.

     Avoid the use of the 'backslash' method of creating continuation lines,
since this tends to mar the otherwise pristine indentation structure of your
code (except on global-declaration lines which are not indented anyhow).

2.12 Blank Lines

     Use a single blank line to separate:

     > the block comment header from the '#include' statements
     > the '#include' statements from the global declarations section
     > each new function definition from what precedes it
     > the declarations at the top of a function from its code

     You can use blank lines, sparingly, in other places too, but be careful
of the syndrome that some programmers fall into in which they try to enclose
every minor grouping of variables or code between blank lines -- it is
important that the reader of your code be able to fit as much of it as
possible on the CRT at the same time.  Double-spacing your code lines, in
effect, makes your CRT act like it is only 12 lines high rather than 24.
This makes it more difficult to relate sections of code to each other that
may be, say, 20 lines apart.

2.13 Function Definitions

     Function definitions should always be in the following form:

          STATIC void              /*   document less-than-obvious retvals */
          loadrec(                 /* always describe the routine here     */
          struct person *dst,      /*   document less-than-obvious params  */
          char *user)              /*                                      */
          {
          }

     Any functions intended as "private" should have the STATIC keyword in
front of them.  STATIC is defined to be "static", but may be changed to ""
when attempting to get more details from the linker to help track down a GP.

2.14 ANSI Function Prototypes

     Use function prototypes as a global rule.  Function prototypes in
public header files (non-STATIC functions) should be in the following form:

          STATIC void              /*   document less-than-obvious retvals */
          loadrec(                 /* always describe the routine here     */
          struct person *dst,      /*   document less-than-obvious params  */
          char *user);             /*                                      */

     This is just a block copy of the loadrec() function definition, plus a
semicolon.  These prototypes are easy to create (by block copying the
definitions) and are well documented for those using our header files.

     Function prototypes for private functions within a .C file should just
be one line, with no comments:

          STATIC void loadrec(struct person *dst,char *user);

     To easily generate lots of one-line prototypes, you can use the PROE
utility:

          PROE FILENAME.C

     From DOS, this command will put one-line prototypes in PROTOS.H for all
the functions in FILENAME.C.  You can then block copy these from PROTOS.H to
the top of FILENAME.C.

     For functions that have a variable number of parameters (e.g. spr()),
there is a great way to write the prototype, using "...", for example:

     char *
     spr(
     char *ctlstg,
     ...);

     Then the compiler doesn't care what parameters you pass after the
"ctlstg".  Unfortunately, when defining the function itself:

     char *
     spr(
     char *ctlstg,
     char *parm1,
     char *parm2,
     char *parm3)
     {
          ...
     }

     then the compiler gets all bent out of shape.  There is a way to use
the "..." stuff inside the definition (va_start, va_arg, va_end), but it is
not very object-code efficient.  We should avoid having full-blown
prototypes for functions like these, reverting to a variation of the old
form:

     char *spr();                  /* just to declare return value         */

     char *
     spr(
     char *ctlstg,
     char *parm1,
     char *parm2,
     char *parm3)
     {
          ...
     }

2.15 Character Array Declarations

     When defining a constant for a string (NUL-terminated character array),
make the value of the #define the actual number of bytes in the array, not
that number plus one.  This makes calls to alcmem(), fgets(), btuitz(),
setmem(), etc. less cluttered, not to mention the initial declaration.  If
you like, you can make the #define itself a number plus one, for clarity...
but be careful to put parentheses around the sum, to avoid precedence
problems.  For example:

     #define MAXLEN (15+1)
     char string[MAXLEN];

     setmem(string,MAXLEN,0);
     printf("Enter look-up string: ");
     fgets(string,MAXLEN,stdin);
     if (qeqbtv(string,0)) {
          great();
     }
     else {
          barf();
     }

2.16 Booleans

     Use the BOOL type for strictly boolean variables and return values.
Although the compiler treats a BOOL as an int, these are the only values
that a type BOOL variable should ever contain:

   o   1 (TRUE)
   o   0 (FALSE)
   o  -1 (VBTRUE)

     VBTRUE should only be used when directly returning values to VB code.
When VB code passes BOOL parameters to C code, immediately translate the VB
BOOL (that is either VBTRUE or FALSE) to a C BOOL (that is either TRUE or
FALSE) with the "VBOOL2C(varname);" statement.  This way, BOOL variables
will be either TRUE or FALSE within 99.9% of all C code, and only be VBTRUE
for the direct VB interface.

2.17 Parentheses in Expressions

     To avoid excessive and unnecessary parentheses in expressions, please
refer to (or memorize) the following rules of operator precedence:

     The  .   structure subfield,
          ->  pointer to structure dereference and subfield,
          []  array subscript, and
          ()  function dereference operators
              all bind tighter than any other operators.  (These operators
              offer such cohesion that you don't normally think of them as
              operators.  For example, "a->b" is a thing, not a result.)

     The  *   pointer dereference operator, when used with the auto
              increment or decrement operator, binds left to right, so that
              "*pointer++" will work:  it gets a value and then increments
              the pointer.

     The  *   pointer dereference operator binds tighter than any
              arithmetic, comparison, bitwise, boolean, or assignment
              operators.

     The  *   multiply and
          /   divide operators
              bind tighter than the
          +   add and
          -   subtract operators, e.g. 2+2*2 == 6, not 8

     The arithmetic operators bind tighter than the comparison operators.
              e.g. 2+2 == 5 is false

     The comparison operators bind tighter than the boolean operators.
              e.g. A == B || A == C is true if A equals either B or C

     The  &&  boolean-and operator binds tighter than the
          ||  boolean-or operator

     The  ?:  tertiary operator binds looser than all arithmetic,
              comparison, bitwise, and boolean operators

     The  =   and all other assignment operators bind looser than all
              other operators, except the (,) comma operator (which is
              frowned upon).  (So put parentheses around any assignment
              taking place within an expression evaluation.)

     No other precedences are assumed, so use parenthesis in any case not
covered here.  In particular, be careful not to assume any precedence
between the bitwise operators and the arithmetic or comparison operators.
For example, the line "if (xyz&1 == 0)" will always fail, because the
compiler generates code that compares 1 to 0, gets a 0 boolean result, and
then bitwise AND's this with xyz, yielding 0 every time.  Code instead:
"if ((xyz&1) == 0)".

2.18 Dereferencing Pointers

     There are two ways to treat a char *:  as a pointer and as an array.
Handily enough, there are also two ways to dereference a char *:  the "*"
operator and the "[]" operator.  When treating a char * as a pointer, use
the "*" operator.  Otherwise, use the "[]" operator.  Treat any one char *
as either a pointer or an array.

     Normally, treat every-day char *'s that point to strings as arrays.
Only treat a char * as a pointer if it's used to zoom around within strings.
An example of treating a char * as a pointer:

          if (*ptr != '\0') {
               do {
                    if (*ptr == 'a' && *(ptr+1) == 'b') {
                         break;
                    }
                    ptr++;
               } while (*ptr != '\0');
          }

     An example of treating a char * as an array:

          if (stg[0] != '\0') {
               do {
                    if (stg[i] == 'a' && stg[i+1] == 'b') {
                         break;
                    }
                    i++;
               } while (stg[i] != '\0');
          }

2.19 Shady Characters: C Syntax for Non-Printable Characters

     Don't use hex 00-1F or 7F characters literally in character constants
or text strings in your source code, because of the resulting difficulty in
listing out that code on various printers.  Here's the syntax to use for C
and for ASM code:

     Decimal   Hex  Ctrl  ASCII  C syntax                   ASM syntax
     -------   ---  ----  -----  --------                   ----------
        0       00   ^@    NUL   '\x00' or '\0'                00H
        1       01   ^A    SOH   '\x01'                        01H
        2       02   ^B    STX   '\x02'                        02H
        3       03   ^C    ETX   '\x03'                        03H
        4       04   ^D    EOT   '\x04'                        04H
        5       05   ^E    ENQ   '\x05'                        05H
        6       06   ^F    ACK   '\x06'                        06H
        7       07   ^G    BEL   '\x07'  (don't use '\a')      07H
        8       08   ^H    BS    '\b'                          08H
        9       09   ^I    HT    '\t'                          09H
       10       0A   ^J    LF    '\n'                          0AH
       11       0B   ^K    VT    '\x0B'  (don't use '\v')      0BH
       12       0C   ^L    FF    '\f'                          0CH
       13       0D   ^M    CR    '\r'                          0DH
       14       0E   ^N    SO    '\x0E'                        0EH
       15       0F   ^O    SI    '\x0F'                        0FH
       16       10   ^P    DLE   '\x10'                        10H
       17       11   ^Q    DC1   '\x11'                        11H
       18       12   ^R    DC2   '\x12'                        12H
       19       13   ^S    DC3   '\x13'                        13H
       20       14   ^T    DC4   '\x14'                        14H
       21       15   ^U    NAK   '\x15'                        15H
       22       16   ^V    SYN   '\x16'                        16H
       23       17   ^W    ETB   '\x17'                        17H
       24       18   ^X    CAN   '\x18'                        18H
       25       19   ^Y    EM    '\x19'                        19H
       26       1A   ^Z    SUB   '\x1A'                        1AH
       27       1B         ESC   '\x1B'                        1BH
       28       1C         FS    '\x1C                         1CH
       29       1D         GS    '\x1D'                        1DH
       30       1E         RS    '\x1E'                        1EH
       31       1F         US    '\x1F'                        1FH

      127       7F         DEL   '\x7F'                        7FH

     In C string constants, if one of the above characters must be followed
by a literal hex digit (0-9, A-F, a-f) use concatenated literal strings to
avoid ambiguity.  Some examples:

          If you want:    Code:
          ------------    ----------
          <NUL> <SOH>     "\x01\x02"
          <Esc> 0         "\x1B""0"          ("\x1B0" is the same as "\xB0"!)
          <Esc> <LF>      "\x1B\n"
          <Esc> n         "\x1Bn"
          <Esc> <BS>      "\x1B\b"
          <Esc> b         "\x1B""b"          ("\x1Bb" is the same as "\xBB"!)
          <Esc> A <CR>    "\x1B""A\r"

2.20 Inline Assembly Coding

     The general idea is to indent the "asm" prefixes to the level of the
surrounding C code or function, and indent jump destination labels to line
up with the "asm"s on the left.  Stick to 5-character-wide columns, not 8
(tab stops at 1,6,11,16,...), just like all the standard C code uses.  If
the code is clearly the equivalent of an *if* clause or a *switch* clause,
you can indent that too, but be careful -- too much indenting can quickly
make a mess.

     The bias against comments in the body of a C language function is
waived for inline assembly code.  Assembly code is almost always grungy.
Add comments sparsely, though, seeking to reveal your strategies rather than
to parrot every instruction.

          int                      /*   return byte read or -1=timeout     */
          getabyte(void)           /* read one byte                        */
          {
               asm  mov  dx,xyzport
               rdyloop:
               asm  in   al,dx
               asm  test al,TMOMASK     /* check for timeout condition     */
               asm  jnz  timeout
               asm  test al,RDYMASK     /* keep looping until data ready   */
               asm  jz   rdyloop
               asm  inc  dx             /* data port is xyzport+1          */
               asm  in   al,dx
               asm  xor  ah,ah
               return(_AX);
               timeout:
               return(-1);
          }

2.21 Conditional Compilation

     Indent as appropriate to reveal structure.  An example:

          void
          protinit(                /* initialize for protected mode        */
          char *pgmname)           /*   program name (end w/1 space) or "" */
          {
               #ifdef PHARLAP
                    extern int colseg,monseg;
                    extern unsigned _maxfarrealloc;

                    setgphand(pgmname);
                    _maxfarrealloc=0;
                    DosMapRealSeg(0xb800,(ULONG)160*25,(SEL *)&colseg);
                    DosMapRealSeg(0xb000,(ULONG)160*25,(SEL *)&monseg);
               #else
                    pgmname=pgmname;
               #endif
               #ifdef ECLIPSE
                    extern int colseg,monseg;

                    colseg=0x00B8;
                    monseg=0x00B0;
               #endif
          }

2.22 Text File Format

     All source files should be stored in NOTABS form, with literal spaces,
without any hex 09 characters at all.  The only exceptions are BRKTHU.ASM,
BBSBTU.ASM and all the .MAC files included by them.

2.23 Miscellaneous Idiosyncracies

     Here are a few hairsplitters that yield a generally more graceful look
and feel to your code:

     > When dealing with an 'int' variable that you are using as a counter
       or index, and making a test based on whether it is or is not zero,
       use an explicit 'blah == 0' or 'blah != 0' test, don't just say
       'if (!blah) {' or 'if (blah) {' respectively.  This helps the code
       reader understand that 'blah' takes on values other than 0 and 1.

     > When incrementing or decrementing a variable on a line by itself, use
       the statement 'blah++;' or 'blah--;' rather than 'blah+=1;' or
       'blah-=1;'.

     > Always use parentheses around the return value (if any) in a 'return'
       statement.  Somehow it looks more well-defined that way.  This is one
       of those purely arbitrary situations where the only justification for
       having a standard is that people who get used to seeing it one way
       will be distracted by its appearance the other way, so to minimize
       debate about nonessential issues we just mandate that return values
       should always have parentheses around them and we can all relax.

     > When setting or comparing a character value to zero, always write it
       as '\0' to distinguish it from the ordinary integer 0.  This cues
       your reader in to the fact that it is an ASCII NUL character you are
       talking about, not just any old zero value.

     > Similarly, when setting or comparing a pointer to zero, always write
       it as NULL to distinguish it from an ordinary 0.  This cues your
       reader in to the fact that you are talking about a null pointer, not
       just any old zero value.

     > Coding techniques to avoid: the comma "operator", typedefs, the
       "continue" statement, lots of macros, particularly when heavily
       nested or interdependent, and complicated data entities such as casts
       of dereferenced pointers to arrays of pointers to functions returning
       pointers to doubly-indexed arrays of data structures.  Nuff said.
