Compare commits
No commits in common. "f290245b41ff4c5c8844933634ac752f9d6aa1d5" and "c15b100a0371374560a2e99859d1388bf7304243" have entirely different histories.
f290245b41
...
c15b100a03
|
@ -1,7 +1,8 @@
|
||||||
bin_PROGRAMS = mysql-dbadm mysql-useradm
|
bin_PROGRAMS = mysql-dbadm mysql-useradm
|
||||||
mysql_admutils_SOURCE = common.c mysql-admutils.h toml.c toml.h pwfile.c
|
mysql_admutils_SOURCE = common.c mysql-admutils.h pwyacc.y pwlex.l pwfile.c
|
||||||
mysql_dbadm_SOURCES = mysql-dbadm.c $(mysql_admutils_SOURCE)
|
mysql_dbadm_SOURCES = mysql-dbadm.c $(mysql_admutils_SOURCE)
|
||||||
mysql_useradm_SOURCES = mysql-useradm.c $(mysql_admutils_SOURCE)
|
mysql_useradm_SOURCES = mysql-useradm.c $(mysql_admutils_SOURCE)
|
||||||
|
BUILT_SOURCES = pwyacc.c pwyacc.h pwlex.c
|
||||||
AM_YFLAGS = -d
|
AM_YFLAGS = -d
|
||||||
AM_CPPFLAGS = @MYSQL_INCLUDE@ -DSYSCONFDIR=\"$(sysconfdir)\"
|
AM_CPPFLAGS = @MYSQL_INCLUDE@ -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||||
LDADD = @MYSQL_LIBS@ @LEXLIB@
|
LDADD = @MYSQL_LIBS@ @LEXLIB@
|
||||||
|
|
10
README.md
10
README.md
|
@ -16,13 +16,3 @@ For å rydde til start:
|
||||||
|
|
||||||
make maintainer-clean
|
make maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
## Opprett filen `/etc/mysql-admutils.toml`
|
|
||||||
|
|
||||||
Filen skal ha innhold som dette:
|
|
||||||
```toml
|
|
||||||
[server]
|
|
||||||
host="localhost"
|
|
||||||
user="brukernavn"
|
|
||||||
password="passord"
|
|
||||||
```
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ extern const char *db_user;
|
||||||
extern const char *db_passwd;
|
extern const char *db_passwd;
|
||||||
extern const char *db_name;
|
extern const char *db_name;
|
||||||
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
wrong_use(char *format, ...);
|
wrong_use(char *format, ...);
|
||||||
|
|
||||||
|
@ -31,7 +30,8 @@ extern char **get_group_names(int *numgroups);
|
||||||
extern int
|
extern int
|
||||||
version(void);
|
version(void);
|
||||||
|
|
||||||
extern const char* read_toml_file(void);
|
extern int
|
||||||
|
read_config_file(void);
|
||||||
|
|
||||||
/* same as strcpy, but returns a pointer to the end of dest instead of start */
|
/* same as strcpy, but returns a pointer to the end of dest instead of start */
|
||||||
extern char *strmov(char *, const char *);
|
extern char *strmov(char *, const char *);
|
||||||
|
@ -40,7 +40,8 @@ extern int name_isclean(char*);
|
||||||
|
|
||||||
#ifdef _mysql_h
|
#ifdef _mysql_h
|
||||||
|
|
||||||
extern int dberror(MYSQL *pmysql, char *format, ...);
|
extern int
|
||||||
|
dberror(MYSQL *pmysql, char *format, ...);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
reload(MYSQL *pmysql);
|
reload(MYSQL *pmysql);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "mysql-admutils.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -16,9 +17,7 @@
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "mysql-admutils.h"
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
strchr_whitespace(const char *s)
|
strchr_whitespace(const char *s)
|
||||||
|
@ -620,7 +619,7 @@ main(int argc, char *argv[])
|
||||||
if ((command != c_show) && (argc < 3))
|
if ((command != c_show) && (argc < 3))
|
||||||
return wrong_use(NULL);
|
return wrong_use(NULL);
|
||||||
|
|
||||||
read_toml_file();
|
/* read_config_file(); */
|
||||||
|
|
||||||
/* connect to the database server and select the mysql database */
|
/* connect to the database server and select the mysql database */
|
||||||
if (!mysql_real_connect(&mysql, db_server, db_user, db_passwd, db_name, 0, NULL, 0))
|
if (!mysql_real_connect(&mysql, db_server, db_user, db_passwd, db_name, 0, NULL, 0))
|
||||||
|
|
|
@ -170,7 +170,7 @@ show(MYSQL *pmysql, const char *user)
|
||||||
char **
|
char **
|
||||||
list(MYSQL *pmysql)
|
list(MYSQL *pmysql)
|
||||||
{
|
{
|
||||||
char query[40960], *end;
|
char query[4096], *end;
|
||||||
char **usrgroups, **cp;
|
char **usrgroups, **cp;
|
||||||
MYSQL_RES *res;
|
MYSQL_RES *res;
|
||||||
int rows, numgroups;
|
int rows, numgroups;
|
||||||
|
@ -278,7 +278,6 @@ main(int argc, char *argv[])
|
||||||
return wrong_use(NULL);
|
return wrong_use(NULL);
|
||||||
|
|
||||||
/* read_config_file(); */
|
/* read_config_file(); */
|
||||||
read_toml_file();
|
|
||||||
|
|
||||||
/* connect to the database server and select the mysql database */
|
/* connect to the database server and select the mysql database */
|
||||||
if (!mysql_real_connect(&mysql, db_server, db_user, db_passwd, db_name, 0, NULL, 0))
|
if (!mysql_real_connect(&mysql, db_server, db_user, db_passwd, db_name, 0, NULL, 0))
|
||||||
|
|
146
pwfile.c
146
pwfile.c
|
@ -12,13 +12,15 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include "mysql-admutils.h"
|
#include "mysql-admutils.h"
|
||||||
// #include "pwyacc.h"
|
#include "pwyacc.h"
|
||||||
#include "toml.h"
|
|
||||||
|
/* the MySQL maximum */
|
||||||
|
#define MAXPWCHARS 16
|
||||||
|
|
||||||
/* defaults for configurable values */
|
/* defaults for configurable values */
|
||||||
const char* db_server = NULL;
|
const char* db_user = "root";
|
||||||
const char* db_user = NULL;
|
const char* db_server = "mysql.stud.ntnu.no";
|
||||||
const char* db_passwd = NULL ;
|
const char* db_passwd = MYSQLPW ;
|
||||||
const char* db_name = "mysql";
|
const char* db_name = "mysql";
|
||||||
|
|
||||||
extern int yyparse(void);
|
extern int yyparse(void);
|
||||||
|
@ -26,81 +28,81 @@ extern FILE *yyin;
|
||||||
|
|
||||||
int config_line = 1;
|
int config_line = 1;
|
||||||
|
|
||||||
FILE* fp;
|
static FILE *pwfile;
|
||||||
toml_table_t* conf;
|
static char *filename = SYSCONFDIR "/mysql-admutils.conf";
|
||||||
toml_table_t* server;
|
|
||||||
const char* raw;
|
|
||||||
char* host;
|
|
||||||
char* user;
|
|
||||||
char* password;
|
|
||||||
char errbuf[200];
|
|
||||||
|
|
||||||
static char *tomlfile = SYSCONFDIR "/mysql-admutils.toml";
|
int
|
||||||
|
read_config_file(void)
|
||||||
const char* read_toml_file(void)
|
|
||||||
{
|
{
|
||||||
if (0 == (fp = fopen(tomlfile, "r"))) {
|
struct rlimit rlim;
|
||||||
perror("fopen");
|
int rc; /* return code */
|
||||||
|
|
||||||
|
/* to stop the user from obtaining the password from a core dump. */
|
||||||
|
if (getrlimit(RLIMIT_CORE, &rlim) == -1) {
|
||||||
|
perror("getrlimit");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
rlim.rlim_max = 0;
|
||||||
|
if (setrlimit(RLIMIT_CORE, &rlim) == -1) {
|
||||||
|
perror("setrlimit");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
pwfile = fopen(filename, "r");
|
||||||
fclose(fp);
|
if (!pwfile) {
|
||||||
if (0 == conf) {
|
fatal_error("cannot open configuration file %s", filename);
|
||||||
fprintf(stderr, "ERROR: parsing %s\n", errbuf);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == (server = toml_table_in(conf, "server"))) {
|
/* we don't need to be SUID anymore. */
|
||||||
fprintf(stderr, "ERROR: missing [server]\n");
|
if (seteuid(getuid()) != 0)
|
||||||
toml_free(conf);
|
perror("seteuid");
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == (raw = toml_raw_in(server, "host"))) {
|
yyin = pwfile;
|
||||||
fprintf(stderr, "ERROR: missing 'host' in [server]\n");
|
rc = yyparse();
|
||||||
toml_free(conf);
|
fclose(pwfile);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (toml_rtos(raw, &host)) {
|
|
||||||
fprintf(stderr, "ERROR: bad value in 'host'\n");
|
|
||||||
toml_free(conf);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == (raw = toml_raw_in(server, "user"))) {
|
return rc;
|
||||||
fprintf(stderr, "ERROR: missing 'user' in [server]\n");
|
}
|
||||||
toml_free(conf);
|
|
||||||
exit(1);
|
|
||||||
}
|
int
|
||||||
if (toml_rtos(raw, &user)) {
|
yywrap(void)
|
||||||
fprintf(stderr, "ERROR: bad value in 'user'\n");
|
{
|
||||||
toml_free(conf);
|
return 1;
|
||||||
exit(1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == (raw = toml_raw_in(server, "password"))) {
|
int
|
||||||
fprintf(stderr, "ERROR: missing 'password' in [server]\n");
|
yyerror(const char *msg)
|
||||||
toml_free(conf);
|
{
|
||||||
exit(1);
|
fprintf(stderr, "%s:%d: %s\n", filename, config_line, msg);
|
||||||
}
|
return 0;
|
||||||
if (toml_rtos(raw, &password)) {
|
}
|
||||||
fprintf(stderr, "ERROR: bad value in 'password'\n");
|
|
||||||
toml_free(conf);
|
|
||||||
exit(1);
|
int
|
||||||
}
|
config_set_string_var(int var, const char *value)
|
||||||
|
{
|
||||||
toml_free(conf);
|
assert(value);
|
||||||
|
switch (var) {
|
||||||
db_server = host;
|
case USER:
|
||||||
db_user = user;
|
db_user = value;
|
||||||
db_passwd = password;
|
break;
|
||||||
|
case HOST:
|
||||||
return db_server;
|
db_server = value;
|
||||||
return db_user;
|
break;
|
||||||
return db_passwd;
|
case PASSWORD:
|
||||||
|
if (strlen(value) > MAXPWCHARS) {
|
||||||
free(host);
|
fprintf(stderr, "%s:%d: password is too long (%d chars > %d chars)\n",
|
||||||
free(user);
|
filename, config_line, strlen(value), MAXPWCHARS);
|
||||||
free(password);
|
fclose(pwfile);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
db_passwd = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"We should never get here.");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* @(#) $Id: pwlex.l,v 1.1.1.1 2001-11-25 00:41:16 lkarsten Exp $
|
||||||
|
*
|
||||||
|
* lex source for the configuration file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "pwyacc.h"
|
||||||
|
|
||||||
|
extern int config_line;
|
||||||
|
extern int yylval;
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
#.*\n config_line++;
|
||||||
|
|
||||||
|
set { yylval = SET; return(SET); }
|
||||||
|
host { yylval = HOST; return(HOST); };
|
||||||
|
user { yylval = USER; return(USER); };
|
||||||
|
password { yylval = PASSWORD; return(PASSWORD); }
|
||||||
|
|
||||||
|
\"[^"]*\" {
|
||||||
|
if (yytext[yyleng - 1] == '\\')
|
||||||
|
yymore();
|
||||||
|
else
|
||||||
|
yytext[yyleng - 1] = '\0';
|
||||||
|
yylval = (int)strdup(yytext + 1);
|
||||||
|
return(STRING);
|
||||||
|
};
|
||||||
|
|
||||||
|
; return(';');
|
||||||
|
|
||||||
|
[^ \t\n\;]* {
|
||||||
|
yylval = (int)strdup(yytext);
|
||||||
|
return(STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ \t] ;
|
||||||
|
|
||||||
|
\n config_line++;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* @(#) $Id: pwyacc.y,v 1.1.1.1 2001-11-25 00:41:16 lkarsten Exp $
|
||||||
|
*
|
||||||
|
* yacc source for parsing the configuration file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
int yyerror(const char *msg);
|
||||||
|
int yylex(void);
|
||||||
|
int config_set_string_var(int var, const char *value);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%token SET HOST USER PASSWORD STRING
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
input: ;
|
||||||
|
input: statement input ;
|
||||||
|
|
||||||
|
statement: SET variable STRING ';'
|
||||||
|
{
|
||||||
|
$$ = config_set_string_var($2, (const char *)$3);
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
variable: USER | PASSWORD | HOST
|
||||||
|
{ $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,42 +0,0 @@
|
||||||
HFILES = toml.h
|
|
||||||
CFILES = toml.c
|
|
||||||
OBJ = $(CFILES:.c=.o)
|
|
||||||
EXEC = toml_json toml_cat
|
|
||||||
|
|
||||||
CFLAGS = -std=c99 -Wall -Wextra -fpic
|
|
||||||
LIB = libtoml.a
|
|
||||||
LIB_SHARED = libtoml.so
|
|
||||||
|
|
||||||
# to compile for debug: make DEBUG=1
|
|
||||||
# to compile for no debug: make
|
|
||||||
ifdef DEBUG
|
|
||||||
CFLAGS += -O0 -g
|
|
||||||
else
|
|
||||||
CFLAGS += -O2 -DNDEBUG
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
all: $(LIB) $(LIB_SHARED) $(EXEC)
|
|
||||||
|
|
||||||
*.o: $(HFILES)
|
|
||||||
|
|
||||||
libtoml.a: toml.o
|
|
||||||
ar -rcs $@ $^
|
|
||||||
|
|
||||||
libtoml.so: toml.o
|
|
||||||
$(CC) -shared -o $@ $^
|
|
||||||
|
|
||||||
toml_json: toml_json.c $(LIB)
|
|
||||||
|
|
||||||
toml_cat: toml_cat.c $(LIB)
|
|
||||||
|
|
||||||
prefix ?= /usr/local
|
|
||||||
|
|
||||||
install: all
|
|
||||||
install -d ${prefix}/include ${prefix}/lib
|
|
||||||
install toml.h ${prefix}/include
|
|
||||||
install $(LIB) ${prefix}/lib
|
|
||||||
install $(LIB_SHARED) ${prefix}/lib
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o $(EXEC) $(LIB) $(LIB_SHARED)
|
|
|
@ -1,124 +0,0 @@
|
||||||
# tomlc99
|
|
||||||
|
|
||||||
TOML in c99; v1.0 compliant.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Please see the `toml.h` file for details. What follows is a simple example that
|
|
||||||
parses this config file:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[server]
|
|
||||||
host = "www.example.com"
|
|
||||||
port = 80
|
|
||||||
```
|
|
||||||
|
|
||||||
The steps for getting values from our file is usually :
|
|
||||||
|
|
||||||
1. Parse the whole TOML file.
|
|
||||||
2. Get a single table from the file.
|
|
||||||
3. Find a value from the table.
|
|
||||||
4. Convert that value to the appropriate type, i.e., string, int, etc.
|
|
||||||
5. Then, free up that memory if needed.
|
|
||||||
|
|
||||||
Below is an example of parsing the values from the example table.
|
|
||||||
|
|
||||||
1. Parse the whole TOML file.
|
|
||||||
|
|
||||||
```c
|
|
||||||
FILE* fp;
|
|
||||||
toml_table_t* conf;
|
|
||||||
char errbuf[200];
|
|
||||||
|
|
||||||
/* Open the file. */
|
|
||||||
if (0 == (fp = fopen("path/to/file.toml", "r"))) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run the file through the parser. */
|
|
||||||
conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
|
||||||
if (0 == conf) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/* Alternatively, use `toml_parse` which takes a string rather than a file. */
|
|
||||||
conf = toml_parse("A null terminated string that is TOML\0", errbuf, sizeof(errbuf));
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Get a single table from the file.
|
|
||||||
|
|
||||||
```c
|
|
||||||
toml_table_t* server;
|
|
||||||
|
|
||||||
/* Locate the [server] table. */
|
|
||||||
if (0 == (server = toml_table_in(conf, "server"))) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Find a value from the table.
|
|
||||||
4. Convert that value to the appropriate type (I.E. string, int).
|
|
||||||
|
|
||||||
```c
|
|
||||||
toml_raw_t raw;
|
|
||||||
char* host;
|
|
||||||
int64_t port;
|
|
||||||
|
|
||||||
/* Extract 'host' config value. */
|
|
||||||
if (0 == (raw = toml_raw_in(server, "host"))) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert the raw value into a string. */
|
|
||||||
if (toml_rtos(raw, &host)) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract 'port' config value. */
|
|
||||||
if (0 == (raw = toml_raw_in(server, "port"))) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert the raw value into an int. */
|
|
||||||
if (toml_rtoi(raw, &port)) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Then, free up that memory if needed.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Use `toml_free` on the table returned from `toml_parse[_file]`. */
|
|
||||||
toml_free(conf);
|
|
||||||
|
|
||||||
/* Free any values returned from `toml_rto*`. */
|
|
||||||
free(host);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
A normal *make* suffices. Alternately, you can also simply include the
|
|
||||||
`toml.c` and `toml.h` files in your project.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
To test against the standard test set provided by BurntSushi/toml-test:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% make
|
|
||||||
% cd test1
|
|
||||||
% bash build.sh # do this once
|
|
||||||
% bash run.sh # this will run the test suite
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
To test against the standard test set provided by iarna/toml:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% make
|
|
||||||
% cd test2
|
|
||||||
% bash build.sh # do this once
|
|
||||||
% bash run.sh # this will run the test suite
|
|
||||||
```
|
|
|
@ -1,3 +0,0 @@
|
||||||
/goworkspace
|
|
||||||
/toml-test
|
|
||||||
/toml-test-decoder
|
|
|
@ -1,9 +0,0 @@
|
||||||
How to run the tests
|
|
||||||
===
|
|
||||||
|
|
||||||
```
|
|
||||||
% bash build.sh
|
|
||||||
% bash run.sh
|
|
||||||
77 passed, 0 failed
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
mkdir -p $DIR/goworkspace
|
|
||||||
export GOPATH=$DIR/goworkspace
|
|
||||||
go get github.com/BurntSushi/toml-test # install test suite
|
|
||||||
go get github.com/BurntSushi/toml/cmd/toml-test-decoder # e.g., install my parser
|
|
||||||
cp $GOPATH/bin/* .
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
x = [ {'a'= 1}, {'a'= 2} ]
|
|
|
@ -1 +0,0 @@
|
||||||
x = [1,2,3]
|
|
|
@ -1 +0,0 @@
|
||||||
x = {'a'= 1, 'b'= 2 }
|
|
|
@ -1,4 +0,0 @@
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
export GOPATH=$DIR/goworkspace # if it isn't already set
|
|
||||||
# $GOPATH/bin/toml-test $GOPATH/bin/toml-test-decoder # e.g., run tests on my parser
|
|
||||||
$GOPATH/bin/toml-test ../toml_json
|
|
|
@ -1 +0,0 @@
|
||||||
/toml-spec-tests
|
|
|
@ -1,6 +0,0 @@
|
||||||
Note that we utilize the 'jq' command to normalize json files for comparison. Depending the
|
|
||||||
verson of jq on your system, some tests may generate error that looks like this:
|
|
||||||
|
|
||||||
parse error: Exceeds depth limit for parsing at line 1
|
|
||||||
|
|
||||||
This is an error in 'jq', and it does not indicate that the tests themselves fail.
|
|
|
@ -1,6 +0,0 @@
|
||||||
set -e
|
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
[ -d toml-spec-tests ] || git clone https://github.com/cktan/toml-spec-tests.git
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
if ! (which jq >& /dev/null); then
|
|
||||||
echo "ERROR: please install the 'jq' utility"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# POSITIVE tests
|
|
||||||
#
|
|
||||||
for i in toml-spec-tests/values/*.toml; do
|
|
||||||
fname="$i"
|
|
||||||
ext="${fname##*.}"
|
|
||||||
fname="${fname%.*}"
|
|
||||||
echo -n $fname ' '
|
|
||||||
res='[OK]'
|
|
||||||
if (../toml_json $fname.toml >& $fname.json.out); then
|
|
||||||
jq -S . $fname.json.out > t.json
|
|
||||||
mv t.json $fname.json.out
|
|
||||||
if [ -f $fname.json ]; then
|
|
||||||
if ! (diff $fname.json $fname.json.out >& /dev/null); then
|
|
||||||
res='[FAILED]'
|
|
||||||
else
|
|
||||||
rm -f $fname.json.out
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
res='[??]'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo ... $res
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# NEGATIVE tests
|
|
||||||
#
|
|
||||||
for i in toml-spec-tests/errors/*.toml; do
|
|
||||||
echo -n $i ' '
|
|
||||||
res='[OK]'
|
|
||||||
if (../toml_json $i >& $i.json.out); then
|
|
||||||
res='[FAILED]'
|
|
||||||
fi
|
|
||||||
echo ... $res
|
|
||||||
done
|
|
2146
tomlc99/toml.c
2146
tomlc99/toml.c
File diff suppressed because it is too large
Load Diff
150
tomlc99/toml.h
150
tomlc99/toml.h
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
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
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
#ifndef TOML_H
|
|
||||||
#define TOML_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define TOML_EXTERN extern "C"
|
|
||||||
#else
|
|
||||||
#define TOML_EXTERN extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct toml_table_t toml_table_t;
|
|
||||||
typedef struct toml_array_t toml_array_t;
|
|
||||||
|
|
||||||
/* A raw value, must be processed by toml_rto* before using. */
|
|
||||||
typedef const char* toml_raw_t;
|
|
||||||
|
|
||||||
/* 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,
|
|
||||||
char* errbuf,
|
|
||||||
int errbufsz);
|
|
||||||
|
|
||||||
/* Parse a string containing the full config.
|
|
||||||
* Return a table on success, or 0 otherwise.
|
|
||||||
* Caller must toml_free(the-return-value) after use.
|
|
||||||
*/
|
|
||||||
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(). */
|
|
||||||
TOML_EXTERN void toml_free(toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Retrieve the key in table at keyidx. Return 0 if out of range. */
|
|
||||||
TOML_EXTERN const char* toml_key_in(const toml_table_t* tab, int keyidx);
|
|
||||||
|
|
||||||
/* Lookup table by key. Return the element or 0 if not found. */
|
|
||||||
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key);
|
|
||||||
TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab,
|
|
||||||
const char* key);
|
|
||||||
TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab,
|
|
||||||
const char* key);
|
|
||||||
|
|
||||||
/* Return the array kind: 't'able, 'a'rray, 'v'alue */
|
|
||||||
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
|
|
||||||
0 if unknown
|
|
||||||
*/
|
|
||||||
TOML_EXTERN char toml_array_type(const toml_array_t* arr);
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the number of elements in the array */
|
|
||||||
TOML_EXTERN int toml_array_nelem(const toml_array_t* arr);
|
|
||||||
|
|
||||||
/* Return the key of an array */
|
|
||||||
TOML_EXTERN const char* toml_array_key(const toml_array_t* arr);
|
|
||||||
|
|
||||||
/* Return the number of key-values in a table */
|
|
||||||
TOML_EXTERN int toml_table_nkval(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Return the number of arrays in a table */
|
|
||||||
TOML_EXTERN int toml_table_narr(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Return the number of sub-tables in a table */
|
|
||||||
TOML_EXTERN int toml_table_ntab(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Return the key of a table*/
|
|
||||||
TOML_EXTERN const char* toml_table_key(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Deref array by index. Return the element at idx or 0 if out of range. */
|
|
||||||
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_array_t* toml_array_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_table_t* toml_table_at(const toml_array_t* arr, int idx);
|
|
||||||
|
|
||||||
/* Raw to String. Caller must call free(ret) after use.
|
|
||||||
* Return 0 on success, -1 otherwise.
|
|
||||||
*/
|
|
||||||
TOML_EXTERN int toml_rtos(toml_raw_t s, char** ret);
|
|
||||||
|
|
||||||
/* Raw to Boolean. Return 0 on success, -1 otherwise. */
|
|
||||||
TOML_EXTERN int toml_rtob(toml_raw_t s, int* ret);
|
|
||||||
|
|
||||||
/* Raw to Integer. Return 0 on success, -1 otherwise. */
|
|
||||||
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t* ret);
|
|
||||||
|
|
||||||
/* Raw to Double. Return 0 on success, -1 otherwise. */
|
|
||||||
TOML_EXTERN int toml_rtod(toml_raw_t s, double* ret);
|
|
||||||
|
|
||||||
/* Same as toml_rtod, but return the sanitized double in string form as well */
|
|
||||||
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double* ret, char* buf, int buflen);
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
*/
|
|
||||||
typedef struct toml_timestamp_t toml_timestamp_t;
|
|
||||||
struct toml_timestamp_t {
|
|
||||||
struct { /* internal. do not use. */
|
|
||||||
int year, month, day;
|
|
||||||
int hour, minute, second, millisec;
|
|
||||||
char z[10];
|
|
||||||
} __buffer;
|
|
||||||
int *year, *month, *day;
|
|
||||||
int *hour, *minute, *second, *millisec;
|
|
||||||
char* z;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Raw to Timestamp. Return 0 on success, -1 otherwise. */
|
|
||||||
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t* ret);
|
|
||||||
|
|
||||||
/* 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]);
|
|
||||||
TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t),
|
|
||||||
void (*xxfree)(void*),
|
|
||||||
void* (*xxcalloc)(size_t, size_t),
|
|
||||||
void* (*xxrealloc)(void*, size_t));
|
|
||||||
|
|
||||||
#endif /* TOML_H */
|
|
|
@ -1,193 +0,0 @@
|
||||||
/*
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef NDEBUG
|
|
||||||
#undef NDEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "toml.h"
|
|
||||||
|
|
||||||
typedef struct node_t node_t;
|
|
||||||
struct node_t {
|
|
||||||
const char* key;
|
|
||||||
toml_table_t* tab;
|
|
||||||
};
|
|
||||||
|
|
||||||
node_t stack[20];
|
|
||||||
int stacktop = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static void print_table_title(const char* arrname)
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void print_array(toml_array_t* curarr)
|
|
||||||
{
|
|
||||||
toml_array_t* arr;
|
|
||||||
const char* raw;
|
|
||||||
toml_table_t* tab;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (toml_array_kind(curarr)) {
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
|
||||||
printf(" %d: %s,\n", i, raw);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack[stacktop].tab = tab;
|
|
||||||
stack[stacktop].key = "";
|
|
||||||
stacktop++;
|
|
||||||
print_table(tab);
|
|
||||||
stacktop--;
|
|
||||||
|
|
||||||
toml_free(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (argc == 1) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,214 +0,0 @@
|
||||||
/*
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
#ifdef NDEBUG
|
|
||||||
#undef NDEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "toml.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void print_escape_string(const char* s)
|
|
||||||
{
|
|
||||||
for ( ; *s; s++) {
|
|
||||||
int ch = *s;
|
|
||||||
switch (ch) {
|
|
||||||
case '\b': printf("\\b"); break;
|
|
||||||
case '\t': printf("\\t"); break;
|
|
||||||
case '\n': printf("\\n"); break;
|
|
||||||
case '\f': printf("\\f"); break;
|
|
||||||
case '\r': printf("\\r"); break;
|
|
||||||
case '"': printf("\\\""); break;
|
|
||||||
case '\\': printf("\\\\"); break;
|
|
||||||
default: printf("%c", ch); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_raw(const char* s)
|
|
||||||
{
|
|
||||||
char* sval;
|
|
||||||
int64_t ival;
|
|
||||||
int bval;
|
|
||||||
double dval;
|
|
||||||
toml_timestamp_t ts;
|
|
||||||
char dbuf[100];
|
|
||||||
|
|
||||||
if (0 == toml_rtos(s, &sval)) {
|
|
||||||
printf("{\"type\":\"string\",\"value\":\"");
|
|
||||||
print_escape_string(sval);
|
|
||||||
printf("\"}");
|
|
||||||
free(sval);
|
|
||||||
} else if (0 == toml_rtoi(s, &ival)) {
|
|
||||||
printf("{\"type\":\"integer\",\"value\":\"%" PRId64 "\"}", ival);
|
|
||||||
} else if (0 == toml_rtob(s, &bval)) {
|
|
||||||
printf("{\"type\":\"bool\",\"value\":\"%s\"}", bval ? "true" : "false");
|
|
||||||
} else if (0 == toml_rtod_ex(s, &dval, dbuf, sizeof(dbuf))) {
|
|
||||||
printf("{\"type\":\"float\",\"value\":\"%s\"}", dbuf);
|
|
||||||
} else if (0 == toml_rtots(s, &ts)) {
|
|
||||||
char millisec[10];
|
|
||||||
if (ts.millisec)
|
|
||||||
sprintf(millisec, ".%d", *ts.millisec);
|
|
||||||
else
|
|
||||||
millisec[0] = 0;
|
|
||||||
if (ts.year && ts.hour) {
|
|
||||||
printf("{\"type\":\"datetime\",\"value\":\"%04d-%02d-%02dT%02d:%02d:%02d%s%s\"}",
|
|
||||||
*ts.year, *ts.month, *ts.day, *ts.hour, *ts.minute, *ts.second,
|
|
||||||
millisec,
|
|
||||||
(ts.z ? ts.z : ""));
|
|
||||||
} else if (ts.year) {
|
|
||||||
printf("{\"type\":\"date\",\"value\":\"%04d-%02d-%02d\"}",
|
|
||||||
*ts.year, *ts.month, *ts.day);
|
|
||||||
} else if (ts.hour) {
|
|
||||||
printf("{\"type\":\"time\",\"value\":\"%02d:%02d:%02d%s\"}",
|
|
||||||
*ts.hour, *ts.minute, *ts.second, millisec);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "unknown type\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void print_array(toml_array_t* arr);
|
|
||||||
static void print_table(toml_table_t* curtab)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char* key;
|
|
||||||
const char* raw;
|
|
||||||
toml_array_t* arr;
|
|
||||||
toml_table_t* tab;
|
|
||||||
|
|
||||||
|
|
||||||
printf("{");
|
|
||||||
for (i = 0; 0 != (key = toml_key_in(curtab, i)); i++) {
|
|
||||||
|
|
||||||
printf("%s\"", i > 0 ? "," : "");
|
|
||||||
print_escape_string(key);
|
|
||||||
printf("\":");
|
|
||||||
|
|
||||||
if (0 != (raw = toml_raw_in(curtab, key))) {
|
|
||||||
print_raw(raw);
|
|
||||||
} else if (0 != (arr = toml_array_in(curtab, key))) {
|
|
||||||
print_array(arr);
|
|
||||||
} else if (0 != (tab = toml_table_in(curtab, key))) {
|
|
||||||
print_table(tab);
|
|
||||||
} else {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_table_array(toml_array_t* curarr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
toml_table_t* tab;
|
|
||||||
|
|
||||||
printf("[");
|
|
||||||
for (i = 0; 0 != (tab = toml_table_at(curarr, i)); i++) {
|
|
||||||
printf("%s", i > 0 ? "," : "");
|
|
||||||
print_table(tab);
|
|
||||||
}
|
|
||||||
printf("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_array(toml_array_t* curarr)
|
|
||||||
{
|
|
||||||
toml_array_t* arr;
|
|
||||||
const char* raw;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (toml_array_kind(curarr) == 't') {
|
|
||||||
print_table_array(curarr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("{\"type\":\"array\",\"value\":[");
|
|
||||||
switch (toml_array_kind(curarr)) {
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
|
||||||
printf("%s", i > 0 ? "," : "");
|
|
||||||
print_raw(raw);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'a':
|
|
||||||
for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) {
|
|
||||||
printf("%s", i > 0 ? "," : "");
|
|
||||||
print_array(arr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("]}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
print_table(tab);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
toml_free(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (argc == 1) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
CFLAGS = -g -I..
|
|
||||||
|
|
||||||
TESTS = t1
|
|
||||||
|
|
||||||
all: $(TESTS)
|
|
||||||
|
|
||||||
t1: t1.c ../toml.c
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(TESTS)
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "../toml.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
|
||||||
{
|
|
||||||
char xxbuf[6], buf[6];
|
|
||||||
int64_t xxcode, code;
|
|
||||||
int xxsize;
|
|
||||||
|
|
||||||
|
|
||||||
xxsize = 2, xxcode = 0x80; memcpy(xxbuf, "\xc2\x80", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 2, xxcode = 0x7ff; memcpy(xxbuf, "\xdf\xbf", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 3, xxcode = 0x800; memcpy(xxbuf, "\xe0\xa0\x80", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 3, xxcode = 0xfffd; memcpy(xxbuf, "\xef\xbf\xbd", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 4, xxcode = 0x10000; memcpy(xxbuf, "\xf0\x90\x80\x80", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 4, xxcode = 0x1fffff; memcpy(xxbuf, "\xf7\xbf\xbf\xbf", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 5, xxcode = 0x200000; memcpy(xxbuf, "\xf8\x88\x80\x80\x80", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 5, xxcode = 0x3ffffff; memcpy(xxbuf, "\xfb\xbf\xbf\xbf\xbf", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 6, xxcode = 0x4000000; memcpy(xxbuf, "\xfc\x84\x80\x80\x80\x80", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
xxsize = 6, xxcode = 0x7fffffff; memcpy(xxbuf, "\xfd\xbf\xbf\xbf\xbf\xbf", xxsize);
|
|
||||||
assert(toml_ucs_to_utf8(xxcode, buf) == xxsize && 0 == memcmp(buf, xxbuf, xxsize));
|
|
||||||
assert(toml_utf8_to_ucs(buf, xxsize, &code) == xxsize && code == xxcode);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue