+static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd);
+
+static int sp_range(struct source_parser *sp, data1_node *n, RecWord *wrd)
+{
+ int start, len;
+ RecWord tmp_w;
+
+ /* ( */
+ sp_lex(sp);
+ if (sp->lookahead != '(')
+ return 0;
+ sp_lex(sp); /* skip ( */
+
+ /* 1st arg: string */
+ if (!sp_expr(sp, n, wrd))
+ return 0;
+
+ if (sp->lookahead != ',')
+ return 0;
+ sp_lex(sp); /* skip , */
+
+ /* 2nd arg: start */
+ if (!sp_expr(sp, n, &tmp_w))
+ return 0;
+ start = atoi_n(tmp_w.string, tmp_w.length);
+
+ if (sp->lookahead == ',')
+ {
+ sp_lex(sp); /* skip , */
+
+ /* 3rd arg: length */
+ if (!sp_expr(sp, n, &tmp_w))
+ return 0;
+ len = atoi_n(tmp_w.string, tmp_w.length);
+ }
+ else
+ len = wrd->length;
+
+ /* ) */
+ if (sp->lookahead != ')')
+ return 0;
+ sp_lex(sp);
+
+ if (wrd->string && wrd->length)
+ {
+ wrd->string += start;
+ wrd->length -= start;
+ if (wrd->length > len)
+ wrd->length = len;
+ }
+ return 1;
+}
+
+static int sp_first(struct source_parser *sp, data1_node *n, RecWord *wrd)
+{
+ char num_str[20];
+ int min_pos = -1;
+ sp_lex(sp);
+ if (sp->lookahead != '(')
+ return 0;
+ sp_lex(sp); /* skip ( */
+ if (!sp_expr(sp, n, wrd))
+ return 0;
+ while (sp->lookahead == ',')
+ {
+ RecWord search_w;
+ int i;
+ sp_lex(sp); /* skip , */
+
+ if (!sp_expr(sp, n, &search_w))
+ return 0;
+ for (i = 0; i<wrd->length; i++)
+ {
+ int j;
+ for (j = 0; j<search_w.length && i+j < wrd->length; j++)
+ if (wrd->string[i+j] != search_w.string[j])
+ break;
+ if (j == search_w.length) /* match ? */
+ {
+ if (min_pos == -1 || i < min_pos)
+ min_pos = i;
+ break;
+ }
+ }
+ }
+ if (sp->lookahead != ')')
+ return 0;
+ sp_lex(sp);
+ if (min_pos == -1)
+ min_pos = 0; /* the default if not found */
+ sprintf(num_str, "%d", min_pos);
+ wrd->string = nmem_strdup(sp->nmem, num_str);
+ wrd->length = strlen(wrd->string);
+ return 1;
+}