-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstring_parser.c
151 lines (134 loc) · 3.68 KB
/
string_parser.c
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
#include "shell.h"
#include <stdlib.h>
#include <stdio.h>
#define LOGIC_DELIMS "&|;"
int is_logic(char *token);
char **get_command_tokens(char **raw_tokens, int beg_ind, int end_ind);
/**
* parse_string - Writes tokens to a linked list
*
* @str: Pointer to the token stream
*
* Return: NULL (failure) head (success)
*/
queue_t *parse_string(char *str)
{
char **raw_tokens, **sub_tokens;
char separator = '\0';
int beg_ind = 0, tok_ind = 0, end_ind = -1, sep_ind = -1;
queue_t *q = NULL;
if (!str)
return (NULL);
q = create_queue();
if (!q)
return (NULL);
raw_tokens = strtow(str, NORM_DELIMS);
if (!raw_tokens)
return (NULL);
/* does not deal with logical seperators combined with words e.g: */
/* echo cat&&echo test, echo cat&& echo test, etc... */
while (raw_tokens[tok_ind]) /* NULL terminated array of tokens */
{
if (is_logic(raw_tokens[tok_ind + 1]))
{
/* create new node */
end_ind = tok_ind; /* token before logic token */
sub_tokens = get_command_tokens(raw_tokens, beg_ind, end_ind);
if (!sub_tokens)
{
free_token_list(raw_tokens);
free_command_queue(q);
return (NULL);
}
separator = (sep_ind >= 0) ? *(raw_tokens[sep_ind]) : '\0';
if (!enqueue(q, separator, sub_tokens)) /* insert fail */
{
/* free everything & return NULL */
free_token_list(sub_tokens);
free_token_list(raw_tokens);
free_command_queue(q);
return (NULL);
}
sep_ind = tok_ind + 1; /* found seperator */
beg_ind = sep_ind + 1; /* beg command index moves forward */
}
tok_ind++;
}
free_token_list(raw_tokens);
return (q);
}
/**
* is_logic - checks if current token is a logical seperator token
* @token: token to check
*
* Return: 1 if it is a logical seperator, 0 if not, -1 if not only sep e.g:
* &&echo, doesn't account for words before delim, will just return 0, e.g:
* cat&&echo, cat&&, will return 0.
*/
int is_logic(char *token)
{
if (!token) /* NULL logical seperator, aka end of input */
return (1);
else if (*token == ';')
{
if (*(token + 1) == '\0')
return (1);
return (-1);
} /* will not be run if sep is ';' */
else if (is_delim(*token, LOGIC_DELIMS))
{
if (is_delim(*(token + 1), LOGIC_DELIMS))
{
if (*(token + 2) == '\0') /* only contains delim and NULL */
return (1);
return (-1); /* contains extra characters */
}
else
return (0);
}
return (0);
}
/**
* get_command_tokens - gets the command tokens given raw and beg to end pos's
* @raw_tokens: array of raw tokens (contains logical tokens like &&, ||, ;
* @beg_ind: index in raw_tokens of beginning of command, e.g: echo
* @end_ind: index in raw_tokens of end of command, e.g: cat
*
* Return: Pointer to new NULL terminated array of tokens, removing logical sep
*/
char **get_command_tokens(char **raw_tokens, int beg_ind, int end_ind)
{
char **com_tokens = NULL;
int com_ind = 0;
int ctrl_ctr = 0;
int word_len = 0;
/* +1 account for index starting at 0, +1 for NULL too */
com_tokens = malloc(sizeof(char *) * (((end_ind + 1) - beg_ind) + 1));
if (!com_tokens)
return (NULL);
while (beg_ind <= end_ind)
{
word_len = 0;
/* gets length of current token */
while (raw_tokens[beg_ind][word_len])
word_len++;
/* create space for chars of each word */
com_tokens[com_ind] = malloc(sizeof(char) * word_len + 1);
if (!com_tokens[com_ind])
{
free_token_list(com_tokens);
return (NULL);
}
ctrl_ctr = 0;
/* copy the raw_token to word_copy */
while (raw_tokens[beg_ind][ctrl_ctr])
{
com_tokens[com_ind][ctrl_ctr] = raw_tokens[beg_ind][ctrl_ctr];
ctrl_ctr++;
}
com_tokens[com_ind][ctrl_ctr] = '\0';
beg_ind++, com_ind++;
}
com_tokens[com_ind] = NULL; /* NULL terminate the array */
return (com_tokens);
}