Back to index

tetex-bin  3.0
Functions
search.c File Reference
#include "info.h"
#include "search.h"
#include "nodes.h"

Go to the source code of this file.

Functions

SEARCH_BINDINGmake_binding (char *buffer, long int start, long int end)
SEARCH_BINDINGcopy_binding (SEARCH_BINDING *binding)
long search (char *string, SEARCH_BINDING *binding)
long search_forward (char *string, SEARCH_BINDING *binding)
long search_backward (char *input_string, SEARCH_BINDING *binding)
int string_in_line (char *string, char *line)
int looking_at (char *string, SEARCH_BINDING *binding)
int skip_whitespace (char *string)
int skip_whitespace_and_newlines (char *string)
int skip_non_whitespace (char *string)
int skip_node_characters (char *string, int newlines_okay)
long find_node_separator (SEARCH_BINDING *binding)
int skip_node_separator (char *body)
int skip_line (char *string)
long find_tags_table (SEARCH_BINDING *binding)
long find_node_in_binding (char *nodename, SEARCH_BINDING *binding)

Function Documentation

Definition at line 54 of file search.c.

{
  SEARCH_BINDING *copy;

  copy = make_binding (binding->buffer, binding->start, binding->end);
  copy->flags = binding->flags;
  return (copy);
}

Here is the call graph for this function:

Here is the caller graph for this function:

long find_node_in_binding ( char *  nodename,
SEARCH_BINDING binding 
)

Definition at line 459 of file search.c.

