⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 frmwri.c

📁 德州仪器(TI) 的超低功耗16 位RISC 混合信号处理器的MSP430 平台为电池供电的测量应用提供了最终解决方案。应用包括便携式医疗设备、低功耗工业操作、无线、实用计量等
💻 C
📖 第 1 页 / 共 2 页
字号:
/*            - FRMWRI.C -

   Basic "printf", "sprintf" and "fprintf" formatter.

   This module is 100% reentrant and can be adapted to user-defined routines
   that needs formatters with special properties like different output chann-
   els or new format specifiers.

   To reduce size in applications not using real numbers or long integers
   the formatter may be compiled to exclude certain parts.  This is
   controlled by giving a -D option a compilation time.

      -DFLOAT_SUPPORT        Full ANSI formatter
      -DNO_FLOATS            Full ANSI except floats
      -DREDUCED_SUPPORT        Reduced 'int' type of converter

   The reduced version of formatter is suitable when program size is critical
   rather than formatting power.  This routine uses less than 20 bytes of
   stack space which makes it practical even in systems with less than 256
   bytes of user RAM.

   The only formatting specifiers supported by the reduced formatter are:

         %% %c %s %d %o %x %X and %hd %ho %hx %hX %ld %lo %lx %lX.

   It means that real variables are not supported as well as field
   width and precision arguments.

   The last eight (h and l modifiers) can easily be removed by
   removing the line "#define MODIFIERS_IN_REDUCED".

   $Revision: 1.6 $

   Copyright 1986 - 1999 IAR Systems. All rights reserved.
*/

#ifndef FLOAT_SUPPORT
#ifndef NO_FLOATS
#ifndef REDUCED_SUPPORT
#error -DFLOAT_SUPPORT, -DNO_FLOATS or -DREDUCED_SUPPORT missing
#endif
#endif
#endif

/* Make it easy for customers to disable h and l
   modifiers in REDUCED_SUPPORT by removing the next #define */
#define MODIFIERS_IN_REDUCED

#include "stdarg.h"
#include "float.h"
#include "icclbutl.h"    /* Low-level declarations */
#include "sysmac.h"

#ifndef FRMWRI_BUFSIZE
#define FRMWRI_BUFSIZE 134
#endif

#ifndef MEM_ATTRIBUTE
#define MEM_ATTRIBUTE
#endif

#ifdef MODIFIERS_IN_REDUCED
#define IS_SHORT (h_modifier || (sizeof(int) == 2 && !l_modifier))
#else
#define IS_SHORT (sizeof(int) == 2)
#endif


#ifdef FLOAT_SUPPORT

