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

genlist.c

/* genlist.c - generate listing and error reports for assembler */

#include "syshead.h"
#include "const.h"
#include "type.h"
#include "address.h"
#include "flag.h"
#include "file.h"
#include "globvar.h"
#include "macro.h"
#include "scan.h"
#include "source.h"

#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1)
                        /* length of formatted code listing */
#define MAXERR 6        /* maximum errors listed per line */

struct error_s                /* to record error info */
{
    char * err_str;
    unsigned char position;
};

/* code listing format */

struct code_listing_s
{
    union linum_macro_u
    {
      char linum[LINUM_LEN];
      struct
      {
          char pad[1];
          char mark[1];
          char level[1];
      }
       macro;
    }
     linum_or_macro;
    char padlinum[1];
    char lc[4];
    char padlc[1];
#ifdef I80386
    char lprefix[2];
    char aprefix[2];
    char oprefix[2];
    char sprefix[2];
#endif
    char page[2];
    char opcode[2];
    char postb[2];
#ifdef I80386
    char sib[2];
#endif
    char padopcode[1];
#if SIZEOF_OFFSET_T > 2
    char displ4[2];
    char displ3[2];
#endif
    char displ2[2];
    char displ1[2];
    char reldispl[1];
    char paddispl[1];
#ifdef I80386
    char imm4[2];
    char imm3[2];
    char imm2[2];
    char imm1[2];
    char relimm[1];
    char padimm[1];
#endif
    char nullterm;
};

PRIVATE struct error_s errbuf[MAXERR];    /* error buffer */
PRIVATE unsigned char errcount;     /* # errors in line */
PRIVATE bool_t erroverflow;   /* set if too many errors on line */

FORWARD char *build_1hex_number P((opcode_pt num, char *where));
FORWARD void list1 P((fd_t fd));
FORWARD void listcode P((void));
FORWARD void listerrors P((void));
FORWARD void paderrorline P((unsigned nspaces));

/* format 1 byte number as 2 hex digits, return ptr to end */

PRIVATE char *build_1hex_number(num, where)
opcode_pt num;
register char *where;
{
    where[0] = hexdigit[((unsigned) num % 256) / 16];
    where[1] = hexdigit[(unsigned) num % 16];
    return where + 2;
}

/* format 2 byte number as 4 hex digits, return ptr to end */

PUBLIC char *build_2hex_number(num, where)
unsigned num;
char *where;
{
    return build_1hex_number((opcode_pt) num,
                       build_1hex_number((opcode_pt) (num / 256), where));
}

/* format 2 byte number as decimal with given width (pad with leading '0's) */
/* return ptr to end */

PUBLIC char *build_number(num, width, where)
unsigned num;
unsigned width;
register char *where;
{
    static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,};
    unsigned char digit;
    unsigned char power;
    register unsigned power_of_10;

    power = 5;                /* actually 1 more than power */
    do
    {
      for (digit = '0', power_of_10 = (powers_of_10 - 1)[power];
           num >= power_of_10; num -= power_of_10)
          ++digit;
      if (power <= width)
          *where++ = digit;
    }
    while (--power != 0);
    return where;
}

/* record number and position of error (or error buffer overflow) */

PUBLIC void warning(err_str)
char * err_str;
{
    if (!as_warn.current) return;
    ++totwarn;
    --toterr;
    error(err_str);
}

PUBLIC void error(err_str)
char * err_str;
{
    register struct error_s *errptr;
    register struct error_s *errptrlow;
    unsigned char position;

    if (errcount >= MAXERR)
      erroverflow = TRUE;
    else
    {
      position = symname - linebuf;
      for (errptr = errbuf + errcount;
           errptr > errbuf && errptr->position > position;
           errptr = errptrlow)
      {
          errptrlow = errptr - 1;
          errptr->err_str = errptrlow->err_str;
          errptr->position = errptrlow->position;
      }
      errptr->err_str = err_str;
      errptr->position = position;
      ++errcount;
      ++toterr;
    }
}

