| /* |
| Copyright 2002-2003 John Plevyak, All Rights Reserved |
| */ |
| |
| #include "d.h" |
| |
| int |
| scan_buffer(d_loc_t *loc, D_State *parse_state, ShiftResult *results) { |
| char *s = loc->s, *scol = 0; |
| int col = loc->col, collast = col, line = loc->line; |
| int nresults = 0, i, j; |
| D_Shift **shift = NULL; |
| |
| if (parse_state->scan_kind != D_SCAN_LONGEST) { |
| /* all matches */ |
| SB_uint8 *st = (SB_uint8*)parse_state->scanner_table; |
| SB_trans_uint8 *tst = (SB_trans_uint8*)parse_state->transition_table; |
| uint8 state = 0, last = state; |
| uint8 c; |
| uint32 sb, so; |
| c = (uint8)*s++; |
| while ((state = st[state].scanner_block[(sb = (c >> SCANNER_BLOCK_SHIFT))] |
| [(so = c & SCANNER_BLOCK_MASK)])) |
| { |
| state -= 1; |
| if (st[state].shift) { |
| last = state; |
| loc->s = s; collast = col; loc->line = line; |
| shift = parse_state->accepts_diff[tst[state].scanner_block[sb][so]]; |
| for (; *shift; shift++) { |
| results[nresults].loc = *loc; |
| results[nresults++].shift = *shift; |
| } |
| } |
| if (c == '\n') { line++; col = 0; scol = s; } else col++; |
| c = (uint8)*s++; |
| } |
| loc->col = scol ? s - scol : -1; |
| shift = st[last].shift; |
| if (shift) { |
| loc->line = line; |
| for (; *shift; shift++) { |
| results[nresults].loc = *loc; |
| results[nresults++].shift = *shift; |
| } |
| } |
| if (nresults && parse_state->scan_kind == D_SCAN_MIXED) { |
| char *end = results[nresults-1].loc.s; |
| int longest = 0; |
| for (i = nresults - 1; i >= 0; i--) { |
| if (results[i].shift->shift_kind == D_SCAN_LONGEST) |
| longest = 1; |
| if (results[i].loc.s < end) |
| break; |
| } |
| if (!longest) { |
| /* only keep non-longest */ |
| for (j = i; j >= 0; j--) |
| if (results[j].shift->shift_kind != D_SCAN_LONGEST) { |
| if (i != j) |
| results[i] = results[j]; |
| i--; |
| } |
| nresults = nresults - i - 1; |
| if (i != -1) |
| memmove(&results[0], &results[i + 1], nresults * sizeof(results[0])); |
| } else { |
| /* keep only 'longest' */ |
| i = 0; |
| for (j = 0; j < nresults; j++) |
| if (results[j].loc.s == end) { |
| if (i != j) |
| results[i] = results[j]; |
| i++; |
| } |
| nresults = i; |
| } |
| } |
| return nresults; |
| } else { |
| /* longest match only */ |
| switch (parse_state->scanner_size) { |
| case 1: { |
| SB_uint8 *st = (SB_uint8*)parse_state->scanner_table; |
| uint8 state = 0, last = state; |
| uint8 c; |
| c = (uint8)*s++; |
| while ((state = st[state].scanner_block[c >> SCANNER_BLOCK_SHIFT] |
| [c & SCANNER_BLOCK_MASK])) |
| { |
| state -= 1; |
| if (st[state].shift) { |
| last = state; |
| loc->s = s; collast = col; loc->line = line; |
| } |
| if (c == '\n') { line++; col = 0; scol = s; } else col++; |
| c = (uint8)*s++; |
| } |
| shift = st[last].shift; |
| break; |
| } |
| case 2: { |
| SB_uint16 *st = (SB_uint16*)parse_state->scanner_table; |
| uint16 state = 0, last = state; |
| uint8 c; |
| c = (uint8)*s++; |
| while ((state = st[state].scanner_block[c >> SCANNER_BLOCK_SHIFT] |
| [c & SCANNER_BLOCK_MASK])) |
| { |
| state -= 1; |
| if (st[state].shift) { |
| last = state; |
| loc->s = s; collast = col; loc->line = line; |
| } |
| if (c == '\n') { line++; col = 0; scol = s; } else col++; |
| c = (uint8)*s++; |
| } |
| shift = st[last].shift; |
| break; |
| } |
| case 4: { |
| SB_uint32 *st = (SB_uint32*)parse_state->scanner_table; |
| uint32 state = 0, last = state; |
| uint8 c; |
| c = (uint8)*s++; |
| while ((state = st[state].scanner_block[c >> SCANNER_BLOCK_SHIFT] |
| [c & SCANNER_BLOCK_MASK])) |
| { |
| state -= 1; |
| if (st[state].shift) { |
| last = state; |
| loc->s = s; collast = col; loc->line = line; |
| } |
| if (c == '\n') { line++; col = 0; scol = s; } else col++; |
| c = (uint8)*s++; |
| } |
| shift = st[last].shift; |
| break; |
| } |
| } |
| loc->col = scol ? s - scol : -1; |
| if (shift) { |
| loc->line = line; |
| for (; *shift; shift++) { |
| results[nresults].loc = *loc; |
| results[nresults++].shift = *shift; |
| } |
| } |
| return nresults; |
| } |
| } |
| |