static char *float_conversion(MEM_ATTRIBUTE long double value,
                              MEM_ATTRIBUTE short nr_of_digits,
                              MEM_ATTRIBUTE char *buf,
                              MEM_ATTRIBUTE char format_flag,
                              MEM_ATTRIBUTE char g_flag,
                              MEM_ATTRIBUTE char alternate_flag)
{
  MEM_ATTRIBUTE char *cp, *buf_pointer;
  MEM_ATTRIBUTE short n, i, dec_point_pos, integral_10_log;

  buf_pointer = buf;
  integral_10_log = 0;

#ifdef _CLIB_FP_INF_NAN
  if (value == 0.Infinity)
  {
    *buf_pointer++ = 'i';
    *buf_pointer++ = 'n';
    *buf_pointer++ = 'f';
    return buf_pointer;
  }
  else if (value != value)
  {
    *buf_pointer++ = 'n';
    *buf_pointer++ = 'a';
    *buf_pointer++ = 'n';
    return buf_pointer;
  }
#endif

  if (value >= 1)
  {
    while (value >= 1e11)        /* To speed up things a bit */
    {
      value /= 1e10;
      integral_10_log += 10;
    }
    while (value >= 10)
    {
      value /= 10;
      integral_10_log++;
    }
  }
  else if (value)            /* Not just 0.0 */
  {
    while (value <= 1e-10)        /* To speed up things a bit */
    {
      value *= 1e10;
      integral_10_log -= 10;
    }
    while (value < 1)
    {
      value *= 10;
      integral_10_log--;
    }
  }
  if (g_flag)
  {
    if (integral_10_log < nr_of_digits && integral_10_log >= -4)
    {
      format_flag = 0;
      nr_of_digits -= integral_10_log;
    }
    nr_of_digits--;
    if (alternate_flag)
    {
      g_flag = 0;         /* %#G - No removal of trailing zeros */
    }
    else
    {
      alternate_flag = 1;  /* %G - Removal of trailing zeros */
    }
  }

  if (format_flag)        /* %e or %E */
  {
    dec_point_pos = 0;
  }
  else
  {
    if (integral_10_log < 0)        /* Less than one.... */
    {
      *buf_pointer++ = '0';
      if ((n = nr_of_digits) || alternate_flag)
      {
        *buf_pointer++ = '.';
      }
      i = 0;
      while (--i > integral_10_log && nr_of_digits)
      {
        *buf_pointer++ = '0';
        nr_of_digits--;
      }
      if (integral_10_log < (-n - 1))
      {
        goto CLEAN_UP;     /* Nothing more to do */
      }
      dec_point_pos = 1;
    }
    else
    {
      dec_point_pos = - integral_10_log;
    }
  }

  i = dec_point_pos;
  while (i <= nr_of_digits )
  {
    value -= n = value;     /* n=Digit value=Remainder */
    value *= 10;         /* Prepare for next shot */
    *buf_pointer++ = n + '0';
    if ( ! i++ && (nr_of_digits || alternate_flag))
    {
      *buf_pointer++ = '.';
    }
  }
  if (value >= 5)    /* Rounding possible */
  {
    n = 1;    /* Carry */
    cp = buf_pointer - 1;
    do
    {
      if (*cp != '.')
        if ( (*cp += n) == ('9' + 1) )
        {
          *cp = '0';
          n = 1;
        }
        else
        {
          n = 0;
        }
    } while (cp-- > buf);
    if (n)
    {
      if (format_flag)        /* %e or %E */
      {
        cp = buf_pointer;
        while (cp > buf)
        {
          if (*(cp - 1) == '.')
          {
            *cp = *(cp - 2);
            cp--;
          }
          else
          {
            *cp = *(cp - 1);
          }
          cp--;
        }
        integral_10_log++;
      }
      else
      {
        cp = ++buf_pointer;
        while (cp > buf)
        {
          *cp = *(cp - 1);
          cp--;
        }
      }
      *buf = '1';
    }
  }
CLEAN_UP:
  if (g_flag)            /* %G - Remove trailing zeros */
  {
    while (*(buf_pointer - 1) == '0')
    {
      buf_pointer--;
    }
    if (*(buf_pointer - 1) == '.')
    {
      buf_pointer--;
    }
  }
  if (format_flag)        /* %e or %E */
  {
    *buf_pointer++ = format_flag;
    if (integral_10_log < 0)
    {
      *buf_pointer++ = '-';
      integral_10_log = -integral_10_log;
    }
    else
    {
      *buf_pointer++ = '+';
    }
    n = 0;
    buf_pointer +=10;
    do
    {
      n++;
      *buf_pointer++ = (integral_10_log % 10) + '0';
      integral_10_log /= 10;
    } while ( integral_10_log || n < 2 );
    for ( i = n ; n > 0 ; n-- )
      *(buf_pointer - 11 - i + n) = *(buf_pointer - n);
    buf_pointer -= 10;
  }
  return buf_pointer;
}

#endif


/*----------------------------------------------------------------------*/
/*                                                                      */
/*                        - _formatted_write -                          */
/*                                                                      */
/* This routine forms the core and entry of the formatter.  The con-    */
/* version performed conforms to the ANSI specification for "printf".   */
/*----------------------------------------------------------------------*/

