File: argize.c

package info (click to toggle)
qtads 2.1.6-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 16,156 kB
  • ctags: 18,767
  • sloc: cpp: 133,078; ansic: 26,048; xml: 18; makefile: 11
file content (146 lines) | stat: -rw-r--r-- 4,517 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* 
 *   Copyright (c) 1998 by Christopher Nebel.  All Rights Reserved.
 *   
 *   Please see the accompanying license file, LICENSE.TXT, for information
 *   on using and copying this software.  
 */
/*
Name:
  argize.c

Function:
  Break a string into argc/argv-style arguments.

Notes:
  none

Modified:
  <2>07/04/98  CNebel   - Fixed so that args wouldn't pick up trailing 
                          whitespace.
  <1>07/04/98  CNebel   - Created based on older Mac-specific argize source
*/

#include "argize.h"

#include <stddef.h>
#include <ctype.h>


/*
 *   Return what argc would be if this string were fed to argize.  
 */
int countargs(const char *cmdline)
{
    const char *p = cmdline;
    int                     state = 0;
    int                     argc = 0;

    while (*p) {
        switch (state) {
        case 0:                                 /* skip leading white space */
            while (isspace((unsigned char)*p)) p++;
            if (!*p) break;            /* If there's nothing left, get out. */
            state = 1;
            /* fall through */;

        case 1:                                                /* begin arg */
            argc++;
            state = 2;
            /* fall through */

        case 2:                            /* collect chars for current arg */
            if (isspace((unsigned char)*p))
                p++, state = 0;                       /* Terminate this arg */
            else if (*p == '"')
                p++, state = 3;                              /* Open quote. */
            else if (*p == '\\')
                p++, state = 4;                         /* Escape sequence. */
            else
                p++;                                    /* Just keep going. */

            break;

        case 3:                             /* collect chars inside quotes. */
            switch (*p) {
            case '"' : p++; state = 2; break;                /* Close quote */
            case '\\': p++; state = 5; break;           /* Escape sequence. */
            default:   p++; break;
            }
            break;

        case 4:                        /* escaped character outside quotes. */
            p++; state = 2;
            break;

        case 5:                         /* escaped character inside quotes. */
            p++; state = 3;
            break;
        }
    }

    return argc;
}


/*
 *   Break a string <cmdline> into argc/argv arguments, removing quotes in
 *   the process.  Returns 0 on success, 1 if there were too many
 *   arguments.  
 */
int argize(char *cmdline, int *const argc, char *argv[], const size_t argvlen)
{
    char   *p, *q;
    int             state;

    p = q = cmdline;
    *argc = 0;
    state = 0;

    while (*p) {
        switch (state) {
        case 0:                                 /* skip leading white space */
            while (isspace((unsigned char)*p)) p++, q++;
            if (!*p) break;            /* If there's nothing left, get out. */
            state = 1;
            /* fall through */;

        case 1:                                                /* begin arg */
            if ((size_t)*argc < argvlen)
                argv[(*argc)++] = q;
            else
                return 1;
            state = 2;
            /* fall through */

        case 2:                            /* collect chars for current arg */
            if (isspace((unsigned char)*p))
                *q++ = *p++ = '\0', state = 0;        /* Terminate this arg */
            else if (*p == '"')
                p++, state = 3;                              /* Open quote. */
            else if (*p == '\\')
                p++, state = 4;                         /* Escape sequence. */
            else
                *q++ = *p++;                            /* Just keep going. */

            break;

        case 3:                             /* collect chars inside quotes. */
            switch (*p) {
            case '"' : p++; state = 2; break;                /* Close quote.*/
            case '\\': p++; state = 5; break;           /* Escape sequence. */
            default:   *q++ = *p++; break;
            }
            break;

        case 4:                        /* escaped character outside quotes. */
            *q++ = *p++; state = 2;
            break;

        case 5:                         /* escaped character inside quotes. */
            *q++ = *p++; state = 3;
            break;
        }
    }
    *q = '\0';
    return 0;
}