src/cline.c

Wed, 31 May 2017 12:20:04 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 31 May 2017 12:20:04 +0200
changeset 48
0d2c13c24fd0
parent 44
9574a181ec26
child 50
63477d92411d
permissions
-rw-r--r--

adds remaining autoconf files

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 
     3  * Copyright 2017 Mike Becker. All rights reserved.
     4  * 
     5  * Redistribution and use in source and binary forms, with or without
     6  * modification, are permitted provided that the following conditions are met:
     7  * 
     8  * 1. Redistributions of source code must retain the above copyright
     9  * notice, this list of conditions and the following disclaimer.
    10  * 
    11  * 2. Redistributions in binary form must reproduce the above copyright
    12  * notice, this list of conditions and the following disclaimer in the
    13  * documentation and/or other materials provided with the distribution.
    14  * 
    15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    22  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    25  *
    26  * cline.c
    27  *
    28  *  Created on: 23.05.2011
    29  *      Author: Mike
    30  */
    32 #include "cline.h"
    33 #include "scanner.h"
    34 #include "settings.h"
    35 #include "arguments.h"
    36 #include "regex_parser.h"
    38 void printHelpText() {
    39   printf(
    40     "\nUsage:"
    41     "\n      cline [Options] [Directories...]"
    42     "\n      cline [Options] [Directories...]"
    43     "\n\nCounts the line terminator characters (\\n) within all"
    44     " files in the specified\ndirectories."
    45     "\n\nOptions:"
    46     "\n  -b <level>          - binary file heuristics level (default medium)"
    47     "\n                        One of: ignore low medium high"
    48     "\n  -E <pattern>        - Excludes any line matching the <pattern>"
    49     "\n  -e <start> <end>    - Excludes lines between <start> and <end>"
    50     "\n                        You may use these options multiple times"
    51     "\n  -h, --help          - this help text"
    52     "\n  -m                  - print information about matching files only"
    53     "\n  -s <suffixes>       - only count files with these suffixes (separated"
    54     "\n                        by commas)"
    55     "\n  -S <suffixes>       - count any file except those with these suffixes"
    56     "\n                        (separated by commas)"
    57     "\n  -r, -R              - includes subdirectories"
    58     "\n  -v, --version       - print out version information"
    59     "\n  -V                  - turn verbose output off, print the result only"
    60     "\n\nShortcuts:"
    61     "\n  --exclude-cstyle-comments"
    62     "\n = -E \"\\s*//\" -e \"\\s*/\\*\" \"\\*/\\s*\""
    63     "\n\n"
    64     "The default call without any options is:"    
    65     "\n  cline ./\n\n"
    66     "So each file in the working directory is counted. If you want to count C"
    67     "\nsource code in your working directory and its subdirectories, type:"
    68     "\n  cline -rs .c\n"
    69     "\nIf you want to exclude comment lines, you may use the -e/-E option."
    70     "\nAfter a line matches the regex pattern <start> any following line is"
    71     "\nnot counted unless a line matches the <end> pattern. A line is still "
    72     "\ncounted when it does not start or end with the respective patterns."
    73     "\nPlease note, that cline does not remove whitespace characters as this"
    74     "\nmight not be reasonable in some cases."
    75     "\n\nExample (C without comments):"
    76     "\n  cline -s .c,.h --exclude-cstyle-comments"
    77     "\n");
    78 }
    80 int exit_with_version(settings_t* settings) {
    81   printf("cline - Version: " VERSION "\n");
    82   destroy_settings_t(settings);
    83   return 0;
    84 }
    86 int exit_with_help(settings_t* settings, int code) {
    87   printf("cline - Version: " VERSION "\n\n");
    88   printHelpText();
    89   destroy_settings_t(settings);
    90   return code;
    91 }
    93 int main(int argc, char** argv) {
    95   /* Settings */
    96   settings_t *settings = new_settings_t();
    97   if (settings == NULL) {
    98     fprintf(stderr, "Memory allocation failed.\n");
    99     return 1;
   100   }
   102   /* Get arguments */
   103   string_list_t *directories = new_string_list_t();
   104   if (directories == NULL) {
   105     fprintf(stderr, "Memory allocation failed.\n");
   106     return 1;
   107   }
   108   char* includeSuffix = NULL;
   109   char* excludeSuffix = NULL;
   110   int checked = 0;
   112   for (int t = 1 ; t < argc ; t++) {
   114     int argflags = checkArgument(argv[t], "hsSrRmvVbeE");
   115     int paropt = 0;
   117     /* s */
   118     if ((argflags & 2) > 0) {
   119       if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) {
   120         return exit_with_help(settings, 1);
   121       }
   122       t++;
   123       if (t >= argc) {
   124         return exit_with_help(settings, 1);
   125       }
   126       includeSuffix = argv[t];
   127     }
   128     /* S */
   129     if ((argflags & 4) > 0) {
   130       if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) {
   131         return exit_with_help(settings, 1);
   132       }
   133       t++;
   134       if (t >= argc) {
   135         return exit_with_help(settings, 1);
   136       }
   137       excludeSuffix = argv[t];
   138     }
   139     /* h */
   140     if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
   141       return exit_with_help(settings, 0);
   142     }
   143     /* r, R */
   144     if ((argflags & 24) > 0) {
   145       if (registerArgument(&checked, 24)) {
   146         return exit_with_help(settings, 1);
   147       }
   148       settings->recursive = true;
   149     }
   150     /* m */
   151     if ((argflags & 32) > 0) {
   152       if (registerArgument(&checked, 32)) {
   153         return exit_with_help(settings, 1);
   154       }
   155       settings->matchesOnly = true;
   156     }
   157     /* v */
   158     if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
   159       return exit_with_version(settings);
   160     }
   161     /* V */
   162     if ((argflags & 128) > 0) {
   163       if (registerArgument(&checked, 128)) {
   164         return exit_with_help(settings, 1);
   165       }
   166       settings->verbose = false;
   167     }
   168     /* b */
   169     if ((argflags & 256) > 0) {
   170       if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) {
   171         return exit_with_help(settings, 1);
   172       }
   173       t++;
   174       if (t >= argc) {
   175         return exit_with_help(settings, 1);
   176       }
   177       if (strcasecmp(argv[t], "ignore") == 0) {
   178         settings->bfileHeuristics->level = BFILE_IGNORE;
   179       } else if (strcasecmp(argv[t], "low") == 0) {
   180         settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
   181       } else if (strcasecmp(argv[t], "medium") == 0) {
   182         settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
   183       } else if (strcasecmp(argv[t], "high") == 0) {
   184         settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
   185       } else {
   186         return exit_with_help(settings, 1);
   187       }
   188     }
   189     /* e */
   190     if ((argflags & 512) > 0) {
   191       if (!checkParamOpt(&paropt) || t + 2 >= argc) {
   192         return exit_with_help(settings, 1);
   193       }
   194       t++; add_string(settings->regex->pattern_list, argv[t]);
   195       t++; add_string(settings->regex->pattern_list, argv[t]);
   196     }
   197     /* E */
   198     if ((argflags & 1024) > 0) {
   199       t++;
   200       if (!checkParamOpt(&paropt) || t >= argc) {
   201         return exit_with_help(settings, 1);
   202       }
   203       add_string(settings->regex->pattern_list, argv[t]);
   204       add_string(settings->regex->pattern_list, "$");
   205     }
   206     if (argflags == 0) {
   207       /* SHORTCUTS */
   208       /* exclude-cstyle-comments */
   209       if (strcmp(argv[t], "--exclude-cstyle-comments") == 0) {
   210         add_string(settings->regex->pattern_list, "\\s*//");
   211         add_string(settings->regex->pattern_list, "$");
   212         add_string(settings->regex->pattern_list, "\\s*/\\*");
   213         add_string(settings->regex->pattern_list, "\\*/\\s*");
   214       }
   215       /* Path */
   216       else {
   217         add_string(directories, argv[t]);
   218       }
   219     }
   220   }
   222   /* Find tokens */
   223   parseCSL(includeSuffix, settings->includeSuffixes);
   224   parseCSL(excludeSuffix, settings->excludeSuffixes);
   226   /* Scan directories */
   227   if (regex_compile_all(settings->regex)) {
   228     /* Don't waste memory when only the total sum is needed */
   229     string_list_t *output = settings->verbose ? new_string_list_t() : NULL;
   230     char *outbuf;
   232     int lineSum = 0, lines;
   233     if (directories->count == 0) {
   234         add_string(directories, ".");
   235     }
   236     for (int t = 0 ; t < directories->count ; t++) {
   237       lines = scanDirectory((scanner_t){directories->items[t], 0}, settings,
   238           output);
   239       lineSum += lines;
   240       if (directories->count > 1 ) {
   241         outbuf = (char*) malloc(81);
   242         memset(outbuf, '-', 79);
   243         outbuf[79] = '\n';
   244         outbuf[80] = 0;
   245         add_string(output, outbuf);
   246         outbuf = (char*) malloc(81);
   247         snprintf(outbuf, 81, "%-63s%10d lines\n", directories->items[t], lines);
   248         add_string(output, outbuf);
   249         outbuf = (char*) malloc(81);
   250         memset(outbuf, '-', 79);
   251         outbuf[79] = '\n';
   252         outbuf[80] = 0;
   253         add_string(output, outbuf);
   254       }
   255     }
   256     destroy_string_list_t(directories);
   258     /* Print result */
   259     if (settings->verbose) {
   260       for (int i = 0 ; i < output->count ; i++) {
   261         printf("%s", output->items[i]);
   262         free(output->items[i]);
   263       }
   265       for (int t = 0 ; t < 79 ; t++) {
   266         printf("=");
   267       }
   268       printf("\n%73d lines\n", lineSum);
   270       if (settings->confusing_lnlen &&
   271           settings->regex->pattern_list->count > 0) {
   273         printf("\nSome files contain too long lines.\n"
   274           "The regex parser currently supports a maximum line length of %d."
   275           "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
   276       }
   277     } else {
   278       printf("%d", lineSum);
   279     }
   280     destroy_string_list_t(output);
   281     destroy_settings_t(settings);
   282   }
   284   fflush(stdout);
   285   fflush(stderr);
   286   return 0;
   287 }

mercurial