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

📄 frmrd.c

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

   Common formatter to "sscanf" and "scanf".

   It conforms to the ANSI specifications with the following exceptions:
   -------------------------------------------------------------
   1.   No overflow checking for integer types
   -------------------------------------------------------------
   2.   "scanf" reads complete lines which means that
        "getchar" and "scanf" cannot be combined (e.g.
        first reading a double with "scanf" and then
        read something else on that line with "getchar").
   -------------------------------------------------------------
        Should be compiled with:
          -DFLOAT_SUPPORT               Full formatter
          -DNO_FLOATS                   All but floats
          -DREDUCED_SUPPORT             Basic 'int' type of converter

   $Revision: 1.4 $

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

#include "stdarg.h"
#include "stdio.h"
#include "ctype.h"
#include "limits.h"
#include "float.h"
#include "icclbutl.h"   /* Contains low-level declarations */
#include "sysmac.h"


#ifdef FLOAT_SUPPORT
#define WANT_LONG_TYPES
#define WANT_FLOAT_TYPES
#else
#ifdef NO_FLOATS
#define WANT_LONG_TYPES
#else
#ifndef REDUCED_SUPPORT
#error -DFLOAT_SUPPORT, -DNO_FLOATS or -DREDUCED_SUPPORT missing
#endif
#endif
#endif


#define ILL_BASE                100     /* ILL_BASE indicator           */
#define MAX_FIELD_ALLOWED       512     /* Limit to one conversion      */

#define ASSIGN_FLAG             0x01
#define ITEM_FLAG               0x02
#define SHORT_FLAG              0x04
#define LONG_FLAG               0x08


static int get_num_and_scan(const char **ptr, int *wptr)
{
  int n = 0;

  while (isdigit(**ptr) && *wptr)
  {
    if ((n = 10 * n + *(*ptr)++ - '0') > 1000)
    {
      n = 1000;
    }
    (*wptr)--;
  }
  return n;
}


static char get_non_space(const char **strptr)
{
  char c;

  c = **strptr;
  while (isspace(c))
  {
    c = *++(*strptr);
  }
  return c;
}


static char get_num_base(char c, char b)
{
  c = toupper(c);

  if ('A' <= c && c <= 'Z')
    c = (c - 'A') + 10;
  else if (isdigit(c))
    c -= '0';
  else
    return ILL_BASE;
  if (c >= b)
    return ILL_BASE;
  return c;
}


static char get_sign_etc(const char **str_ptr, char *sign_ptr, int *wptr)
{
  char c;

  if ((c = get_non_space(str_ptr)) == '+' || c == '-')
  {
    if (*wptr)
    {
      (*wptr)--;
      if (c == '-')
      {
        *sign_ptr = 1;
      }
      c = *++(*str_ptr);
    }
  }
  return c;
}


#ifndef REDUCED_SUPPORT
static char get_valid_char(char ch, char standard_compare, const char *str)
{
  do
  {
    if (ch == *str)
    {
      return standard_compare;
    }
  }
  while (*++str && *str != ']');
  return !standard_compare;
}
#endif


#ifdef FLOAT_SUPPORT
static double pow10(int i)
{
  double factor, temp;

  factor = 10;
  temp = 1;
  while (i)
  {
    if (i & 1)
    {
      temp *= factor;
    }
    if (i >>= 1)
    {
      factor *= factor;
    }
  }
  return temp;
}
#endif


/*======================================================================*/
/*                                                                      */
/*      Formatter for [scanf] function. Reads data from "line".         */
/*                                                                      */
/*      Returns: the number of parameters successfully scanned.         */
/*                                                                      */
/*======================================================================*/

int _formatted_read(const char **line, const char **format, va_list ap)
{
  char flags, c, sign_flag, *temp_string_ptr;
  int  assigned_items, i, field_width;
  short num_base;

#ifdef  WANT_LONG_TYPES
  unsigned long value;
#else
  unsigned int value;
#endif

#ifndef REDUCED_SUPPORT
  const char *save_line = *line;
#endif

#ifdef  FLOAT_SUPPORT
  long double fvalue, factor;
  char exp_sign;
  int main_digs;
#endif

  assigned_items = 0;

  while (c = *(*format))
  {
    if (isspace(c))
    {
      while (isspace(**line))
      {
        (*line)++;
      }
      (*format)++;
      continue;
    }

    if (**format != '%' || *(*format + 1) != 'n')
    {
      if (!**line)
      {
        goto BAD_CONVERSION;
      }
    }

    if (c != '%')
    {
      (*format)++;
      if (c != get_non_space(line))
      {
        break;
      }
      else
      {
        (*line)++;
      }
      continue;
    }

/*======================================================================*/
/*      Process a conversion specification                              */
/*======================================================================*/
    sign_flag = 0;

    if ((c = *++(*format)) == '*')
    {
      c = *++(*format);
      flags &= ~ASSIGN_FLAG;
    }
    else
    {
      flags |= ASSIGN_FLAG;
    }
    if (isdigit(c))
    {
      i = MAX_FIELD_ALLOWED;
      field_width = get_num_and_scan(format, &i);
      c = **format;
    }
    else
    {
      field_width = MAX_FIELD_ALLOWED;
    }

#ifndef  REDUCED_SUPPORT
    flags &= ~(LONG_FLAG | SHORT_FLAG);
    if (c == 'l' || c == 'L')
    {
      flags |= LONG_FLAG;
      c = *++(*format);
    }
    else
    {
      if (c == 'h')
      {
        if (sizeof(int) == sizeof(long))
          flags |= SHORT_FLAG;
        c = *++(*format);
      }
    }
#endif

    (*format)++;
    switch (c)
    {

#ifdef  FLOAT_SUPPORT
/*======================================================================*/
/*        Convert a double                                              */
/*======================================================================*/
    case 'f':
    case 'g':
    case 'e':
    case 'G':
    case 'E':
      c = get_sign_etc(line, &sign_flag, &field_width);

      fvalue = 0;
      i = field_width;
      main_digs = -1;

      while (field_width && c == '0')
      {
        field_width--;
        c = *++(*line);
      }

      while (field_width && isdigit(c))
      {
        if (sizeof(float) == sizeof(double))
        {
          if (++main_digs == FLT_MAX_10_EXP)
          {
            goto BAD_CONVERSION;
          }
        }
        if (sizeof(float) != sizeof(double))
        {
          if (++main_digs == ((flags & LONG_FLAG) ?
                              DBL_MAX_10_EXP : FLT_MAX_10_EXP))
          {
            goto BAD_CONVERSION;
          }
        }

        field_width--;
        fvalue = fvalue * 10 + (c - '0');
        c = *++(*line);
      }

      if (c == '.' && field_width)
      {
        factor = 1;
        field_width--;
        i--;
        while (field_width && isdigit(c = *++(*line)))
        {
          field_width--;
          if (   (fvalue += (c - '0') * (factor *= 0.1))
              && !factor)
          {
            goto BAD_CONVERSION;
          }
        }
      }

      if (i == field_width)
      {
        goto BAD_CONVERSION;
      }

      if (field_width-- && tolower(c) == 'e')
      {
        (*line)++;
        exp_sign = 0;
        if (!isdigit(get_sign_etc(line, &exp_sign, &field_width)))
        {
          goto BAD_CONVERSION;
        }

        i = get_num_and_scan(line, &field_width);
        if (exp_sign)
        {

⌨️ 快捷键说明

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