Logo Search packages:      
Sourcecode: m68k-vme-tftplilo version File versions  Download package

misc.c

/*
 *  VME Linux/m68k TFTP Loader
 *
 *  (c) Copyright 1998 by Nick Holgate
 *
 *  This file is subject to the terms and conditions of the GNU General
 *  Public License.  See the file COPYING for more details.
 */

/*--------------------------------------------------------------------------*/

#include "defs.h"

/*--------------------------------------------------------------------------*/

void
mem_clear
(     void              *mem,
      unsigned long     count
)
{
      unsigned long     a = (unsigned long) mem;

      while ((a & 3) && count)
      {
            *(char *)a = 0;
            a++;
            count--;
      }
      while (count > 3)
      {
            *(long *)a = 0;
            a     += 4;
            count -= 4;
      }
      while (count)
      {
            *(char *)a = 0;
            a++;
            count--;
      }
}

/*--------------------------------------------------------------------------*/

void
mem_move
(     void              *dest,
      const void        *srce,
      unsigned long     count
)
{
      char              *d = dest;
      const char        *s = srce;

      if (d > s)
      {
            d += count;
            s += count;
            while (count--)
            {
                  *--d = *--s;
            }
      }
      else
      {
            while (count--)
            {
                  *d++ = *s++;
            }
      }
}

/*--------------------------------------------------------------------------*/

void *
memcpy
(     void              *dest,
      const void        *srce,
      unsigned long     count
)
{
      mem_move(dest, srce, count);

      return dest;
}

/*--------------------------------------------------------------------------*/

int
mem_cmp
(     void              *mem1,
      void              *mem2,
      unsigned long     count
)
{     unsigned char     c   = 0;
      unsigned char     *p1 = (unsigned char *) mem1;
      unsigned char     *p2 = (unsigned char *) mem2;

      while (c == 0 && count--)
            c = *p1++ - *p2++;

      return (int) c;
}

/*--------------------------------------------------------------------------*/

typedef struct memfrag_str
{
      unsigned long           size;             /* size of free block including header  */
      struct memfrag_str      *next;            /* pointer to next memory fragment        */

} memfrag_t;

/*--------------------------------------------------------------------------*/

static memfrag_t  *free_list = NULL;      /* ptr to first free mem frag       */

/*--------------------------------------------------------------------------*/
/* initialise memory allocator
 */

void
malloc_init
(     void              *heap_base,
      unsigned long     heap_size
)
{
      if (free_list == NULL)
      {
            free_list       = heap_base;
            free_list->size = heap_size;
            free_list->next = NULL;
      }
}

/*--------------------------------------------------------------------------*/

int
free
(     void        *memaddr
)
{     memfrag_t   *last;
      memfrag_t   *frag;
      memfrag_t   *dead;

      if (memaddr == NULL)
      {
            return FAILURE;
      }

      /* recover pointer to base of allocation */
      dead = (memfrag_t *) ((char *)memaddr - sizeof(frag->size));

      frag = free_list;
      last = NULL;

      /* find fragment that will follow us */
      while (frag && (frag < dead))
      {
            last = frag;
            frag = frag->next;
      }

      /* make sure it doesn't overlap previous fragment */
      if (last)
      {
            if ((char *)dead < ((char *)last + last->size))
            {
                  return FAILURE;
            }
      }

      /* make sure it doesn't overlap next fragment */
      if (frag)
      {
            if (((char *)dead + dead->size) > (char *)frag)
            {
                  return FAILURE;
            }
      }

      /* can we merge with next fragment */
      if (((char *)dead + dead->size) == (char *)frag)
      {
            /* merge with next fragment */
            dead->next  = frag->next;
            dead->size += frag->size;
      }
      else
      {
            /* link to next */
            dead->next = frag;
      }

      /* if there is a previous fragment */
      if (last)
      {
            /* can we merge with previous fragment */
            if (((char *)last + last->size) == (char *)dead)
            {
                  /* merge with previous fragment */
                  last->next  = dead->next;
                  last->size += dead->size;
            }
            else
            {
                  /* just link to previous fragment */
                  last->next  = dead;
            }
      }

      /* no previous fragment */
      else
      {
            /* make new head of list */
            free_list = dead;
      }

      return SUCCESS;
}

/*--------------------------------------------------------------------------*/

