home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 210_01 / kittylnt.c < prev    next >
Text File  |  1985-11-15  |  22KB  |  716 lines

  1. /*lintoff*/
  2. /* Saturday, July 12, 1986  3:41 PM                                  */
  3. /*                                                                   */
  4. /*     KITTENSOFT                                                    */
  5. /*                                                                   */
  6. /*     Dan Schechter                                                 */
  7. /*     Route 1 Box 19                                                */
  8. /*     Amenia, North Dakota 58004                                    */
  9. /*     (701) 967-8371                                                */
  10. /*                                                                   */
  11. /*     Do what you like with this program. Please let me know if     */
  12. /*     you find bugs. Exactly as is it compiles under Aztec C II     */
  13. /*     for CP/M. I have no idea how portable it is because I do      */
  14. /*     not know how compatible the Manx library functions are with   */
  15. /*     those of other compilers.                                     */
  16. /*                                                                   */
  17. /*     This is not intended to be a real LINT program. That would    */
  18. /*     be far beyond my programming ability. This is just a sort     */
  19. /*     of delimiter checker. I have used it only for a short time    */
  20. /*     but I have found it useful. I hope you will also.             */
  21. /*                                                                   */
  22. /*     Following are some general comments about this program:       */
  23. /*
  24. When checking for proper line termination it returns <good> on
  25. end-of-comment marker. This might not be the best choice as it could mask
  26. an error on the same line (when a short comment is on the same line as
  27. a line of code).
  28.  
  29. It expects if, for, and while loops to be terminated by closing parenthesis
  30. (no semicolon) if and only if the loop declaration has no following statement.
  31.  
  32.     Example 1:    if (a==b)
  33.                 x=y;
  34.  
  35.     Example 2:    if (a==b) x=y;
  36.  
  37. Both the above are correct and will not cause error messages.
  38.  
  39.     Example 3:    while(a[i++]!=0);
  40.  
  41. In the above, the programmer wants to increment i until a[i] is 0,
  42. thus the semicolon is correct, but the lint program expects any kind of
  43. loop to control a statement or block of statements, and so generates
  44. the error message "Check line termination".
  45.  
  46. Sometimes, line labels will generate spurious error messages.
  47.  
  48. It will check printf(), fprintf(), sprintf and scanf() to see that the number
  49. of parameters matches the number of <%> conversion characters. However it
  50. does NOT check for type consistency, or anything about parameters 
  51. passed to functions. It will check to make sure that a for() loop has
  52. exactly two semicolons inside the parentheses. A spurious error message
  53. will be generated if a function name ends in "for" as the program thinks
  54. it is a for() loop.
  55.  
  56. It will check for the balance of () parentheses, [] brackets, "" quote marks, 
  57. and {} braces. Spurious error messgaes may be generated if any of these are
  58. used as text characters. Parentheses, braces, and quotes, but not brackets,
  59. may be balanced on following lines if the LAST character on a line is a
  60. backslash. Even white space following a backslash is not permitted. This is
  61. consistent with Aztec C. This program will flag white space following the 
  62. last backslash on a line.
  63.  
  64. It will flag a line that appears to be a function declaration with a
  65. semicolon. This may generate some spurious error messages.
  66.  
  67. It will flag nested or unbalanced comment markers.
  68.  
  69. It will not check for undeclared variables.
  70.  
  71. It does not recognize the comma that terminates lines in initializing
  72. statements as permissable. Thus initializers will generate spurious error
  73. messages. I suggest toggling lint off for these. 
  74.  
  75. Most of the time it will find the syntax mistakes I make most often:
  76. unbalanced parentheses, brackets, braces, and quotes; missing semicolons,
  77. semicolons after function declarations, nested comments, parameters
  78. left out of printf() statements, and too many or two few semicolons
  79. inside for() statements.
  80.  
  81. Checking is toggled on and off with the words                         */
  82. /*linton*/
  83. /*lintoff*/                                                           /*
  84. which must appear starting at column 1, between comment markers,
  85. without spaces. They may not be nested.
  86.                                                                       */
  87. /*linton*/
  88.  
  89. #include <stdio.h>
  90. #define BELL 7
  91. int errno;
  92. main(n,arg)
  93. int n;
  94. char **arg;
  95. {
  96.     int i,op=0,cp=0,ob=0,cb=0,os=0,cs=0,cmt=0,sq=0,quo=0,quot=0,l=0,conline=0;
  97.     char disab=0,q,string[300],fn[20],*fgets(),*r=1,cmtb=0;
  98.     FILE *fp;
  99.  
  100. /* If there is a file name on the command line it will use it. Otherwise */
  101. /* it will ask for a file name                                           */
  102.  
  103.     if (n==2) strcpy(fn,arg[1]);
  104.     else getfn(fn);
  105.  
  106. o:    if ((fp=fopen(fn,"r"))==0){
  107.         printf("Can't find %s  errno=%d",fn,errno);
  108.         errno=0;
  109.         getfn(fn);
  110.         goto o;
  111.     }
  112.     
  113.     while(r){
  114.         l++;
  115.  
  116. /* The following initializes string to all newline characters. Without this, */
  117. /* under rare circumstances, the last line can get spurious error flags as   */
  118. /* the string winds up with part of the next-to-last line hanging on.        */
  119.  
  120.         for (i=0;i<255;i++) string[i]='\n';
  121.  
  122. /* The following gets one line of source code */
  123.  
  124.         r=fgets(string,250,fp);
  125.  
  126. /* It ignores lines beginning with # because they usually require no */
  127. /* special line termination:                                         */
  128.  
  129.         if (string[0]=='#') continue;
  130.         if ((i=strncmp(string,"/*lintoff*/",11))==0) {
  131.             disab=1;
  132.  
  133. /* conline keeps track of how many lines have been printed, so the */
  134. /* program can pause for you to read the error messages.           */
  135.  
  136.             conline++;
  137.             printf("\
  138. %s line: %d --> LINT TURNED OFF.\n\n",fn,l);
  139.             if (conline>9) pause(&conline);
  140.         }
  141.         if ((i=strncmp(string,"/*linton*/",10))==0) {
  142.             disab=0;
  143.             conline++;
  144.             printf("\
  145. %s line: %d --> LINT TURNED BACK ON.\n\n",fn,l);
  146.             if (conline>9) pause(&conline);
  147.         }
  148.         if (disab) continue;
  149.         q=cktsp(string);
  150.         if (q=='b'){
  151.             conline++;
  152.             printf("\
  153. %s line: %d --> White space after backslash:\n%s",fn,l,string);
  154.             q='r';
  155.             if (conline>9) pause(&conline);
  156.         }
  157.         diddle(string);
  158.  
  159. /* This is to skip blank lines:  */ 
  160.  
  161.         if (string[0]=='\n') continue;
  162.         q=endcheck(string);    
  163.         if (  (q=='f') && ((op!=cp)||(ob!=cb))  ) {
  164.             conline++;
  165.             printf("\
  166. %s line: %d --> New function declaration. --> %s\
  167. Unbalanced parentheses<%d> or wavy brackets<%d> in the preceding function.\n",\
  168. fn,l,string,(op-cp),(ob-cb));
  169.             if (conline>9) pause(&conline);
  170.             op=0;cp=0;ob=0;cb=0;os=0;cs=0;
  171.         }
  172.         if (q=='b'){
  173.             q=endexcpt(string);
  174.             if (q=='b'){                     
  175.                 conline++;
  176.                 printf("\
  177. %s line: %d --> check line termination:\n%s",fn,l,string);
  178.                 if (conline>9) pause(&conline);
  179.             }                                
  180.             q='r';
  181.         }
  182.         if (q=='g'){
  183.             q=loopwscn(string);
  184.             if (q=='b'){                     
  185.                 conline++;
  186.                 printf("\
  187. %s line: %d --> check line termination:\n%s",fn,l,string);
  188.                 if (conline>9) pause(&conline);
  189.             }                                
  190.             q='r';
  191.         }
  192.  
  193. /* These keep track of brackets: */
  194.  
  195.         for (i=0;string[i]!='\n';i++){
  196.             if (string[i]=='(') op++;
  197.             if (string[i]==')') cp++;
  198.             if (string[i]=='{') ob++;
  199.             if (string[i]=='}') cb++;
  200.             if (string[i]=='[') os++;
  201.             if (string[i]==']') cs++;
  202.  
  203. /* This keeps track of comment markers: */
  204.  
  205.             if (string[i]=='*'){
  206.                 if (string[i-1]=='/') cmt++;
  207.                 if (string[i+1]=='/') cmt--;
  208.                 if ((cmt>1)||(cmt<0)) cmtb=1; 
  209.             }
  210.  
  211. /* These keep track of apostrophes and quotes: */
  212.  
  213.             if (string[i]=='\'') sq^=1;
  214.             if (string[i]=='\"') {
  215.                 quo^=1;
  216.                 quot++;
  217.             }
  218.         }
  219.         if (os!=cs) {
  220.             conline++;
  221.             printf("\
  222. %s line: %d --> unbalanced square brackets:\n%s",fn,l,string);
  223.             if (conline>9) pause(&conline);
  224.         }
  225.         os=0;
  226.         cs=0;
  227.         if (op!=cp) {
  228.             q=querybks(string);
  229.             if (q=='b') {
  230.                 conline++;
  231.                 printf("\
  232. %s line: %d --> unbalanced parentheses:\n%s",fn,l,string);
  233.