blob: 22a73a6ec214491615ffed347a15bb548f938e88 [file] [log] [blame]
Michal Vaskoe0cb2522015-07-01 10:24:53 +02001/**
2 * @file commands.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang's yanglint tool commands
Michal Vaskof3e59f12015-06-18 11:53:56 +02005 *
Michal Vaskoe0cb2522015-07-01 10:24:53 +02006 * Copyright (c) 2015 CESNET, z.s.p.o.
Michal Vaskof3e59f12015-06-18 11:53:56 +02007 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
Michal Vaskof3e59f12015-06-18 11:53:56 +020020 */
Michal Vaskoe0cb2522015-07-01 10:24:53 +020021
Michal Vaskof3e59f12015-06-18 11:53:56 +020022#define _GNU_SOURCE
23#include <string.h>
24#include <stdio.h>
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/mman.h>
29#include <fcntl.h>
30#include <unistd.h>
31#include <getopt.h>
32
Michal Vasko203b4e72015-06-30 15:25:15 +020033#include "commands.h"
Michal Vaskof3e59f12015-06-18 11:53:56 +020034#include "../../src/libyang.h"
35#include "../../src/tree.h"
Michal Vasko520d4732015-07-13 15:53:33 +020036#include "../../src/parser.h"
Michal Vaskof3e59f12015-06-18 11:53:56 +020037
Michal Vasko203b4e72015-06-30 15:25:15 +020038COMMAND commands[];
Michal Vaskof3e59f12015-06-18 11:53:56 +020039extern int done;
40extern struct ly_ctx *ctx;
41extern char *search_path;
42
43void
Michal Vaskof3e59f12015-06-18 11:53:56 +020044cmd_add_help(void)
45{
46 printf("add <path-to-model>\n");
47}
48
49void
50cmd_print_help(void)
51{
Michal Vasko7df7f142015-07-15 12:10:53 +020052 printf("print [-f (yang | tree | info)] [-t <info-target-node>] [-o <output-file>] <model-name>\n\n");
53 printf("\tinfo-target-node: <absolute-schema-node> | typedef/<typedef-name> |\n");
Michal Vasko035f5232015-07-15 12:26:52 +020054 printf("\t | identity/<identity-name> | feature/<feature-name> |\n");
55 printf("\t | type/<absolute-schema-node-leaf-or-leaflist>\n");
Michal Vaskof3e59f12015-06-18 11:53:56 +020056}
57
58void
Michal Vasko520d4732015-07-13 15:53:33 +020059cmd_data_help(void)
60{
61 printf("data [-f (xml | json)] [-o <output-file>] <data-file-name>\n");
62}
63
64void
Michal Vaskof3e59f12015-06-18 11:53:56 +020065cmd_list_help(void)
66{
67 printf("list\n");
68}
69
70void
Michal Vasko50cfb782015-07-07 11:37:34 +020071cmd_feature_help(void)
72{
73 printf("feature -(-p)rint | (-(-e)nable | -(-d)isable (* | <feature-name>)) <model-name>\n");
74}
75
76void
Michal Vaskof3e59f12015-06-18 11:53:56 +020077cmd_searchpath_help(void)
78{
Michal Vasko6572fb42015-07-07 09:55:05 +020079 printf("searchpath <model-dir-path>\n");
Michal Vaskof3e59f12015-06-18 11:53:56 +020080}
81
82void
83cmd_verb_help(void)
84{
85 printf("verb (error | warning | verbose | debug)\n");
86}
87
88int
89cmd_add(const char *arg)
90{
91 int fd;
Michal Vasko203b4e72015-06-30 15:25:15 +020092 char *addr, *ptr;
93 const char *path;
Michal Vaskof3e59f12015-06-18 11:53:56 +020094 struct ly_module *model;
95 struct stat sb;
96 LY_MINFORMAT format;
97
Michal Vasko203b4e72015-06-30 15:25:15 +020098 if (strlen(arg) < 5) {
Michal Vaskof3e59f12015-06-18 11:53:56 +020099 cmd_add_help();
100 return 1;
101 }
102
Michal Vasko203b4e72015-06-30 15:25:15 +0200103 path = (arg + strlen("add "));
104
Michal Vaskof3e59f12015-06-18 11:53:56 +0200105 if ((ptr = strrchr(path, '.')) != NULL) {
106 ++ptr;
107 if (!strcmp(ptr, "yin")) {
108 format = LY_IN_YIN;
109 } else if (!strcmp(ptr, "yang")) {
110 format = LY_IN_YANG;
111 } else {
112 fprintf(stderr, "Input file in an unknown format \"%s\".\n", ptr);
113 return 1;
114 }
115 } else {
116 fprintf(stdout, "Input file without extension, assuming YIN format.\n");
117 format = LY_IN_YIN;
118 }
119
120 fd = open(path, O_RDONLY);
121 if (fd == -1) {
122 fprintf(stderr, "Opening input file failed (%s).\n", strerror(errno));
123 return 1;
124 }
Radek Krejci4041a2d2015-07-02 09:16:42 +0200125
126 if (fstat(fd, &sb) == -1) {
127 fprintf(stderr, "Unable to get input file information (%s).\n", strerror(errno));
128 close(fd);
129 return 1;
130 }
131
132 if (!S_ISREG(sb.st_mode)) {
133 fprintf(stderr, "Input file not a file.\n");
134 close(fd);
135 return 1;
136 }
137
Michal Vaskof3e59f12015-06-18 11:53:56 +0200138 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
139
Radek Krejci63a91a92015-07-29 13:31:04 +0200140 model = lys_parse(ctx, addr, format);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200141 munmap(addr, sb.st_size);
142 close(fd);
143
144 if (!model) {
145 /* libyang printed the error messages */
146 return 1;
147 }
148
Michal Vaskof3e59f12015-06-18 11:53:56 +0200149 return 0;
150}
151
152int
153cmd_print(const char *arg)
154{
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200155 int c, i, argc, option_index, ret = 1;
Radek Krejci96a10da2015-07-30 11:00:14 +0200156 char **argv = NULL, *ptr, *target_node = NULL;
157 const char **names;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200158 const char *out_path = NULL;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200159 struct ly_module *model, *parent_model;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200160 LY_MOUTFORMAT format = LY_OUT_TREE;
161 FILE *output = stdout;
162 static struct option long_options[] = {
163 {"help", no_argument, 0, 'h'},
164 {"format", required_argument, 0, 'f'},
165 {"output", required_argument, 0, 'o'},
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200166 {"target-node", required_argument, 0, 't'},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200167 {NULL, 0, 0, 0}
168 };
169
170 argc = 1;
171 argv = malloc(2*sizeof *argv);
172 *argv = strdup(arg);
173 ptr = strtok(*argv, " ");
174 while ((ptr = strtok(NULL, " "))) {
175 argv = realloc(argv, (argc+2)*sizeof *argv);
176 argv[argc++] = ptr;
177 }
178 argv[argc] = NULL;
179
Michal Vasko50cfb782015-07-07 11:37:34 +0200180 optind = 0;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200181 while (1) {
Michal Vasko1074ce92015-07-03 16:16:31 +0200182 option_index = 0;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200183 c = getopt_long(argc, argv, "hf:o:t:", long_options, &option_index);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200184 if (c == -1) {
185 break;
186 }
187
188 switch (c) {
189 case 'h':
190 cmd_print_help();
191 ret = 0;
192 goto cleanup;
193 case 'f':
194 if (!strcmp(optarg, "yang")) {
195 format = LY_OUT_YANG;
196 } else if (!strcmp(optarg, "tree")) {
197 format = LY_OUT_TREE;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200198 } else if (!strcmp(optarg, "info")) {
199 format = LY_OUT_INFO;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200200 } else {
201 fprintf(stderr, "Unknown output format \"%s\".\n", optarg);
202 goto cleanup;
203 }
204 break;
205 case 'o':
206 if (out_path) {
207 fprintf(stderr, "Output specified twice.\n");
208 goto cleanup;
209 }
210 out_path = optarg;
211 break;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200212 case 't':
213 target_node = optarg;
214 break;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200215 case '?':
216 fprintf(stderr, "Unknown option \"%d\".\n", (char)c);
217 goto cleanup;
218 }
219 }
220
221 /* file name */
222 if (optind == argc) {
223 fprintf(stderr, "Missing the model name.\n");
224 goto cleanup;
225 }
Michal Vaskocf0a41c2015-07-07 11:43:10 +0200226
Radek Krejci63a91a92015-07-29 13:31:04 +0200227 model = ly_ctx_get_module(ctx, argv[optind], NULL);
Michal Vaskocf0a41c2015-07-07 11:43:10 +0200228 if (model == NULL) {
229 names = ly_ctx_get_module_names(ctx);
230 for (i = 0; names[i]; i++) {
231 if (!model) {
Radek Krejci63a91a92015-07-29 13:31:04 +0200232 parent_model = ly_ctx_get_module(ctx, names[i], NULL);
233 model = (struct ly_module *)ly_ctx_get_submodule(parent_model, argv[optind], NULL);
Michal Vaskocf0a41c2015-07-07 11:43:10 +0200234 }
Michal Vaskocf0a41c2015-07-07 11:43:10 +0200235 }
236 free(names);
237 }
Michal Vaskof3e59f12015-06-18 11:53:56 +0200238
239 if (model == NULL) {
240 fprintf(stderr, "No model \"%s\" found.\n", argv[optind]);
241 goto cleanup;
242 }
243
244 if (out_path) {
245 output = fopen(out_path, "w");
246 if (!output) {
247 fprintf(stderr, "Could not open the output file (%s).\n", strerror(errno));
248 goto cleanup;
249 }
250 }
251
Radek Krejci912da452015-07-29 14:10:06 +0200252 ret = lys_print(output, model, format, target_node);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200253
254cleanup:
255 free(*argv);
256 free(argv);
257
Radek Krejci94f05832015-06-19 09:58:53 +0200258 if (output && (output != stdout)) {
Michal Vaskof3e59f12015-06-18 11:53:56 +0200259 fclose(output);
260 }
261
262 return ret;
263}
264
265int
Michal Vasko520d4732015-07-13 15:53:33 +0200266cmd_data(const char *arg)
267{
Michal Vaskoa3b45ca2015-07-14 16:01:20 +0200268 int c, argc, option_index, ret = 1, fd = -1;
269 struct stat sb;
270 char **argv = NULL, *ptr, *addr;
Michal Vasko520d4732015-07-13 15:53:33 +0200271 const char *out_path = NULL;
272 struct lyd_node *data = NULL;
273 LY_DFORMAT format = LY_DATA_UNKNOWN;
274 FILE *output = stdout;
275 static struct option long_options[] = {
276 {"help", no_argument, 0, 'h'},
277 {"format", required_argument, 0, 'f'},
278 {"output", required_argument, 0, 'o'},
279 {NULL, 0, 0, 0}
280 };
281
282 argc = 1;
283 argv = malloc(2*sizeof *argv);
284 *argv = strdup(arg);
285 ptr = strtok(*argv, " ");
286 while ((ptr = strtok(NULL, " "))) {
287 argv = realloc(argv, (argc+2)*sizeof *argv);
288 argv[argc++] = ptr;
289 }
290 argv[argc] = NULL;
291
292 optind = 0;
293 while (1) {
294 option_index = 0;
295 c = getopt_long(argc, argv, "hf:o:", long_options, &option_index);
296 if (c == -1) {
297 break;
298 }
299
300 switch (c) {
301 case 'h':
302 cmd_data_help();
303 ret = 0;
304 goto cleanup;
305 case 'f':
306 if (!strcmp(optarg, "xml")) {
307 format = LY_DATA_XML;
308 } else if (!strcmp(optarg, "json")) {
309 format = LY_DATA_JSON;
310 } else {
311 fprintf(stderr, "Unknown output format \"%s\".\n", optarg);
312 goto cleanup;
313 }
314 break;
315 case 'o':
316 if (out_path) {
317 fprintf(stderr, "Output specified twice.\n");
318 goto cleanup;
319 }
320 out_path = optarg;
321 break;
322 case '?':
323 fprintf(stderr, "Unknown option \"%d\".\n", (char)c);
324 goto cleanup;
325 }
326 }
327
328 /* file name */
329 if (optind == argc) {
330 fprintf(stderr, "Missing the data file name.\n");
331 goto cleanup;
332 }
333
Michal Vaskoa3b45ca2015-07-14 16:01:20 +0200334 fd = open(argv[optind], O_RDONLY);
335 if (fd == -1) {
Michal Vasko0c16d662015-07-13 15:54:37 +0200336 fprintf(stderr, "The input file could not be opened (%s).\n", strerror(errno));
Michal Vasko520d4732015-07-13 15:53:33 +0200337 goto cleanup;
338 }
339
Michal Vaskoa3b45ca2015-07-14 16:01:20 +0200340 if (fstat(fd, &sb) == -1) {
341 fprintf(stderr, "Unable to get input file information (%s).\n", strerror(errno));
342 goto cleanup;
343 }
Michal Vasko520d4732015-07-13 15:53:33 +0200344
Michal Vaskoa3b45ca2015-07-14 16:01:20 +0200345 if (!S_ISREG(sb.st_mode)) {
346 fprintf(stderr, "Input file not a file.\n");
347 goto cleanup;
348 }
349
350 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
351 data = xml_read_data(ctx, addr);
352 munmap(addr, sb.st_size);
353
Michal Vasko520d4732015-07-13 15:53:33 +0200354 if (data == NULL) {
355 fprintf(stderr, "Failed to parse data.\n");
356 goto cleanup;
357 }
358
359 if (out_path) {
360 output = fopen(out_path, "w");
361 if (!output) {
362 fprintf(stderr, "Could not open the output file (%s).\n", strerror(errno));
363 goto cleanup;
364 }
365
366 if (format == LY_DATA_UNKNOWN) {
367 /* default */
368 format = LY_DATA_XML;
369 }
370 }
371
372 if (format != LY_DATA_UNKNOWN) {
Radek Krejci912da452015-07-29 14:10:06 +0200373 lyd_print(output, data, format);
Michal Vasko520d4732015-07-13 15:53:33 +0200374 }
375
376cleanup:
377 free(*argv);
378 free(argv);
379
380 if (output && (output != stdout)) {
381 fclose(output);
382 }
383
Michal Vaskoa3b45ca2015-07-14 16:01:20 +0200384 if (fd != -1) {
385 close(fd);
386 }
387
Michal Vaskof54f2f82015-07-17 13:12:05 +0200388 lyd_node_siblings_free(data);
Michal Vasko520d4732015-07-13 15:53:33 +0200389
390 return ret;
391}
392
393int
Michal Vaskof3e59f12015-06-18 11:53:56 +0200394cmd_list(const char *UNUSED(arg))
395{
Radek Krejci96a10da2015-07-30 11:00:14 +0200396 const char **names, **sub_names;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200397 int i, j;
Michal Vaskoe0cb2522015-07-01 10:24:53 +0200398
Michal Vaskof3e59f12015-06-18 11:53:56 +0200399 printf("List of the loaded models:\n");
400
Michal Vaskoe0cb2522015-07-01 10:24:53 +0200401 names = ly_ctx_get_module_names(ctx);
402
403 for (i = 0; names[i]; ++i) {
404 printf("\t%s\n", names[i]);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200405
406 sub_names = ly_ctx_get_submodule_names(ctx, names[i]);
407 for (j = 0; sub_names[j]; ++j) {
408 printf("\t\t%s\n", sub_names[j]);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200409 }
410 free(sub_names);
Michal Vaskoe0cb2522015-07-01 10:24:53 +0200411 }
412 free(names);
413
414 if (i == 0) {
415 printf("\t(none)\n");
416 }
Michal Vaskof3e59f12015-06-18 11:53:56 +0200417
418 return 0;
419}
420
421int
Michal Vasko50cfb782015-07-07 11:37:34 +0200422cmd_feature(const char *arg)
423{
424 int c, i, argc, option_index, ret = 1, task = -1;
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200425 char **argv = NULL, *ptr;
Radek Krejci96a10da2015-07-30 11:00:14 +0200426 const char *feat_name = NULL, **names;
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200427 uint8_t *states;
Michal Vasko50cfb782015-07-07 11:37:34 +0200428 struct ly_module *model, *parent_model;
429 static struct option long_options[] = {
430 {"help", no_argument, 0, 'h'},
431 {"print", no_argument, 0, 'p'},
432 {"enable", required_argument, 0, 'e'},
433 {"disable", required_argument, 0, 'd'},
434 {NULL, 0, 0, 0}
435 };
436
437 argc = 1;
438 argv = malloc(2*sizeof *argv);
439 *argv = strdup(arg);
440 ptr = strtok(*argv, " ");
441 while ((ptr = strtok(NULL, " "))) {
442 argv = realloc(argv, (argc+2)*sizeof *argv);
443 argv[argc++] = ptr;
444 }
445 argv[argc] = NULL;
446
447 optind = 0;
448 while (1) {
449 option_index = 0;
450 c = getopt_long(argc, argv, "hpe:d:", long_options, &option_index);
451 if (c == -1) {
452 break;
453 }
454
455 switch (c) {
456 case 'h':
457 cmd_feature_help();
458 ret = 0;
459 goto cleanup;
460 case 'p':
461 if (task != -1) {
462 fprintf(stderr, "Only one of print, enable, or disable can be specified.\n");
463 goto cleanup;
464 }
465 task = 0;
466 break;
467 case 'e':
468 if (task != -1) {
469 fprintf(stderr, "Only one of print, enable, or disable can be specified.\n");
470 goto cleanup;
471 }
472 task = 1;
473 feat_name = optarg;
474 break;
475 case 'd':
476 if (task != -1) {
477 fprintf(stderr, "Only one of print, enable, or disable can be specified.\n");
478 goto cleanup;
479 }
480 task = 2;
481 feat_name = optarg;
482 break;
483 case '?':
484 fprintf(stderr, "Unknown option \"%d\".\n", (char)c);
485 goto cleanup;
486 }
487 }
488
489 /* model name */
490 if (optind == argc) {
491 fprintf(stderr, "Missing the model name.\n");
492 goto cleanup;
493 }
Radek Krejci63a91a92015-07-29 13:31:04 +0200494 model = ly_ctx_get_module(ctx, argv[optind], NULL);
Michal Vasko50cfb782015-07-07 11:37:34 +0200495 if (model == NULL) {
496 names = ly_ctx_get_module_names(ctx);
497 for (i = 0; names[i]; i++) {
498 if (!model) {
Radek Krejci63a91a92015-07-29 13:31:04 +0200499 parent_model = ly_ctx_get_module(ctx, names[i], NULL);
500 model = (struct ly_module *)ly_ctx_get_submodule(parent_model, argv[optind], NULL);
Michal Vasko50cfb782015-07-07 11:37:34 +0200501 }
Michal Vasko50cfb782015-07-07 11:37:34 +0200502 }
503 free(names);
504 }
505 if (model == NULL) {
506 fprintf(stderr, "No model \"%s\" found.\n", argv[optind]);
507 goto cleanup;
508 }
509
510 if (task == -1) {
511 fprintf(stderr, "One of print, enable, or disable must be specified.\n");
512 goto cleanup;
513 }
514
515 if (task == 0) {
516 printf("%s features:\n", model->name);
517
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200518 names = lys_features_list(model, &states);
Michal Vasko50cfb782015-07-07 11:37:34 +0200519 for (i = 0; names[i]; ++i) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200520 printf("\t%s %s\n", names[i], states[i] ? "on" : "off");
Michal Vasko50cfb782015-07-07 11:37:34 +0200521 }
522 free(names);
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200523 free(states);
Michal Vasko50cfb782015-07-07 11:37:34 +0200524 if (!i) {
525 printf("\t(none)\n");
526 }
527 } else if (task == 1) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200528 if (lys_features_enable(model, feat_name)) {
Michal Vasko50cfb782015-07-07 11:37:34 +0200529 fprintf(stderr, "Feature \"%s\" not found.\n", feat_name);
530 ret = 1;
531 }
532 } else if (task == 2) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200533 if (lys_features_disable(model, feat_name)) {
Michal Vasko50cfb782015-07-07 11:37:34 +0200534 fprintf(stderr, "Feature \"%s\" not found.\n", feat_name);
535 ret = 1;
536 }
537 }
538
539cleanup:
540 free(*argv);
541 free(argv);
542
543 return ret;
544}
545
546int
Michal Vaskof3e59f12015-06-18 11:53:56 +0200547cmd_searchpath(const char *arg)
548{
549 const char *path;
550 struct stat st;
551
552 if (strchr(arg, ' ') == NULL) {
553 fprintf(stderr, "Missing the search path.\n");
554 return 1;
555 }
556 path = strchr(arg, ' ')+1;
557
558 if (!strcmp(path, "-h") || !strcmp(path, "--help")) {
559 cmd_searchpath_help();
560 return 0;
561 }
562
563 if (stat(path, &st) == -1) {
564 fprintf(stderr, "Failed to stat the search path (%s).\n", strerror(errno));
565 return 1;
566 }
567 if (!S_ISDIR(st.st_mode)) {
568 fprintf(stderr, "\"%s\" is not a directory.\n", path);
569 return 1;
570 }
571
572 free(search_path);
573 search_path = strdup(path);
574
Michal Vasko6572fb42015-07-07 09:55:05 +0200575 ly_ctx_set_searchdir(ctx, search_path);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200576
Michal Vasko6572fb42015-07-07 09:55:05 +0200577 return 0;
578}
Michal Vaskof3e59f12015-06-18 11:53:56 +0200579
Michal Vasko50cfb782015-07-07 11:37:34 +0200580int
581cmd_clear(const char *UNUSED(arg))
582{
583 ly_ctx_destroy(ctx);
584 ctx = ly_ctx_new(search_path);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200585 return 0;
586}
587
588int
589cmd_verb(const char *arg)
590{
591 const char *verb;
Radek Krejci7408bf12015-07-20 18:15:51 +0200592 if (strlen(arg) < 5) {
593 cmd_verb_help();
594 return 1;
595 }
Michal Vaskof3e59f12015-06-18 11:53:56 +0200596
597 verb = arg + 5;
598 if (strcmp(verb, "error") == 0) {
599 ly_verb(0);
600 } else if (strcmp(verb, "warning") == 0) {
601 ly_verb(1);
602 } else if (strcmp(verb, "verbose") == 0) {
603 ly_verb(2);
604 } else if (strcmp(verb, "debug") == 0) {
605 ly_verb(3);
606 } else {
Radek Krejci7408bf12015-07-20 18:15:51 +0200607 fprintf(stderr, "Unknown verbosity \"%s\"\n", verb);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200608 return 1;
609 }
610
611 return 0;
612}
613
614int
615cmd_quit(const char *UNUSED(arg))
616{
617 done = 1;
618 return 0;
619}
620
621int
622cmd_help(const char *arg)
623{
624 int i;
625 char *args = strdupa(arg);
626 char *cmd = NULL;
627
628 strtok(args, " ");
629 if ((cmd = strtok(NULL, " ")) == NULL) {
630
631generic_help:
632 fprintf(stdout, "Available commands:\n");
633
634 for (i = 0; commands[i].name; i++) {
635 if (commands[i].helpstring != NULL) {
636 fprintf(stdout, " %-15s %s\n", commands[i].name, commands[i].helpstring);
637 }
638 }
639 } else {
640 /* print specific help for the selected command */
641
642 /* get the command of the specified name */
643 for (i = 0; commands[i].name; i++) {
644 if (strcmp(cmd, commands[i].name) == 0) {
645 break;
646 }
647 }
648
649 /* execute the command's help if any valid command specified */
650 if (commands[i].name) {
651 if (commands[i].help_func != NULL) {
652 commands[i].help_func();
653 } else {
654 printf("%s\n", commands[i].helpstring);
655 }
656 } else {
657 /* if unknown command specified, print the list of commands */
658 printf("Unknown command \'%s\'\n", cmd);
659 goto generic_help;
660 }
661 }
662
663 return 0;
664}
665
666COMMAND commands[] = {
667 {"help", cmd_help, NULL, "Display commands description"},
668 {"add", cmd_add, cmd_add_help, "Add a new model"},
669 {"print", cmd_print, cmd_print_help, "Print model"},
Michal Vasko520d4732015-07-13 15:53:33 +0200670 {"data", cmd_data, cmd_data_help, "Load, validate and optionally print data"},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200671 {"list", cmd_list, cmd_list_help, "List all the loaded models"},
Michal Vasko50cfb782015-07-07 11:37:34 +0200672 {"feature", cmd_feature, cmd_feature_help, "Print/enable/disable all/specific features of models"},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200673 {"searchpath", cmd_searchpath, cmd_searchpath_help, "Set the search path for models"},
Michal Vasko6572fb42015-07-07 09:55:05 +0200674 {"clear", cmd_clear, NULL, "Clear the context - remove all the loaded models"},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200675 {"verb", cmd_verb, cmd_verb_help, "Change verbosity"},
676 {"quit", cmd_quit, NULL, "Quit the program"},
677 /* synonyms for previous commands */
678 {"?", cmd_help, NULL, "Display commands description"},
679 {"exit", cmd_quit, NULL, "Quit the program"},
680 {NULL, NULL, NULL, NULL}
681};