|
|
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.