Logo Search packages:      
Sourcecode: fhist version File versions

input.c

/*
 *    fhist - file history and comparison tools
 *    Copyright (C) 2000-2002 Peter Miller;
 *    All rights reserved.
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 *
 * MANIFEST: functions for reading input
 */

#include <ac/ctype.h>
#include <ac/string.h>

#include <fcheck.h>
#include <input/private.h>
#include <mem.h>
#include <trace.h>


#ifdef input_name
#undef input_name
#endif

const char *
input_name(input_ty *fp)
{
    const char      *result;

    trace(("input_name(fp = %8.8lX)\n{\n", (long)fp));
    result = fp->vptr->name(fp);
    trace(("return \"%s\";\n", result));
    trace(("}\n"));
    return result;
}


#ifdef input_length
#undef input_length
#endif

long
input_length(input_ty *fp)
{
    long        result;

    trace(("input_length(fp = %8.8lX)\n{\n", (long)fp));
    result = fp->vptr->length(fp);
    trace(("return %ld;\n", result));
    trace(("}\n"));
    return result;
}


#ifdef input_ftell
#undef input_ftell
#endif

long
input_ftell(input_ty *fp)
{
    long        result;

    trace(("input_ftell(fp = %8.8lX)\n{\n", (long)fp));
    result = fp->vptr->ftell(fp) - fp->pushback_len;
    trace(("return %ld;\n", result));
    trace(("}\n"));
    return result;
}


#ifdef input_read
#undef input_read
#endif

long
input_read(input_ty *fp, void *data, long len)
{
    long        result;

    trace(("input_read(fp = %8.8lX, data = %8.8lX, len = %8.8lX)\n{\n",
      (long)fp, (long)data, len));
    if (len <= 0)
    {
      result = 0;
    }
    else
    {
      if (fp->pushback_len > 0)
      {
          fp->pushback_len--;
          *(char *)data = fp->pushback_buf[fp->pushback_len];
          result = 1;
      }
      else
      {
          result = fp->vptr->read(fp, data, len);
      }
    }
    trace(("return %ld;\n", result));
    trace(("}\n"));
    return result;
}


#ifdef DEBUG

static char *
unctrl(int c)
{
    static char       buffer[10];

    if (c < 0 || c >= 256)
    {
      snprintf(buffer, sizeof(buffer), "%d", c);
      return buffer;
    }
    switch (c)
    {
    case '\'':
    case '\\':
      escape:
      buffer[0] = '\'';
      buffer[1] = '\\';
      buffer[2] = c;
      buffer[3] = '\'';
      buffer[4] = 0;
      break;

    case '\b': c = 'b'; goto escape;
    case '\f': c = 'f'; goto escape;
    case '\n': c = 'n'; goto escape;
    case '\r': c = 'r'; goto escape;
    case '\t': c = 't'; goto escape;

    default:
      if (isprint((unsigned char)c))
      {
          buffer[0] = '\'';
          buffer[1] = c;
          buffer[2] = '\'';
          buffer[3] = 0;
      }
      else
          snprintf(buffer, sizeof(buffer), "'\\%o'", c);
      break;
    }
    return buffer;
}

#endif



#ifdef input_getc
#undef input_getc
#endif

int
input_getc(input_ty *fp)
{
    int               result;

    trace(("input_getc(fp = %8.8lX)\n{\n", (long)fp));
    if (fp->pushback_len > 0)
    {
      fp->pushback_len--;
      result = fp->pushback_buf[fp->pushback_len];
    }
    else
      result = fp->vptr->get(fp);
    trace(("return %s;\n", unctrl(result)));
    trace(("}\n"));
    return result;
}


#ifdef input_ungetc
#undef input_ungetc
#endif

void
input_ungetc(input_ty *fp, int c)
{
    trace(("input_ungetc(fp = %8.8lX, c = %s)\n{\n", (long)fp, unctrl(c)));
    if (c >= 0)
    {
      if (fp->pushback_len >= fp->pushback_max)
      {
          fp->pushback_max = 16 + 2 * fp->pushback_max;
          fp->pushback_buf =
                mem_change_size(fp->pushback_buf, fp->pushback_max);
      }
      fp->pushback_buf[fp->pushback_len++] = c;
    }
    trace(("}\n"));
}


void
input_delete(input_ty *fp)
{
    trace(("input_delete(fp = %8.8lX)\n{\n", (long)fp));
    if (fp->vptr->destruct)
      fp->vptr->destruct(fp);
    if (fp->pushback_buf)
      mem_free(fp->pushback_buf);
    fp->pushback_buf = 0;
    fp->pushback_len = 0;
    fp->pushback_max = 0;
    fp->vptr = 0; /* paranoia */
    mem_free(fp);
    trace(("}\n"));
}


#include <cmalloc.h>

/*
 * Routine to read in the next line from a file, no matter how long it is.
 * This returns a pointer to the string, and also indirectly its length.
 * The string is normally returned from a static string, which is reused
 * for each call.  But if keep is non-zero, then the returned string
 * belongs to the caller and must later be freed.  The returned line
 * is ended with a newline and null character, but the returned length
 * does not count the null character.  Returns 0 on an error, with the
 * error stored in the fp structure.
 */

char *
input_readline(input_ty *fp, long *retlen, int keep, int *is_bin_file)
{
    char        *dp;    /* destination pointer */
    size_t      totallen;     /* total length of data */
    static char   *linebuffer;      /* common line buffer */
    static size_t    linelength; /* total length of line */

    trace(("input_readline(fp = %8.8lX, retlen = %8.8lX, keep = %d)\n{\n",
      (long)fp, (long)retlen, keep));
    if (linelength == 0)
    {
      /* allocate line buffer */
      linelength = 16;
      linebuffer = r_alloc_and_check(linelength + 1);
    }
    totallen = 0;
    for (;;)
    {
      int c = input_getc(fp);
      if (c < 0)
      {
          if (totallen == 0)
                  return 0;
          warning_last_line_unterminated(input_name(fp));
          c = '\n';
      }
      if (c == 0)
      {
          *is_bin_file = 1;
          c = 0x80;
      }
      if (totallen >= linelength)
      {
          /*
           * doubling gives O(1) behaviour
           * over the life of the prog
           */
          linelength = linelength * 2 + 16;
          linebuffer = r_realloc_and_check(linebuffer, linelength + 1);
      }
      linebuffer[totallen++] = c;
      if (c == '\n')
          break;
    }
    linebuffer[totallen] = 0;

    if (retlen)
          *retlen = totallen;
    if (!keep)
      dp = linebuffer;
    else
    {
      dp = cm_alloc_and_check(totallen + 1);
      memcpy(dp, linebuffer, (size_t)totallen);
    }
    trace(("return %8.8lX;\n", (long)dp));
    trace(("}\n"));
    return dp;
}


void
input_skip_lines(input_ty *fp, int numlines)
{
    while (numlines > 0)
    {
      int c = input_getc(fp);
      if (c < 0)
          break;
      if (c == '\n')
          --numlines;
    }
}

Generated by  Doxygen 1.6.0   Back to index