1462 lines
32 KiB
C
1462 lines
32 KiB
C
/****************************************************************************
|
|
* apps/testing/scanftest/scanftest_main.c
|
|
*
|
|
* Copyright (C) 2005-01-26, Greg King (https://github.com/cc65)
|
|
*
|
|
* Original License:
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from
|
|
* the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in
|
|
* a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
*
|
|
* 2. Altered source versions must be plainly marked as such, and must not
|
|
* be misrepresented as being the original software.
|
|
*
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
* Modified: Johannes Schock
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <dirent.h>
|
|
#include <limits.h>
|
|
#include <libgen.h>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define ARRAYSIZE(a) (sizeof (a) / sizeof (a)[0])
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: cmd_basename
|
|
****************************************************************************/
|
|
|
|
static const struct
|
|
{
|
|
FAR const char *input;
|
|
FAR const char *format;
|
|
int rvalue;
|
|
enum TYPE
|
|
{
|
|
INT,
|
|
CHAR,
|
|
FLOAT,
|
|
DOUBLE
|
|
} type1;
|
|
union
|
|
{
|
|
int nvalue;
|
|
float fvalue;
|
|
double dvalue;
|
|
const char *svalue;
|
|
} v1;
|
|
enum TYPE type2;
|
|
union
|
|
{
|
|
int nvalue;
|
|
float fvalue;
|
|
double dvalue;
|
|
const char *svalue;
|
|
} v2;
|
|
}
|
|
test_data[] =
|
|
{
|
|
/* Input sequences for character specifiers must be less than 80 characters
|
|
* long. These format strings are allowwed a maximum of two assignment
|
|
* specifications.
|
|
*/
|
|
|
|
/* Test that literals match, and that they aren't seen as conversions. **
|
|
* Test that integer specifiers can handle end-of-file.
|
|
*/
|
|
|
|
{
|
|
"qwerty Dvorak", "qwerty Dvorak", 0, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 1 */
|
|
{
|
|
"qwerty", "qwerty %d%i", EOF, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 2 */
|
|
{
|
|
"qwerty ", "qwerty %d%i", EOF, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 3 */
|
|
|
|
/* Test that integer specifiers scan properly. */
|
|
|
|
{
|
|
"qwerty a", "qwerty %d%i", 0, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 4 */
|
|
{
|
|
"qwerty -", "qwerty %d%i", 0, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 5 */
|
|
{
|
|
"qwerty -9", "qwerty %d%i", 1, INT,
|
|
{
|
|
.nvalue = -9
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 6 */
|
|
{
|
|
"qwerty -95", "qwerty %d%i", 1, INT,
|
|
{
|
|
.nvalue = -95
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 7 */
|
|
{
|
|
"qwerty -95a", "qwerty %d%i", 1, INT,
|
|
{
|
|
.nvalue = -95
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 8 */
|
|
{
|
|
"qwerty -95a 1", "qwerty %d%i", 1, INT,
|
|
{
|
|
.nvalue = -95
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 9 */
|
|
{
|
|
"qwerty -a", "qwerty %d%i", 0, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 10 */
|
|
{
|
|
"qwerty -95 1", "qwerty %d%i", 2, INT,
|
|
{
|
|
.nvalue = -95
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 1
|
|
}
|
|
}, /* 11 */
|
|
{
|
|
"qwerty 95 2", "qwerty %i", 1, INT,
|
|
{
|
|
.nvalue = 95
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 12 */
|
|
{
|
|
"qwerty -95 +2", "qwerty %x%o", 2, INT,
|
|
{
|
|
.nvalue = -0x95
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 2
|
|
}
|
|
}, /* 13 */
|
|
{
|
|
"qwerty 0x9e 02", "qwerty %i%i", 2, INT,
|
|
{
|
|
.nvalue = 0x9e
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 2
|
|
}
|
|
}, /* 14 */
|
|
{
|
|
"qwerty 095 2", "qwerty %i%i", 2, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 95
|
|
}
|
|
}, /* 15 */
|
|
{
|
|
"qwerty 0e5 2", "qwerty %i%i", 1, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 16 */
|
|
|
|
/* Test that character specifiers can handle end-of-file. */
|
|
|
|
{
|
|
"qwerty", "qwerty %s%s", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 17 */
|
|
{
|
|
"qwerty ", "qwerty %s%s", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 18 */
|
|
{
|
|
"qwerty", "qwerty %c%c", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 19 */
|
|
{
|
|
"qwerty ", "qwerty %c%c", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 20 */
|
|
{
|
|
"qwerty", "qwerty %[ a-z]%c", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 21 */
|
|
{
|
|
"qwerty ", "qwerty %[ a-z]%c", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 22 */
|
|
{
|
|
"qwerty ", "qwerty%s%s", EOF, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 23 */
|
|
|
|
/* Test that character specifiers scan properly. */
|
|
|
|
{
|
|
"123456qwertyasdfghzxcvbn!@#$%^QWERTYASDFGHZXCV"
|
|
"BN7890-=uiop[]\\jkl;'m,./&*()_+UIOP{}|JKL:\"M<>?", "%79s%79s", 2, CHAR,
|
|
{
|
|
.svalue = "123456qwertyasdfghzxcvbn!@#$%^QWERTYASDFGHZXCV"
|
|
"BN7890-=uiop[]\\jkl;'m,./&*()_+UIO"
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = "P{}|JKL:\"M<>?"
|
|
}
|
|
}, /* 24 */
|
|
{
|
|
"qwerty ", "qwerty%c%c", 2, CHAR,
|
|
{
|
|
.svalue = " "
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = " "
|
|
}
|
|
}, /* 25 */
|
|
{
|
|
"qwerty ", "qwerty%2c%c", 2, CHAR,
|
|
{
|
|
.svalue = " "
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = " "
|
|
}
|
|
}, /* 26 */
|
|
{
|
|
"qwerty ", "qwerty%2c%2c", 1, CHAR,
|
|
{
|
|
.svalue = " "
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = " "
|
|
}
|
|
}, /* 27 */
|
|
{
|
|
"qwerty ", "qwerty%[ a-z]%c", 1, CHAR,
|
|
{
|
|
.svalue = " "
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 28 */
|
|
{
|
|
"qwerty q", "qwerty%[ a-z]%c", 1, CHAR,
|
|
{
|
|
.svalue = " q"
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 29 */
|
|
{
|
|
"qwerty Q", "qwerty%[ a-z]%c", 2, CHAR,
|
|
{
|
|
.svalue = " "
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = "Q"
|
|
}
|
|
}, /* 30 */
|
|
{
|
|
"qwerty-QWERTY-", "%[q-ze-]%[-A-Z]", 2, CHAR,
|
|
{
|
|
.svalue = "qwerty-"
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = "QWERTY-"
|
|
}
|
|
}, /* 31 */
|
|
|
|
/* Test the space-separation of strings. */
|
|
|
|
{
|
|
"qwerty qwerty", "qwerty%s%s", 1, CHAR,
|
|
{
|
|
.svalue = "qwerty"
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 32 */
|
|
{
|
|
"qwerty qwerty Dvorak", "qwerty%s%s", 2, CHAR,
|
|
{
|
|
.svalue = "qwerty"
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = "Dvorak"
|
|
}
|
|
}, /* 33 */
|
|
|
|
/* Test the mixxing of types. */
|
|
|
|
{
|
|
"qwerty abc3", "qwerty%s%X", 1, CHAR,
|
|
{
|
|
.svalue = "abc3"
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 34 */
|
|
{
|
|
"qwerty abc3", "qwerty%[ a-z]%X", 2, CHAR,
|
|
{
|
|
.svalue = " abc"
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 3
|
|
}
|
|
}, /* 35 */
|
|
{
|
|
"qwerty abc3", "qwerty%[ a-z3]%X", 1, CHAR,
|
|
{
|
|
.svalue = " abc3"
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 36 */
|
|
{
|
|
"qwerty abc3", "qwerty%[ A-Z]%X", 2, CHAR,
|
|
{
|
|
.svalue = " "
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0xabc3
|
|
}
|
|
}, /* 37 */
|
|
{
|
|
"qwerty 3abc", "qwerty%i%[ a-z]", 2, INT,
|
|
{
|
|
.nvalue = 3
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = "abc"
|
|
}
|
|
}, /* 38 */
|
|
{
|
|
"qwerty 3abc", "qwerty%i%[ A-Z]", 1, INT,
|
|
{
|
|
.nvalue = 3
|
|
},
|
|
CHAR,
|
|
{
|
|
.svalue = ""
|
|
}
|
|
}, /* 39 */
|
|
|
|
/* Test the character-count specifier. */
|
|
|
|
{
|
|
" 95 5", "%n%i", 1, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 95
|
|
}
|
|
}, /* 40 */
|
|
{
|
|
" a5 5", "%n%i", 0, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 41 */
|
|
{
|
|
" a5 5", "%x%n", 1, INT,
|
|
{
|
|
.nvalue = 0xa5
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 4
|
|
}
|
|
}, /* 42 */
|
|
{
|
|
" a5 5", " %4c%n", 1, CHAR,
|
|
{
|
|
.svalue = "a5 5"
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 6
|
|
}
|
|
}, /* 43 */
|
|
{
|
|
" 05a9", "%i%n", 1, INT,
|
|
{
|
|
.nvalue = 5
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 3
|
|
}
|
|
}, /* 44 */
|
|
|
|
/* Test assignment-suppression. */
|
|
|
|
{
|
|
" 95 6", "%n%*i", 0, INT,
|
|
{
|
|
.nvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 45 */
|
|
{
|
|
" a5 6", "%*x%n", 0, INT,
|
|
{
|
|
.nvalue = 4
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 46 */
|
|
{
|
|
" a5 6", "%*x%n%o", 1, INT,
|
|
{
|
|
.nvalue = 4
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 6
|
|
}
|
|
}, /* 47 */
|
|
{
|
|
" a5 6", " %*4c%d", 0, CHAR,
|
|
{
|
|
.svalue = ""
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 48 */
|
|
{
|
|
"The first number is 7. The second number is 8.\n",
|
|
"%*[ .A-Za-z]%d%*[ .A-Za-z]%d", 2, INT,
|
|
{
|
|
.nvalue = 7
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 8
|
|
}
|
|
}, /* 49 */
|
|
|
|
/* Test that float specifiers can handle end-of-file. */
|
|
|
|
{
|
|
"qwerty", "qwerty %f%i", EOF, FLOAT,
|
|
{
|
|
.fvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 50 */
|
|
{
|
|
"qwerty ", "qwerty %f%i", EOF, FLOAT,
|
|
{
|
|
.fvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 51 */
|
|
|
|
/* Test that float specifiers scan properly. */
|
|
|
|
{
|
|
"qwerty a", "qwerty %f%i", 0, FLOAT,
|
|
{
|
|
.fvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 52 */
|
|
{
|
|
"qwerty -", "qwerty %f%i", 0, FLOAT,
|
|
{
|
|
.fvalue = 0
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 53 */
|
|
{
|
|
"qwerty 9.87654321", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = 9.87654321f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 54 */
|
|
{
|
|
"qwerty +9.87654321", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = 9.87654321f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 55 */
|
|
{
|
|
"qwerty -9.87654321", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = -9.87654321f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 56 */
|
|
{
|
|
"qwerty 9.87654321E8", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = 9.87654321E8f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 57 */
|
|
{
|
|
"qwerty +9.87654321E+8", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = 9.87654321E8f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 58 */
|
|
{
|
|
"qwerty -9.87654321e8", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = -9.87654321E8f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 59 */
|
|
{
|
|
"qwerty 9.87654321E-8", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = 9.87654321E-8f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 60 */
|
|
{
|
|
"qwerty -9.87654321e-8", "qwerty %f%i", 1, FLOAT,
|
|
{
|
|
.fvalue = -9.87654321E-8f
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 61 */
|
|
{
|
|
"qwerty 9.87654321", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = 9.87654321l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 62 */
|
|
{
|
|
"qwerty +9.87654321", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = 9.87654321l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 63 */
|
|
{
|
|
"qwerty -9.87654321", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = -9.87654321l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 64 */
|
|
{
|
|
"qwerty 9.87654321e8", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = 9.87654321E8l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 65 */
|
|
{
|
|
"qwerty +9.87654321e+8", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = 9.87654321E8l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 66 */
|
|
{
|
|
"qwerty -9.87654321E8", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = -9.87654321E8l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 67 */
|
|
{
|
|
"qwerty 9.87654321e-8", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = 9.87654321E-8l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 68 */
|
|
{
|
|
"qwerty -9.87654321E-8", "qwerty %lf%i", 1, DOUBLE,
|
|
{
|
|
.dvalue = -9.87654321E-8l
|
|
},
|
|
INT,
|
|
{
|
|
.nvalue = 0
|
|
}
|
|
}, /* 69 */
|
|
};
|
|
|
|
/* Test the char, short, and long specification-modifiers. */
|
|
|
|
static const struct
|
|
{
|
|
FAR const char *input;
|
|
FAR const char *format;
|
|
union
|
|
{
|
|
long long s;
|
|
unsigned long long u;
|
|
} value;
|
|
enum MODTYPE
|
|
{
|
|
HH_MOD_S,
|
|
HH_MOD_U,
|
|
H_MOD_S,
|
|
H_MOD_U,
|
|
NO_MOD_S,
|
|
NO_MOD_U,
|
|
L_MOD_S,
|
|
L_MOD_U,
|
|
LL_MOD_S,
|
|
LL_MOD_U
|
|
} type;
|
|
}
|
|
type_data[] =
|
|
{
|
|
{
|
|
" 123456789", "%hhd",
|
|
{
|
|
.s = (signed char)123456789L
|
|
},
|
|
HH_MOD_S
|
|
}, /* 1 */
|
|
{
|
|
"+123456789", "%hhd",
|
|
{
|
|
.s = (signed char)123456789L
|
|
},
|
|
HH_MOD_S
|
|
}, /* 2 */
|
|
{
|
|
"-123456789", "%hhd",
|
|
{
|
|
.s = (signed char)-123456789L
|
|
},
|
|
HH_MOD_S
|
|
}, /* 3 */
|
|
{
|
|
"+123456789", "%hhu",
|
|
{
|
|
.u = (unsigned char)123456789L
|
|
},
|
|
HH_MOD_U
|
|
}, /* 4 */
|
|
{
|
|
"-123456789", "%hhu",
|
|
{
|
|
.u = (unsigned char)-123456789L
|
|
},
|
|
HH_MOD_U
|
|
}, /* 5 */
|
|
{
|
|
" 123456789", "%hd",
|
|
{
|
|
.s = (signed short)123456789L
|
|
},
|
|
H_MOD_S
|
|
}, /* 6 */
|
|
{
|
|
"+123456789", "%hd",
|
|
{
|
|
.s = (signed short)123456789L
|
|
},
|
|
H_MOD_S
|
|
}, /* 7 */
|
|
{
|
|
"-123456789", "%hd",
|
|
{
|
|
.s = (signed short)-123456789L
|
|
},
|
|
H_MOD_S
|
|
}, /* 8 */
|
|
{
|
|
"+123456789", "%hu",
|
|
{
|
|
.u = (unsigned short)123456789L
|
|
},
|
|
H_MOD_U
|
|
}, /* 9 */
|
|
{
|
|
"-123456789", "%hu",
|
|
{
|
|
.u = (unsigned short)-123456789L
|
|
},
|
|
H_MOD_U
|
|
}, /* 10 */
|
|
{
|
|
" 123456789", "%d",
|
|
{
|
|
.s = (signed int)123456789L
|
|
},
|
|
NO_MOD_S
|
|
}, /* 11 */
|
|
{
|
|
"+123456789", "%d",
|
|
{
|
|
.s = (signed int)123456789L
|
|
},
|
|
NO_MOD_S
|
|
}, /* 12 */
|
|
{
|
|
"-123456789", "%d",
|
|
{
|
|
.s = (signed int)-123456789L
|
|
},
|
|
NO_MOD_S
|
|
}, /* 13 */
|
|
{
|
|
"+123456789", "%u",
|
|
{
|
|
.u = (unsigned int)123456789L
|
|
},
|
|
NO_MOD_U
|
|
}, /* 14 */
|
|
{
|
|
"-123456789", "%u",
|
|
{
|
|
.u = (unsigned int)-123456789L
|
|
},
|
|
NO_MOD_U
|
|
}, /* 15 */
|
|
{
|
|
" 123456789", "%ld",
|
|
{
|
|
.s = (signed long)123456789L
|
|
},
|
|
L_MOD_S
|
|
}, /* 16 */
|
|
{
|
|
"+123456789", "%ld",
|
|
{
|
|
.s = (signed long)123456789L
|
|
},
|
|
L_MOD_S
|
|
}, /* 17 */
|
|
{
|
|
"-123456789", "%ld",
|
|
{
|
|
.s = (signed long)-123456789L
|
|
},
|
|
L_MOD_S
|
|
}, /* 18 */
|
|
{
|
|
"+123456789", "%lu",
|
|
{
|
|
.u = (unsigned long)123456789L
|
|
},
|
|
L_MOD_U
|
|
}, /* 19 */
|
|
{
|
|
"-123456789", "%lu",
|
|
{
|
|
.u = (unsigned long)-123456789L
|
|
},
|
|
L_MOD_U
|
|
}, /* 20 */
|
|
{
|
|
" 123456789123456789", "%lld",
|
|
{
|
|
.s = (signed long long)123456789123456789LL
|
|
},
|
|
LL_MOD_S
|
|
}, /* 21 */
|
|
{
|
|
"+123456789123456789", "%lld",
|
|
{
|
|
.s = (signed long long)123456789123456789LL
|
|
},
|
|
LL_MOD_S
|
|
}, /* 22 */
|
|
{
|
|
"-123456789123456789", "%lld",
|
|
{
|
|
.s = (signed long long)-123456789123456789LL
|
|
},
|
|
LL_MOD_S
|
|
}, /* 23 */
|
|
{
|
|
"+123456789123456789", "%llu",
|
|
{
|
|
.u = (unsigned long long)123456789123456789LL
|
|
},
|
|
LL_MOD_U
|
|
}, /* 24 */
|
|
{
|
|
"-123456789123456789", "%llu",
|
|
{
|
|
.u = (unsigned long long)-123456789123456789LL
|
|
},
|
|
LL_MOD_U
|
|
}, /* 25 */
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* scanftest_main
|
|
****************************************************************************/
|
|
|
|
#if defined(BUILD_MODULE)
|
|
int main(int argc, FAR char *argv[])
|
|
#else
|
|
int scanftest_main(int argc, char *argv[])
|
|
#endif
|
|
{
|
|
int t;
|
|
int i;
|
|
int c;
|
|
int n1 = 12345;
|
|
int n2;
|
|
bool ok;
|
|
char s1[80];
|
|
char s2[80];
|
|
float f1;
|
|
float f2;
|
|
double d1;
|
|
double d2;
|
|
FAR FILE *fp;
|
|
|
|
FAR const char *teststring = "teststring a";
|
|
FAR const char *fname = "/mnt/fs/test.txt";
|
|
|
|
/* Test that scanf() can recognize percent-signs in the input. ** Test that
|
|
* integer converters skip white-space. ** Test that "%i" can scan a single
|
|
* zero digit (followed by EOF).
|
|
*/
|
|
|
|
sscanf("% \n\f\v\t 0", "%%%i", &n1);
|
|
if (n1 != 0)
|
|
{
|
|
printf("sscanf()'s \"%%%%%%i\" couldn't scan either a \"%%\" "
|
|
"or a single zero digit.\n\n");
|
|
}
|
|
|
|
/* Test scanf()'s return-value: EOF if input ends before the first *
|
|
* conversion-attempt begins; an assignment-count, otherwise. * Test that
|
|
* scanf() properly converts and assigns the correct number * of arguments.
|
|
*/
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
if (i)
|
|
{
|
|
char s3[3];
|
|
|
|
printf("\nBack to Back Test...\n");
|
|
|
|
memset(s1, '\0', sizeof s1);
|
|
memset(s2, '\0', sizeof s2);
|
|
memset(s3, '\0', sizeof s3);
|
|
|
|
fp = fopen(fname, "wb");
|
|
if (fp)
|
|
{
|
|
fputs(teststring, fp);
|
|
fclose(fp);
|
|
fp = fopen(fname, "rb");
|
|
if (fp != NULL)
|
|
{
|
|
fscanf(fp, "%s", s2);
|
|
fscanf(fp, "%2c", s3);
|
|
sprintf(s1, "%s%s", s2, s3);
|
|
|
|
if (strcmp(s1, teststring) != 0)
|
|
{
|
|
printf("Error %s != %s.\n", teststring, s1);
|
|
}
|
|
else
|
|
{
|
|
printf("Test PASSED.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("Error opening %s for read.\n", fname);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("Error opening %s for write.\n", fname);
|
|
}
|
|
}
|
|
|
|
printf("\nTesting %cscanf()'s return-value,\nconversions, and "
|
|
"assignments...\n",
|
|
i ? 'f' : 's');
|
|
|
|
for (t = 0; t < ARRAYSIZE(test_data); ++t)
|
|
{
|
|
/* Prefill the arguments with zeroes. */
|
|
|
|
f1 = f2 = d1 = d2 = n1 = n2 = 0;
|
|
memset(s1, '\0', sizeof s1);
|
|
memset(s2, '\0', sizeof s2);
|
|
|
|
ok = true;
|
|
|
|
if (i)
|
|
{
|
|
fp = fopen(fname, "wb");
|
|
if (fp)
|
|
{
|
|
fputs(test_data[t].input, fp);
|
|
fclose(fp);
|
|
}
|
|
else
|
|
{
|
|
printf("Error opening %s for write.\n", fname);
|
|
break;
|
|
}
|
|
|
|
fp = fopen(fname, "rb");
|
|
if (fp)
|
|
{
|
|
c = fscanf
|
|
(fp, test_data[t].format,
|
|
|
|
/* Avoid warning messages about different pointer-
|
|
* types, by casting them to void-pointers.
|
|
*/
|
|
|
|
test_data[t].type1 == INT ? (FAR void *)&n1 :
|
|
test_data[t].type1 == FLOAT ? (FAR void *)&f1 :
|
|
test_data[t].type1 == DOUBLE ? (FAR void *)&d1 :
|
|
(FAR void *)s1,
|
|
test_data[t].type2 == INT ? (FAR void *)&n2 :
|
|
test_data[t].type2 == FLOAT ? (FAR void *)&f2 :
|
|
test_data[t].type2 == DOUBLE ? (FAR void *)&d2 :
|
|
(FAR void *)s2
|
|
);
|
|
|
|
fclose(fp);
|
|
}
|
|
else
|
|
{
|
|
printf("Error opening %s for read.\n", fname);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
c = sscanf
|
|
(test_data[t].input, test_data[t].format,
|
|
|
|
/* Avoid warning messages about different pointer-types, by
|
|
* casting them to void-pointers.
|
|
*/
|
|
|
|
test_data[t].type1 == INT ? (FAR void *)&n1 :
|
|
test_data[t].type1 == FLOAT ? (FAR void *)&f1 :
|
|
test_data[t].type1 == DOUBLE ? (FAR void *)&d1 :
|
|
(FAR void *)s1,
|
|
test_data[t].type2 == INT ? (FAR void *)&n2 :
|
|
test_data[t].type2 == FLOAT ? (FAR void *)&f2 :
|
|
test_data[t].type2 == DOUBLE ? (FAR void *)&d2 :
|
|
(FAR void *)s2
|
|
);
|
|
}
|
|
if (c != test_data[t].rvalue)
|
|
{
|
|
printf("Test #%u returned %d instead of %d.\n", t + 1, c,
|
|
test_data[t].rvalue);
|
|
ok = false;
|
|
}
|
|
|
|
if (test_data[t].type1 == INT)
|
|
{
|
|
if (test_data[t].v1.nvalue != n1)
|
|
{
|
|
printf("Test #%u assigned %i, instead of %i,\n"
|
|
"\tto the first argument.\n\n", t + 1, n1,
|
|
test_data[t].v1.nvalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
else if (test_data[t].type1 == FLOAT)
|
|
{
|
|
if (test_data[t].v1.fvalue != f1)
|
|
{
|
|
printf("Test #%u assigned %e, instead of %e,\n"
|
|
"\tto the first argument.\n\n", t + 1, f1,
|
|
test_data[t].v1.fvalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
else if (test_data[t].type1 == DOUBLE)
|
|
{
|
|
if (test_data[t].v1.dvalue != d1)
|
|
{
|
|
printf("Test #%u assigned %le, instead of %le,\n"
|
|
"\tto the first argument.\n\n", t + 1, d1,
|
|
test_data[t].v1.dvalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* test_data[t].type1 == CHAR */
|
|
|
|
if (strcmp(test_data[t].v1.svalue, s1))
|
|
{
|
|
printf("Test #%u assigned\n\"%s\",\n"
|
|
"\tinstead of\n\"%s\",\n"
|
|
"\tto the first argument.\n\n", t + 1, s1,
|
|
test_data[t].v1.svalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
if (test_data[t].type2 == INT)
|
|
{
|
|
if (test_data[t].v2.nvalue != n2)
|
|
{
|
|
printf("Test #%u assigned %i, instead of %i,\n"
|
|
"\tto the second argument.\n\n", t + 1, n2,
|
|
test_data[t].v2.nvalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
else if (test_data[t].type2 == FLOAT)
|
|
{
|
|
if (test_data[t].v2.fvalue != f2)
|
|
{
|
|
printf("Test #%u assigned %e, instead of %e,\n"
|
|
"\tto the second argument.\n\n", t + 1, f2,
|
|
test_data[t].v2.fvalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
else if (test_data[t].type2 == DOUBLE)
|
|
{
|
|
if (test_data[t].v2.dvalue != d2)
|
|
{
|
|
printf("Test #%u assigned %le, instead of %le,\n"
|
|
"\tto the second argument.\n\n", t + 1, d2,
|
|
test_data[t].v2.dvalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* test_data[t].type2 == CHAR */
|
|
|
|
if (strcmp(test_data[t].v2.svalue, s2))
|
|
{
|
|
printf("Test #%u assigned\n\"%s\",\n"
|
|
"\tinstead of\n\"%s\",\n"
|
|
"\tto the second argument.\n\n", t + 1, s2,
|
|
test_data[t].v2.svalue);
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
if (ok)
|
|
{
|
|
printf("Test #%u PASSED.\n", t + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Test the char, short, and long specification-modifiers. */
|
|
|
|
printf("\nTesting scanf()'s type-modifiers...\n");
|
|
for (t = 0; t < ARRAYSIZE(type_data); ++t)
|
|
{
|
|
unsigned char hhu;
|
|
unsigned short hu;
|
|
unsigned int nou;
|
|
unsigned long lu;
|
|
unsigned long long llu;
|
|
signed char hhs;
|
|
signed short hs;
|
|
signed int nos;
|
|
signed long ls;
|
|
signed long long lls;
|
|
|
|
ok = true;
|
|
switch (type_data[t].type)
|
|
{
|
|
case HH_MOD_S:
|
|
hhs = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &hhs);
|
|
if (type_data[t].value.s != hhs)
|
|
{
|
|
printf("Test #%u assigned %hhd instead of %lli.\n", t + 1,
|
|
hhs, type_data[t].value.s);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case HH_MOD_U:
|
|
hhu = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &hhu);
|
|
if (type_data[t].value.u != hhu)
|
|
{
|
|
printf("Test #%u assigned %hhu instead of %lli.\n",
|
|
t + 1, hhu, type_data[t].value.u);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case H_MOD_S:
|
|
hs = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &hs);
|
|
if (type_data[t].value.s != hs)
|
|
{
|
|
printf("Test #%u assigned %hd instead of %lli.\n",
|
|
t + 1, hs, type_data[t].value.s);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case H_MOD_U:
|
|
hu = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &hu);
|
|
if (type_data[t].value.u != hu)
|
|
{
|
|
printf("Test #%u assigned %hu instead of %lli.\n",
|
|
t + 1, hu, type_data[t].value.u);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case NO_MOD_S:
|
|
nos = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &nos);
|
|
if (type_data[t].value.s != nos)
|
|
{
|
|
printf("Test #%u assigned %d instead of %lli.\n",
|
|
t + 1, nos, type_data[t].value.s);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case NO_MOD_U:
|
|
nou = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &nou);
|
|
if (type_data[t].value.u != nou)
|
|
{
|
|
printf("Test #%u assigned %nou instead of %lli.\n",
|
|
t + 1, nou, type_data[t].value.u);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case L_MOD_S:
|
|
ls = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &ls);
|
|
if (type_data[t].value.s != ls)
|
|
{
|
|
printf("Test #%u assigned %ld instead of %lli.\n",
|
|
t + 1, ls, type_data[t].value.s);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case L_MOD_U:
|
|
lu = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &lu);
|
|
if (type_data[t].value.u != lu)
|
|
{
|
|
printf("Test #%u assigned %lu instead of %lli.\n",
|
|
t + 1, lu, type_data[t].value.u);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case LL_MOD_S:
|
|
lls = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &lls);
|
|
if (type_data[t].value.s != lls)
|
|
{
|
|
printf("Test #%u assigned %lld instead of %lli.\n",
|
|
t + 1, lls, type_data[t].value.s);
|
|
ok = false;
|
|
}
|
|
break;
|
|
|
|
case LL_MOD_U:
|
|
llu = 0L;
|
|
sscanf(type_data[t].input, type_data[t].format, &llu);
|
|
if (type_data[t].value.u != llu)
|
|
{
|
|
printf("Test #%u assigned %llu instead of %lli.\n",
|
|
t + 1, llu, type_data[t].value.u);
|
|
ok = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (ok)
|
|
{
|
|
printf("Test #%u PASSED.\n", t + 1);
|
|
}
|
|
}
|
|
|
|
return OK;
|
|
}
|