#include "info.h"
#include "search.h"
#include "nodes.h"
SEARCH_BINDING *
make_binding (buffer, start, end)
char *buffer;
long start, end;
{
SEARCH_BINDING *binding;
binding = (SEARCH_BINDING *)xmalloc (sizeof (SEARCH_BINDING));
binding->buffer = buffer;
binding->start = start;
binding->end = end;
binding->flags = 0;
return (binding);
}
SEARCH_BINDING *
copy_binding (binding)
SEARCH_BINDING *binding;
{
SEARCH_BINDING *copy;
copy = make_binding (binding->buffer, binding->start, binding->end);
copy->flags = binding->flags;
return (copy);
}
long
search (string, binding)
char *string;
SEARCH_BINDING *binding;
{
long result;
if (binding->start > binding->end)
result = search_backward (string, binding);
else
result = search_forward (string, binding);
return (result);
}
long
search_forward (string, binding)
char *string;
SEARCH_BINDING *binding;
{
register int c, i, len;
register char *buff, *end;
char *alternate = (char *)NULL;
len = strlen (string);
if (binding->flags & S_FoldCase)
{
alternate = xstrdup (string);
for (i = 0; i < len; i++)
{
if (islower (alternate[i]))
alternate[i] = toupper (alternate[i]);
else if (isupper (alternate[i]))
alternate[i] = tolower (alternate[i]);
}
}
buff = binding->buffer + binding->start;
end = binding->buffer + binding->end + 1;
while (buff < (end - len))
{
for (i = 0; i < len; i++)
{
c = buff[i];
if ((c != string[i]) && (!alternate || c != alternate[i]))
break;
}
if (!string[i])
{
if (alternate)
free (alternate);
if (binding->flags & S_SkipDest)
buff += len;
return ((long) (buff - binding->buffer));
}
buff++;
}
if (alternate)
free (alternate);
return ((long) -1);
}
long
search_backward (input_string, binding)
char *input_string;
SEARCH_BINDING *binding;
{
register int c, i, len;
register char *buff, *end;
char *string;
char *alternate = (char *)NULL;
len = strlen (input_string);
string = (char *)xmalloc (1 + len);
for (c = 0, i = len - 1; input_string[c]; c++, i--)
string[i] = input_string[c];
string[c] = '\0';
if (binding->flags & S_FoldCase)
{
alternate = xstrdup (string);
for (i = 0; i < len; i++)
{
if (islower (alternate[i]))
alternate[i] = toupper (alternate[i]);
else if (isupper (alternate[i]))
alternate[i] = tolower (alternate[i]);
}
}
buff = binding->buffer + binding->start - 1;
end = binding->buffer + binding->end;
while (buff > (end + len))
{
for (i = 0; i < len; i++)
{
c = *(buff - i);
if (c != string[i] && (alternate && c != alternate[i]))
break;
}
if (!string[i])
{
free (string);
if (alternate)
free (alternate);
if (binding->flags & S_SkipDest)
buff -= len;
return ((long) (1 + (buff - binding->buffer)));
}
buff--;
}
free (string);
if (alternate)
free (alternate);
return ((long) -1);
}
int
string_in_line (string, line)
char *string, *line;
{
register int end;
SEARCH_BINDING binding;
for (end = 0; line[end] && line[end] != '\n'; end++);
binding.buffer = line;
binding.start = 0;
binding.end = end;
binding.flags = S_FoldCase | S_SkipDest;
return (search_forward (string, &binding));
}
int
looking_at (string, binding)
char *string;
SEARCH_BINDING *binding;
{
long search_end;
search_end = search (string, binding);
return (search_end == binding->start);
}
int
skip_whitespace (string)
char *string;
{
register int i;
for (i = 0; string && whitespace (string[i]); i++);
return (i);
}
int
skip_whitespace_and_newlines (string)
char *string;
{
register int i;
for (i = 0; string && (whitespace (string[i]) || string[i] == '\n'); i++);
return (i);
}
int
skip_non_whitespace (string)
char *string;
{
register int i;
for (i = 0; string && !whitespace (string[i]); i++);
return (i);
}
int
skip_node_characters (string, newlines_okay)
char *string;
int newlines_okay;
{
register int c, i = 0;
int paren_seen = 0;
int paren = 0;
if (string && *string == '.')
return (0);
if (string && *string == '(')
{
paren++;
paren_seen++;
i++;
}
for (; string && (c = string[i]); i++)
{
if (paren)
{
if (c == '(')
paren++;
else if (c == ')')
paren--;
continue;
}
if (c == '\t' ||
c == ',' ||
c == INFO_TAGSEP ||
((!newlines_okay) && (c == '\n')) ||
((paren_seen && string[i - 1] == ')') &&
(c == ' ' || c == '.')) ||
(c == '.' &&
(
#if 0
(!string[i + 1]) ||
#endif
(whitespace_or_newline (string[i + 1])) ||
(string[i + 1] == ')'))))
break;
}
return (i);
}
long
find_node_separator (binding)
SEARCH_BINDING *binding;
{
register long i;
char *body;
body = binding->buffer;
for (i = binding->start; i < binding->end - 1; i++)
if (((body[i] == INFO_FF && body[i + 1] == INFO_COOKIE) &&
(body[i + 2] == '\n' ||
(body[i + 2] == INFO_FF && body[i + 3] == '\n'))) ||
((body[i] == INFO_COOKIE) &&
(body[i + 1] == '\n' ||
(body[i + 1] == INFO_FF && body[i + 2] == '\n'))))
return (i);
return (-1);
}
int
skip_node_separator (body)
char *body;
{
register int i;
i = 0;
if (body[i] == INFO_FF)
i++;
if (body[i++] != INFO_COOKIE)
return (0);
if (body[i] == INFO_FF)
i++;
if (body[i++] != '\n')
return (0);
return (i);
}
int
skip_line (string)
char *string;
{
register int i;
for (i = 0; string && string[i] && string[i] != '\n'; i++);
if (string[i] == '\n')
i++;
return (i);
}
long
find_tags_table (binding)
SEARCH_BINDING *binding;
{
SEARCH_BINDING search;
long position;
search.buffer = binding->buffer;
search.start = binding->start;
search.end = binding->end;
search.flags = S_FoldCase;
while ((position = find_node_separator (&search)) != -1 )
{
search.start = position;
search.start += skip_node_separator (search.buffer + search.start);
if (looking_at (TAGS_TABLE_BEG_LABEL, &search))
return (position);
}
return (-1);
}
long
find_node_in_binding (nodename, binding)
char *nodename;
SEARCH_BINDING *binding;
{
long position;
int offset, namelen;
SEARCH_BINDING search;
namelen = strlen (nodename);
search.buffer = binding->buffer;
search.start = binding->start;
search.end = binding->end;
search.flags = 0;
while ((position = find_node_separator (&search)) != -1)
{
search.start = position;
search.start += skip_node_separator (search.buffer + search.start);
offset = string_in_line (INFO_NODE_LABEL, search.buffer + search.start);
if (offset == -1)
continue;
search.start += offset;
search.start += skip_whitespace (search.buffer + search.start);
offset = skip_node_characters
(search.buffer + search.start, DONT_SKIP_NEWLINES);
if ((offset == namelen) &&
(search.buffer[search.start] == nodename[0]) &&
(strncmp (search.buffer + search.start, nodename, offset) == 0))
return (position);
}
return (-1);
}