fixed issue #51
This commit is contained in:
parent
1cfa8e42c4
commit
715fa54d45
55 changed files with 747 additions and 366 deletions
1
stdex/.gitignore
vendored
Normal file
1
stdex/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/*.out
|
15
stdex/RUN.sh
Normal file
15
stdex/RUN.sh
Normal file
|
@ -0,0 +1,15 @@
|
|||
rm -f *.out
|
||||
for i in *.toml; do
|
||||
echo -n $i
|
||||
../toml_cat $i >& $i.out
|
||||
if [ -f $i.res ]; then
|
||||
if $(diff $i.out $i.res >& /dev/null); then
|
||||
echo " [OK]"
|
||||
else
|
||||
echo " [FAILED]"
|
||||
fi
|
||||
else
|
||||
echo " [??]"
|
||||
fi
|
||||
|
||||
done
|
3
stdex/comment.toml
Normal file
3
stdex/comment.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# This is a full-line comment
|
||||
key = "value" # This is a comment at the end of a line
|
||||
another = "# This is not a comment"
|
4
stdex/comment.toml.res
Normal file
4
stdex/comment.toml.res
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
key = "value",
|
||||
another = "# This is not a comment",
|
||||
}
|
4
stdex/keys00.toml
Normal file
4
stdex/keys00.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
key = "value"
|
||||
bare_key = "value"
|
||||
bare-key = "value"
|
||||
1234 = "value"
|
6
stdex/keys00.toml.res
Normal file
6
stdex/keys00.toml.res
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
key = "value",
|
||||
bare_key = "value",
|
||||
bare-key = "value",
|
||||
1234 = "value",
|
||||
}
|
5
stdex/keys01.toml
Normal file
5
stdex/keys01.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
"127.0.0.1" = "value"
|
||||
"character encoding" = "value"
|
||||
"ʎǝʞ" = "value"
|
||||
'key2' = "value"
|
||||
'quoted "value"' = "value"
|
7
stdex/keys01.toml.res
Normal file
7
stdex/keys01.toml.res
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
127.0.0.1 = "value",
|
||||
character encoding = "value",
|
||||
ʎǝʞ = "value",
|
||||
key2 = "value",
|
||||
quoted "value" = "value",
|
||||
}
|
1
stdex/keys02.toml
Normal file
1
stdex/keys02.toml
Normal file
|
@ -0,0 +1 @@
|
|||
= "no key name" # INVALID
|
1
stdex/keys02.toml.res
Normal file
1
stdex/keys02.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 1: syntax error
|
1
stdex/keys03.toml
Normal file
1
stdex/keys03.toml
Normal file
|
@ -0,0 +1 @@
|
|||
"" = "blank" # VALID but discouraged
|
3
stdex/keys03.toml.res
Normal file
3
stdex/keys03.toml.res
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
= "blank",
|
||||
}
|
4
stdex/keys04.toml
Normal file
4
stdex/keys04.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
name = "Orange"
|
||||
physical.color = "orange"
|
||||
physical.shape = "round"
|
||||
site."google.com" = true
|
10
stdex/keys04.toml.res
Normal file
10
stdex/keys04.toml.res
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
name = "Orange",
|
||||
physical = {
|
||||
color = "orange",
|
||||
shape = "round",
|
||||
},
|
||||
site = {
|
||||
google.com = true,
|
||||
},
|
||||
}
|
3
stdex/keys05.toml
Normal file
3
stdex/keys05.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
fruit.name = "banana" # this is best practice
|
||||
fruit. color = "yellow" # same as fruit.color
|
||||
fruit . flavor = "banana" # same as fruit.flavor
|
7
stdex/keys05.toml.res
Normal file
7
stdex/keys05.toml.res
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
fruit = {
|
||||
name = "banana",
|
||||
color = "yellow",
|
||||
flavor = "banana",
|
||||
},
|
||||
}
|
3
stdex/keys06.toml
Normal file
3
stdex/keys06.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# DO NOT DO THIS
|
||||
name = "Tom"
|
||||
name = "Pradyun"
|
1
stdex/keys06.toml.res
Normal file
1
stdex/keys06.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 3: key exists
|
3
stdex/keys07.toml
Normal file
3
stdex/keys07.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# THIS WILL NOT WORK
|
||||
spelling = "favorite"
|
||||
"spelling" = "favourite"
|
1
stdex/keys07.toml.res
Normal file
1
stdex/keys07.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 3: key exists
|
5
stdex/keys08.toml
Normal file
5
stdex/keys08.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
# This makes the key "fruit" into a table.
|
||||
fruit.apple.smooth = true
|
||||
|
||||
# So then you can add to the table "fruit" like so:
|
||||
fruit.orange = 2
|
8
stdex/keys08.toml.res
Normal file
8
stdex/keys08.toml.res
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
fruit = {
|
||||
orange = 2,
|
||||
apple = {
|
||||
smooth = true,
|
||||
},
|
||||
},
|
||||
}
|
8
stdex/keys09.toml
Normal file
8
stdex/keys09.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# THE FOLLOWING IS INVALID
|
||||
|
||||
# This defines the value of fruit.apple to be an integer.
|
||||
fruit.apple = 1
|
||||
|
||||
# But then this treats fruit.apple like it's a table.
|
||||
# You can't turn an integer into a table.
|
||||
fruit.apple.smooth = true
|
1
stdex/keys09.toml.res
Normal file
1
stdex/keys09.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 8: key exists
|
10
stdex/keys10.toml
Normal file
10
stdex/keys10.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
# VALID BUT DISCOURAGED
|
||||
|
||||
apple.type = "fruit"
|
||||
orange.type = "fruit"
|
||||
|
||||
apple.skin = "thin"
|
||||
orange.skin = "thick"
|
||||
|
||||
apple.color = "red"
|
||||
orange.color = "orange"
|
12
stdex/keys10.toml.res
Normal file
12
stdex/keys10.toml.res
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
apple = {
|
||||
type = "fruit",
|
||||
skin = "thin",
|
||||
color = "red",
|
||||
},
|
||||
orange = {
|
||||
type = "fruit",
|
||||
skin = "thick",
|
||||
color = "orange",
|
||||
},
|
||||
}
|
9
stdex/keys11.toml
Normal file
9
stdex/keys11.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
# RECOMMENDED
|
||||
|
||||
apple.type = "fruit"
|
||||
apple.skin = "thin"
|
||||
apple.color = "red"
|
||||
|
||||
orange.type = "fruit"
|
||||
orange.skin = "thick"
|
||||
orange.color = "orange"
|
12
stdex/keys11.toml.res
Normal file
12
stdex/keys11.toml.res
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
apple = {
|
||||
type = "fruit",
|
||||
skin = "thin",
|
||||
color = "red",
|
||||
},
|
||||
orange = {
|
||||
type = "fruit",
|
||||
skin = "thick",
|
||||
color = "orange",
|
||||
},
|
||||
}
|
1
stdex/keys12.toml
Normal file
1
stdex/keys12.toml
Normal file
|
@ -0,0 +1 @@
|
|||
3.14159 = "pi"
|
5
stdex/keys12.toml.res
Normal file
5
stdex/keys12.toml.res
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
3 = {
|
||||
14159 = "pi",
|
||||
},
|
||||
}
|
1
stdex/kvpair0.toml
Normal file
1
stdex/kvpair0.toml
Normal file
|
@ -0,0 +1 @@
|
|||
key = "value"
|
3
stdex/kvpair0.toml.res
Normal file
3
stdex/kvpair0.toml.res
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
key = "value",
|
||||
}
|
1
stdex/kvpair1.toml
Normal file
1
stdex/kvpair1.toml
Normal file
|
@ -0,0 +1 @@
|
|||
key = # INVALID
|
1
stdex/kvpair1.toml.res
Normal file
1
stdex/kvpair1.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 1: syntax error
|
1
stdex/kvpair2.toml
Normal file
1
stdex/kvpair2.toml
Normal file
|
@ -0,0 +1 @@
|
|||
first = "Tom" last = "Preston-Werner" # INVALID
|
1
stdex/kvpair2.toml.res
Normal file
1
stdex/kvpair2.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 1: extra chars after value
|
1
stdex/string0.toml
Normal file
1
stdex/string0.toml
Normal file
|
@ -0,0 +1 @@
|
|||
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
|
3
stdex/string0.toml.res
Normal file
3
stdex/string0.toml.res
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
str = "I'm a string. \"You can quote me\". Name\tJos\0xc3\0xa9\nLocation\tSF.",
|
||||
}
|
9
stdex/string1.toml
Normal file
9
stdex/string1.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
str1 = """
|
||||
Roses are red
|
||||
Violets are blue"""
|
||||
|
||||
# On a Unix system, the above multi-line string will most likely be the same as:
|
||||
str2 = "Roses are red\nViolets are blue"
|
||||
|
||||
# On a Windows system, it will most likely be equivalent to:
|
||||
str3 = "Roses are red\r\nViolets are blue"
|
5
stdex/string1.toml.res
Normal file
5
stdex/string1.toml.res
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
str1 = "Roses are red\nViolets are blue",
|
||||
str2 = "Roses are red\nViolets are blue",
|
||||
str3 = "Roses are red\r\nViolets are blue",
|
||||
}
|
15
stdex/string3.toml
Normal file
15
stdex/string3.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
# The following strings are byte-for-byte equivalent:
|
||||
str1 = "The quick brown fox jumps over the lazy dog."
|
||||
|
||||
str2 = """
|
||||
The quick brown \
|
||||
|
||||
|
||||
fox jumps over \
|
||||
the lazy dog."""
|
||||
|
||||
str3 = """\
|
||||
The quick brown \
|
||||
fox jumps over \
|
||||
the lazy dog.\
|
||||
"""
|
5
stdex/string3.toml.res
Normal file
5
stdex/string3.toml.res
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
str1 = "The quick brown fox jumps over the lazy dog.",
|
||||
str2 = "The quick brown fox jumps over the lazy dog.",
|
||||
str3 = "The quick brown fox jumps over the lazy dog.",
|
||||
}
|
7
stdex/string4.toml
Normal file
7
stdex/string4.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
str4 = """Here are two quotation marks: "". Simple enough."""
|
||||
# str5 = """Here are three quotation marks: """.""" # INVALID
|
||||
str5 = """Here are three quotation marks: ""\"."""
|
||||
str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
|
||||
|
||||
# "This," she said, "is just a pointless statement."
|
||||
str7 = """"This," she said, "is just a pointless statement.""""
|
6
stdex/string4.toml.res
Normal file
6
stdex/string4.toml.res
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
str4 = "Here are two quotation marks: \"\". Simple enough.",
|
||||
str5 = "Here are three quotation marks: \"\"\".",
|
||||
str6 = "Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".",
|
||||
str7 = "\"This,\" she said, \"is just a pointless statement.\"",
|
||||
}
|
5
stdex/string5.toml
Normal file
5
stdex/string5.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
# What you see is what you get.
|
||||
winpath = 'C:\Users\nodejs\templates'
|
||||
winpath2 = '\\ServerX\admin$\system32\'
|
||||
quoted = 'Tom "Dubs" Preston-Werner'
|
||||
regex = '<\i\c*\s*>'
|
6
stdex/string5.toml.res
Normal file
6
stdex/string5.toml.res
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
winpath = "C:\\Users\\nodejs\\templates",
|
||||
winpath2 = "\\\\ServerX\\admin$\\system32\\",
|
||||
quoted = "Tom \"Dubs\" Preston-Werner",
|
||||
regex = "<\\i\\c*\\s*>",
|
||||
}
|
7
stdex/string6.toml
Normal file
7
stdex/string6.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
regex2 = '''I [dw]on't need \d{2} apples'''
|
||||
lines = '''
|
||||
The first newline is
|
||||
trimmed in raw strings.
|
||||
All other whitespace
|
||||
is preserved.
|
||||
'''
|
4
stdex/string6.toml.res
Normal file
4
stdex/string6.toml.res
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
regex2 = "I [dw]on't need \\d{2} apples",
|
||||
lines = "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n",
|
||||
}
|
4
stdex/string7.toml
Normal file
4
stdex/string7.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
quot15 = '''Here are fifteen quotation marks: """""""""""""""'''
|
||||
|
||||
# 'That,' she said, 'is still pointless.'
|
||||
str = ''''That,' she said, 'is still pointless.''''
|
4
stdex/string7.toml.res
Normal file
4
stdex/string7.toml.res
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
quot15 = "Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"",
|
||||
str = "'That,' she said, 'is still pointless.'",
|
||||
}
|
3
stdex/string8.toml
Normal file
3
stdex/string8.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID
|
||||
apos15 = "Here are fifteen apostrophes: '''''''''''''''"
|
||||
|
1
stdex/string8.toml.res
Normal file
1
stdex/string8.toml.res
Normal file
|
@ -0,0 +1 @@
|
|||
ERROR: line 2: triple-s-quote inside string lit
|
34
toml.h
34
toml.h
|
@ -1,19 +1,19 @@
|
|||
/*
|
||||
MIT License
|
||||
|
||||
|
||||
Copyright (c) 2017 - 2019 CK Tan
|
||||
https://github.com/cktan/tomlc99
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
@ -41,14 +41,14 @@ typedef struct toml_table_t toml_table_t;
|
|||
typedef struct toml_array_t toml_array_t;
|
||||
typedef struct toml_datum_t toml_datum_t;
|
||||
|
||||
/* Parse a file. Return a table on success, or 0 otherwise.
|
||||
/* Parse a file. Return a table on success, or 0 otherwise.
|
||||
* Caller must toml_free(the-return-value) after use.
|
||||
*/
|
||||
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
|
||||
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
|
||||
char* errbuf,
|
||||
int errbufsz);
|
||||
|
||||
/* Parse a string containing the full config.
|
||||
/* Parse a string containing the full config.
|
||||
* Return a table on success, or 0 otherwise.
|
||||
* Caller must toml_free(the-return-value) after use.
|
||||
*/
|
||||
|
@ -56,14 +56,14 @@ TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */
|
|||
char* errbuf,
|
||||
int errbufsz);
|
||||
|
||||
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
||||
* this function is called, any handles accessed through this tab
|
||||
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
||||
* this function is called, any handles accessed through this tab
|
||||
* directly or indirectly are no longer valid.
|
||||
*/
|
||||
TOML_EXTERN void toml_free(toml_table_t* tab);
|
||||
|
||||
|
||||
/* Timestamp types. The year, month, day, hour, minute, second, z
|
||||
/* Timestamp types. The year, month, day, hour, minute, second, z
|
||||
* fields may be NULL if they are not relevant. e.g. In a DATE
|
||||
* type, the hour, minute, second and z fields will be NULLs.
|
||||
*/
|
||||
|
@ -80,7 +80,7 @@ struct toml_timestamp_t {
|
|||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Enhanced access methods
|
||||
* Enhanced access methods
|
||||
*/
|
||||
struct toml_datum_t {
|
||||
int ok;
|
||||
|
@ -122,13 +122,13 @@ TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab,
|
|||
const char* key);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* lesser used
|
||||
* lesser used
|
||||
*/
|
||||
/* Return the array kind: 't'able, 'a'rray, 'v'alue */
|
||||
/* Return the array kind: 't'able, 'a'rray, 'v'alue, 'm'ixed */
|
||||
TOML_EXTERN char toml_array_kind(const toml_array_t* arr);
|
||||
|
||||
/* For array kind 'v'alue, return the type of values
|
||||
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp
|
||||
/* For array kind 'v'alue, return the type of values
|
||||
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp, 'm'ixed
|
||||
0 if unknown
|
||||
*/
|
||||
TOML_EXTERN char toml_array_type(const toml_array_t* arr);
|
||||
|
@ -149,7 +149,7 @@ TOML_EXTERN int toml_table_ntab(const toml_table_t* tab);
|
|||
TOML_EXTERN const char* toml_table_key(const toml_table_t* tab);
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
* misc
|
||||
* misc
|
||||
*/
|
||||
TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret);
|
||||
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
|
||||
|
@ -158,7 +158,7 @@ TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t),
|
|||
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
* deprecated
|
||||
* deprecated
|
||||
*/
|
||||
/* A raw value, must be processed by toml_rto* before using. */
|
||||
typedef const char* toml_raw_t;
|
||||
|
|
321
toml_cat.c
321
toml_cat.c
|
@ -1,26 +1,26 @@
|
|||
/*
|
||||
MIT License
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 CK Tan
|
||||
https://github.com/cktan/tomlc99
|
||||
Copyright (c) 2017 CK Tan
|
||||
https://github.com/cktan/tomlc99
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
@ -33,6 +33,8 @@ SOFTWARE.
|
|||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
#include "toml.h"
|
||||
|
||||
typedef struct node_t node_t;
|
||||
|
@ -43,128 +45,229 @@ struct node_t {
|
|||
|
||||
node_t stack[20];
|
||||
int stacktop = 0;
|
||||
int indent = 0;
|
||||
|
||||
|
||||
static void print_table_title(const char* arrname)
|
||||
static void prindent()
|
||||
{
|
||||
int i;
|
||||
printf("%s", arrname ? "[[" : "[");
|
||||
for (i = 1; i < stacktop; i++) {
|
||||
printf("%s", stack[i].key);
|
||||
if (i + 1 < stacktop)
|
||||
printf(".");
|
||||
}
|
||||
if (arrname)
|
||||
printf(".%s]]\n", arrname);
|
||||
else
|
||||
printf("]\n");
|
||||
for (int i = 0; i < indent; i++) printf(" ");
|
||||
}
|
||||
|
||||
|
||||
static void print_string(const char* s)
|
||||
{
|
||||
int ok = 1;
|
||||
for (const char* p = s; *p && ok; p++) {
|
||||
int ch = *p;
|
||||
ok = isprint(ch) && ch != '"' && ch != '\\';
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
printf("\"%s\"", s);
|
||||
return;
|
||||
}
|
||||
|
||||
int len = strlen(s);
|
||||
|
||||
printf("\"");
|
||||
for ( ; len; len--, s++) {
|
||||
int ch = *s;
|
||||
if (isprint(ch) && ch != '"' && ch != '\\') {
|
||||
putchar(ch);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case 0x8: printf("\\b"); continue;
|
||||
case 0x9: printf("\\t"); continue;
|
||||
case 0xa: printf("\\n"); continue;
|
||||
case 0xc: printf("\\f"); continue;
|
||||
case 0xd: printf("\\r"); continue;
|
||||
case '"': printf("\\\""); continue;
|
||||
case '\\': printf("\\\\"); continue;
|
||||
default: printf("\\0x%02x", ch & 0xff); continue;
|
||||
}
|
||||
}
|
||||
printf("\"");
|
||||
}
|
||||
|
||||
|
||||
static void print_array_of_tables(toml_array_t* arr, const char* key);
|
||||
static void print_array(toml_array_t* arr);
|
||||
|
||||
|
||||
static void print_table(toml_table_t* curtab)
|
||||
{
|
||||
toml_datum_t d;
|
||||
int i;
|
||||
const char* key;
|
||||
const char* raw;
|
||||
toml_array_t* arr;
|
||||
toml_table_t* tab;
|
||||
|
||||
|
||||
for (i = 0; 0 != (key = toml_key_in(curtab, i)); i++) {
|
||||
if (0 != (raw = toml_raw_in(curtab, key))) {
|
||||
printf("%s = %s\n", key, raw);
|
||||
} else if (0 != (arr = toml_array_in(curtab, key))) {
|
||||
if (toml_array_kind(arr) == 't') {
|
||||
print_array_of_tables(arr, key);
|
||||
}
|
||||
else {
|
||||
printf("%s = [\n", key);
|
||||
print_array(arr);
|
||||
printf(" ]\n");
|
||||
}
|
||||
} else if (0 != (tab = toml_table_in(curtab, key))) {
|
||||
stack[stacktop].key = key;
|
||||
stack[stacktop].tab = tab;
|
||||
stacktop++;
|
||||
print_table_title(0);
|
||||
print_table(tab);
|
||||
stacktop--;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_array_of_tables(toml_array_t* arr, const char* key)
|
||||
{
|
||||
int i;
|
||||
toml_table_t* tab;
|
||||
printf("\n");
|
||||
for (i = 0; 0 != (tab = toml_table_at(arr, i)); i++) {
|
||||
print_table_title(key);
|
||||
print_table(tab);
|
||||
printf("\n");
|
||||
if (0 != (arr = toml_array_in(curtab, key))) {
|
||||
prindent();
|
||||
printf("%s = [\n", key);
|
||||
indent++;
|
||||
print_array(arr);
|
||||
indent--;
|
||||
prindent();
|
||||
printf("],\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (0 != (tab = toml_table_in(curtab, key))) {
|
||||
stack[stacktop].key = key;
|
||||
stack[stacktop].tab = tab;
|
||||
stacktop++;
|
||||
prindent();
|
||||
printf("%s = {\n", key);
|
||||
indent++;
|
||||
print_table(tab);
|
||||
indent--;
|
||||
prindent();
|
||||
printf("},\n");
|
||||
stacktop--;
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_string_in(curtab, key);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%s = ", key);
|
||||
print_string(d.u.s);
|
||||
printf(",\n");
|
||||
free(d.u.s);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_bool_in(curtab, key);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%s = %s,\n", key, d.u.b ? "true" : "false");
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_int_in(curtab, key);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%s = %" PRId64 ",\n", key, d.u.i);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_double_in(curtab, key);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%s = %g,\n", key, d.u.d);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_timestamp_in(curtab, key);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf(" %s = %s,\n", key, toml_raw_in(curtab, key));
|
||||
free(d.u.ts);
|
||||
continue;
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void print_array(toml_array_t* curarr)
|
||||
{
|
||||
toml_datum_t d;
|
||||
toml_array_t* arr;
|
||||
const char* raw;
|
||||
toml_table_t* tab;
|
||||
int i;
|
||||
const int n = toml_array_nelem(curarr);
|
||||
|
||||
switch (toml_array_kind(curarr)) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
||||
case 'v':
|
||||
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
||||
printf(" %d: %s,\n", i, raw);
|
||||
if (0 != (arr = toml_array_at(curarr, i))) {
|
||||
prindent();
|
||||
printf("[\n");
|
||||
indent++;
|
||||
print_array(arr);
|
||||
indent--;
|
||||
prindent();
|
||||
printf("],\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (0 != (tab = toml_table_at(curarr, i))) {
|
||||
prindent();
|
||||
printf("{\n");
|
||||
indent++;
|
||||
print_table(tab);
|
||||
indent--;
|
||||
prindent();
|
||||
printf("},\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_string_at(curarr, i);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
print_string(d.u.s);
|
||||
printf(",\n");
|
||||
free(d.u.s);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_bool_at(curarr, i);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%s,\n", d.u.b ? "true" : "false");
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_int_at(curarr, i);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%" PRId64 ",\n", d.u.i);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_double_at(curarr, i);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%g,\n", d.u.d);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = toml_timestamp_at(curarr, i);
|
||||
if (d.ok) {
|
||||
prindent();
|
||||
printf("%s,\n", toml_raw_at(curarr, i));
|
||||
free(d.u.ts);
|
||||
continue;
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) {
|
||||
printf(" %d: \n", i);
|
||||
print_array(arr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
for (i = 0; 0 != (tab = toml_table_at(curarr, i)); i++) {
|
||||
print_table(tab);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void cat(FILE* fp)
|
||||
{
|
||||
char errbuf[200];
|
||||
|
||||
|
||||
toml_table_t* tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||
if (!tab) {
|
||||
fprintf(stderr, "ERROR: %s\n", errbuf);
|
||||
return;
|
||||
fprintf(stderr, "ERROR: %s\n", errbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
stack[stacktop].tab = tab;
|
||||
stack[stacktop].key = "";
|
||||
stacktop++;
|
||||
printf("{\n");
|
||||
indent++;
|
||||
print_table(tab);
|
||||
indent--;
|
||||
printf("}\n");
|
||||
stacktop--;
|
||||
|
||||
toml_free(tab);
|
||||
|
@ -175,19 +278,19 @@ int main(int argc, const char* argv[])
|
|||
{
|
||||
int i;
|
||||
if (argc == 1) {
|
||||
cat(stdin);
|
||||
cat(stdin);
|
||||
} else {
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
FILE* fp = fopen(argv[i], "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: cannot open %s: %s\n",
|
||||
argv[i], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
cat(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
FILE* fp = fopen(argv[i], "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: cannot open %s: %s\n",
|
||||
argv[i], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
cat(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue