summaryrefslogtreecommitdiff
path: root/apps/FaCE/CE_ARGV.CPP
blob: 6b97a30b6405746b6b7bb51cbbeff759acfa4bcb (plain)
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
// $Id$

#include "CE_ARGV.H"


CE_ARGV::CE_ARGV(wchar_t* cmdLine)
: ce_argv_(0)
, ce_argc_(0)
{
    const wchar_t* dummyArgv = L"root";  // dummy for the first argv
    const wchar_t* separator = L" ";     // blank space is a separator

    int formattedCmdLineLength = wcslen(dummyArgv) +
                                 wcslen(separator) +
                                 1;  // 1 is for the NULL at the end

    if (wcslen(cmdLine) > 0) {
        formattedCmdLineLength += wcslen(cmdLine);
        formattedCmdLineLength += wcslen(separator);
    }

    // formattedCmdLine will have dummyArgv and a separator at the beginning of cmdLine
    // and a separator at the end to generalize format and reduce the amount of code
    wchar_t* formattedCmdLine = 0;
    formattedCmdLine = new wchar_t[formattedCmdLineLength];

    wcscpy(formattedCmdLine, dummyArgv);
    wcscat(formattedCmdLine, separator);

    int max_possible_argc = 1;  // start with 1 because of the dummyArgv at the beginning

    if (wcslen(cmdLine) > 0) {
        int formattedPos  = wcslen(formattedCmdLine);
        int cmdLineLength = wcslen(cmdLine);

        // Inside of this for loop, it does same thing as strcat except it
        // checks and puts only one single white space between two argv entries.
        for (int i = 0; i < cmdLineLength; ++i) {
            if (iswspace(cmdLine[i]) != 0) {
                ++max_possible_argc;  // counting the number of white spaces
            }

            formattedCmdLine[formattedPos++] = cmdLine[i];

            if (iswspace(cmdLine[i]) != 0) {
                // make sure there is only one white space between two argv entries.
                while ((i < cmdLineLength) && (iswspace(cmdLine[i + 1]) != 0)) {
                    ++i;
                }
            }
        }

        formattedCmdLine[formattedPos] = 0;
        wcscat(formattedCmdLine, separator);  // make sure formattedCmdLine ends with a blank
    }

    int formattedCmdLength = wcslen(formattedCmdLine);

    bool insideQuotation = false;
    int* argv_strlen = 0;
    int entry_size = 0;
    argv_strlen = new int[max_possible_argc];

    // determine argc
    for (int i = 0; i < formattedCmdLength; ++i) {
        if (formattedCmdLine[i] == '\\') {
            ++i; // ignore the following character
            ++entry_size;
        }
        else if (formattedCmdLine[i] == '"') {
            insideQuotation = !insideQuotation;
        }
        else if ((!insideQuotation) && (iswspace(formattedCmdLine[i]) != 0)) {
            // new argv entry end found
            argv_strlen[ce_argc_++] = entry_size;  // cache the size of this entry
            entry_size = 0;
        }
        else {
            ++entry_size;
        }
    }

    ce_argv_ = new wchar_t*[ce_argc_ + 1];
    ce_argv_[ce_argc_] = 0;  // Last command line entry is a NULL.

    for (int j = 0, cmdLinePos = 0; j < ce_argc_; ++j, ++cmdLinePos) {
        int length = argv_strlen[j];

        ce_argv_[j] = new wchar_t[length + 1];
        ce_argv_[j][length] = 0;  // string termination null

        if (iswspace(formattedCmdLine[cmdLinePos]) != 0) {
            // This is where prior argv has trailing '"' at the end.
            ++cmdLinePos;
        }

        for (int n = 0; n < length; ++n, ++cmdLinePos) {
            if ((formattedCmdLine[cmdLinePos] == '\\') || (formattedCmdLine[cmdLinePos] == '"')) {
                ++cmdLinePos;
            }

            ce_argv_[j][n] = formattedCmdLine[cmdLinePos];
        }
    }

    delete argv_strlen;
    delete formattedCmdLine;
}


CE_ARGV::~CE_ARGV(void)
{
    for (int i = 0; i < ce_argc_; ++i) {
        delete [] ce_argv_[i];
    }

    delete [] ce_argv_;
}