Logo Search packages:      
Sourcecode: joe version File versions  Download package

uerror.c

/*
 *    Compiler error handler
 *    Copyright
 *          (C) 1992 Joseph H. Allen
 *
 *    This file is part of JOE (Joe's Own Editor)
 */
#include "types.h"

/* Error database */

typedef struct error ERROR;

struct error {
      LINK(ERROR) link; /* Linked list of errors */
      long line;        /* Target line number */
      long org;         /* Original target line number */
      unsigned char *file;    /* Target file name */
      long src;         /* Error-file line number */
      unsigned char *msg;     /* The message */
} errors = { { &errors, &errors} };
ERROR *errptr = &errors;      /* Current error row */

B *errbuf = NULL;       /* Buffer with error messages */

/* Function which allows stepping through all error buffers,
   for multi-file search and replace.  Give it a buffer.  It finds next
   buffer in error list.  Look at 'berror' for error information. */

/* This is made to work like bafter: it does not increment refcount of buffer */

B *beafter(B *b)
{
      struct error *e;
      unsigned char *name = b->name;
      if (!name) name = USTR "";
      for (e = errors.link.next; e != &errors; e = e->link.next)
            if (!zcmp(name, e->file))
                  break;
      if (e == &errors) {
            /* Given buffer is not in list?  Return first buffer in list. */
            e = errors.link.next;
      }
      while (e != &errors && !zcmp(name, e->file))
            e = e->link.next;
      berror = 0;
      if (e != &errors) {
            B *b = bfind(e->file);
            /* bfind bumps refcount, so we have to unbump it */
            if (b->count == 1)
                  b->orphan = 1; /* Oops */
            else
                  --b->count;
            return b;
      }
      return 0;
}

/* Insert and delete notices */

void inserr(unsigned char *name, long int where, long int n, int bol)
{
      ERROR *e;

      if (!n)
            return;

      if (name) {
            for (e = errors.link.next; e != &errors; e = e->link.next) {
                  if (!zcmp(e->file, name)) {
                        if (e->line > where)
                              e->line += n;
                        else if (e->line == where && bol)
                              e->line += n;
                  }
            }
      }
}

void delerr(unsigned char *name, long int where, long int n)
{
      ERROR *e;

      if (!n)
            return;

      if (name) {
            for (e = errors.link.next; e != &errors; e = e->link.next) {
                  if (!zcmp(e->file, name)) {
                        if (e->line > where + n)
                              e->line -= n;
                        else if (e->line > where)
                              e->line = where;
                  }
            }
      }
}

/* Abort notice */

void abrerr(unsigned char *name)
{
      ERROR *e;

      if (name)
            for (e = errors.link.next; e != &errors; e = e->link.next)
                  if (!zcmp(e->file, name))
                        e->line = e->org;
}

/* Save notice */

void saverr(unsigned char *name)
{
      ERROR *e;

      if (name)
            for (e = errors.link.next; e != &errors; e = e->link.next)
                  if (!zcmp(e->file, name))
                        e->org = e->line;
}

/* Pool of free error nodes */
ERROR errnodes = { {&errnodes, &errnodes} };

/* Free an error node */

static void freeerr(ERROR *n)
{
      vsrm(n->file);
      vsrm(n->msg);
      enquef(ERROR, link, &errnodes, n);
}

/* Free all errors */

static void freeall(void)
{
      while (!qempty(ERROR, link, &errors))
            freeerr(deque_f(ERROR, link, errors.link.next));
      errptr = &errors;
}

/* Parse error messages into database */

/* From joe's joe 2.9 */

/* First word (allowing ., /, _ and -) with a . is the file name.  Next number
   is line number.  Then there should be a ':' */

static void parseone(struct charmap *map,unsigned char *s,unsigned char **rtn_name,long *rtn_line)
{
      int x, y, flg;
      unsigned char *name = NULL;
      long line = -1;

      y=0;
      flg=0;

      do {
            /* Skip to first word */
            for (x = y; s[x] && !(joe_isalnum_(map,s[x]) || s[x] == '.' || s[x] == '/'); ++x) ;

            /* Skip to end of first word */
            for (y = x; joe_isalnum_(map,s[y]) || s[y] == '.' || s[y] == '/' || s[y]=='-'; ++y)
                  if (s[y] == '.')
                        flg = 1;
      } while (!flg && x!=y);

      /* Save file name */
      if (x != y)
            name = vsncpy(NULL, 0, s + x, y - x);

      /* Skip to first number */
      for (x = y; s[x] && (s[x] < '0' || s[x] > '9'); ++x) ;

      /* Skip to end of first number */
      for (y = x; s[y] >= '0' && s[y] <= '9'; ++y) ;

      /* Save line number */
      if (x != y)
            sscanf((char *)(s + x), "%ld", &line);
      if (line != -1)
            --line;

      /* Look for ':' */
      flg = 0;
      while (s[y]) {
      /* Allow : anywhere on line: works for MIPS C compiler */
/*
      for (y = 0; s[y];)
*/
            if (s[y]==':') {
                  flg = 1;
                  break;
            }
            ++y;
      }

      if (!flg)
            line = -1;

      *rtn_name = name;
      *rtn_line = line;
}

/* Parser for file name lists from grep, find and ls.
 *
 * filename
 * filename:*
 * filename:line-number:*
 */

void parseone_grep(struct charmap *map,unsigned char *s,unsigned char **rtn_name,long *rtn_line)
{
      int y;
      unsigned char *name = NULL;
      long line = -1;

      /* Skip to first : or end of line */
      for (y = 0;s[y] && s[y] != ':';++y);
      if (y) {
            /* This should be the file name */
            name = vsncpy(NULL,0,s,y);
            line = 0;
            if (s[y] == ':') {
                  /* Maybe there's a line number */
                  ++y;
                  while (s[y] >= '0' && s[y] <= '9')
                        line = line * 10 + (s[y++] - '0');
                  --line;
                  if (line < 0 || s[y] != ':') {
                        /* Line number is only valid if there's a second : */
                        line = 0;
                  }
            }
      }

      *rtn_name = name;
      *rtn_line = line;
}

static int parseit(struct charmap *map,unsigned char *s, long int row,
  void (*parseone)(struct charmap *map, unsigned char *s, unsigned char **rtn_name, long *rtn_line))
{
      unsigned char *name = NULL;
      long line = -1;
      ERROR *err;

      parseone(map,s,&name,&line);

      if (name) {
            if (line != -1) {
                  /* We have an error */
                  err = (ERROR *) alitem(&errnodes, sizeof(ERROR));
                  err->file = name;
                  err->org = err->line = line;
                  err->src = row;
                  err->msg = vsncpy(NULL, 0, sc("\\i"));
                  err->msg = vsncpy(sv(err->msg), sv(s));
                  enqueb(ERROR, link, &errors, err);
                  return 1;
            } else
                  vsrm(name);
      }
      return 0;
}

/* Parse the error output contained in a buffer */

static long parserr(B *b)
{
      P *p = pdup(b->bof, USTR "parserr");
      P *q = pdup(p, USTR "parserr");
      long nerrs = 0;

      freeall();
      do {
            unsigned char *s;

            pset(q, p);
            p_goto_eol(p);
            s = brvs(q, (int) (p->byte - q->byte));
            if (s) {
                  nerrs += parseit(b->o.charmap, s, q->line, (b->parseone ? b->parseone : parseone));
                  vsrm(s);
            }
      } while (pgetc(p) != NO_MORE_DATA);
      prm(p);
      prm(q);
      return nerrs;
}

BW *find_a_good_bw(B *b)
{
      W *w;
      BW *bw = 0;
      /* Find lowest window with buffer */
      if ((w = maint->topwin) != NULL) {
            do {
                  if ((w->watom->what&TYPETW) && ((BW *)w->object)->b==b && w->y>=0)
                        bw = (BW *)w->object;
                  w = w->link.next;
            } while (w != maint->topwin);
      }
      if (bw)
            return bw;
      /* Otherwise just find lowest window */
      if ((w = maint->topwin) != NULL) {
            do {
                  if ((w->watom->what&TYPETW) && w->y>=0)
                        bw = (BW *)w->object;
                  w = w->link.next;
            } while (w != maint->topwin);
      }
      return bw;
}