{
  long position;
  int offset, namelen;
  SEARCH_BINDING tmp_search;

  namelen = strlen (nodename);

  tmp_search.buffer = binding->buffer;
  tmp_search.start = binding->start;
  tmp_search.end = binding->end;
  tmp_search.flags = 0;

  while ((position = find_node_separator (&tmp_search)) != -1)
    {
      tmp_search.start = position;
      tmp_search.start += skip_node_separator
        (tmp_search.buffer + tmp_search.start);

      offset = string_in_line
        (INFO_NODE_LABEL, tmp_search.buffer + tmp_search.start);

      if (offset == -1)
        continue;

      tmp_search.start += offset;
      tmp_search.start += skip_whitespace (tmp_search.buffer + tmp_search.start);
      offset = skip_node_characters
        (tmp_search.buffer + tmp_search.start, DONT_SKIP_NEWLINES);

      /* Notice that this is an exact match.  You cannot grovel through
         the buffer with this function looking for random nodes. */
       if ((offset == namelen) &&
           (tmp_search.buffer[tmp_search.start] == nodename[0]) &&
           (strncmp (tmp_search.buffer + tmp_search.start, nodename, offset) == 0))
         return (position);
    }
  return (-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

long find_node_separator ( SEARCH_BINDING binding)

Definition at line 367 of file search.c.

{
  register long i;
  char *body;

  body = binding->buffer;

  /* A node is started by [^L]^_[^L]\n.  That is to say, the C-l's are
     optional, but the DELETE and NEWLINE are not.  This separator holds
     true for all separated elements in an Info file, including the tags
     table (if present) and the indirect tags table (if present). */
  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);
}

Here is the caller graph for this function:

long find_tags_table ( SEARCH_BINDING binding)

Definition at line 431 of file search.c.

{
  SEARCH_BINDING tmp_search;
  long position;

  tmp_search.buffer = binding->buffer;
  tmp_search.start = binding->start;
  tmp_search.end = binding->end;
  tmp_search.flags = S_FoldCase;

  while ((position = find_node_separator (&tmp_search)) != -1 )
    {
      tmp_search.start = position;
      tmp_search.start += skip_node_separator (tmp_search.buffer
          + tmp_search.start);

      if (looking_at (TAGS_TABLE_BEG_LABEL, &tmp_search))
        return (position);
    }
  return (-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int looking_at ( char *  string,
SEARCH_BINDING binding 
)

Definition at line 238 of file search.c.

{
  long search_end;

  search_end = search (string, binding);

  /* If the string was not found, SEARCH_END is -1.  If the string was found,
     but not right away, SEARCH_END is != binding->start.  Otherwise, the
     string was found at binding->start. */
  return (search_end == binding->start);
}

Here is the caller graph for this function:

SEARCH_BINDING* make_binding ( char *  buffer,
long int  start,
long int  end 
)

Definition at line 39 of file search.c.

{
  SEARCH_BINDING *binding;

  binding = (SEARCH_BINDING *)xmalloc (sizeof (SEARCH_BINDING));
  binding->buffer = buffer;
  binding->start = start;
  binding->end = end;
  binding->flags = 0;

  return (binding);
}

Here is the call graph for this function:

Here is the caller graph for this function:

long search ( char *  string,
SEARCH_BINDING binding 
)

Definition at line 73 of file search.c.

{
  long result;

  /* If the search is backwards, then search backwards, otherwise forwards. */
  if (binding->start > binding->end)
    result = search_backward (string, binding);
  else
    result = search_forward (string, binding);

  return (result);
}

Here is the call graph for this function:

long search_backward ( char *  input_string,
SEARCH_BINDING binding 
)

Definition at line 147 of file search.c.

{
  register int c, i, len;
  register char *buff, *end;
  char *string;
  char *alternate = (char *)NULL;

  len = strlen (input_string);

  /* Reverse the characters in the search 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';

  /* We match characters in the search buffer against STRING and ALTERNATE.
     ALTERNATE is a case reversed version of STRING; this is cheaper than
     case folding each character before comparison.   ALTERNATE is only
     used if the case folding bit is turned on in the passed BINDING. */

  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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

long search_forward ( char *  string,
SEARCH_BINDING binding 
)

Definition at line 88 of file search.c.

{
  register int c, i, len;
  register char *buff, *end;
  char *alternate = (char *)NULL;

  len = strlen (string);

  /* We match characters in the search buffer against STRING and ALTERNATE.
     ALTERNATE is a case reversed version of STRING; this is cheaper than
     case folding each character before comparison.   Alternate is only
     used if the case folding bit is turned on in the passed BINDING. */

  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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int skip_line ( char *  string)

Definition at line 416 of file search.c.

{
  register int i;

  for (i = 0; string && string[i] && string[i] != '\n'; i++);

  if (string[i] == '\n')
    i++;

  return (i);
}
int skip_node_characters ( char *  string,
int  newlines_okay 
)

Definition at line 301 of file search.c.

{
  register int c, i = 0;
  int paren_seen = 0;
  int paren = 0;

  /* Handle special case.  This is when another function has parsed out the
     filename component of the node name, and we just want to parse out the
     nodename proper.  In that case, a period at the start of the nodename
     indicates an empty nodename. */
  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 the character following the close paren is a space or period,
         then this node name has no more characters associated with it. */
      if (c == '\t' ||
          c == ','  ||
          c == INFO_TAGSEP ||
          ((!newlines_okay) && (c == '\n')) ||
          ((paren_seen && string[i - 1] == ')') &&
           (c == ' ' || c == '.')) ||
          (c == '.' &&
           (
#if 0
/* This test causes a node name ending in a period, like `This.', not to
   be found.  The trailing . is stripped.  This occurs in the jargon
   file (`I see no X here.' is a node name).  */
           (!string[i + 1]) ||
#endif
            (whitespace_or_newline (string[i + 1])) ||
            (string[i + 1] == ')'))))
        break;
    }
  return (i);
}

Here is the caller graph for this function:

int skip_node_separator ( char *  body)

Definition at line 392 of file search.c.

{
  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);
}

Here is the caller graph for this function:

int skip_non_whitespace ( char *  string)

Definition at line 285 of file search.c.

{
  register int i;

  for (i = 0; string && string[i] && !whitespace (string[i]); i++);
  return (i);
}
int skip_whitespace ( char *  string)

Definition at line 264 of file search.c.

{
  register int i;

  for (i = 0; string && whitespace (string[i]); i++);
  return (i);
}

Here is the caller graph for this function:

int skip_whitespace_and_newlines ( char *  string)

Definition at line 275 of file search.c.

{
  register int i;

  for (i = 0; string && whitespace_or_newline (string[i]); i++);
  return (i);
}

Here is the caller graph for this function:

int string_in_line ( char *  string,
char *  line 
)

Definition at line 219 of file search.c.

{
  register int end;
  SEARCH_BINDING binding;

  /* Find the end of the line. */
  for (end = 0; line[end] && line[end] != '\n'; end++);

  /* Search for STRING within these confines. */
  binding.buffer = line;
  binding.start = 0;
  binding.end = end;
  binding.flags = S_FoldCase | S_SkipDest;

  return (search_forward (string, &binding));
}

Here is the call graph for this function:

Here is the caller graph for this function: