/*  LCHECK by Richard Conn

       LCHECK displays to the user the nesting level number of each
BEGIN/END ({/}) group, thereby helping him to identify problem areas
in his C programs.  It recognizes quoted material and comments and
ignores { and } within these.

*/

#define vers    12      /* Version Number */

#include        "a:bdscio.h"

#define SSCROLL TRUE    /* Set TRUE for Smooth Scrolling on TVI 950 */

#define quote   0x27    /* Single Quote */
#define dquote  0x22    /* Double Quote */
#define BS      0x08    /* Back Space Char */
#define TAB     0x09    /* Tab Char */
#define LF      0x0a    /* Line Feed Char */
#define CR      0x0d    /* Carriage Return Char */
#define YES     'Y'
#define NO      'N'
#define ovfl    YES     /* Line Overflow */
#define noovfl  NO      /* No Line Overflow */

char    iobuf[BUFSIZ];
int     level, chval, pos, nroutines;

main(argc,argv)
int argc;
char **argv;
{
       int done;

       if (argc == 1) {
               printf("LCHECK, Version %d.%d\n",vers/10,vers%10);
               printf("Format of Command Line is --\n");
               printf("  LCHECK filename.typ");
               exit(FALSE);
               }
       if (fopen(argv[1],iobuf) == ERROR) {
               printf("Cannot Find File %s\n",argv[1]);
               exit(FALSE);
               }
       if (SSCROLL) printf("%c%c",ESC,'8');  /* Smooth Scroll */
       printf("LCHECK, Version %d.%d -- File:  %s\n",vers/10,
          vers%10,argv[1]);
       level = 0; nroutines = 0;  /* Init nesting level, routine count */
       prlevel();  /* Print level number */
       do {
               getit();  /* Get next char */
               if (chval == quote) do {  /* If quote, flush to end quote */
                               getit();
                       } while (chval != quote);
               if (chval == dquote) do {  /* If dquote, flush to dquote */
                               getit();
                       } while (chval != dquote);
               if (chval == '/') {  /* Possible comment */
                       getit();
                       if (chval == '*') {  /* Yes, it is a comment */
                               getit();
                               done = FALSE;
                               do {
                                       if (chval == '*') {  /* End comment? */
                                               getit();
                                               if (chval == '/')  /* Yes */
                                                       done = TRUE;
                                               }
                                       else getit();
                               } while (!done);
                               }
                       }
               if (chval == '{') level++;  /* BEGIN */
               if (chval == '}') {  /* END */
                       level--;
                       if (level == 0) {
                               nroutines++;
                               printf("\n** Routine %d **", nroutines);
                               }
                       }
       } while ((chval != CPMEOF) && (chval != ERROR));

       printf("\nProgram Level Check is ");
       if (level == 0) printf("OK");
               else printf("NOT OK");
       printf("\nNumber of Routines Encountered: %d",--nroutines);
       if (SSCROLL) printf("%c%c",ESC,'9');  /* Hard Scroll */
}

getit()  /* Get and Echo Character */
{
       chval = getc(iobuf);
       if ((pos >= TWIDTH) & (chval != CR)) prlevel(ovfl);
       if (chval != CPMEOF) echo(chval);
}

echo(chval)  /* Echo Char with tabulation */
char chval;
{
       switch (chval) {
               case TAB : putchar(' '); pos++;
                          while (pos%9 != 0) {
                               putchar(' ');
                               pos++;
                               }
                          break;
               case BS  : putchar(BS);
                          pos--;
                          break;
               case LF  : prlevel(noovfl);
                          break;
               case CR  : putchar(CR);
                          pos = 0;
                          break;
               default  : if (chval >= ' ') {
                               putchar(chval);
                               pos++;
                               }
                          break;
               }
}

prlevel(ovfl_flag)  /* Print Level Number and Set Col Count */
char ovfl_flag;
{
       putchar(LF);
       if (level < 10) printf(" %d",level);
               else printf("%d",level);
       if (ovfl_flag == YES) putchar('-');
               else putchar(':');
       putchar(' ');
       pos = 5;
}