int _formatted_write(const char *format,
                     void put_one_char(char, void *),
                     void *secret_pointer,
                     va_list ap)
#ifndef REDUCED_SUPPORT
{
  MEM_ATTRIBUTE char format_flag;
  MEM_ATTRIBUTE int precision;
  MEM_ATTRIBUTE int n;
  MEM_ATTRIBUTE int field_width, nr_of_chars;
  MEM_ATTRIBUTE char plus_space_flag, left_adjust, l_L_modifier;
  MEM_ATTRIBUTE char h_modifier, alternate_flag;
  MEM_ATTRIBUTE char nonzero_value;
  MEM_ATTRIBUTE unsigned long ulong, div_factor;

#ifdef FLOAT_SUPPORT
  MEM_ATTRIBUTE long double fvalue;
#endif

  MEM_ATTRIBUTE char *buf_pointer;
  MEM_ATTRIBUTE char *ptr, *hex;
  MEM_ATTRIBUTE char zeropad;
  MEM_ATTRIBUTE char buf[FRMWRI_BUFSIZE];

  nr_of_chars = 0;
  for (;;)    /* Until full format string read */
  {
    while ((format_flag = *format++) != '%')    /* Until '%' or '\0' */
    {
      if (!format_flag)
        return nr_of_chars;
      put_one_char(format_flag, secret_pointer);
      nr_of_chars++;
    }
    if (*format == '%')    /* %% prints as % */
    {
      format++;
      put_one_char('%',secret_pointer);
      nr_of_chars++;
      continue;
    }

    plus_space_flag = left_adjust = alternate_flag = zeropad = 0;
    ptr = buf_pointer = &buf[0];
    hex = "0123456789ABCDEF";
    /*===================================================*/
    /* check for leading '-', '+', ' ','#' or '0' flags  */
    /*===================================================*/
    for (;;)
    {
      switch (*format)
      {
      case ' ':
        if (plus_space_flag)
          goto NEXT_FLAG;
      case '+':
        plus_space_flag = *format;
        goto NEXT_FLAG;
      case '-':
        left_adjust++;
        goto NEXT_FLAG;
      case '#':
        alternate_flag++;
        goto NEXT_FLAG;
      case '0':
        zeropad++;
        goto NEXT_FLAG;
      }
      break;
NEXT_FLAG:
      format++;
    }

    /*===================================*/
    /* Optional field width (may be '*') */
    /*===================================*/
    if (*format == '*')
    {
      field_width = va_arg(ap, int);
      if (field_width < 0)
      {
        field_width = -field_width;
        left_adjust++;
      }
      format++;
    }
    else
    {
      field_width = 0;
      while (*format >= '0' && *format <= '9')
        field_width = field_width * 10 + (*format++ - '0');
    }

    if (left_adjust)
      zeropad = 0;
    /*=============================*/
    /* Optional precision (or '*') */
    /*=============================*/
    if (*format=='.')
    {
      if (*++format == '*')
      {
        precision = va_arg(ap, int);
        format++;
      }
      else
      {
        precision = 0;
        while (*format >= '0' && *format <= '9')
          precision = precision * 10 + (*format++ - '0');
      }
    }
    else
      precision = -1;

    /*======================================================*/
    /* At this point, "left_adjust" is nonzero if there was */
    /* a sign, "zeropad" is 1 if there was a leading zero   */
    /* and 0 otherwise, "field_width" and "precision"       */
    /* contain numbers corresponding to the digit strings   */
    /* before and after the decimal point, respectively,    */
    /* and "plus_space_flag" is either 0 (no flag) or con-  */
    /* tains a plus or space character. If there was no     */
    /* decimal point, "precision" will be -1.               */
    /*======================================================*/

    l_L_modifier = h_modifier = 0;
    /*==================================*/
    /* Optional 'l','L' r 'h' modifier? */
    /*==================================*/
    switch (*format)

⌨️ 快捷键说明

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