blob: 3bb47b0f3720cb5c0c4f8d08263bbf681b77039c [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
140 model = ly_module_read(ctx, addr, format);
141 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;
156 char **argv = NULL, *ptr, *target_node = NULL, **names;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200157 const char *out_path = NULL;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200158 struct ly_module *model, *parent_model;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200159 LY_MOUTFORMAT format = LY_OUT_TREE;
160 FILE *output = stdout;
161 static struct option long_options[] = {
162 {"help", no_argument, 0, 'h'},
163 {"format", required_argument, 0, 'f'},
164 {"output", required_argument, 0, 'o'},
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200165 {"target-node", required_argument, 0, 't'},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200166 {NULL, 0, 0, 0}
167 };
168
169 argc = 1;
170 argv = malloc(2*sizeof *argv);
171 *argv = strdup(arg);
172 ptr = strtok(*argv, " ");
173 while ((ptr = strtok(NULL, " "))) {
174 argv = realloc(argv, (argc+2)*sizeof *argv);
175 argv[argc++] = ptr;
176 }
177 argv[argc] = NULL;
178
Michal Vasko50cfb782015-07-07 11:37:34 +0200179 optind = 0;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200180 while (1) {
Michal Vasko1074ce92015-07-03 16:16:31 +0200181 option_index = 0;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200182 c = getopt_long(argc, argv, "hf:o:t:", long_options, &option_index);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200183 if (c == -1) {
184 break;
185 }
186
187 switch (c) {
188 case 'h':
189 cmd_print_help();
190 ret = 0;
191 goto cleanup;
192 case 'f':
193 if (!strcmp(optarg, "yang")) {
194 format = LY_OUT_YANG;
195 } else if (!strcmp(optarg, "tree")) {
196 format = LY_OUT_TREE;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200197 } else if (!strcmp(optarg, "info")) {
198 format = LY_OUT_INFO;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200199 } else {
200 fprintf(stderr, "Unknown output format \"%s\".\n", optarg);
201 goto cleanup;
202 }
203 break;
204 case 'o':
205 if (out_path) {
206 fprintf(stderr, "Output specified twice.\n");
207 goto cleanup;
208 }
209 out_path = optarg;
210 break;
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200211 case 't':
212 target_node = optarg;
213 break;
Michal Vaskof3e59f12015-06-18 11:53:56 +0200214 case '?':
215 fprintf(stderr, "Unknown option \"%d\".\n", (char)c);
216 goto cleanup;
217 }
218 }
219
220 /* file name */
221 if (optind == argc) {
222 fprintf(stderr, "Missing the model name.\n");
223 goto cleanup;
224 }
Michal Vaskocf0a41c2015-07-07 11:43:10 +0200225
Michal Vaskof3e59f12015-06-18 11:53:56 +0200226 model = ly_ctx_get_module(ctx, argv[optind], NULL, 0);
Michal Vaskocf0a41c2015-07-07 11:43:10 +0200227 if (model == NULL) {
228 names = ly_ctx_get_module_names(ctx);
229 for (i = 0; names[i]; i++) {
230 if (!model) {
231 parent_model = ly_ctx_get_module(ctx, names[i], NULL, 0);
232 model = (struct ly_module *)ly_ctx_get_submodule(parent_model, argv[optind], NULL, 0);
233 }
234 free(names[i]);
235 }
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
Michal Vaskodd3b8bc2015-07-07 11:42:28 +0200252 ret = ly_model_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) {
373 ly_data_print(output, data, format);
374 }
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{
Michal Vaskofa8c8282015-07-03 15:14:59 +0200396 char **names, **sub_names;
397 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]);
409 free(sub_names[j]);
410 }
411 free(sub_names);
412
Michal Vaskoe0cb2522015-07-01 10:24:53 +0200413 free(names[i]);
414 }
415 free(names);
416
417 if (i == 0) {
418 printf("\t(none)\n");
419 }
Michal Vaskof3e59f12015-06-18 11:53:56 +0200420
421 return 0;
422}
423
424int
Michal Vasko50cfb782015-07-07 11:37:34 +0200425cmd_feature(const char *arg)
426{
427 int c, i, argc, option_index, ret = 1, task = -1;
428 char **argv = NULL, *ptr, **names, **enable_state;
429 const char *feat_name = NULL;
430 struct ly_module *model, *parent_model;
431 static struct option long_options[] = {
432 {"help", no_argument, 0, 'h'},
433 {"print", no_argument, 0, 'p'},
434 {"enable", required_argument, 0, 'e'},
435 {"disable", required_argument, 0, 'd'},
436 {NULL, 0, 0, 0}
437 };
438
439 argc = 1;
440 argv = malloc(2*sizeof *argv);
441 *argv = strdup(arg);
442 ptr = strtok(*argv, " ");
443 while ((ptr = strtok(NULL, " "))) {
444 argv = realloc(argv, (argc+2)*sizeof *argv);
445 argv[argc++] = ptr;
446 }
447 argv[argc] = NULL;
448
449 optind = 0;
450 while (1) {
451 option_index = 0;
452 c = getopt_long(argc, argv, "hpe:d:", long_options, &option_index);
453 if (c == -1) {
454 break;
455 }
456
457 switch (c) {
458 case 'h':
459 cmd_feature_help();
460 ret = 0;
461 goto cleanup;
462 case 'p':
463 if (task != -1) {
464 fprintf(stderr, "Only one of print, enable, or disable can be specified.\n");
465 goto cleanup;
466 }
467 task = 0;
468 break;
469 case 'e':
470 if (task != -1) {
471 fprintf(stderr, "Only one of print, enable, or disable can be specified.\n");
472 goto cleanup;
473 }
474 task = 1;
475 feat_name = optarg;
476 break;
477 case 'd':
478 if (task != -1) {
479 fprintf(stderr, "Only one of print, enable, or disable can be specified.\n");
480 goto cleanup;
481 }
482 task = 2;
483 feat_name = optarg;
484 break;
485 case '?':
486 fprintf(stderr, "Unknown option \"%d\".\n", (char)c);
487 goto cleanup;
488 }
489 }
490
491 /* model name */
492 if (optind == argc) {
493 fprintf(stderr, "Missing the model name.\n");
494 goto cleanup;
495 }
496 model = ly_ctx_get_module(ctx, argv[optind], NULL, 0);
497 if (model == NULL) {
498 names = ly_ctx_get_module_names(ctx);
499 for (i = 0; names[i]; i++) {
500 if (!model) {
501 parent_model = ly_ctx_get_module(ctx, names[i], NULL, 0);
502 model = (struct ly_module *)ly_ctx_get_submodule(parent_model, argv[optind], NULL, 0);
503 }
504 free(names[i]);
505 }
506 free(names);
507 }
508 if (model == NULL) {
509 fprintf(stderr, "No model \"%s\" found.\n", argv[optind]);
510 goto cleanup;
511 }
512
513 if (task == -1) {
514 fprintf(stderr, "One of print, enable, or disable must be specified.\n");
515 goto cleanup;
516 }
517
518 if (task == 0) {
519 printf("%s features:\n", model->name);
520
521 names = ly_get_features(model, &enable_state);
522 for (i = 0; names[i]; ++i) {
523 printf("\t%s %s\n", names[i], enable_state[i]);
524 free(names[i]);
525 free(enable_state[i]);
526 }
527 free(names);
528 free(enable_state);
529 if (!i) {
530 printf("\t(none)\n");
531 }
532 } else if (task == 1) {
533 if (ly_features_enable(model, feat_name)) {
534 fprintf(stderr, "Feature \"%s\" not found.\n", feat_name);
535 ret = 1;
536 }
537 } else if (task == 2) {
538 if (ly_features_disable(model, feat_name)) {
539 fprintf(stderr, "Feature \"%s\" not found.\n", feat_name);
540 ret = 1;
541 }
542 }
543
544cleanup:
545 free(*argv);
546 free(argv);
547
548 return ret;
549}
550
551int
Michal Vaskof3e59f12015-06-18 11:53:56 +0200552cmd_searchpath(const char *arg)
553{
554 const char *path;
555 struct stat st;
556
557 if (strchr(arg, ' ') == NULL) {
558 fprintf(stderr, "Missing the search path.\n");
559 return 1;
560 }
561 path = strchr(arg, ' ')+1;
562
563 if (!strcmp(path, "-h") || !strcmp(path, "--help")) {
564 cmd_searchpath_help();
565 return 0;
566 }
567
568 if (stat(path, &st) == -1) {
569 fprintf(stderr, "Failed to stat the search path (%s).\n", strerror(errno));
570 return 1;
571 }
572 if (!S_ISDIR(st.st_mode)) {
573 fprintf(stderr, "\"%s\" is not a directory.\n", path);
574 return 1;
575 }
576
577 free(search_path);
578 search_path = strdup(path);
579
Michal Vasko6572fb42015-07-07 09:55:05 +0200580 ly_ctx_set_searchdir(ctx, search_path);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200581
Michal Vasko6572fb42015-07-07 09:55:05 +0200582 return 0;
583}
Michal Vaskof3e59f12015-06-18 11:53:56 +0200584
Michal Vasko50cfb782015-07-07 11:37:34 +0200585int
586cmd_clear(const char *UNUSED(arg))
587{
588 ly_ctx_destroy(ctx);
589 ctx = ly_ctx_new(search_path);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200590 return 0;
591}
592
593int
594cmd_verb(const char *arg)
595{
596 const char *verb;
Radek Krejci7408bf12015-07-20 18:15:51 +0200597 if (strlen(arg) < 5) {
598 cmd_verb_help();
599 return 1;
600 }
Michal Vaskof3e59f12015-06-18 11:53:56 +0200601
602 verb = arg + 5;
603 if (strcmp(verb, "error") == 0) {
604 ly_verb(0);
605 } else if (strcmp(verb, "warning") == 0) {
606 ly_verb(1);
607 } else if (strcmp(verb, "verbose") == 0) {
608 ly_verb(2);
609 } else if (strcmp(verb, "debug") == 0) {
610 ly_verb(3);
611 } else {
Radek Krejci7408bf12015-07-20 18:15:51 +0200612 fprintf(stderr, "Unknown verbosity \"%s\"\n", verb);
Michal Vaskof3e59f12015-06-18 11:53:56 +0200613 return 1;
614 }
615
616 return 0;
617}
618
619int
620cmd_quit(const char *UNUSED(arg))
621{
622 done = 1;
623 return 0;
624}
625
626int
627cmd_help(const char *arg)
628{
629 int i;
630 char *args = strdupa(arg);
631 char *cmd = NULL;
632
633 strtok(args, " ");
634 if ((cmd = strtok(NULL, " ")) == NULL) {
635
636generic_help:
637 fprintf(stdout, "Available commands:\n");
638
639 for (i = 0; commands[i].name; i++) {
640 if (commands[i].helpstring != NULL) {
641 fprintf(stdout, " %-15s %s\n", commands[i].name, commands[i].helpstring);
642 }
643 }
644 } else {
645 /* print specific help for the selected command */
646
647 /* get the command of the specified name */
648 for (i = 0; commands[i].name; i++) {
649 if (strcmp(cmd, commands[i].name) == 0) {
650 break;
651 }
652 }
653
654 /* execute the command's help if any valid command specified */
655 if (commands[i].name) {
656 if (commands[i].help_func != NULL) {
657 commands[i].help_func();
658 } else {
659 printf("%s\n", commands[i].helpstring);
660 }
661 } else {
662 /* if unknown command specified, print the list of commands */
663 printf("Unknown command \'%s\'\n", cmd);
664 goto generic_help;
665 }
666 }
667
668 return 0;
669}
670
671COMMAND commands[] = {
672 {"help", cmd_help, NULL, "Display commands description"},
673 {"add", cmd_add, cmd_add_help, "Add a new model"},
674 {"print", cmd_print, cmd_print_help, "Print model"},
Michal Vasko520d4732015-07-13 15:53:33 +0200675 {"data", cmd_data, cmd_data_help, "Load, validate and optionally print data"},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200676 {"list", cmd_list, cmd_list_help, "List all the loaded models"},
Michal Vasko50cfb782015-07-07 11:37:34 +0200677 {"feature", cmd_feature, cmd_feature_help, "Print/enable/disable all/specific features of models"},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200678 {"searchpath", cmd_searchpath, cmd_searchpath_help, "Set the search path for models"},
Michal Vasko6572fb42015-07-07 09:55:05 +0200679 {"clear", cmd_clear, NULL, "Clear the context - remove all the loaded models"},
Michal Vaskof3e59f12015-06-18 11:53:56 +0200680 {"verb", cmd_verb, cmd_verb_help, "Change verbosity"},
681 {"quit", cmd_quit, NULL, "Quit the program"},
682 /* synonyms for previous commands */
683 {"?", cmd_help, NULL, "Display commands description"},
684 {"exit", cmd_quit, NULL, "Quit the program"},
685 {NULL, NULL, NULL, NULL}
686};