void *
do_malloc
(     unsigned long     size,
      int                     high
)
{     memfrag_t         *frag;
      memfrag_t         *last;
      memfrag_t         *curr;
      memfrag_t         *prev;

      /* long word align and add space to store allocation size */
      size = (size + sizeof(frag->size) + 3) & ~3;

      curr = free_list;
      last = NULL;
      prev = NULL;
      frag = NULL;

      while (curr)
      {
            if (curr->size >= size)
            {
                  frag = curr;
                  last = prev;

                  if (!high)
                  {
                        break;
                  }
            }

            /* onwards ... */
            prev = curr;
            curr = curr->next;
      }

      /* nothing found! */
      if (frag == NULL)
      {
            return NULL;
      }

      /* A suitable fragment has been found
       * now we must unlink it from the free list.
       * If the fragment is large enough just take
       * the allocation from either the end or the
       * beginning depending on the the 'high' flag.
       */

      /* is it big enough to split into two fragments */
      if (frag->size >= (size + sizeof(memfrag_t)))
      {
            if (high)
            {
                  /* adjust for amount removed */
                  frag->size -= size;

                  /* point at allocated chunk at end */
                  frag = (memfrag_t *) ((char *)frag + frag->size);

                  /* store allocated size */
                  frag->size = size;
            }
            else
            {
                  /* add allocator overhead to required size */
                  size += sizeof(frag->size);

                  /* get pointer to the part of the fragment we don't want */
                  curr = (memfrag_t *) ((char *)frag + size);

                  /* link it back into list */
                  curr->next = frag->next;
                  curr->size = frag->size - size;
                  if (last)
                  {
                        last->next = curr;
                  }
                  else
                  {
                        free_list = curr;
                  }

                  /* save size of fragment we are keeping */
                  frag->size = size;
            }
      }
      else
      {
            /* unlink found fragment */
            if (last)
            {
                  last->next = frag->next;
            }
            else
            {
                  free_list  = frag->next;
            }
      }

#if 0
      /* zero intialise allocated memory */
      mem_clear(&(frag->next), frag->size - sizeof(frag->size));
#endif

      /* return pointer to allocated memory */
      return &(frag->next);
}

/*--------------------------------------------------------------------------*/
/* Allocate chunk of memory from heap. Allocation is always made from
 * highest address that will satisfy the request.
 */

void *
malloc
(     unsigned long     size
)
{
      return do_malloc(size, TRUE);
}

/*--------------------------------------------------------------------------*/
/* Allocate chunk of memory from heap. Allocation is always made from
 * lowest address that will satisfy the request.
 */

void *
malloc_low
(     unsigned long     size
)
{
      return do_malloc(size, FALSE);
}

/*--------------------------------------------------------------------------*/
/* return size of largest free memory block
 */

unsigned long
maxfree
(     void
)
{     memfrag_t         *frag;
      unsigned long     size = 0;

      /* find size of largest fragment */
      for (frag = free_list; frag; frag = frag->next)
      {
            if (frag->size > size)
            {
                  size = frag->size;
            }
      }

      /* anything found? */
      if (size)
      {
            /* adjust for allocator overhead */
            size -= sizeof(frag->size);
      }

      /* return size available */
      return size;
}

/*--------------------------------------------------------------------------*/
/* move specified number of bytes from beginning to end of given
 * memory allocation, give unused memory at beginning to heap and return
 * a pointer to the start of the moved data.
 */

void *
move_up
(     void              *memaddr,
      unsigned long     memsize
)
{     memfrag_t         *frag;
      memfrag_t         *newfrag;
      unsigned long     size;

      if (memaddr == NULL)
      {
            return NULL;
      }

      /* recover pointer to base of allocation */
      frag = (memfrag_t *) ((char *)memaddr - sizeof(frag->size));

      /* long word align */
      size = (memsize + sizeof(frag->size) + 3) & ~3;

      /* make sure we have enough room */
      if (frag->size < size)
      {
            return NULL;
      }

      /* get pointer to new fragment */
      newfrag = (memfrag_t *) ((char *)frag + frag->size - size);

      /* move data up */
      mem_move(&(newfrag->next), memaddr, memsize);

      /* record fragment size */
      newfrag->size = size;

      /* fix original fragment size */
      frag->size -= size;

      /* discard chunk at beginning */
      free(&(frag->next));

      /* return new memory address */
      return &(newfrag->next);
}

/*--------------------------------------------------------------------------*/
/* resize block of allocated memory
 */

#ifdef NOT_USED
void *
realloc
(     void              *memaddr,
      unsigned long     size
)
{     memfrag_t         *frag;
      memfrag_t         *newfrag;
      void              *newaddr;
      unsigned long     newsize;

      if (memaddr == NULL)
      {
            return malloc(size);
      }

      /* recover pointer to base of allocation */
      frag = (memfrag_t *) ((char *)memaddr - sizeof(frag->size));

      /* long word align and add space to store allocation size */
      newsize = (size + sizeof(frag->size) + 3) & ~3;

      /* do they want more than we have */
      if (newsize > frag->size)
      {
            /* allocate a new chunk */
            if ((newaddr = malloc(size)) != NULL)
            {
                  /* copy old data to new allocation */
                  mem_move(newaddr, memaddr, frag->size - sizeof(frag->size));

                  /* discard old data */
                  free(memaddr);
            }

            return newaddr;
      }

      /* is there enough to make a new fragment from remainder */
      if ((frag->size - newsize) >= sizeof(memfrag_t))
      {
            /* make new fragment from end of old */
            newfrag       = (memfrag_t *)((char *)frag + newsize);
            newfrag->size = frag->size - newsize; 

            /* give fragment back to heap */
            free(&(newfrag->next));

            /* remember new fragment size */
            frag->size = newsize;
      }

      return memaddr;
}
#endif /* NOT_USED */

