xref: /haiku/src/tests/add-ons/kernel/file_systems/fs_shell/argv.c (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*
2    This file contains a function, build_argv(), which will take an input
3    string and chop it into individual words.  The return value is an
4    argv style array (i.e. like what main() receives).
5 
6   THIS CODE COPYRIGHT DOMINIC GIAMPAOLO.  NO WARRANTY IS EXPRESSED
7   OR IMPLIED.  YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR
8   NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED.
9 
10   FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com).
11 
12   Dominic Giampaolo
13   dbg@be.com
14 */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ctype.h>
19 #include <string.h>
20 
21 #include "argv.h"
22 
23 #define DOUBLE_QUOTE  '"'
24 #define SINGLE_QUOTE  '\''
25 #define BACK_SLASH    '\\'
26 
27 char **
28 build_argv(char *str, int *argc)
29 {
30     int table_size = 16, _argc;
31     char **argv;
32 
33     if (argc == NULL)
34         argc = &_argc;
35 
36     *argc = 0;
37     argv  = (char **)calloc(table_size, sizeof(char *));
38 
39     if (argv == NULL)
40         return NULL;
41 
42     while(*str) {
43         /* skip intervening white space */
44         while(*str != '\0' && (*str == ' ' || *str == '\t' || *str == '\n'))
45             str++;
46 
47         if (*str == '\0')
48             break;
49 
50         if (*str == DOUBLE_QUOTE) {
51             argv[*argc] = ++str;
52             while(*str && *str != DOUBLE_QUOTE) {
53                 if (*str == BACK_SLASH)
54                     strcpy(str, str+1);  /* copy everything down */
55                 str++;
56             }
57         } else if (*str == SINGLE_QUOTE) {
58             argv[*argc] = ++str;
59             while(*str && *str != SINGLE_QUOTE) {
60                 if (*str == BACK_SLASH)
61                     strcpy(str, str+1);  /* copy everything down */
62                 str++;
63             }
64         } else {
65             argv[*argc] = str;
66             while(*str && *str != ' ' && *str != '\t' && *str != '\n') {
67                 if (*str == BACK_SLASH)
68                     strcpy(str, str+1);  /* copy everything down */
69                 str++;
70             }
71         }
72 
73         if (*str != '\0')
74             *str++ = '\0';   /* chop the string */
75 
76         *argc = *argc + 1;
77         if (*argc >= table_size-1) {
78             char **nargv;
79 
80             table_size = table_size * 2;
81             nargv = (char **)calloc(table_size, sizeof(char *));
82 
83             if (nargv == NULL) {   /* drats! failure. */
84                 free(argv);
85                 return NULL;
86             }
87 
88             memcpy(nargv, argv, (*argc) * sizeof(char *));
89             free(argv);
90             argv = nargv;
91         }
92     }
93 
94     return argv;
95 }
96