1 /*
2 ** Copyright (C) 2008-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 
9 /*
10 **  skoptions-notes.c
11 **
12 **    Provide support for the --note-add, --note-file-add, and
13 **    --note-strip switches.
14 **
15 */
16 
17 
18 #include <silk/silk.h>
19 
20 RCSIDENT("$SiLK: skoptions-notes.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
21 
22 #include <silk/utils.h>
23 #include <silk/skstream.h>
24 #include <silk/skvector.h>
25 
26 
27 /* LOCAL DEFINES AND TYPEDEFS */
28 
29 typedef enum {
30     OPT_NOTE_STRIP,
31     OPT_NOTE_ADD,
32     OPT_NOTE_FILE_ADD
33 } noteopt_type_t;
34 
35 typedef struct noteopt_arg_st {
36     noteopt_type_t  type;
37     const char     *arg;
38 } noteopt_arg_t;
39 
40 
41 /* LOCAL VARIABLE DEFINITIONS */
42 
43 /* a vector of noteopt_arg_t that is filled in by the user's use of
44  * the --note-add and --note-file-add switches. */
45 static sk_vector_t *noteopt_vec = NULL;
46 
47 /* whether the application wants to ignore the --note-strip option */
48 static int noteopt_strip_ignored = 0;
49 
50 
51 
52 /* OPTIONS SETUP */
53 
54 static struct option noteopt_options[] = {
55     {"note-strip",          NO_ARG,       0, OPT_NOTE_STRIP},
56     {"note-add",            REQUIRED_ARG, 0, OPT_NOTE_ADD},
57     {"note-file-add",       REQUIRED_ARG, 0, OPT_NOTE_FILE_ADD},
58     {0,0,0,0}               /* sentinel */
59 };
60 
61 static const char *noteopt_help[] = {
62     "Do not copy notes from the input files to the output file",
63     ("Store the textual argument in the output SiLK file's header\n"
64      "\tas an annotation. Switch may be repeated to add multiple annotations"),
65     ("Store the content of the named text file in the output\n"
66      "\tSiLK file's header as an annotation.  Switch may be repeated."),
67     (char*)NULL
68 };
69 
70 
71 /* FUNCTION DEFINITIONS */
72 
73 
74 static int
noteopt_handler(clientData cData,int opt_index,char * opt_arg)75 noteopt_handler(
76     clientData          cData,
77     int                 opt_index,
78     char               *opt_arg)
79 {
80     int *note_strip = (int*)cData;
81     noteopt_arg_t note;
82 
83     switch ((noteopt_type_t)opt_index) {
84       case OPT_NOTE_ADD:
85       case OPT_NOTE_FILE_ADD:
86         note.type = (noteopt_type_t)opt_index;
87         note.arg = opt_arg;
88         if (noteopt_vec == NULL) {
89             noteopt_vec = skVectorNew(sizeof(noteopt_arg_t));
90             if (noteopt_vec == NULL) {
91                 skAppPrintOutOfMemory(NULL);
92                 return 1;
93             }
94         }
95         if (skVectorAppendValue(noteopt_vec, &note)) {
96             skAppPrintOutOfMemory(NULL);
97             return 1;
98         }
99         break;
100 
101       case OPT_NOTE_STRIP:
102         assert(noteopt_strip_ignored == 0);
103         *note_strip = 1;
104         break;
105 
106     }
107 
108     return 0;
109 }
110 
111 
112 int
skOptionsNotesRegister(int * note_strip)113 skOptionsNotesRegister(
114     int                *note_strip)
115 {
116     if (note_strip == NULL) {
117         noteopt_strip_ignored = 1;
118     }
119 
120     assert((sizeof(noteopt_options)/sizeof(struct option))
121            == (sizeof(noteopt_help)/sizeof(char*)));
122 
123     return skOptionsRegister(&noteopt_options[noteopt_strip_ignored],
124                              &noteopt_handler, (clientData)note_strip);
125 }
126 
127 
128 void
skOptionsNotesTeardown(void)129 skOptionsNotesTeardown(
130     void)
131 {
132     if (noteopt_vec) {
133         skVectorDestroy(noteopt_vec);
134     }
135     noteopt_vec = NULL;
136 }
137 
138 
139 void
skOptionsNotesUsage(FILE * fh)140 skOptionsNotesUsage(
141     FILE               *fh)
142 {
143     int i;
144 
145     for (i = noteopt_strip_ignored; noteopt_options[i].name; ++i) {
146         fprintf(fh, "--%s %s. %s\n", noteopt_options[i].name,
147                 SK_OPTION_HAS_ARG(noteopt_options[i]), noteopt_help[i]);
148     }
149 }
150 
151 
152 int
skOptionsNotesAddToStream(skstream_t * stream)153 skOptionsNotesAddToStream(
154     skstream_t         *stream)
155 {
156     sk_file_header_t *hdr = skStreamGetSilkHeader(stream);
157     noteopt_arg_t *note;
158     size_t i;
159     int rv = 0;
160 
161     if (noteopt_vec) {
162         for (i = 0;
163              ((note = (noteopt_arg_t*)skVectorGetValuePointer(noteopt_vec, i))
164               != NULL);
165              ++i)
166         {
167             if (note->type == OPT_NOTE_ADD) {
168                 rv = skHeaderAddAnnotation(hdr, note->arg);
169             } else {
170                 rv = skHeaderAddAnnotationFromFile(hdr, note->arg);
171             }
172             if (rv) {
173                 return rv;
174             }
175         }
176     }
177 
178     return rv;
179 }
180 
181 
182 /*
183 ** Local Variables:
184 ** mode:c
185 ** indent-tabs-mode:nil
186 ** c-basic-offset:4
187 ** End:
188 */
189