/*--------------------------------------------------------------------------*/

unsigned long
disable_icache
(     void
)
{     unsigned long     old_cacr;

      /* disable and invalidate instruction cache */
      __asm__ __volatile__ (
      "     movec %%cacr,%%d1                         \n\
            move.l      %%d1,%0                                   \n\
            bclr  #15,%%d1                            \n\
            movec %%d1,%%cacr                         \n\
            .word 0xf498                  | cinva     ic    \n\
      "
      : "=d" (old_cacr)
      : /* no inputs */
      : "d1"
      );

      return old_cacr;
}

/*--------------------------------------------------------------------------*/

unsigned long
enable_icache
(     void
)
{     unsigned long     old_cacr;

      /* enable instruction cache */
      __asm__ __volatile__ (
      "     movec %%cacr,%%d1       \n\
            move.l      %%d1,%0                 \n\
            bset  #15,%%d1          \n\
            movec %%d1,%%cacr       \n\
      "
      : "=d" (old_cacr)
      : /* no inputs */
      : "d1"
      );

      return old_cacr;
}

/*--------------------------------------------------------------------------*/

void
invalidate_icache
(     void
)
{
      __asm__ __volatile__ (
      "     .word 0xf498            | cinva ic - invalidate instruction cache"
      );
}

/*--------------------------------------------------------------------------*/

void
erase
(     int         n
)
{
      while (n--)
            put_str("\b \b");
}

/*--------------------------------------------------------------------------*/

int
strlen
(     const char  *s
)
{     const char  *e = s;

      while (*e++)
            ;

      return (e - s) - 1;
}

/*--------------------------------------------------------------------------*/

char *
strcpy
(     char        *d,
      const char  *s
)
{     char        *sd = d;

      while ((*d++ = *s++) != '\0')
            ;

      return sd;
}

/*--------------------------------------------------------------------------*/

void
strcat
(     char        *d,
      const char  *s
)
{
      while (*d++ != '\0')
            ;

      d--;

      while ((*d++ = *s++) != '\0')
            ;
}

/*--------------------------------------------------------------------------*/

void
strcatn
(     char              *d,
      const char        *s,
      unsigned long     n
)
{
      while (n && (*d++ != '\0'))
      {
            n--;
      }

      d--;

      while (--n && *s)
      {
            *d++ = *s++;
      }

      *d = '\0';
}

/*--------------------------------------------------------------------------*/

void
strncpy
(     char              *d,
      const char        *s,
      unsigned long     n
)
{     const char        *save;
      unsigned long     max;

      save = s;
      max  = 1;

      while (*s++) max++;

      s = save;

      if (n < max) max = n;

      n -= max;

      while (max--)
      {
            *d++ = *s++;
      }

      while (n--)
      {
            *d++ = '\0';
      }
}

/*--------------------------------------------------------------------------*/
/* printf style output formatter
 */

