cannam@226
|
1 /*
|
cannam@226
|
2 Copyright 2011-2016 David Robillard <http://drobilla.net>
|
cannam@226
|
3
|
cannam@226
|
4 Permission to use, copy, modify, and/or distribute this software for any
|
cannam@226
|
5 purpose with or without fee is hereby granted, provided that the above
|
cannam@226
|
6 copyright notice and this permission notice appear in all copies.
|
cannam@226
|
7
|
cannam@226
|
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
cannam@226
|
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
cannam@226
|
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
cannam@226
|
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
cannam@226
|
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
cannam@226
|
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
cannam@226
|
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
cannam@226
|
15 */
|
cannam@226
|
16
|
cannam@226
|
17 #include <assert.h>
|
cannam@226
|
18 #include <stdlib.h>
|
cannam@226
|
19 #include <string.h>
|
cannam@226
|
20
|
cannam@226
|
21 #ifdef _WIN32
|
cannam@226
|
22 # include <windows.h>
|
cannam@226
|
23 #endif
|
cannam@226
|
24
|
cannam@226
|
25 #include "serd/serd.h"
|
cannam@226
|
26 #include "sord/sord.h"
|
cannam@226
|
27 #include "sord_config.h"
|
cannam@226
|
28
|
cannam@226
|
29 #define SORDI_ERROR(msg) fprintf(stderr, "sordi: " msg);
|
cannam@226
|
30 #define SORDI_ERRORF(fmt, ...) fprintf(stderr, "sordi: " fmt, __VA_ARGS__);
|
cannam@226
|
31
|
cannam@226
|
32 typedef struct {
|
cannam@226
|
33 SerdWriter* writer;
|
cannam@226
|
34 SerdEnv* env;
|
cannam@226
|
35 SerdNode base_uri_node;
|
cannam@226
|
36 SerdURI base_uri;
|
cannam@226
|
37 SordModel* sord;
|
cannam@226
|
38 } State;
|
cannam@226
|
39
|
cannam@226
|
40 static int
|
cannam@226
|
41 print_version(void)
|
cannam@226
|
42 {
|
cannam@226
|
43 printf("sordi " SORD_VERSION " <http://drobilla.net/software/sord>\n");
|
cannam@226
|
44 printf("Copyright 2011-2016 David Robillard <http://drobilla.net>.\n"
|
cannam@226
|
45 "License: <http://www.opensource.org/licenses/isc>\n"
|
cannam@226
|
46 "This is free software; you are free to change and redistribute it."
|
cannam@226
|
47 "\nThere is NO WARRANTY, to the extent permitted by law.\n");
|
cannam@226
|
48 return 0;
|
cannam@226
|
49 }
|
cannam@226
|
50
|
cannam@226
|
51 static int
|
cannam@226
|
52 print_usage(const char* name, bool error)
|
cannam@226
|
53 {
|
cannam@226
|
54 FILE* const os = error ? stderr : stdout;
|
cannam@226
|
55 fprintf(os, "%s", error ? "\n" : "");
|
cannam@226
|
56 fprintf(os, "Usage: %s [OPTION]... INPUT [BASE_URI]\n", name);
|
cannam@226
|
57 fprintf(os, "Load and re-serialise RDF data.\n");
|
cannam@226
|
58 fprintf(os, "Use - for INPUT to read from standard input.\n\n");
|
cannam@226
|
59 fprintf(os, " -h Display this help and exit\n");
|
cannam@226
|
60 fprintf(os, " -i SYNTAX Input syntax (`turtle' or `ntriples')\n");
|
cannam@226
|
61 fprintf(os, " -o SYNTAX Output syntax (`turtle' or `ntriples')\n");
|
cannam@226
|
62 fprintf(os, " -s INPUT Parse INPUT as string (terminates options)\n");
|
cannam@226
|
63 fprintf(os, " -v Display version information and exit\n");
|
cannam@226
|
64 return error ? 1 : 0;
|
cannam@226
|
65 }
|
cannam@226
|
66
|
cannam@226
|
67 static bool
|
cannam@226
|
68 set_syntax(SerdSyntax* syntax, const char* name)
|
cannam@226
|
69 {
|
cannam@226
|
70 if (!strcmp(name, "turtle")) {
|
cannam@226
|
71 *syntax = SERD_TURTLE;
|
cannam@226
|
72 } else if (!strcmp(name, "ntriples")) {
|
cannam@226
|
73 *syntax = SERD_NTRIPLES;
|
cannam@226
|
74 } else {
|
cannam@226
|
75 SORDI_ERRORF("unknown syntax `%s'\n", name);
|
cannam@226
|
76 return false;
|
cannam@226
|
77 }
|
cannam@226
|
78 return true;
|
cannam@226
|
79 }
|
cannam@226
|
80
|
cannam@226
|
81 int
|
cannam@226
|
82 main(int argc, char** argv)
|
cannam@226
|
83 {
|
cannam@226
|
84 if (argc < 2) {
|
cannam@226
|
85 return print_usage(argv[0], true);
|
cannam@226
|
86 }
|
cannam@226
|
87
|
cannam@226
|
88 FILE* in_fd = NULL;
|
cannam@226
|
89 SerdSyntax input_syntax = SERD_TURTLE;
|
cannam@226
|
90 SerdSyntax output_syntax = SERD_NTRIPLES;
|
cannam@226
|
91 bool from_file = true;
|
cannam@226
|
92 const uint8_t* in_name = NULL;
|
cannam@226
|
93 int a = 1;
|
cannam@226
|
94 for (; a < argc && argv[a][0] == '-'; ++a) {
|
cannam@226
|
95 if (argv[a][1] == '\0') {
|
cannam@226
|
96 in_name = (const uint8_t*)"(stdin)";
|
cannam@226
|
97 in_fd = stdin;
|
cannam@226
|
98 break;
|
cannam@226
|
99 } else if (argv[a][1] == 'h') {
|
cannam@226
|
100 return print_usage(argv[0], false);
|
cannam@226
|
101 } else if (argv[a][1] == 'v') {
|
cannam@226
|
102 return print_version();
|
cannam@226
|
103 } else if (argv[a][1] == 's') {
|
cannam@226
|
104 in_name = (const uint8_t*)"(string)";
|
cannam@226
|
105 from_file = false;
|
cannam@226
|
106 ++a;
|
cannam@226
|
107 break;
|
cannam@226
|
108 } else if (argv[a][1] == 'i') {
|
cannam@226
|
109 if (++a == argc) {
|
cannam@226
|
110 SORDI_ERROR("option requires an argument -- 'i'\n\n");
|
cannam@226
|
111 return print_usage(argv[0], true);
|
cannam@226
|
112 }
|
cannam@226
|
113 if (!set_syntax(&input_syntax, argv[a])) {
|
cannam@226
|
114 return print_usage(argv[0], true);
|
cannam@226
|
115 }
|
cannam@226
|
116 } else if (argv[a][1] == 'o') {
|
cannam@226
|
117 if (++a == argc) {
|
cannam@226
|
118 SORDI_ERROR("option requires an argument -- 'o'\n\n");
|
cannam@226
|
119 return print_usage(argv[0], true);
|
cannam@226
|
120 }
|
cannam@226
|
121 if (!set_syntax(&output_syntax, argv[a])) {
|
cannam@226
|
122 return print_usage(argv[0], true);
|
cannam@226
|
123 }
|
cannam@226
|
124 } else {
|
cannam@226
|
125 SORDI_ERRORF("invalid option -- '%s'\n", argv[a] + 1);
|
cannam@226
|
126 return print_usage(argv[0], true);
|
cannam@226
|
127 }
|
cannam@226
|
128 }
|
cannam@226
|
129
|
cannam@226
|
130 if (a == argc) {
|
cannam@226
|
131 SORDI_ERROR("missing input\n");
|
cannam@226
|
132 return print_usage(argv[0], true);
|
cannam@226
|
133 }
|
cannam@226
|
134
|
cannam@226
|
135 const uint8_t* input = (const uint8_t*)argv[a++];
|
cannam@226
|
136 if (from_file) {
|
cannam@226
|
137 in_name = in_name ? in_name : input;
|
cannam@226
|
138 if (!in_fd) {
|
cannam@226
|
139 input = serd_uri_to_path(in_name);
|
cannam@226
|
140 if (!input || !(in_fd = fopen((const char*)input, "rb"))) {
|
cannam@226
|
141 return 1;
|
cannam@226
|
142 }
|
cannam@226
|
143 }
|
cannam@226
|
144 }
|
cannam@226
|
145
|
cannam@226
|
146 SerdURI base_uri = SERD_URI_NULL;
|
cannam@226
|
147 SerdNode base = SERD_NODE_NULL;
|
cannam@226
|
148 if (a < argc) { // Base URI given on command line
|
cannam@226
|
149 base = serd_node_new_uri_from_string(
|
cannam@226
|
150 (const uint8_t*)argv[a], NULL, &base_uri);
|
cannam@226
|
151 } else if (from_file && in_fd != stdin) { // Use input file URI
|
cannam@226
|
152 base = serd_node_new_file_uri(input, NULL, &base_uri, true);
|
cannam@226
|
153 }
|
cannam@226
|
154
|
cannam@226
|
155 SordWorld* world = sord_world_new();
|
cannam@226
|
156 SordModel* sord = sord_new(world, SORD_SPO|SORD_OPS, false);
|
cannam@226
|
157 SerdEnv* env = serd_env_new(&base);
|
cannam@226
|
158 SerdReader* reader = sord_new_reader(sord, env, input_syntax, NULL);
|
cannam@226
|
159
|
cannam@226
|
160 SerdStatus status = (from_file)
|
cannam@226
|
161 ? serd_reader_read_file_handle(reader, in_fd, in_name)
|
cannam@226
|
162 : serd_reader_read_string(reader, input);
|
cannam@226
|
163
|
cannam@226
|
164 serd_reader_free(reader);
|
cannam@226
|
165
|
cannam@226
|
166 FILE* out_fd = stdout;
|
cannam@226
|
167 SerdEnv* write_env = serd_env_new(&base);
|
cannam@226
|
168
|
cannam@226
|
169 int output_style = SERD_STYLE_RESOLVED;
|
cannam@226
|
170 if (output_syntax == SERD_NTRIPLES) {
|
cannam@226
|
171 output_style |= SERD_STYLE_ASCII;
|
cannam@226
|
172 } else {
|
cannam@226
|
173 output_style |= SERD_STYLE_CURIED | SERD_STYLE_ABBREVIATED;
|
cannam@226
|
174 }
|
cannam@226
|
175
|
cannam@226
|
176 SerdWriter* writer = serd_writer_new(
|
cannam@226
|
177 output_syntax,
|
cannam@226
|
178 (SerdStyle)output_style,
|
cannam@226
|
179 write_env, &base_uri, serd_file_sink, stdout);
|
cannam@226
|
180
|
cannam@226
|
181 // Write @prefix directives
|
cannam@226
|
182 serd_env_foreach(env,
|
cannam@226
|
183 (SerdPrefixSink)serd_writer_set_prefix,
|
cannam@226
|
184 writer);
|
cannam@226
|
185
|
cannam@226
|
186 // Write statements
|
cannam@226
|
187 sord_write(sord, writer, NULL);
|
cannam@226
|
188
|
cannam@226
|
189 serd_writer_finish(writer);
|
cannam@226
|
190 serd_writer_free(writer);
|
cannam@226
|
191
|
cannam@226
|
192 serd_env_free(env);
|
cannam@226
|
193 serd_env_free(write_env);
|
cannam@226
|
194 serd_node_free(&base);
|
cannam@226
|
195
|
cannam@226
|
196 sord_free(sord);
|
cannam@226
|
197 sord_world_free(world);
|
cannam@226
|
198
|
cannam@226
|
199 if (from_file) {
|
cannam@226
|
200 fclose(in_fd);
|
cannam@226
|
201 }
|
cannam@226
|
202
|
cannam@226
|
203 if (fclose(out_fd)) {
|
cannam@226
|
204 perror("sordi: write error");
|
cannam@226
|
205 status = SERD_ERR_UNKNOWN;
|
cannam@226
|
206 }
|
cannam@226
|
207
|
cannam@226
|
208 return (status > SERD_FAILURE) ? 1 : 0;
|
cannam@226
|
209 }
|