/* list 1 line to list file if any errors or flags permit */
/* list line to console as well if any errors and list file is not console */

PUBLIC void listline()
{
    if (!listpre && lineptr != 0)
    {
      if (errcount || (list.current && (!macflag || mcount != 0)) ||
          (macflag && maclist.current) || list_force )
          list1(lstfil);
      if (errcount)
      {
          if (lstfil != STDOUT)
            list1(STDOUT);
          errcount = 0;
          erroverflow = FALSE;
      }
    }
}

/* list 1 line unconditionally */

PRIVATE void list1(fd)
fd_t fd;
{
    outfd = fd;
    listcode();
    write(outfd, linebuf, (unsigned) (lineptr - linebuf));
    writenl();
    if (errcount != 0)
      listerrors();
    listpre = TRUE;
    list_force=FALSE;
}

/* list object code for 1 line */

PRIVATE void listcode()
{
    unsigned char count;
    struct code_listing_s *listptr;
    unsigned numlength;
    char *numptr;

    listptr = (struct code_listing_s *) temp_buf();
    memset((char *) listptr, ' ', sizeof *listptr);
    listptr->nullterm = 0;
    if (macflag)
    {
      listptr->linum_or_macro.macro.mark[0] = '+';
      listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1);
    }
    else
    {
      numlength = LINUM_LEN;
      numptr = listptr->linum_or_macro.linum;
      if (infiln != infil0)
      {
          *numptr++ = infiln - infil0 + ('a' - 1);
          numlength = LINUM_LEN - 1;
      }
      build_number(linum, numlength, numptr);
    }
    if ((count = mcount) != 0 || popflags & POPLC)
      build_2hex_number((u16_T) lc, listptr->lc);
    if (popflags & POPLO)
    {
#if SIZEOF_OFFSET_T > 2
      if (popflags & POPLONG)
          build_2hex_number((u16_T) (lastexp.offset / (offset_t) 0x10000L),
                        listptr->displ4);
#endif
      if (popflags & POPHI)
          build_2hex_number((u16_T) lastexp.offset, listptr->displ2);
      else
          build_1hex_number((opcode_pt) /* XXX */(u16_T) lastexp.offset, listptr->displ1);
      if (lastexp.data & RELBIT)
          listptr->reldispl[0] = '>';
    }
    else if (count != 0)
    {
#ifdef I80386
      if (aprefix != 0)
      {
          --count;
          build_1hex_number(aprefix, listptr->aprefix);
      }
      if (oprefix != 0)
      {
          --count;
          build_1hex_number(oprefix, listptr->oprefix);
      }
      if (sprefix != 0)
      {
          --count;
          build_1hex_number(sprefix, listptr->sprefix);
      }
#endif
      if (page != 0)
      {
          build_1hex_number(page, listptr->page);
          --count;
      }
      build_1hex_number(opcode, listptr->opcode);
      --count;
      if (postb != 0)
      {
          --count;
          build_1hex_number(postb,
#ifdef MC6809
                        count == 0 ? listptr->displ1 :
#endif
                        listptr->postb);
      }
#ifdef I80386
      if (sib != NO_SIB)
      {
          --count;
          build_1hex_number(sib, listptr->sib);
      }
#endif
      if (count > 0)
      {
          build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1);
          if (lastexp.data & RELBIT)
            listptr->reldispl[0] = '>';
      }
      if (count > 1)
          build_1hex_number((opcode_pt) (lastexp.offset >> 0x8),
                        listptr->displ2);
#if SIZEOF_OFFSET_T > 2
      if (count > 2)
      {
          build_1hex_number((opcode_pt) (lastexp.offset >> 0x10),
                        listptr->displ3);
          build_1hex_number((opcode_pt) (lastexp.offset >> 0x18),
                        listptr->displ4);
      }