int
vsoutput
(     void        (*output)(const int),
      const char  *fmt,
      va_list           va
)
{     int               c;
      int               pos   = 0;
#define                 BUFSZ 15

      while ((c = *fmt++))
      {
          if (c != '%')
          {
                  (*output)(c);
                  pos++;
            }
            else
            {
                  enum {
                        FF_DEFAULT = 0,
                        FF_DUMP    = 0x01,      /* dump string to output      */
                        FF_ALT     = 0x02,      /* #, alternate format        */
                        FF_SHORT   = 0x04,      /* h, short arg                     */
                        FF_LONG    = 0x08,      /* l, long arg                      */
                        FF_ZERO    = 0x10,      /* 0, zero fill                     */
                        FF_LEFT    = 0x20,      /* -, left adjust             */
                        FF_PREC    = 0x40,      /* .*, precision              */
                        FF_NEG     = 0x80 /* signed arg                       */
                  }                       flags   = FF_DEFAULT;
                  long              n;
                  unsigned long     u;
                  char              buf[BUFSZ + 1];
                  char              *p    = buf + BUFSZ;
                  int                     sign  = '-';
                  int                     width = 0;
                  int                     prec  = 0;

                  *p = '\0';

                  /* scan flags */
                  while (1)
                  {
                        switch (c = *fmt++)
                        {
                              case '0':
                              {
                                    flags |= FF_ZERO;
                                    break;
                              }

                              case '#':         /* alternate format */
                              {
                                    flags |= FF_ALT;
                                    break;
                              }

                              case ' ':         /* blank sign */
                              {
                                    sign = ' ';
                                    break;
                              }

                              case '+':         /* +/- sign */
                              {
                                    sign = '+';
                                    break;
                              }

                              case '-':         /* left justified */
                              {
                                    flags |= FF_LEFT;
                                    break;
                              }

                              default:
                              {
                                    goto scan_width;
                              }
                        }
                  }

            scan_width:
                  /* scan width */
                  if (c == '*')
                  {
                        /* width from arg list */
                        if ((width = va_arg(va, int)) < 0)
                        {
                              width  = -width;
                              flags |= FF_LEFT;
                        }
                        c = *fmt++;
                  }
                  else
                  {
                        while ('0' <= c && c <= '9')
                        {
                              width = (width * 10) + (c - '0');
                              c     = *fmt++;
                        }
                  }

                  if (c == '.')
                  {
                        /* scan precision */
                        flags |= FF_PREC;
                        c      = *fmt++;

                        if (c == '*')
                        {
                              /* precision from arg list */
                              if ((prec = va_arg(va, int)) < 0)
                              {
                                    prec = -prec;
                              }
                              c = *fmt++;
                        }
                        else
                        {
                              while ('0' <= c && c <= '9')
                              {
                                    prec = (prec * 10) + (c - '0');
                                    c    = *fmt++;
                              }
                        }
                  }

                  /* length modifiers */
                  if (c == 'h')
                  {
                        flags |= FF_SHORT;
                        c      = *fmt++;
                  }
                  else if (c == 'l')
                  {
                        flags |= FF_LONG;
                        c      = *fmt++;
                  }

                  /* do conversion */
                  switch (c)
                  {
                        case '%':         /* %% -> % */
                        {
                              (*output)(c);
                              pos++;
                              break;
                        }

                        case 'n':         /* save position */
                        {
                              *va_arg(va, int *) = pos;
                              break;
                        }

                        case 'c':         /* character */
                        {
                              u = (flags & FF_SHORT) ? va_arg(va, unsigned int)
                                : (flags & FF_LONG ) ? va_arg(va, unsigned long )
                                : va_arg(va, unsigned int);
                              *--p = u;
                              flags |= FF_DUMP;
                              break;
                        }

                        case 's':         /* string */
                        {
                              if ((p = va_arg(va, char *)) == NULL)
                              {
                                    p = "";
                              }

                              if ((flags & FF_PREC) && strlen(p) > prec)
                              {
                                    pos += prec;

                                    while (--prec >= 0)
                                    {
                                          (*output)(*p++);
                                    }

                                    break;
                              }

                              flags |= FF_DUMP;
                              break;
                        }

                        case 'i': case 'd': case 'u': /* decimal */
                        {
                              if (c != 'u')
                              {
                                    /* signed */
                                    n = (flags & FF_SHORT) ? va_arg(va, int)
                                      : (flags & FF_LONG ) ? va_arg(va, long )
                                      : va_arg(va, int);

                                    if (n < 0)
                                    {
                                          flags |= FF_NEG;
                                    }

                                    u = (n < 0) ? -n : n;
                              }
                              else
                              {
                                    u = (flags & FF_SHORT) ? va_arg(va, unsigned int)
                                      : (flags & FF_LONG ) ? va_arg(va, unsigned long )
                                      : va_arg(va, unsigned int);
                              }

                              do    {
                                    *--p = '0' + u % 10;
                                    u   /= 10;
                              } while (u != 0);

                              prec -= buf + BUFSZ - p;

                              while (--prec >= 0)
                              {
                                    *--p = '0';
                              }

                              if (flags & FF_NEG)
                              {
                                    *--p = '-';
                              }
                              else
                              {
                                    if (sign != '-')
                                    {
                                          *--p = (sign == '+') ? '+' : ' ';
                                    }
                              }

                              flags |= FF_DUMP;
                              break;
                        }

                        case 'x': case 'X':     /* hex, Hex */
                        {
                              u = (flags & FF_SHORT) ? va_arg(va, unsigned int)
                                : (flags & FF_LONG ) ? va_arg(va, unsigned long )
                                : va_arg(va, unsigned int);
                              do    {
                                    *--p = "0123456789ABCDEF"[u%16];
                                    u   /= 16;
                              } while (u);

                              prec -= buf + BUFSZ - p;

                              while (--prec >= 0)
                              {
                                    *--p = '0';
                              }

                              if (flags & FF_ALT)
                              {
                                    *--p = 'x';
                                    *--p = '0';
                              }

                              flags |= FF_DUMP;
                              break;
                        }

                        case 'o':         /* octal */
                        {
                              u = (flags & FF_SHORT) ? va_arg(va, unsigned int)
                                : (flags & FF_LONG ) ? va_arg(va, unsigned long )
                                : va_arg(va, unsigned int);
                              do    {
                                    *--p = '0' + u % 8;
                                    u   /= 8;
                              } while (u);

                              prec -= buf + BUFSZ - p;

                              while (--prec >= 0)
                              {
                                    *--p = '0';
                              }

                              if ((flags & FF_ALT) && *p != '0')
                              {
                                    *--p = '0';
                              }

                              flags |= FF_DUMP;
                              break;
                        }

                        default:          /* error */
                        {
                              (*output)('%');
                              (*output)(c);
                              pos += 2;
                              break;
                        }
                  }

                  /* copy adjusted string "p" to output */
                  if (flags & FF_DUMP)
                  {
                        int len = strlen(p);
                        int pad = width - len;

                        if (!(flags & FF_LEFT))
                        {
                              int padder = (flags & FF_ZERO) ? '0' : ' ';

                              while (--pad >= 0)
                              {
                                    (*output)(padder);
                              }
                        }

                        while (*p)
                        {
                              (*output)(*p++);
                        }

                        if (flags & FF_LEFT)
                        {
                              while (--pad >= 0)
                              {
                                    (*output)(' ');
                              }
                        }

                        pos += (len < width) ? width : len;
                  }
            }
      }

      return pos;
}

