Skip to content

Commit 799b306

Browse files
committed
fixes #112 add support for if "==" echo Hello and similar IF constructs
supports properly quoted strings with delimeters, otherwise stops on left an right side of == after first delimiter character and allows junk characters to left of == (but not right of it, e.g. garbage== but not ==garbage) and updates tst-if.bat
1 parent 5edefba commit 799b306

File tree

4 files changed

+82
-10
lines changed

4 files changed

+82
-10
lines changed

cmd/if.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,34 +148,41 @@ int cmd_if(char *param)
148148

149149
/* Check that '==' is present, syntax error if not */
150150
else {
151-
size_t len;
151+
size_t len_l, len_r;
152152
char *r; /* right operand */
153153

154154
pp = skipqword(param, "==");
155155

156+
/* skip past any garbage characters before the == */
157+
while (*pp && (*pp != '=') && !isargdelim(*pp)) pp++;
158+
156159
if(*pp != '=' || pp[1] != '=') {
157160
error_syntax(0);
158161
return 0;
159162
}
160163

161164
*pp = '\0'; /* param[] points to the left operand */
162165

163-
/* skip over the '==' and subsquent spaces and
164-
assign the end of the right operator to pp */
165-
pp = skipqword(r = ltrimcl(pp + 2), 0);
166+
/* skip over the '==' and subsquent spaces */
167+
r = ltrimcl(pp + 2);
168+
/* and assign the end of the right operator to pp */
169+
pp = skipqword(r, 0);
166170

167171
/* now: param := beginning of the left operand
168172
r := beginning of the right operand
169173
pp := end of right operand
170174
*/
171175

172176
rtrimcl(param); /* ensure that spurious whitespaces are ignored */
173-
len = strlen(param);
177+
len_l = strlen(param);
178+
len_r = strlen(r);
179+
dprintf(("left side=[%s] %i\n", param, len_l));
180+
dprintf(("rigt side=[%s] %i\n", r, len_r));
174181

175182
/* check if strings differ */
176-
if ( ((pp - r) == len) &&
177-
((ignore_case && strnicmp(param, r, len) == 0) ||
178-
(memcmp(param, r, len) == 0)) )
183+
if ( (len_l == len_r) &&
184+
((ignore_case && strnicmp(param, r, len_l) == 0) ||
185+
(memcmp(param, r, len_l) == 0)) )
179186
x_flag = X_EXEC;
180187
}
181188

include/cmdline.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ typedef int (* const optScanner)(const char * const optstr, int ch, int bool, co
8888
#define optLong(str) (strcmpi(optstr, (str)) == 0)
8989

9090

91-
char *skipqword(const char *str, const char * const stop);
91+
char *skipqword(char *str, const char * const stop);
9292

9393
/* Use matchtok() to compare string constants */
9494
#define match(line,word,len) match_(&(line), (word), (len))

lib/skqwd.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "../include/command.h"
5757
#include "../include/cmdline.h"
5858

59+
#if 0
5960
char *skipqword(const char *pp, const char * const stop)
6061
{ size_t len;
6162
int quote = 0;
@@ -74,3 +75,51 @@ char *skipqword(const char *pp, const char * const stop)
7475

7576
return (char *) pp; /* strip const */
7677
}
78+
#else
79+
char *skipqword(char *pp, const char * const stop)
80+
{ size_t len;
81+
int quote = 0;
82+
char *pp_trunc = 0;
83+
84+
len = stop? strlen(stop): 0;
85+
86+
if(*pp) do {
87+
/* if we find a quote then continue until terminator or end of string found */
88+
if(quote) {
89+
if(quote == *pp) {
90+
pp_trunc = 0;
91+
quote = 0;
92+
} else if(len && (memcmp(pp, stop, len) == 0)) {
93+
/* no matching quote, so back up to delimiter and mark end of pp */
94+
char *p = pp;
95+
while(*p && (!quote || (quote != *p)) && !isargdelim(*p)) p--;
96+
p++;
97+
if (p < pp) *p='\0';
98+
break;
99+
} else if(!pp_trunc && isargdelim(*pp)) {
100+
pp_trunc = pp; /* if end of string but no matching quote, terminate at 1st delimiter instead */
101+
}
102+
} else if(strchr(QUOTE_STR, *pp))
103+
quote = *pp;
104+
else if(len && (memcmp(pp, stop, len) == 0)) {
105+
/* no matching quote, so back up to delimiter and mark end of pp */
106+
char *p = pp;
107+
while(*p && (!quote || (quote != *p)) && !isargdelim(*p)) p--;
108+
p++;
109+
if (p < pp) *p='\0';
110+
break;
111+
} else if(!pp_trunc && isargdelim(*pp)) {
112+
pp_trunc = pp; /* truncate at delimter if not in quoted string */
113+
break;
114+
}
115+
} while(*++pp);
116+
if (pp_trunc) {
117+
*pp_trunc = '\0'; /* never found end of quote so stop at first delimiter */
118+
dprintf(("returning [%s]\n", pp_trunc+1));
119+
return pp_trunc+1;
120+
}
121+
122+
dprintf(("returning [%s]\n", pp));
123+
return (char *) pp; /* strip const */
124+
}
125+
#endif

tests/tst-if.bat

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ if 1== 1 echo Probe #9 passed
6565
if 1== 2 echo Probe #10 failed
6666
if not 1=="1" echo Probe #11 passed
6767
if not "1 2 3 4"=="1 2 3 4" echo Probe #12 failed
68+
if "1 2 3 4"=="1 2 3 4" echo Probe #13 passed
6869
echo.
69-
echo You should see passed probes 1, 3, 5, 7, 9,& 11 and no failed one
70+
echo You should see passed probes 1, 3, 5, 7, 9, 11,& 13 and no failed one
7071
echo.
7172
pause
7273

@@ -100,5 +101,20 @@ if a==a
100101
echo.
101102
pause
102103

104+
cls
105+
echo Testing " and extra characters included with ==
106+
echo .
107+
if "a=="a echo Probe #1 passed
108+
if "a == "a echo Probe #2 passed
109+
if a "== a echo Probe #3 passed
110+
if a garbage== a echo Probe #4 passed
111+
if a garbage==garbage a echo Probe #5 failed
112+
if .a == .a echo Probe #6 passed
113+
if " a==" a echo Probe #7 failed, a is not a valid command
114+
if " echo==" echo Probe #8 passed
115+
echo .
116+
echo You should see passed probes 1,2,3,4,6,& 8 with 7 giving a bad command error
117+
pause
118+
103119
echo.
104120
echo Test finished

0 commit comments

Comments
 (0)