#endif
#ifdef I80386
      if (immcount > 0)
      {
          build_1hex_number((opcode_pt) immadr.offset, listptr->imm1);
          if (immadr.data & RELBIT)
            listptr->relimm[0] = '>';
      }
      if (immcount > 1)
          build_1hex_number((opcode_pt) (immadr.offset >> 0x8),
                        listptr->imm2);
      if (immcount > 2)
      {
          build_1hex_number((opcode_pt) (immadr.offset >> 0x10),
                        listptr->imm3);
          build_1hex_number((opcode_pt) (immadr.offset >> 0x18),
                        listptr->imm4);
      }
#endif
    }
    writes((char *) listptr);
}

/* list errors, assuming some */

PRIVATE void listerrors()
{
    unsigned char column;
    unsigned char errcol;     /* column # in error line */
    unsigned char errcolw;    /* working column in error line */
    char *errmsg;
    struct error_s *errptr;
    char *linep;
    unsigned char remaining;

#ifdef I80386
    paderrorline(1);
#else
    paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
#endif
    remaining = errcount;
    column = 0;               /* column to match with error column */
    errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */
    errptr = errbuf;
    linep = linebuf;
    do
    {
#ifdef I80386
        if(errcol != CODE_LIST_LENGTH)
      {
          writenl(); paderrorline(1);
      }
      writes(errmsg = errptr->err_str);
      errcol = strlen(errmsg)+LINUM_LEN+1;
      column = 0; linep = linebuf;
        errcolw = CODE_LIST_LENGTH;
      while (errcolw > errcol)
      {
          writec('.');
          ++errcol;
      }
#endif
      while (errptr && errptr->position < 132 && column < errptr->position)
      {
          ++column;
          if (*linep++ == '\t')     /* next tab (standard tabs only) */
            errcolw = (errcolw + 8) & 0xf8;
          else
            ++errcolw;
          while (errcolw > errcol)
          {
#ifdef I80386
              writec('.');
#else
            writec(' ');
#endif
            ++errcol;
          }
      }
#ifdef I80386
      writec('^'); ++errcol;
#else
      if (errcolw < errcol)   /* position under error on new line */
      {
          writenl();
          paderrorline((unsigned) errcolw - LINUM_LEN);
      }
      writec('^');
      writes(errmsg = errptr->err_str);
      errcol += strlen(errmsg);
#endif
      ++errptr;
    }
    while (--remaining != 0);
    writenl();
    if (erroverflow)
    {
#ifdef I80386
      paderrorline(1);
#else
      paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
#endif
      writesn(FURTHER);
    }
}

/* pad out error line to begin under 1st char of source listing */

PRIVATE void paderrorline(nspaces)
unsigned nspaces;
{
    int nstars = LINUM_LEN;

    while (nstars-- != 0)
      writec('*');            /* stars under line number */
    while (nspaces-- != 0)
      writec(' ');            /* spaces out to error position */
}

/* write 1 character */

PUBLIC void writec(ch)
char ch;
{
    write(outfd, &ch, 1);
}

/* write newline */

PUBLIC void writenl()
{
    writes(SOS_EOLSTR);
}

/* write 1 offset_t, order to suit target */

PUBLIC void writeoff(offset)
offset_t offset;
{
    char buf[sizeof offset];

#if SIZEOF_OFFSET_T > 2
    u4c4(buf, offset);
#else
    u2c2(buf, offset);
#endif
    write(outfd, buf, sizeof buf);
}

/* write string */

PUBLIC void writes(s)
char *s;
{
    write(outfd, s, strlen(s));
}

/* write string followed by newline */

PUBLIC void writesn(s)
char *s;
{
    writes(s);
    writenl();
}

/* write 1 word, order to suit target */

PUBLIC void writew(word)
unsigned word;
{
    char buf[2];

    u2c2(buf, (u16_T) word);
    write(outfd, buf, sizeof buf);
}

Generated by  Doxygen 1.6.0   Back to index