"Fossies" - the Fresh Open Source Software Archive

Member "global-6.6.5/libutil/args.c" (3 Sep 2020, 7009 Bytes) of package /linux/misc/global-6.6.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "args.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 6.6.4_vs_6.6.5.

    1 /*
    2  * Copyright (c) 2010, 2014, 2020 Tama Communications Corporation
    3  *
    4  * This file is part of GNU GLOBAL.
    5  *
    6  * This program is free software: you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License as published by
    8  * the Free Software Foundation, either version 3 of the License, or
    9  * (at your option) any later version.
   10  * 
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  * 
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   18  */
   19 
   20 #ifdef HAVE_CONFIG_H
   21 #include <config.h>
   22 #endif
   23 #include <ctype.h>
   24 #include <stdio.h>
   25 #include "getopt.h"
   26 #include "checkalloc.h"
   27 #include "die.h"
   28 #include "env.h"
   29 #include "locatestring.h"
   30 #include "strbuf.h"
   31 #include "test.h"
   32 #include "gpathop.h"
   33 #include "args.h"
   34 #if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(__DJGPP__)
   35 #include "path.h"
   36 #endif
   37 
   38 #define ARGS_NOP    0
   39 #define ARGS_ARGS   1
   40 #define ARGS_FILELIST   2
   41 #define ARGS_GFIND  3
   42 #define ARGS_BOTH   4
   43 
   44 static int type;
   45 static char *const *argslist;
   46 static FILE *ip;
   47 static GFIND *gp;
   48 
   49 /**
   50  * args_open:
   51  *
   52  *  @param[in]  args    args array
   53  */
   54 void
   55 args_open(char *const *argv)
   56 {
   57     type = ARGS_ARGS;
   58     argslist = argv;
   59 }
   60 /**
   61  * args_open_filelist: args_open like interface for handling output of find(1).
   62  *
   63  *  @param[in]  filename    file including list of file names.
   64  *              When "-" is specified, read from standard input.
   65  */
   66 void
   67 args_open_filelist(const char *filename)
   68 {
   69     type = ARGS_FILELIST;
   70     if (!strcmp(filename, "-")) {
   71         ip = stdin;
   72     } else {
   73         ip = fopen(filename, "r");
   74         if (ip == NULL)
   75             die("cannot open '%s'.", filename);
   76     }
   77 }
   78 /**
   79  * args_open_both: args_open like interface for argument and file list.
   80  *
   81  *  @param[in]  args        args array
   82  *  @param[in]  filename    file including list of file names.
   83  *              When "-" is specified, read from standard input.
   84  */
   85 void
   86 args_open_both(char *const *argv, const char *filename)
   87 {
   88     type = ARGS_BOTH;
   89     argslist = argv;
   90     if (!strcmp(filename, "-")) {
   91         ip = stdin;
   92     } else {
   93         ip = fopen(filename, "r");
   94         if (ip == NULL)
   95             die("cannot open '%s'.", filename);
   96     }
   97 }
   98 /**
   99  * args_open_gfind: args_open like interface for handling output of gfind.
  100  *
  101  *  @param[in]  agp GFIND descriptor
  102  */
  103 void
  104 args_open_gfind(GFIND *agp)
  105 {
  106     type = ARGS_GFIND;
  107     gp = agp;
  108 }
  109 void
  110 args_open_nop(void)
  111 {
  112     type = ARGS_NOP;
  113 }
  114 /**
  115  * args_read: read path From args.
  116  *
  117  *  @return     path (NULL: end of argument)
  118  */
  119 const char *
  120 args_read(void)
  121 {
  122     const char *p;
  123     STATIC_STRBUF(sb);
  124 
  125     strbuf_clear(sb);
  126     switch (type) {
  127     case ARGS_NOP:
  128         p = NULL;
  129         break;
  130     case ARGS_ARGS:
  131         p = *argslist++;
  132         break;
  133     case ARGS_FILELIST:
  134         p = strbuf_fgets(sb, ip, STRBUF_NOCRLF);
  135         break;
  136     case ARGS_GFIND:
  137         p = gfind_read(gp);
  138         break;
  139     case ARGS_BOTH:
  140         if (*argslist != NULL)
  141             p = *argslist++;
  142         else
  143             p = strbuf_fgets(sb, ip, STRBUF_NOCRLF);
  144         break;
  145     default:
  146         die("args_read: invalid type.");
  147     }
  148     return p;
  149 }
  150 /**
  151  * args_close: close args.
  152  */
  153 void
  154 args_close(void)
  155 {
  156     switch (type) {
  157     case ARGS_NOP:
  158     case ARGS_ARGS:
  159         break;
  160     case ARGS_FILELIST:
  161     case ARGS_BOTH:
  162         if (ip != NULL && ip != stdin)
  163             fclose(ip);
  164         ip = NULL;
  165         break;
  166     case ARGS_GFIND:
  167         if (gp != NULL)
  168             gfind_close(gp);
  169         gp = NULL;
  170         break;
  171     default:
  172         die("something wrong.");
  173     }
  174 }
  175 /**
  176  * preparse_options
  177  *
  178  *  @param[in]  argc    main()'s argc integer
  179  *  @param[in]  argv    main()'s argv string array
  180  *
  181  * Setup the "GTAGSCONF" and "GTAGSLABEL" environment variables
  182  * according to the --gtagsconf and --gtagslabel options.
  183  * Additionally changes directory acording to the --directory.
  184  */
  185 int
  186 preparse_options(int argc, char *const *argv)
  187 {
  188     int optchar;
  189     int option_index = 0;
  190     char *confpath = NULL;
  191     char *label = NULL;
  192     char *dir = NULL;
  193     extern const char *short_options;
  194     extern struct option const long_options[];
  195 
  196     /*
  197      * restart scanning of the same argv by setting optind = 1.
  198      */
  199         optind = 1;
  200     while ((optchar = getopt_long(argc, argv, short_options, long_options, &option_index)) != EOF) {
  201         switch (optchar) {
  202         case 'C':
  203             dir = optarg;
  204             break;
  205         case OPT_GTAGSCONF:
  206             confpath = optarg;
  207             break;
  208         case OPT_GTAGSLABEL:
  209             label = optarg;
  210             break;
  211         case '?':
  212             return -1;
  213         default:
  214             break;
  215         }
  216     }
  217     /*
  218      * Change the directory before doing all the work including parameter analysis.
  219      */
  220     if (dir)
  221         if (chdir(dir) < 0)
  222             die("cannot change directory to '%s'.", dir);
  223     if (confpath) {
  224         char real[MAXPATHLEN];
  225 
  226         if (!test("f", confpath))
  227             die("--gtagsconf file not found.");
  228         if (!realpath(confpath, real))
  229             die("cannot get absolute path of --gtagsconf file.");
  230         set_env("GTAGSCONF", real);
  231     }
  232     if (label)
  233         set_env("GTAGSLABEL", label);
  234     /*
  235      * restart scanning of the same argv by setting optind = 1.
  236      * This is needed for the calling of getopt() in main().
  237      */
  238         optind = 1;
  239     return 0;
  240 }
  241 /**
  242  * prepend_options: creates a new argv main() array, by prepending (space separated)
  243  *      options and arguments from the string argument options.
  244  *
  245  *  @param[in,out]  argc    pointer to main()'s argc integer
  246  *  @param[in]  argv    main()'s argv string array
  247  *  @param[in]  options string
  248  *  @return The new argv array.
  249  *
  250  *  The program's name is copied back into: returned[0] (argv[0]).
  251  */
  252 char **
  253 prepend_options(int *argc, char *const *argv, const char *options)
  254 {
  255     STRBUF *sb = strbuf_open(0);
  256     const char *p, *opt = check_strdup(options);
  257     int count = 1;
  258     int quote = 0;
  259     const char **newargv;
  260     int i = 0, j = 1;
  261 
  262     for (p = opt; *p && isspace(*p); p++)
  263         ;
  264     for (; *p; p++) {
  265         int c = *p;
  266 
  267         if (quote) {
  268             if (quote == c)
  269                 quote = 0;
  270             else
  271                 strbuf_putc(sb, c);
  272         } else if (c == '\\') {
  273             if (*(p + 1))
  274                 strbuf_putc(sb, *++p);
  275         } else if (c == '\'' || c == '"') {
  276             quote = c;
  277         } else if (isspace(c)) {
  278             strbuf_putc(sb, '\0');
  279             count++;
  280             while (*p && isspace(*p))
  281                 p++;
  282             p--;
  283         } else {
  284             strbuf_putc(sb, *p);
  285         }
  286     }
  287     newargv = (const char **)check_malloc(sizeof(char *) * (*argc + count + 1));
  288     newargv[i++] = argv[0];
  289     p = strbuf_value(sb);
  290     while (count--) {
  291         newargv[i++] = p;
  292         p += strlen(p) + 1;
  293     }
  294     while (j < *argc)
  295         newargv[i++] = argv[j++];
  296     newargv[i] = NULL;
  297     *argc = i;
  298 #ifdef DEBUG
  299     for (i = 0; i < *argc; i++)
  300         fprintf(stderr, "newargv[%d] = '%s'\n", i, newargv[i]);
  301 #endif
  302     /* doesn't close string buffer. */
  303 
  304     return (char **)newargv;
  305 }
  306 /**
  307  * serialize_options
  308  */
  309 char *
  310 serialize_options(int argc, char *const *argv)
  311 {
  312     STRBUF *sb = strbuf_open(0);
  313     char *string = NULL;
  314     char *p = NULL;
  315     int i;
  316     for (i = 0; i < argc; i++) {
  317         if (i > 0)
  318             strbuf_putc(sb, ' ');
  319         for (p = argv[i]; *p; p++) {
  320             /* quote spaces using url encoding */
  321             if (*p == ' ')
  322                 strbuf_puts(sb, "%20");
  323             else
  324                 strbuf_putc(sb, *p);
  325         }
  326     }
  327     string = check_strdup(strbuf_value(sb));
  328     strbuf_close(sb);
  329     return string;
  330 }