int parserrb(B *b)
{
      BW *bw;
      int n;
      errbuf = b;
      freeall();
      n = parserr(b);
      bw = find_a_good_bw(b);
      if (n)
            joe_snprintf_1(msgbuf, JOE_MSGBUFSIZE, joe_gettext(_("%d messages found")), n);
      else
            joe_snprintf_0(msgbuf, JOE_MSGBUFSIZE, joe_gettext(_("No messages found")));
      msgnw(bw->parent, msgbuf);
      return 0;
}

int uparserr(BW *bw)
{
      int n;
      errbuf = bw->b;
      freeall();
      n = parserr(bw->b);
      if (n)
            joe_snprintf_1(msgbuf, JOE_MSGBUFSIZE, joe_gettext(_("%d messages found")), n);
      else
            joe_snprintf_0(msgbuf, JOE_MSGBUFSIZE, joe_gettext(_("No messages found")));
      msgnw(bw->parent, msgbuf);
      return 0;
}

int jump_to_file_line(BW *bw,unsigned char *file,int line,unsigned char *msg)
{
      int omid;
      if (!bw->b->name || zcmp(file, bw->b->name)) {
            if (doswitch(bw, vsdup(file), NULL, NULL))
                  return -1;
            bw = (BW *) maint->curwin->object;
      }
      omid = mid;
      mid = 1;
      pline(bw->cursor, line);
      dofollows();
      mid = omid;
      bw->cursor->xcol = piscol(bw->cursor);
      msgnw(bw->parent, msg);
      return 0;
}

/* Show current message */

int ucurrent_msg(BW *bw)
{
      if (errptr != &errors) {
            msgnw(bw->parent, errptr->msg);
            return 0;
      } else {
            msgnw(bw->parent, joe_gettext(_("No messages")));
            return -1;
      }
}

/* Find line in error database: return pointer to message */

ERROR *srcherr(BW *bw,unsigned char *file,long line)
{
      ERROR *p;
      for (p = errors.link.next; p != &errors; p=p->link.next)
            if (!zcmp(p->file,file) && p->org == line) {
                  errptr = p;
                  setline(errbuf, errptr->src);
                  return errptr;
                  }
      return 0;
}

int ujump(BW *bw)
{
      int rtn = -1;
      P *p = pdup(bw->cursor, USTR "ujump");
      P *q = pdup(p, USTR "ujump");
      unsigned char *s;
      p_goto_bol(p);
      p_goto_eol(q);
      s = brvs(p, (int) (q->byte - p->byte));
      prm(p);
      prm(q);
      if (s) {
            unsigned char *name = NULL;
            long line = -1;
            if (bw->b->parseone)
                  bw->b->parseone(bw->b->o.charmap,s,&name,&line);
            else
                  parseone(bw->b->o.charmap,s,&name,&line);
            if (name && line != -1) {
                  ERROR *p = srcherr(bw, name, line);
                  uprevw((BASE *)bw);
                  /* Check that we made it to a tw */
                  if (p)
                        rtn = jump_to_file_line(maint->curwin->object,name,p->line,NULL /* p->msg */);
                  else
                        rtn = jump_to_file_line(maint->curwin->object,name,line,NULL);
                  vsrm(name);
            }
            vsrm(s);
      }
      return rtn;
}

int unxterr(BW *bw)
{
      if (errptr->link.next == &errors) {
            msgnw(bw->parent, joe_gettext(_("No more errors")));
            return -1;
      }
      errptr = errptr->link.next;
      setline(errbuf, errptr->src);
      return jump_to_file_line(bw,errptr->file,errptr->line,NULL /* errptr->msg */);
}

int uprverr(BW *bw)
{
      if (errptr->link.prev == &errors) {
            msgnw(bw->parent, joe_gettext(_("No more errors")));
            return -1;
      }
      errptr = errptr->link.prev;
      setline(errbuf, errptr->src);
      return jump_to_file_line(bw,errptr->file,errptr->line,NULL /* errptr->msg */);
}

Generated by  Doxygen 1.6.0   Back to index