/*--------------------------------------------------------------------------*/
/* Format string
 */

static char *_sprintf_ptr;
static void  _sprintf_out(const int c) {*_sprintf_ptr++ = c;}

int
sprintf
(     char        *buff,
      const char  *fmt,
      ...
)
{     va_list           args;
      int               n;

    _sprintf_ptr = buff;

    va_start(args, fmt);
      n = vsoutput(_sprintf_out, fmt, args);
    va_end(args);

      *_sprintf_ptr = '\0';

    return n;
}

/*--------------------------------------------------------------------------*/
/* Print formated string.
 */

int
printf
(     const char  *fmt,
      ...
)
{     va_list           args;
      int               n;

    va_start(args, fmt);
      n = vsoutput(put_char, fmt, args);
    va_end(args);

    return n;
}

/*--------------------------------------------------------------------------*/
/* Print quoted string with embedded escapes.
 */

int
put_estr
(     const char  *str
)
{     int               quoted = FALSE;
      int               n      = 0;
      int               i;
      int               c;

      if (str[0] == '\"' && str[1])
      {
            quoted = TRUE;
            str++;
      }

      while ((c = *str++) != '\0')
      {
            /* if end of quoted string */
            if (quoted && c == '\"' && *str == '\0')
            {
                  break;
            }

            if (c == '\\')
            {
                  switch (*str)
                  {
                        case 'n' : c = '\n'; break;
                        case 'r' : c = '\r'; break;
                        case 't' : c = '\t'; break;
                        case 'b' : c = '\b'; break;
                        case 'e' : c = 27;   break;
                        case '\\':           break;
                        default:
                        {
                              if (*str >= '0' && *str <= '7')
                              {
                                    i = 3;
                                    c = 0;

                                    /* evaluate upto 3 octal digits */
                                    while (i-- && *str >= '0' && *str <= '7')
                                    {
                                          c = (c * 8) + (*str++ - '0');
                                    }
                              }
                              str--;
                              break;
                        }
                  }
                  str++;
            }
            put_char(c);
            n++;
      }

      return n;
}

/*--------------------------------------------------------------------------*/
/* Print unformated string.
 */

int
put_str
(     const char  *str
)
{     int               n = 0;

      while (*str)
      {
            put_char(*str++);
            n++;
      }

      return n;
}

/*--------------------------------------------------------------------------*/
/* Report fatal error
 */

void
panic
(     const char  *fmt,
      ...
)
{     va_list           args;

      put_str("\nLILO Panic: ");
    va_start(args, fmt);
    vsoutput(put_char, fmt, args);
    va_end(args);
    put_char('\n');
 
    while (1)
            ;
}

/*--------------------------------------------------------------------------*/

void *
xmalloc
(     int         size
)
{     void  *p;

      if ((p = malloc(size)) == NULL)
      {
            panic("Not enough memory");
      }

      return p;
}

/*--------------------------------------------------------------------------*/

char *
skip_white
(     const char  *p
)
{
      while (*p && (*p < '!'))
            p++;

      return (char *)p;
}

/*--------------------------------------------------------------------------*/

void
trim_white
(     char  *p
)
{     char  *w;

      while (1)
      {
            /* say no white space */
            w = NULL;

            /* skip non-white space */
            while (*p >= '!')
                  p++;

            /* if end of string */
            if (*p == '\0')
            {
                  break;
            }

            /* remember where start of white space is */
            w = p;

            /* skip past white space */
            do    { ++p; } while (*p && *p < '!');

            /* if end of string */
            if (*p == '\0')
            {
                  break;
            }
      }

      /* if we ended up in white space, strip it */
      if (w) *w = '\0';
}

/*--------------------------------------------------------------------------*/
/* replace all space characters in string with hyphen.
 */

char *
despace
(     char  *str
)
{     char  *p = str;

      while (*p)
      {
            if (*p == ' ')
            {
                  *p = '-';
            }
            p++;
      }

      return str;
}

/*--------------------------------------------------------------------------*/
/* Check whether two strings exist and are equal ignoring case.
 */

