ttyio.c

来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 771 行 · 第 1/2 页

C
771
字号
         prefill = postfill;
         postfill = (unsigned)swap;
      }

      while (prefill--)
      {
         doputchar(fillchar); /* do any pre-field padding */
      }
#endif   /* FIELDWIDTH */


#ifdef PRINTF_STDARG
      switch (*sp)
      {
      case 'p':      /* '%p' - pointer */
#ifdef SEG16_16   /* do seg:offset variety */
         hexword(&target, w1);   /* display segment word */
         doputchar(':');
         hexword(&target, w0);   /* display offset word */
#else /* 32 bit flat */
         hexword(&target, (unsigned)(lng >> 16));
         hexword(&target, (unsigned)(lng & 0x0000FFFF));
#endif /* SEG16_16 */   /* else fall to 32 bit code */
         break;
      case 'x':      /* '%x' - this always does 0 prefill */
         if (tmp > 255)
            hexword(&target, tmp);
         else
            hexbyte(&target, tmp);
         break;
      case 'd':      /* '%d' */
         declong(&target, (long) i0);
         break;
      case 'u':      /* '%u' */
         declong(&target, (unsigned long) w0);
         break;
      case 'c':      /* '%c' */
         doputchar(c);
         break;
      case 's':      /* '%s' */
         i = 0;
         while (cap  && (*cap) && (i++ < maxfieldlen))
            doputchar(*cap++);
         break;
      case 'l':
         sp++;
         if (*sp == 'x')      /* '%lx' */
         {
            hexword(&target, (unsigned)(lng >> 16));
            hexword(&target, (unsigned)(lng & 0x0000FFFF));
         }
         else if(*sp == 'd' || *sp == 'u')   /* '%ld' or '%lu' */
         {
            declong(&target, lng);     /* we treat %lu as %ld. */
         }
         /*  else   '%l?', ignore it */
         break;
         default:       /* %?, ignore it */
         break;
      }  /* end switch *sp */
#else /* PRINTF_STDARG */
      switch (*sp)
      {
      case 'p':      /* '%p' - pointer */
#ifdef SEG16_16   /* do seg:offset variety */
         hexword(&target, (unsigned)*(vp+1));   /* display segment word */
         doputchar(':');
         hexword(&target, (unsigned)*vp);    /* display offset word */
         vp += 2;          /* bump var pointer past two words */
#else /* 32 bit flat */
         lng = *vp;
         hexword(&target, (unsigned)(lng >> 16));
         hexword(&target, (unsigned)(lng & 0x0000FFFF));
         vp += 4/sizeof(*vp); /* 2 or 1 */ 
#endif /* SEG16_16 */   /* else fall to 32 bit code */
         break;
      case 'x':      /* '%x' - this always does 0 prefill */
         tmp = *(unsigned *)vp++;
         if (tmp > 255)
            hexword(&target, tmp);
         else
            hexbyte(&target, tmp);
         break;
      case 'd':      /* '%d' */
         declong(&target, (long)*vp++);
         break;
      case 'u':      /* '%u' */
         declong(&target, (unsigned long)*(unsigned *)vp);
         vp++;
         break;
      case 'c':      /* '%c' */
         doputchar((unsigned char)(*vp++));
         break;
      case 's':      /* '%s' */
         cp = *(char **)vp;
         vp += sizeof(char*)/sizeof(int);   
         i = 0;
         while (*cp && i++ < maxfieldlen)
            doputchar(*cp++);
         break;
      case 'l':
         sp++;
         if (*sp == 'x')      /* '%lx' */
         {
            /*          lng = *vp;      */
            lng = *((unsigned long *) vp);
            hexword(&target, (unsigned)(lng >> 16));
            hexword(&target, (unsigned)(lng & 0x0000FFFF));
            vp += 4/sizeof(*vp); /* 2 or 1 */ 
         }
         else if(*sp == 'd' || *sp == 'u')   /* '%ld' or '%lu' */
         {
            declong(&target, *(long  *)vp);     /* we treat %lu as %ld. */
            vp += 2;
         }
         /*  else   '%l?', ignore it */
         break;
         default:       /* %?, ignore it */
         break;
      }  /* end switch *sp */
#endif   /* PRINTF_STDARG */

#ifdef   FIELDWIDTH
      while (postfill--)
      {
         doputchar(fillchar);   /* do any post-field padding */
      }
#endif   /* FIELDWIDTH */

      sp++;       /* point past '%?' */

   }  /* end while *sp */

   if ( target )
      *target='\0' ;   /* Null terminate the string */
}




/* FUNCTION: hexword()
 *
 * hexword(x) - print 16 bit value as hexadecimal
 * 
 * PARAM1: char ** targ
 * PARAM2: unsigned x
 *
 * RETURNS: 
 */

static void
hexword(char ** targ, unsigned x)
{
   char *   target   = *   targ;

   doputchar(digits[x >> 12]);
   doputchar(digits[(x >> 8) & 0x0f]);
   doputchar(digits[(x >> 4) & 0x0f]);
   doputchar(digits[x & 0x0f]);
   if (*targ)
      (*targ) += 4;
}



/* FUNCTION: hexbyte()
 * 
 * PARAM1: char ** targ
 * PARAM2: unsigned  x
 *
 * RETURNS: 
 */

