--- var.c 2001/12/14 14:40:28 1.52
+++ var.c 2001/12/16 23:40:16 1.53
@@ -99,7 +99,8 @@
"index specification of array variable is incomplete", /* VAR_ERR_INCOMPLETE_INDEX_SPEC = -39 */
"bracket expression in array variable's index is not closed", /* VAR_ERR_UNCLOSED_BRACKET_IN_INDEX = -40 */
"division by zero error in index specification", /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX = -41 */
- "unterterminated loop construct" /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT = -42 */
+ "unterminated loop construct", /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT = -42 */
+ "invalid character in loop limits" /* VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS = -43 */
};
rc = 0 - rc;
@@ -502,8 +503,8 @@
const char *p;
for (p = begin;
- p != end
- && *p != config->varinit
+ p != end
+ && *p != config->varinit
&& *p != config->enddelim
&& *p != ':'; p++) {
if (*p == config->escape) {
@@ -543,7 +544,7 @@
return VAR_ERR_INCOMPLETE_INDEX_SPEC;
if (*p == '(') {
- rc = num_exp(++p, end, current_index, result, failed,
+ rc = num_exp(++p, end, current_index, result, failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
return rc;
@@ -555,11 +556,11 @@
++p;
}
else if (*p == config->varinit) {
- rc = variable(p, end, config, nameclass, lookup,
+ rc = variable(p, end, config, nameclass, lookup,
lookup_context, 1, &tmp, current_index, rel_lookup_flag);
if (rc == VAR_ERR_UNDEFINED_VARIABLE) {
*failed = 1;
- rc = variable(p, end, config, nameclass, lookup,
+ rc = variable(p, end, config, nameclass, lookup,
lookup_context, 0, &tmp, current_index, rel_lookup_flag);
if (rc < 0)
return rc;
@@ -570,7 +571,7 @@
if (rc < 0)
return rc;
p += rc;
- rc = num_exp(tmp.begin, tmp.end, current_index, result,
+ rc = num_exp(tmp.begin, tmp.end, current_index, result,
failed, rel_lookup_flag, config, nameclass, lookup, lookup_context);
tokenbuf_free(&tmp);
if (rc < 0)
@@ -622,8 +623,8 @@
if (begin == end)
return VAR_ERR_INCOMPLETE_INDEX_SPEC;
- rc = num_exp_read_operand(p, end, current_index, result,
- failed, rel_lookup_flag, config, nameclass,
+ rc = num_exp_read_operand(p, end, current_index, result,
+ failed, rel_lookup_flag, config, nameclass,
lookup, lookup_context);
if (rc < 0)
return rc;
@@ -632,7 +633,7 @@
while (p != end) {
if (*p == '+' || *p == '-') {
operator = *p++;
- rc = num_exp(p, end, current_index, &right, failed,
+ rc = num_exp(p, end, current_index, &right, failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
return rc;
@@ -644,7 +645,7 @@
}
else if (*p == '*' || *p == '/' || *p == '%') {
operator = *p++;
- rc = num_exp_read_operand(p, end, current_index, &right, failed,
+ rc = num_exp_read_operand(p, end, current_index, &right, failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
return rc;
@@ -747,7 +748,7 @@
/* If the next token is START-INDEX, read the index specification. */
if (config->startindex && *p == config->startindex) {
- rc = num_exp(++p, end, current_index, &idx, &failed,
+ rc = num_exp(++p, end, current_index, &idx, &failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
goto error_return;
@@ -822,11 +823,11 @@
p++;
if (!failed)
rc = command(p, end, config, nameclass, lookup,
- lookup_context, force_expand, result,
+ lookup_context, force_expand, result,
current_index, rel_lookup_flag);
else
rc = command(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &tmp,
+ lookup_context, force_expand, &tmp,
current_index, rel_lookup_flag);
if (rc < 0)
goto error_return;
@@ -1231,7 +1232,7 @@
else
rc = strncmp(p, search->begin,
search->end - search->begin);
- if (rc != 0) {
+ if (rc != 0) {
/* no match, copy character */
if (!tokenbuf_append(&tmp, p, 1)) {
tokenbuf_free(&tmp);
@@ -1352,7 +1353,7 @@
return VAR_ERR_OUT_OF_MEMORY;
i--;
}
- i = (width - (data->end - data->begin))
+ i = (width - (data->end - data->begin))
% (fill->end - fill->begin);
if (!tokenbuf_append(data, fill->begin, i))
return VAR_ERR_OUT_OF_MEMORY;
@@ -1369,7 +1370,7 @@
}
i--;
}
- i = (width - (data->end - data->begin))
+ i = (width - (data->end - data->begin))
% (fill->end - fill->begin);
if (!tokenbuf_append(&result, fill->begin, i)) {
tokenbuf_free(&result);
@@ -1396,7 +1397,7 @@
}
i--;
}
- i = ((width - (data->end - data->begin)) / 2)
+ i = ((width - (data->end - data->begin)) / 2)
% (fill->end - fill->begin);
if (!tokenbuf_append(&result, fill->begin, i)) {
tokenbuf_free(&result);
@@ -1774,7 +1775,7 @@
struct wrapper_context *wcon = context;
int rc;
- rc = (*wcon->lookup)(wcon->context, name, name_len,
+ rc = (*wcon->lookup)(wcon->context, name, name_len,
idx, data, data_len, buffer_size);
if (rc == 0) {
(*wcon->rel_lookup_flag)--;
@@ -1787,6 +1788,105 @@
return rc;
}
+static var_rc_t loop_limits(const char *begin, const char *end,
+ const var_config_t *config,
+ const char_class_t nameclass,
+ var_cb_t lookup, void* lookup_context,
+ int* start, int* step, int* stop, int* open_end)
+ {
+ const char* p = begin;
+ int rc;
+ int failed;
+ int dummy;
+
+ printf("loop_limits() called: '%s'.\n", begin);
+
+ if (begin == end)
+ return 0;
+
+ if (*p != config->startdelim)
+ return 0;
+ else
+ ++p;
+
+ /* Read start value for the loop. */
+
+ failed = 0;
+ rc = num_exp(p, end, 0, start, &failed, &dummy,
+ config, nameclass, lookup, lookup_context);
+ if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
+ *start = 0; /* use default */
+ else if (rc < 0)
+ return rc;
+ else
+ p += rc;
+ if (failed)
+ return VAR_ERR_UNDEFINED_VARIABLE;
+
+ if (*p != ',')
+ return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
+ else
+ ++p;
+
+ /* Read step value for the loop. */
+
+ failed = 0;
+ rc = num_exp(p, end, 0, step, &failed, &dummy,
+ config, nameclass, lookup, lookup_context);
+ if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
+ *step = 1; /* use default */
+ else if (rc < 0)
+ return rc;
+ else
+ p += rc;
+ if (failed)
+ return VAR_ERR_UNDEFINED_VARIABLE;
+
+ if (*p != ',')
+ {
+ if (*p != config->enddelim)
+ return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
+ else
+ {
+ ++p;
+ *stop = *step;
+ *step = 1;
+ if (rc > 0)
+ *open_end = 0;
+ else
+ *open_end = 1;
+ return p - begin;
+ }
+ }
+ else
+ ++p;
+
+ /* Read stop value for the loop. */
+
+ failed = 0;
+ rc = num_exp(p, end, 0, stop, &failed, &dummy,
+ config, nameclass, lookup, lookup_context);
+ if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
+ {
+ *stop = 0; /* use default */
+ *open_end = 1;
+ }
+ else if (rc < 0)
+ return rc;
+ else
+ {
+ *open_end = 0;
+ p += rc;
+ }
+ if (failed)
+ return VAR_ERR_UNDEFINED_VARIABLE;
+
+ if (*p != config->enddelim)
+ return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
+
+ return ++p - begin;
+ }
+
static var_rc_t input(const char *begin, const char *end,
const var_config_t *config,
const char_class_t nameclass, var_cb_t lookup,
@@ -1795,13 +1895,15 @@
size_t recursion_level, int *rel_lookup_flag)
{
const char *p = begin;
- int rc;
+ int rc, rc2;
tokenbuf_t result;
+ int start, step, stop, open_end;
int i;
int output_backup;
struct wrapper_context wcon;
int my_rel_lookup_flag;
int original_rel_lookup_state;
+ int loop_limit_length;
tokenbuf_init(&result);
@@ -1813,14 +1915,23 @@
do {
if (begin != end && config->startindex && *begin == config->startindex) {
original_rel_lookup_state = *rel_lookup_flag;
+ loop_limit_length = -1;
wcon.lookup = lookup;
wcon.context = lookup_context;
wcon.rel_lookup_flag = rel_lookup_flag;
begin++;
- for (i = 0; i == 0 || *rel_lookup_flag > original_rel_lookup_state; i++) {
+ start = 0;
+ step = 1;
+ stop = 0;
+ open_end = 1;
+ re_loop:
+ for (i = start;
+ (open_end && (loop_limit_length < 0 || *rel_lookup_flag > original_rel_lookup_state)) ||
+ (!open_end && i <= stop);
+ i += step) {
*rel_lookup_flag = original_rel_lookup_state;
output_backup = output->end - output->begin;
- rc = input(begin, end, config, nameclass, &lookup_wrapper,
+ rc = input(begin, end, config, nameclass, &lookup_wrapper,
&wcon, 1, output, i, recursion_level+1, rel_lookup_flag);
if (rc < 0)
goto error_return;
@@ -1828,14 +1939,41 @@
rc = VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT;
goto error_return;
}
+ if (loop_limit_length < 0)
+ {
+ rc2 = loop_limits(begin + rc + 1, end, config, nameclass,
+ lookup, lookup_context, &start, &step,
+ &stop, &open_end);
+ if (rc2 < 0)
+ {
+ printf("loop_limits() failed: %d ('%s').\n", rc2, var_strerror(rc2));
+ goto error_return;
+ }
+ else if (rc2 == 0)
+ {
+ loop_limit_length = 0;
+ }
+ else if (rc2 > 0)
+ {
+ printf("Found loop limits: start = %d, step = %d, stop = %d, open_end = %s\n",
+ start, step, stop, (open_end) ? "true" : "false");
+ loop_limit_length = rc2;
+ output->end = output->begin + output_backup;
+ goto re_loop;
+ }
+ }
}
- output->end = output->begin + output_backup;
+ if (open_end)
+ output->end = output->begin + output_backup;
+ else
+ *rel_lookup_flag = original_rel_lookup_state;
begin += rc;
begin++;
+ begin += loop_limit_length;
continue;
}
- rc = text(begin, end, config->varinit, config->startindex,
+ rc = text(begin, end, config->varinit, config->startindex,
config->endindex, config->escape);
if (rc > 0) {
if (!tokenbuf_append(output, begin, rc)) {
@@ -1848,7 +1986,7 @@
goto error_return;
rc = variable(begin, end, config, nameclass, lookup,
- lookup_context, force_expand, &result,
+ lookup_context, force_expand, &result,
current_index, rel_lookup_flag);
if (rc > 0) {
if (!tokenbuf_append(output, result.begin, result.end - result.begin)) {
@@ -1942,4 +2080,3 @@
return rc;
}
-
|