int
equal_strings
(     const char  *s1,
      const char  *s2
)
{     char        c1;
      char        c2;

      if ((s1 == NULL) || (s2 == NULL))
      {
            return FALSE;
      }

      while (*s1 || *s2)
      {
            c1 = *s1++;
            c2 = *s2++;

            /* convert to lower case */
            if ((c1 >= 'A') && (c1 <= 'Z')) c1 += 'a' - 'A';
            if ((c2 >= 'A') && (c2 <= 'Z')) c2 += 'a' - 'A';

            if (c1 != c2)
            {
                  return FALSE;
            }
      }

      return TRUE;
}

/*--------------------------------------------------------------------------*/
/* copy string 'p2' to string 'p1' until 1st whitespace or delimiter
 */

char *
extract
(     char        *p1,
      char        *p2,
      int               len,                    /* size of 'p1' buffer                                */
      int               delim
)
{
      /* leave room for NULL terminator */
      len--;

      /* skip leading white space */
      p2 = skip_white(p2);

      /* until we hit a delimiter */
      while ((*p2 >= '!') && (*p2 != delim))
      {
            if (len)
            {
                  *p1++ = *p2++;
                  len--;
            }
            else
            {
                  p2++;
            }
      }

      /* NULL terminate */
      *p1 = '\0';

      /* skip white space */
      p2 = skip_white(p2);

      /* skip delimiter and following white space */
      if (delim && (*p2 == delim))
      {
            p2 = skip_white(p2 + 1);
      }

      /* return pointer to next argument */
      return p2;
}

/*--------------------------------------------------------------------------*/
/* Convert CR, LF, CRLF or LFCR delimited text in place to a contiguous
 * bunch of null terminated strings. Each line is also stripped of leading
 * and trailing white space. Blank and comment lines are replaced with null
 * strings to preserve the relationship between input and output line
 * numbering. A line ending with a backslash as the last non-whitespace
 * character is merged with the following line, separated by a single space,
 * then extra nulls are inserted to preserve line numbering.
 * The total size of the converted data including the null terminators is
 * returned.
 */

int
prescan
(     char  *data,
      int         size
)
{     char  *end = data + size;
      char  *dst = data;
      char  *eol;
      char  c;
      int         comment;
      int         continued = 0;

      do    {
            /* skip leading white space */
            while (data != end && *data < '!' && *data != LF && *data != CR)
                  data++;

            /* flag if comment line */
            comment = (*data == '#');

            /* first guess at end of line position */
            eol = dst;
      
            /* until end of data */
            while (data != end)
            {
                  /* get next character */
                  c = *data++;
      
                  /* check for CR and CRLF */
                  if (c == CR)
                  {
                        /* check for and skip following LF */
                        if (data != end && *data == LF)
                              data++;

                        break;
                  }
      
                  /* check for LF and LFCR */
                  if (c == LF)
                  {
                        /* check for and skip following CR */
                        if (data != end && *data == CR)
                              data++;

                        break;
                  }

                  /* strip out comments */
                  if (!comment)
                  {
                        /* replace embedded non-printables with spaces */
                        if (c < ' ')
                        {
                              c = ' ';
                        }

                        /* copy character */
                        *dst++ = c;

                        /* record potential end of line position */
                        if (c >= '!')
                        {
                              eol = dst;
                        }
                  }
            }

            /* if this line is a comment and previous line was continued */
            if (comment && continued)
            {
                  /* keep track of line number and let continuation carry on
                   * to next line
                   */
                  continued++;
            }

            /* if line ends with a backslash */
            else if (eol != data && eol[-1] == '\\')
            {
                  /* count number of continuations */
                  continued++;

                  /* replace continuation mark with a space */
                  *--eol = ' ';

                  /* trim trailing whitespace before continuation mark */
                  while (eol != data && eol[-1] == ' ')
                        eol--;

                  /* leave one space */
                  eol++;
            }

            else
            {
                  /* mark end of line (stripping trailing white space)
                   * and add a null for each continued line to preserve
                   * line numbering.
                   */
                  do    {
                        *eol++ = '\0';
                  } while (continued--);

                  /* reset continued line count */
                  continued = 0;
            }

            /* put next line immediately after current */
            dst = eol;

      /* until end of data */
      } while (data != end);

      /* make sure a continued last line is terminated */
      if (continued) dst[-1] = '\0';

      /* return new data size */
      return size - (end - dst);
}

/*--------------------------------------------------------------------------*/

static struct vmetype {
      char              *name;
      unsigned long     code;
} vmetypes[] = {
      {"mvme162",  VME_TYPE_MVME162 },
      {"mvme166",  VME_TYPE_MVME166 },
      {"mvme167",  VME_TYPE_MVME167 },
      {"mvme172",  VME_TYPE_MVME172 },
      {"mvme177",  VME_TYPE_MVME177 },
      {"bvme4000", VME_TYPE_BVME4000},
      {"bvme6000", VME_TYPE_BVME6000}
};

#define NUMVMETYPES (sizeof(vmetypes) / sizeof(vmetypes[0]))

int
check_arch
(     char              *text
)
{     char              name[10];
      unsigned long     vme_type;
      int                     i;

      /* if no architecture specified */
      text = skip_white(text);
      if (*text == '\0')
      {
            return TRUE;
      }

      /* get VME type code for booting crate */
      vme_type = get_vme_type();

      do    {
            /* get the next specified architecture name */
            text = extract(name, text, sizeof(name), '\0');

            /* check if it matches */
            for (i = 0; i < NUMVMETYPES; i++)
            {
                  if (equal_strings(vmetypes[i].name, name))
                  {
                        if (vmetypes[i].code == vme_type)
                        {
                              return TRUE;
                        }
                        break;
                  }
            }
            
      } while (*text);

      return FALSE;
}
      
/*--------------------------------------------------------------------------*/

char *
mkinet
(     unsigned long     ip
)
{     static char       buff[16];

      sprintf(buff, "%u.%u.%u.%u",
                  (unsigned) (ip >> 24),
                  (unsigned) (ip >> 16) & 0xff,
                  (unsigned) (ip >>  8) & 0xff,
                  (unsigned) (ip      ) & 0xff
      );

      return buff;
}

/*--------------------------------------------------------------------------*/

unsigned
atou
(     const char  **strp
)
{     char        *p = skip_white(*strp);
      unsigned    u  = 0;

      /* evaluate digits */
      while (*p >= '0' && *p <= '9')
      {
            u = (u * 10) + (*p++ - '0');
      }

      *strp = skip_white(p);

      return u;
}

/*--------------------------------------------------------------------------*/

int
compare_ip
(     const char        *ipstr,
      const char        *pattern
)
{     unsigned char     lo[4];
      unsigned char     hi[4];
      unsigned          n;
      int                     i;
      const char        *p;

      p = pattern;
      for (i = 0; i < 4; i++)
      {
            if ((n = atou(&p)) > 255)
            {
                  return FALSE;
            }

            lo[i] = n;

            if (*p == '-')
            {
                  p++;
                  if ((n = atou(&p)) > 255)
                  {
                        return FALSE;
                  }

                  hi[i] = n;
            }
            else
            {
                  hi[i] = lo[i];
            }

            if (hi[i] < lo[i])
            {
                  n     = lo[i];
                  lo[i] = hi[i];
                  hi[i] = n;
            }

            if (i < 3)
            {
                  if (*p++ != '.')
                  {
                        return FALSE;
                  }
            }
      }

      if (*p)
      {
            return FALSE;
      }

      p = ipstr;
      for (i = 0; i < 4; i++)
      {
            n = atou(&p);

            if (n < lo[i] || n > hi[i])
            {
                  return FALSE;
            }

            if (i < 3)
            {
                  if (*p++ != '.')
                  {
                        return FALSE;
                  }
            }
      }

      if (*p)
      {
            return FALSE;
      }

      return TRUE;
}

/*--------------------------------------------------------------------------*/
/* append source string to destination buffer replacing %? escape sequences
 * in source with IP addresses in destination. Also replace %% with %, a %
 * followed by any other character is copied unchanged. Escape sequences for
 * unsupported address types are stripped.
 */

void
substip
(     char              *dest,
      const char        *srce,
      int                     maxlen
)
{     int                     len;
      const char        *ip;
      int                     lc;
      char              c;

      /* skip to null terminator of destination string */
      while (*dest++)
            maxlen--;
      dest--;

      /* leave space for new null terminator */
      maxlen--;

      while (maxlen > 0)
      {
            len = 1;
            if (*srce != '%')
            {
                  *dest++ = *srce++;
            }
            else
            {
                  /* skip leading '%' */
                  srce++;

                  /* get option character */
                  c = *srce++;

                  /* flag if option lower case */
                  if ((lc = (c >= 'a' && c <= 'z')) != 0)
                  {
                        /* make it upper case */
                        c -= ('a' - 'A');
                  }

                  switch (c)
                  {
                        default:
                              srce--;
                        case '%':
                              *dest++ = '%';
                              break;
                        case 'C':
                              ip = get_ip(IP_CLIENT);
                              goto doit;
                        case 'S':
                              ip = get_ip(IP_SERVER);
                              goto doit;
                        case 'G':
                              ip = get_ip(IP_GATEWAY);
                              goto doit;
                        case 'B':
                              ip = get_ip(IP_BROADCAST);
                              goto doit;
                        case 'M':
                              ip = get_ip(IP_NETMASK);
                        doit:
                        {
                              /* substitute 0.0.0.0 with empty string
                               * if lowercase option
                               */
                              if (lc && equal_strings(ip, "0.0.0.0"))
                                    ip = NULL;

                              if (ip) 
                              {
                                    len = strlen(ip);
                                    if (len <= maxlen)
                                    {
                                          strcpy(dest, ip);
                                          dest += len;
                                    }
                              }
                              break;
                        }
                  }
            }

            maxlen -= len;
      }

      *dest = '\0';
}

/*--------------------------------------------------------------------------*/

