Logo Search packages:      
Sourcecode: vile version File versions

builtflt.c

/*
 * Main program and I/O for external vile syntax/highlighter programs
 *
 * $Header: /usr/build/vile/vile/RCS/builtflt.c,v 1.30 2003/05/24 00:49:25 tom Exp $
 *
 */

#include "estruct.h"
#include "builtflt.h"

#ifdef _builtflt_h

#include "edef.h"
#include "nevars.h"
#include <stdarg.h>

static FILTER_DEF *current_filter;
static MARK mark_in;
static MARK mark_out;
static TBUFF *gets_data;
static const char *current_params;
static int need_separator;

/******************************************************************************
 * Private functions                                                          *
 ******************************************************************************/

#if OPT_MAJORMODE
/*
 * Given the 'major_name', verify that it applies to this buffer, and if so,
 * lookup $filtername and see if we can associate the external filtername to
 * one of the built-in filters.
 *
 * FIXME:  This only works for filters constructed with the naming convention
 * that we use for our external filters, i.e., "vile-{majormode}-filt".
 *
 * FIXME:  Should we allow lookup of majormodes that aren't assigned to a
 * buffer?
 */
static int
parse_filtername(const char *major_name, const char **params)
{
    static const char prefix[] = "vile-";
    static const char suffix[] = "-filt";

    char *temp;

    *params = 0;

    if (curbp != 0
      && curbp->majr != 0
      && !strcmp(curbp->majr->name, major_name)
      && (temp = b_val_ptr(curbp, VAL_FILTERNAME)) != 0) {
      if (!strncmp(temp, prefix, sizeof(prefix) - 1)) {
          char *base = temp + sizeof(prefix) - 1;
          char *next = base;
          int n;

          while (*next) {
            if (!strncmp(next, suffix, sizeof(suffix) - 1)
                && (isSpace(next[sizeof(suffix) - 1])
                  || (next[sizeof(suffix) - 1] == EOS))) {
                size_t len = next - base;
                for (n = 0; builtflt[n] != 0; n++) {
                  char *name = builtflt[n]->filter_name;
                  if (strlen(name) == len
                      && !strncmp(base, name, len)) {
                      *params = skip_cblanks(next + sizeof(suffix) - 1);
                      return n;
                  }
                }
                break;
            }
            next++;
          }
      }
    }
    return -1;
}
#endif

static char *
param_value(const char **ptr)
{
    char *value = 0;
    const char *s;
    const char *t;

    s = skip_cblanks(*ptr + 1);
    t = skip_ctext(s);
    if (t != s) {
      value = strmalloc(s);
      value[t - s] = EOS;
      *ptr = t;
    }
    return value;
}

/*
 * All we're really interested in are the -k and -t options.  Ignore -v and -q.
 */
static int
process_params(void)
{
    const char *s = current_params;
    char *value;

    memset(flt_options, 0, sizeof(flt_options));
    FltOptions('t') = tabstop_val(curbp);
    while (*s != EOS) {
      s = skip_cblanks(s);
      if (*s == '-') {
          while (*s != EOS && *++s != EOS && !isSpace(*s)) {
            flt_options[CharOf(*s)] += 1;
            switch (*s) {
            case 'k':
                if ((value = param_value(&s)) != 0) {
                  flt_read_keywords(value);
                  free(value);
                }
                break;
            case 't':
                if ((value = param_value(&s)) != 0) {
                  if ((FltOptions('t') = atoi(value)) <= 0)
                      FltOptions('t') = 8;
                  free(value);
                }
                break;
            }
          }
      } else {
          s = skip_ctext(s);
      }
    }
    vile_keywords = !FltOptions('k');
    return !vile_keywords;
}

static void
save_mark(int first)
{
    if (mark_out.o > llength(mark_out.l))
      mark_out.o = llength(mark_out.l);
    if (first)
      DOT = mark_out;
    else
      MK = mark_out;
}

/******************************************************************************
 * Public functions                                                           *
 ******************************************************************************/

/*
 * Trim newline from the string, returning true if it was found.
 */
int
chop_newline(char *s)
{
    size_t len = strlen(s);

    if (len != 0 && s[len - 1] == '\n') {
      s[--len] = '\0';
      return 1;
    }
    return 0;
}

void
flt_echo(const char *string, int length)
{
    while (length-- > 0)
      flt_putc(*string++);
}

void
flt_failed(const char *msg)
{
    mlforce("[Filter: %s]", msg);
}

void
flt_finish(void)
{
    tb_free(&gets_data);
}

char *
flt_gets(char **ptr, unsigned *len)
{
    int need = is_header_line(mark_in, curbp) ? -1 : llength(mark_in.l);

    *len = 0;
    *ptr = 0;

    if (need >= 0
      && tb_init(&gets_data, 0) != 0
      && tb_bappend(&gets_data, mark_in.l->l_text, need) != 0
      && tb_sappend(&gets_data, "\n") != 0
      && tb_append(&gets_data, EOS) != 0) {
      *ptr = tb_values(gets_data);
      *len = need + len_record_sep(curbp);

      TRACE(("flt_gets %6d:%.*s\n",
             line_no(curbp, mark_in.l),
             *ptr ? need : 1,
             *ptr ? *ptr : ""));

      mark_in.l = lforw(mark_in.l);
    } else {
      TRACE(("flt_gets - EOF\n"));
    }
    return *ptr;
}