static void
hexbyte(char ** targ, unsigned  x)
{
   char *   target   = *   targ;

   doputchar(digits[(x >> 4) & 0x0f]);
   doputchar(digits[x & 0x0f]);
   if (*targ)
      (*targ) += 2;
}
 

/* FUNCTION: declong()
 *
 * declong(char*, long) - print a long to target as a decimal number. 
 * Assumes signed, prepends '-' if negative. 
 *
 * 
 * PARAM1: char ** targ
 * PARAM2: long lg
 *
 * RETURNS: 
 */

/* This should be local to declong, but Microsoft C 5.1 
 * breaks if it is. They use implicit lib calls to do long integer 
 * math, and the calls pass pointers to the longs, which assumes the 
 * longs are in local data space. Sheeeesh. -JB- 
 */
long tens;

static void
declong(char ** targ,   /* target buffer or NULL for stdio */
   long  lg)
{
   int   digit;
   char *   target   = *   targ;

   if (lg == 0)
   {
      doputchar('0');
      if (*targ)
         (*targ) = target;
      return;
   }
   else if(lg < 0L)
   {
      doputchar('-');
      lg = -lg;
   }

   /* make "tens" the highest power of 10 smaller than lg */
   tens = 1;
   while ((lg/10) >= tens) 
      tens *= 10;

   while (tens)
   {
      digit = (int)(lg/tens);    /* get highest digit in lg */

      doputchar(digits[digit]);

      lg -= ((long)digit * tens);
      tens /= 10;
   }
   if (*targ)
      (*targ) = target;
}


#ifdef FIELDWIDTH

/* FUNCTION: setnum()
 *
 * returns the value of fieldwidth digits from a 
 * printf format string. fptr should be a pointer to a pointer to one 
 * or more fieldwidth digits. On return, is advanced past the digits 
 * and the value of the digits is returned as an int. 
 *
 * 
 * PARAM1: char ** nptr
 *
 * RETURNS: returns the value of fieldwidth digits from a 
 * printf format string
 */

int      snval;   /* return value, breaks if on stack */

int
setnum(char ** nptr)
{
   snval = 0;

   while (**nptr >= '0' && **nptr <= '9') /* scan through digits */
   {
      snval *= 10;      /* calculate return value */
      snval += **nptr - '0';
      /* bump pointer (not pointer to pointer) past valid digits */   
      (*nptr)++;
   }
   return(snval);
}


/* FUNCTION: fplen()
 *
 * fplen(sp, varp) - returns the number of chars required to print 
 * the value pointed to by varp when formatted accoring to the string 
 * pointer to by sp. 
 *
 * 
 * PARAM1: char * sp
 * PARAM2: void * varp
 *
 * RETURNS: 
 */

long     lng1, lng2;    /* scratch value for longs */

int
fplen(char * sp, void * varp)
{
   char *   cp;

   /* define the maximum digits needed to display a long value in 
    * decimal. Say , sizeof(long) = 4. So it has 8*4=32 bits. 
    * 2^10=1024. So for every 10 bits, we can show 3 digits. So for 
    * long, this value would be 32*3/10=96/10=9. And then we add one 
    * more digit for the roundoff. max_long_dig is used to prevent 
    * long overflow in lng1. There are better ways to prevent this, 
    * but very difficult to verify whether we made the perfect fix. 
    * Hence for now, this should do. 
    */
   static int max_long_dig = (8 * sizeof(long) * 3)/10+1;



   snval = 0;     /* use this for return value */
   lng1 = 1;   /* for figuring lengths of decimal numbers */

   switch (*sp)      /* switch on conversion char */
   {
   case 's':
      cp = *(char**)varp;
      while   (*cp++) snval++;
         return(snval);
   case 'c':
      return(1);
   case 'x':
      return(4);
   case 'p':
      return(9);
   case 'd':
   case 'u':
      lng2 = *(long *)varp;
      if (lng2 == 0) return(1);
         if (lng2 < 0)        /* if variable value is negative... */
      {   if (*sp == 'd')  /* format is signded decimal */ 
         {   snval++;   /* add space for '-' sign */
            lng2 = -lng2;
         }
         else     /* *sp == 'u' - format is unsigned */
            lng2 &= 0xffff;
      }
      while (lng1 <= lng2)
      {
         lng1 *= 10;
         snval++;
         if ( snval >= max_long_dig )
         {
            /* If we don't stop now, there lng1 will have long overflow */
            break;
         }
      }
      return(snval);
   case 'l':
      switch (*(sp+1))
      {
      case 'x':   /* '%lx' always 8 bytes */
         return(8);
      case 'u':      /* treat %lu like %ld */
      case 'd':
         lng2 = (*(long *)(varp));
         if (lng2 == 0) return(1);
            if (lng2 < 0)
         {
            snval++;       /* add space for '-' sign */
            lng2 = -lng2;
         }
         while (lng1 <= lng2)
         {
            lng1 *= 10;
            snval++;
            if ( snval >= max_long_dig )
            {
               /* If we don't stop now, there lng1 will have long overflow */
               break;
            }
         }
         return(snval);
         default:
         return(0);
      }         
      default:
      return(0);
   }
}
#endif   /* FIELDWIDTH */

#endif   /* NATIVE_PRINTF */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?