cline.c

Tue, 02 Oct 2012 10:49:25 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 02 Oct 2012 10:49:25 +0200
changeset 33
1a2d7298bc82
parent 32
51d6e45a7592
permissions
-rw-r--r--

added multi-directory support

fixed parser bug in directory parser locking argument number 1024

fixed freed memory access on settings structure

     1 /*
     2  * cline.c
     3  *
     4  *  Created on: 23.05.2011
     5  *      Author: Mike
     6  */
     8 #include "cline.h"
     9 #include "scanner.h"
    10 #include "settings.h"
    11 #include "arguments.h"
    12 #include "stream.h"
    13 #include "regex_parser.h"
    15 void printHelpText() {
    16   const char* helpText = 
    17     "\nUsage:"
    18     "\n      cline [Options] [Directories...]"
    19     "\n      cline [Options] [Directories...]"
    20     "\n\nCounts the line terminator characters (\\n) within all"
    21     " files in the specified\ndirectories."
    22     "\n\nOptions:"
    23     "\n  -b <level>          - binary file heuristics level (default medium)"
    24     "\n                        One of: ignore low medium high"
    25     "\n  -E <pattern>        - Excludes any line matching the <pattern>"
    26     "\n  -e <start> <end>    - Excludes lines between <start> and <end>"
    27     "\n                        You may use these options multiple times"
    28     "\n  -h, --help          - this help text"
    29     "\n  -m                  - print information about matching files only"
    30     "\n  -s <suffixes>       - only count files with these suffixes (separated"
    31     "\n                        by commas)"
    32     "\n  -S <suffixes>       - count any file except those with these suffixes"
    33     "\n                        (separated by commas)"
    34     "\n  -r, -R              - includes subdirectories"
    35     "\n  -v, --version       - print out version information"
    36     "\n  -V                  - turn verbose output off, print the result only"
    37     "\n\nShortcuts:"
    38     "\n  --exclude-cstyle-comments"
    39     "\n = -E \"\\s*//\" -e \"\\s*/\\*\" \"\\*/\\s*\""
    40     "\n\n"
    41     "The default call without any options is:"    
    42     "\n  cline ./\n\n"
    43     "So each file in the working directory is counted. If you want to count C"
    44     "\nsource code in your working directory and its subdirectories, type:"
    45     "\n  cline -rs .c\n"
    46     "\nIf you want to exclude comment lines, you may use the -e/-E option."
    47     "\nAfter a line matches the regex pattern <start> any following line is"
    48     "\nnot counted unless a line matches the <end> pattern. A line is still "
    49     "\ncounted when it does not start or end with the respective patterns."
    50     "\nPlease note, that cline does not remove whitespace characters as this"
    51     "\nmight not be reasonable in some cases."
    52     "\n\nExample (C without comments):"
    53     "\n  cline -s .c,.h --exclude-cstyle-comments";
    55   printf(helpText);
    56 }
    58 int exit_with_version(settings_t* settings) {
    59   printf("cline - Revision: %s\n", VERSION);
    60   destroy_settings_t(settings);
    61   return 0;
    62 }
    64 int exit_with_help(settings_t* settings, int code) {
    65   printHelpText();
    66   destroy_settings_t(settings);
    67   return code;
    68 }
    70 int main(int argc, char** argv) {
    72   /* Settings */
    73   settings_t *settings = new_settings_t();
    74   if (settings == NULL) {
    75     fprintf(stderr, "Memory allocation failed.\n");
    76     return 1;
    77   }
    79   /* Get arguments */
    80   string_list_t *directories = new_string_list_t();
    81   if (directories == NULL) {
    82     fprintf(stderr, "Memory allocation failed.\n");
    83     return 1;
    84   }
    85   char* includeSuffix = NULL;
    86   char* excludeSuffix = NULL;
    87   int checked = 0;
    89   for (int t = 1 ; t < argc ; t++) {
    91     int argflags = checkArgument(argv[t], "hsSrRmvVbeE");
    92     int paropt = 0;
    94     /* s */
    95     if ((argflags & 2) > 0) {
    96       if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) {
    97         return exit_with_help(settings, 1);
    98       }
    99       t++;
   100       if (t >= argc) {
   101         return exit_with_help(settings, 1);
   102       }
   103       includeSuffix = argv[t];
   104     }
   105     /* S */
   106     if ((argflags & 4) > 0) {
   107       if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) {
   108         return exit_with_help(settings, 1);
   109       }
   110       t++;
   111       if (t >= argc) {
   112         return exit_with_help(settings, 1);
   113       }
   114       excludeSuffix = argv[t];
   115     }
   116     /* h */
   117     if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
   118       return exit_with_help(settings, 0);
   119     }
   120     /* r, R */
   121     if ((argflags & 24) > 0) {
   122       if (registerArgument(&checked, 24)) {
   123         return exit_with_help(settings, 1);
   124       }
   125       settings->recursive = true;
   126     }
   127     /* m */
   128     if ((argflags & 32) > 0) {
   129       if (registerArgument(&checked, 32)) {
   130         return exit_with_help(settings, 1);
   131       }
   132       settings->matchesOnly = true;
   133     }
   134     /* v */
   135     if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
   136       return exit_with_version(settings);
   137     }
   138     /* V */
   139     if ((argflags & 128) > 0) {
   140       if (registerArgument(&checked, 128)) {
   141         return exit_with_help(settings, 1);
   142       }
   143       settings->verbose = false;
   144     }
   145     /* b */
   146     if ((argflags & 256) > 0) {
   147       if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) {
   148         return exit_with_help(settings, 1);
   149       }
   150       t++;
   151       if (t >= argc) {
   152         return exit_with_help(settings, 1);
   153       }
   154       if (strcasecmp(argv[t], "ignore") == 0) {
   155         settings->bfileHeuristics->level = BFILE_IGNORE;
   156       } else if (strcasecmp(argv[t], "low") == 0) {
   157         settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
   158       } else if (strcasecmp(argv[t], "medium") == 0) {
   159         settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
   160       } else if (strcasecmp(argv[t], "high") == 0) {
   161         settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
   162       } else {
   163         return exit_with_help(settings, 1);
   164       }
   165     }
   166     /* e */
   167     if ((argflags & 512) > 0) {
   168       if (!checkParamOpt(&paropt) || t + 2 >= argc) {
   169         return exit_with_help(settings, 1);
   170       }
   171       t++; add_string(settings->regex->pattern_list, argv[t]);
   172       t++; add_string(settings->regex->pattern_list, argv[t]);
   173     }
   174     /* E */
   175     if ((argflags & 1024) > 0) {
   176       t++;
   177       if (!checkParamOpt(&paropt) || t >= argc) {
   178         return exit_with_help(settings, 1);
   179       }
   180       add_string(settings->regex->pattern_list, argv[t]);
   181       add_string(settings->regex->pattern_list, "$");
   182     }
   183     if (argflags == 0) {
   184       /* SHORTCUTS */
   185       /* exclude-cstyle-comments */
   186       if (strcmp(argv[t], "--exclude-cstyle-comments") == 0) {
   187         add_string(settings->regex->pattern_list, "\\s*//");
   188         add_string(settings->regex->pattern_list, "$");
   189         add_string(settings->regex->pattern_list, "\\s*/\\*");
   190         add_string(settings->regex->pattern_list, "\\*/\\s*");
   191       }
   192       /* Path */
   193       else {
   194         add_string(directories, argv[t]);
   195       }
   196     }
   197   }
   199   /* Configure output */
   200   if (!settings->verbose) {
   201     close_stdout();
   202   }
   204   /* Find tokens */
   205   parseCSL(includeSuffix, settings->includeSuffixes);
   206   parseCSL(excludeSuffix, settings->excludeSuffixes);
   208   /* Scan directories */
   209   if (regex_compile_all(settings->regex)) {
   210     int lines = 0;
   211     if (directories->count == 0) {
   212         add_string(directories, ".");
   213     }
   214     for (int t = 0 ; t < directories->count ; t++) {
   215       if (t > 0) {
   216           for (int u = 0 ; u < 79 ; u++) {
   217               printf("-");
   218           }
   219           printf("\n");
   220       }
   221       lines += scanDirectory((scanner_t){directories->items[t], 0}, settings);
   222     }
   223     destroy_string_list_t(directories);
   225     /* Print double line and line count */
   226     for (int t = 0 ; t < 79 ; t++) {
   227       printf("=");
   228     }
   229     printf("\n%73d lines\n", lines);
   231     if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) {
   232       printf("\nSome files contain too long lines.\n"
   233         "The regex parser currently supports a maximum line length of %d."
   234         "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
   235     }
   237     if (!settings->verbose) {
   238       reopen_stdout();
   239       printf("%d", lines);
   240     }
   241     destroy_settings_t(settings);
   242   }
   244   fflush(stdout);
   245   fflush(stderr);
   246   return 0;
   247 }

mercurial