/*
 * This function is used from flex to read chunks from the input file.  We'll
 * make it simple by ending each read at the end of a line; some long lines
 * will be split across successive reads.
 */
int
flt_input(char *buffer, int max_size)
{
    char *separator = "\n";
    int need = strlen(separator);
    int used = 0;

    if (need_separator) {
      strcpy(buffer, separator);
      used = need;
      need_separator = FALSE;
    }
    if (!is_header_line(mark_in, curbp)) {
      while (used < max_size) {
          if (mark_in.o < llength(mark_in.l)) {
            buffer[used++] = (char) lgetc(mark_in.l, mark_in.o++);
          } else {
            mark_in.l = lforw(mark_in.l);
            mark_in.o = w_left_margin(curwp);
            need_separator = TRUE;
            break;
          }
      }
      if (need_separator && (used + need) < max_size) {
          strcpy(buffer + used, separator);
          used += need;
          need_separator = FALSE;
      }
    }
    return used;
}

const char *
flt_name(void)
{
    return current_filter ? current_filter->filter_name : "";
}

char *
flt_put_blanks(char *string)
{
    char *result = skip_blanks(string);
    if (result != string)
      flt_puts(string, result - string, "");
    return result;
}

void
flt_putc(int ch)
{
    if (ch == '\n') {
      if (mark_out.l != buf_head(curbp))
          mark_out.l = lforw(mark_out.l);
      mark_out.o = w_left_margin(curwp);
    } else {
      mark_out.o++;
    }
}

void
flt_puts(const char *string, int length, const char *marker)
{
    char bfr1[NSTRING];
    char bfr2[NSTRING];
    char *last;
    int count;

    if (length > 0) {
      save_mark(TRUE);
      if (marker != 0 && *marker != 0 && *marker != 'N') {
          vl_strncpy(bfr2, marker, sizeof(bfr1) - 10);
          last = lsprintf(bfr1, "%c%d%s:", CTL_A, length, bfr2);
          decode_attribute(bfr1, last - bfr1, 0, &count);
      }
      flt_echo(string, length);
      save_mark(FALSE);
      if (apply_attribute()) {
          REGIONSHAPE save_shape = regionshape;
          regionshape = EXACT;
          (void) attributeregion();
          videoattribute = 0;
          regionshape = save_shape;
      }
    }
}

/*
 * For the given majormode 'name', check if we have a builtin filter by that
 * name, or if it has an associated filtername, check if that is a builtin.
 *
 * Sets current_filter and current_params as a side-effect.
 */
int
flt_lookup(char *name)
{
    int n;

    TRACE(("flt_lookup(%s)\n", name));
    for (n = 0; builtflt[n] != 0; n++) {
      if (!strcmp(name, builtflt[n]->filter_name)) {
          current_filter = builtflt[n];
          current_params = "";
          TRACE(("...%s\n", builtflt[n]->filter_name));
          return TRUE;
      }
    }
#if OPT_MAJORMODE
    if ((n = parse_filtername(name, &current_params)) >= 0) {
      TRACE(("...%s(%s)\n", builtflt[n]->filter_name, current_params));
      current_filter = builtflt[n];
      return TRUE;
    }
#endif
    TRACE(("...not found\n"));
    return FALSE;
}

int
flt_start(char *name)
{
    TRACE(("flt_start(%s)\n", name));
    if (flt_lookup(name)) {
      MARK save_dot;
      MARK save_mk;

      save_dot = DOT;
      save_mk = MK;

      need_separator = FALSE;
      mark_in.l = lforw(buf_head(curbp));
      mark_in.o = w_left_margin(curwp);
      mark_out = mark_in;
      tb_init(&gets_data, 0);

      flt_initialize();
      flt_make_symtab(current_filter->filter_name);

      current_filter->InitFilter(1);

      flt_read_keywords(MY_NAME);
      if (!process_params()) {
          if (strcmp(MY_NAME, current_filter->filter_name)) {
            flt_read_keywords(current_filter->filter_name);
          }
      }
      set_symbol_table(current_filter->filter_name);
      current_filter->InitFilter(0);
      current_filter->DoFilter(stdin);

      DOT = save_dot;
      MK = save_mk;

      return TRUE;
    }
    return FALSE;
}

static TBUFF *filter_list;

int
var_FILTER_LIST(TBUFF ** rp, const char *vp)
{
    int n;

    if (rp) {
      if (filter_list == 0) {
          for (n = 0; builtflt[n] != 0; n++) {
            if (n)
                tb_sappend0(&filter_list, " ");
            tb_sappend0(&filter_list, builtflt[n]->filter_name);
          }
      }
      tb_scopy(rp, tb_values(filter_list));
      return TRUE;
    } else if (vp) {
      return ABORT;           /* read-only */
    } else {
      return FALSE;
    }
}

#if NO_LEAKS
void
flt_leaks(void)
{
    flt_free_symtab();
    FreeIfNeeded(default_attr);
    tb_free(&filter_list);
}
#endif

#else

extern void builtflt(void);
void
builtflt(void)
{
}

#endif /* _builtflt_h */

Generated by  Doxygen 1.6.0   Back to index