-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.cpp
206 lines (190 loc) · 5.14 KB
/
parser.cpp
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include"parser.h"
using namespace std;
vector<struct command_type> parse(string line, int& ret)
{
unsigned int i;
int pipe_flag=0;
std::vector<struct command_type > command_vect; //final vector to be returned by the function
std::vector<std::vector<string> > commands;
std::vector<string> words; //all words of a command
string word; //represent a single word/token of a command
ret = 0;
for(i=0; i<=line.length(); i++)
{
if(i==line.length()) //parsed till the end - now store whatever is left in words vector
{
if(pipe_flag) //means last character was a pipe and the command ends - syntax error
{
ret = -5;
return command_vect;
}
if(word.length() > 0)
words.push_back(word);
word.clear();
if(words.size() > 0)
commands.push_back(words);
words.erase(words.begin(), words.end());
continue;
}
if(line[i] == ' ' || line[i] == '\t')
{
if(word.length() > 0)
words.push_back(word);
word.clear();
continue;
//while(i<line.length() && (line[i] == ' ' || line[i] == '\t'))
// i++;
}
else if(line[i] == '\'' || line[i] == '"' )
{
pipe_flag=0;
string inside_qoute;
int offset;
offset = parse_qouted_string(line.substr(i), inside_qoute);
if(offset==-1) //means it couldnt find ending qoute
{
ret=-1; //No ending qoute found - error
return command_vect;
}
else
{
word = inside_qoute;
i+=offset;
words.push_back(word);
word.clear();
}
}
else if(line[i] == '|' || line[i] == '&' || line[i] == '<' || line[i] == '>')
{
if(word.length() > 0)
words.push_back(word);
word.clear();
if(line[i] == '|')
{
if(pipe_flag) //if pipe comes directly after a pipe - error
{
ret = -6;
return command_vect;
}
if(words.size() <= 0) //no command and a pipe comes - error
{
ret = -7;
return command_vect;
}
commands.push_back(words);
words.erase(words.begin(), words.end());
pipe_flag=1;
}
else
{
if(pipe_flag && line[i] == '&')
{
ret = -2; //ampersand cant come right after a pipe - error
return command_vect;
}
if(line[i] == '&' && words.size() <= 0) //no command and an ampersand comes - error
{
ret = -8;
return command_vect;
}
word+=line[i]; //add & or < or >
words.push_back(word);
word.clear();
}
}
else
{
word+=line[i];
pipe_flag=0;
}
}
/*for(std::vector<vector <string> >::iterator it = commands.begin(); it!=commands.end(); it++)
{
for(std::vector<string>::iterator it2 = (*it).begin(); it2!=(*it).end(); it2++)
cout<<*it2<<"\t";
cout<<"\n";
}*/
for(std::vector<vector <string> >::iterator it = commands.begin(); it!=commands.end(); it++) //iterate over every command
{
words.erase(words.begin(), words.end()); //here variable "words" will be used to store all the args
//of a command except redirection and backgrounding
struct command_type tmp; //temporary structure as need to populate vector
tmp.background = false;
for(std::vector<string>::iterator it2 = (*it).begin(); it2!=(*it).end(); it2++)
{
if(*it2 == ">")
{
it2++;
if(it2!=(*it).end())
tmp.output_redirect = *it2;
else
{
ret = -3; //syntax error near output redirection operator
return command_vect;
}
}
else if(*it2 == "<")
{
it2++;
if(it2!=(*it).end())
tmp.input_redirect = *it2;
else
{
ret = -4; //syntax error near input redirection operator
return command_vect;
}
}
else if(*it2 == "&")
tmp.background = true;
else
words.push_back(*it2);
}
/*tmp.args = new char*[words.size()+1];
for(i=0; i<words.size(); i++)
{
tmp.args[i] = new char[words[i].length()+1];
strcpy(tmp.args[i], words[i].c_str());
}
tmp.args[i] = NULL;*/
tmp.args = words;
command_vect.push_back(tmp);
/*for(i=0; i<tmp.args.size(); i++)
cout<<"args["<<i<<"]: "<<tmp.args[i]<<endl;
cout<<"input_redirect: "<<tmp.input_redirect<<endl;
cout<<"output_redirect: "<<tmp.output_redirect<<endl;
cout<<"backgrounding: "<<tmp.background<<endl;*/
}
return command_vect;
}
/* Following function takes source string as input which starts from a qoute;
parses the token inside qoutes and returns in inside_qoutes token;
returns -1 if qoutes are invalid(no ending qoute found else returns the length of the token(to be used as offset)
*/
int parse_qouted_string(string source, string& inside_qoutes)
{
unsigned int i;
char initial_qoute = source[0]; //initial qoute should be the ending qoute
for(i=1; i<source.length() && source[i]!=initial_qoute; i++)
inside_qoutes += source[i];
if(i>=source.length()) //means ending qoute never came
return -1;
else
return i;
}
/*<scan and break on | OR & > -- check pipe shouldnt come after a '&'
--> & should be included inside a command only - strip the pipe
<scan internal strings and make these flags on - input redirection, output redirection and backgrounding
int execvp(const char *file, char *const argv[]);
just give the program name and
argv = [0] --> [program name\0]
[1] --> [-l\0]
[2] --> [-w\0]
.
.
.
.
[NULL]
fork()
vector of argv's i.e array of pointers to chars
std::vector<char **>
*/