char *
tftp
(     char                    *filename,
      unsigned long           *filesize
)
{     int                           count;
      void                    *buff;
      void                    *data;

      /* allocate largest free memory chunk */
      buff = xmalloc(count = maxfree());

      /* transfer file into buffer */
      if ((count = tftp_read(filename, count, buff)) == FAILURE)
      {
            free(buff);
            return NULL;
      }

      /* shift data to highest possible address and free
       * unused memory
       */
      if ((data = move_up(buff, count)) == NULL)
      {
            free(buff);
            return NULL;
      }

      /* return file size */
      *filesize = count;

      /* return pointer to data */
      return data;
}

/*--------------------------------------------------------------------------*/
/* Determine CPU type:
 *
 * returns 40 if 68040
 * or      60 if 68060
 */

int
get_cpu_type
(     void
)
{     int         cpu;

      __asm__ __volatile__ (
      "     move.w      %%sr,%%d0                                             \n\
            movec %%vbr,%%a0                                            \n\
            move.l      0x10(%%a0),%%d1                                       \n\
            lea.l Illegal(%%pc),%%a1                                    \n\
            move.l      %%a1,0x10(%%a0)                                       \n\
            move.l      %%sp,%%a1                                             \n\
            moveq #60,%%d3                                              \n\
            dc.l  0x4e7aa803              | movec     %%msp,%%a2  \n\
            moveq #40,%%d3                                              \n\
Illegal:                                                                      \n\
            move.l      %%a1,%%sp                                             \n\
            move.l      %%d1,0x10(%%a0)                                       \n\
            move.w      %%d0,%%sr                                             \n\
            move.l      %%d3,%0                                                     \n\
      "
      : "=d" (cpu)
      : /* no inputs */
      : "d0", "d1", "d3", "a0", "a1", "a2", "memory"
);

      return cpu;
}

/*--------------------------------------------------------------------------*/
/* Determine FPU type:
 *
 * returns 0 not present
 */

int
get_fpu_type
(     void
)
{     int         fpu;

      __asm__ __volatile__ (
      "     move.w      %%sr,%%d0               \n\
            movec %%vbr,%%a0              \n\
            move.l      0x2c(%%a0),%%d1         \n\
            lea.l FLine(%%pc),%%a1  \n\
            move.l      %%a1,0x2c(%%a0)         \n\
            move.l      %%sp,%%a1               \n\
            moveq #0,%%d3                       \n\
            dc.l  0xf2800000              \n\
            moveq #1,%%d3                       \n\
FLine:                                                \n\
            move.l      %%a1,%%sp               \n\
            move.l      %%d1,0x2c(%%a0)         \n\
            move.w      %%d0,%%sr               \n\
            move.l      %%d3,%0                       \n\
      "
      : "=d" (fpu)
      : /* no inputs */
      : "d0", "d1", "d3", "a0", "a1", "a2", "memory"
);

      return fpu;
}

/*--------------------------------------------------------------------------*/
/* Probe given address for the existance of RAM
 *
 * Return non-zero if RAM found.
 */

int
ram_probe
(     unsigned long     where
)
{     int                     rv;

      __asm__ __volatile__ (
      "     move.w      %%sr,%%d4                     | save trace flag       \n\
            movec %%vbr,%%a0                    | get vector table ptr  \n\
            move.l      0x8(%%a0),%%d5                | save BERR vector            \n\
            lea.l BusError(%%pc),%%a1           | new BERR handler            \n\
            move.l      %%a1,0x8(%%a0)                | set it                      \n\
            move.l      %%sp,%%a1                     | save stack frame            \n\
            moveq #0,%0                         | say no memory here    \n\
            move.l      #0x7e57ed17,%%d1        | get pattern                 \n\
            move.l      (%1),%%d2                     | save memory                 \n\
            move.l      4(%1),%%d3                    | save memory + 4       \n\
            move.l      %%d1,(%1)                     | store pattern               \n\
            not.l %%d1                          | new pattern                 \n\
            move.l      %%d1,4(%1)                    | store new pattern           \n\
            not.l %%d1                          | old pattern                 \n\
            cmp.l (%1),%%d1                     | did it store                \n\
            bne.s BusError                      | branch if not               \n\
            move.l      %%d2,(%1)                     | restore memory        \n\
            move.l      %%d3,4(%1)                    | restore memory + 4    \n\
            moveq #1,%0                         | say memory found            \n\
BusError:                                                                                 \n\
            move.l      %%a1,%%sp                     | restore SP                  \n\
            move.l      %%d5,0x8(%%a0)                | restore BERR handler  \n\
            move.w      %%d4,%%sr                     | restore trace flag    \n\
      "
      : "=d" (rv)
      : "a" (where)
      : "d1", "d2", "d3", "d4", "d5", "a0", "a1", "memory"
);

      return rv;
}

/*-----------------------------< end of file >------------------------------*/

Generated by  Doxygen 1.6.0   Back to index