FMS  2024.03
Flexible Modeling System
yaml_output_functions.c
1 /***********************************************************************
2  * GNU Lesser General Public License
3  *
4  * This file is part of the GFDL Flexible Modeling System (FMS).
5  *
6  * FMS is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or (at
9  * your option) any later version.
10  *
11  * FMS is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18  **********************************************************************/
19 #ifdef use_yaml
20 
21 #include <stdio.h>
22 #include <yaml.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <ctype.h>
27 
28  // Should always match values of string_len_parameter and lvl2_key_parameter in fms_yaml_output_mod
29 #define LVL2KEY_NUM 8
30 #define KEY_STR_LEN 255
31 #define LVL2KEY_SIZE LVL2KEY_NUM*KEY_STR_LEN
32 
33 #define DEBUG 0
34 
35 struct fmsyamloutkeys {
36  char key1 [KEY_STR_LEN];
37  char key2 [KEY_STR_LEN];
38  char key3 [KEY_STR_LEN];
39  char key4 [KEY_STR_LEN];
40  char key5 [KEY_STR_LEN];
41  char key6 [KEY_STR_LEN];
42  char key7 [KEY_STR_LEN];
43  char key8 [KEY_STR_LEN];
44  char key9 [KEY_STR_LEN];
45  char key10 [KEY_STR_LEN];
46  char key11 [KEY_STR_LEN];
47  char key12 [KEY_STR_LEN];
48  char key13 [KEY_STR_LEN];
49  char key14 [KEY_STR_LEN];
50  char key15 [KEY_STR_LEN];
51  char key16 [KEY_STR_LEN];
52  int level2key_offset;
53  char level2key [LVL2KEY_SIZE];
54 };
55 struct fmsyamloutvalues {
56  char val1 [KEY_STR_LEN];
57  char val2 [KEY_STR_LEN];
58  char val3 [KEY_STR_LEN];
59  char val4 [KEY_STR_LEN];
60  char val5 [KEY_STR_LEN];
61  char val6 [KEY_STR_LEN];
62  char val7 [KEY_STR_LEN];
63  char val8 [KEY_STR_LEN];
64  char val9 [KEY_STR_LEN];
65  char val10 [KEY_STR_LEN];
66  char val11 [KEY_STR_LEN];
67  char val12 [KEY_STR_LEN];
68  char val13 [KEY_STR_LEN];
69  char val14 [KEY_STR_LEN];
70  char val15 [KEY_STR_LEN];
71  char val16 [KEY_STR_LEN];
72 };
73 
74 /* \breif Prints a warning message that the yaml was not written correctly
75  * \param emitter The libyaml emitter for this file
76  * \param event The libyaml eent pointer
77  * \param yamlname The name of the yaml file
78  * \param keys yamlout The file pointer for the yaml file
79  */
80 void error(char * yamlname ,yaml_event_t * event, yaml_emitter_t * emitter, FILE * yamlout){
81  /* Write a warning to stderr and srdout */
82  fprintf(stderr, "WARNING: YAML_OUTPUT: No output %s written. Failed to emit event %d: %s\n", yamlname, event->type, emitter->problem);
83  fprintf(stdout, "WARNING: YAML_OUTPUT: No output %s written. Failed to emit event %d: %s\n", yamlname, event->type, emitter->problem);
84  yaml_emitter_delete(emitter);
85  fclose(yamlout);
86 }
87 void keyerror(yaml_event_t * event, yaml_emitter_t * emitter){
88  /* Write a warning to stderr and srdout */
89  fprintf(stderr, "WARNING: YAML_OUTPUT: Failed to emit event %d: %s\n", event->type, emitter->problem);
90  fprintf(stdout, "WARNING: YAML_OUTPUT: Failed to emit event %d: %s\n", event->type, emitter->problem);
91 }
92 /* \breif Writes the key/value pairs of the fmsyamloutkeys and fmsyamloutvalues structs
93  * \param emitter The libyaml emitter for this file
94  * \param event The libyaml eent pointer
95  * \param aindex The index of keys and vals that are being written currently
96  * \param keys The keys to be written
97  * \param vals The values correcponding to keys
98  */
99 void write_keys_vals_yaml (yaml_emitter_t * emitter, yaml_event_t * event , int aindex, struct fmsyamloutkeys *keys, struct fmsyamloutvalues *vals){
100  /* Check if a key exists */
101  if (keys[aindex].key1[0] !='\0') {
102  /* Write the key */
103  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
104  (yaml_char_t *)keys[aindex].key1, strlen(keys[aindex].key1), 1, 0, YAML_PLAIN_SCALAR_STYLE);
105  /* Check for errors */
106  if (!yaml_emitter_emit(emitter, event)){
107  keyerror(event, emitter);
108  return;
109  }
110  /* Write the value */
111  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
112  (yaml_char_t *)vals[aindex].val1, strlen(vals[aindex].val1), 1, 0, YAML_PLAIN_SCALAR_STYLE);
113  /* check for errors */
114  if (!yaml_emitter_emit(emitter, event)){
115  keyerror(event, emitter);
116  return;
117  }
118  }
119  /* Repeat for all possible keys */
120  if (keys[aindex].key2[0] !='\0') {
121  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
122  (yaml_char_t *)keys[aindex].key2, strlen(keys[aindex].key2), 1, 0, YAML_PLAIN_SCALAR_STYLE);
123  if (!yaml_emitter_emit(emitter, event)){
124  keyerror(event, emitter);
125  return;
126  }
127  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
128  (yaml_char_t *)vals[aindex].val2, strlen(vals[aindex].val2), 1, 0, YAML_PLAIN_SCALAR_STYLE);
129  if (!yaml_emitter_emit(emitter, event)){
130  keyerror(event, emitter);
131  return;
132  }
133  }
134  if (keys[aindex].key3[0] !='\0') {
135  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
136  (yaml_char_t *)keys[aindex].key3, strlen(keys[aindex].key3), 1, 0, YAML_PLAIN_SCALAR_STYLE);
137  if (!yaml_emitter_emit(emitter, event)){
138  keyerror(event, emitter);
139  return;
140  }
141  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
142  (yaml_char_t *)vals[aindex].val3, strlen(vals[aindex].val3), 1, 0, YAML_PLAIN_SCALAR_STYLE);
143  if (!yaml_emitter_emit(emitter, event)){
144  keyerror(event, emitter);
145  return;
146  }
147  }
148  if (keys[aindex].key4[0] !='\0') {
149  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
150  (yaml_char_t *)keys[aindex].key4, strlen(keys[aindex].key4), 1, 0, YAML_PLAIN_SCALAR_STYLE);
151  if (!yaml_emitter_emit(emitter, event)){
152  keyerror(event, emitter);
153  return;
154  }
155  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
156  (yaml_char_t *)vals[aindex].val4, strlen(vals[aindex].val4), 1, 0, YAML_PLAIN_SCALAR_STYLE);
157  if (!yaml_emitter_emit(emitter, event)){
158  keyerror(event, emitter);
159  return;
160  }
161  }
162  if (keys[aindex].key5[0] !='\0') {
163  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
164  (yaml_char_t *)keys[aindex].key5, strlen(keys[aindex].key5), 1, 0, YAML_PLAIN_SCALAR_STYLE);
165  if (!yaml_emitter_emit(emitter, event)){
166  keyerror(event, emitter);
167  return;
168  }
169  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
170  (yaml_char_t *)vals[aindex].val5, strlen(vals[aindex].val5), 1, 0, YAML_PLAIN_SCALAR_STYLE);
171  if (!yaml_emitter_emit(emitter, event)){
172  keyerror(event, emitter);
173  return;
174  }
175  }
176  if (keys[aindex].key6[0] !='\0') {
177  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
178  (yaml_char_t *)keys[aindex].key6, strlen(keys[aindex].key6), 1, 0, YAML_PLAIN_SCALAR_STYLE);
179  if (!yaml_emitter_emit(emitter, event)){
180  keyerror(event, emitter);
181  return;
182  }
183  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
184  (yaml_char_t *)vals[aindex].val6, strlen(vals[aindex].val6), 1, 0, YAML_PLAIN_SCALAR_STYLE);
185  if (!yaml_emitter_emit(emitter, event)){
186  keyerror(event, emitter);
187  return;
188  }
189  }
190  if (keys[aindex].key7[0] !='\0') {
191  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
192  (yaml_char_t *)keys[aindex].key7, strlen(keys[aindex].key7), 1, 0, YAML_PLAIN_SCALAR_STYLE);
193  if (!yaml_emitter_emit(emitter, event)){
194  keyerror(event, emitter);
195  return;
196  }
197  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
198  (yaml_char_t *)vals[aindex].val7, strlen(vals[aindex].val7), 1, 0, YAML_PLAIN_SCALAR_STYLE);
199  if (!yaml_emitter_emit(emitter, event)){
200  keyerror(event, emitter);
201  return;
202  }
203  }
204  if (keys[aindex].key8[0] !='\0') {
205  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
206  (yaml_char_t *)keys[aindex].key8, strlen(keys[aindex].key8), 1, 0, YAML_PLAIN_SCALAR_STYLE);
207  if (!yaml_emitter_emit(emitter, event)){
208  keyerror(event, emitter);
209  return;
210  }
211  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
212  (yaml_char_t *)vals[aindex].val8, strlen(vals[aindex].val8), 1, 0, YAML_PLAIN_SCALAR_STYLE);
213  if (!yaml_emitter_emit(emitter, event)){
214  keyerror(event, emitter);
215  return;
216  }
217  }
218  if (keys[aindex].key9[0] !='\0') {
219  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
220  (yaml_char_t *)keys[aindex].key9, strlen(keys[aindex].key9), 1, 0, YAML_PLAIN_SCALAR_STYLE);
221  if (!yaml_emitter_emit(emitter, event)){
222  keyerror(event, emitter);
223  return;
224  }
225  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
226  (yaml_char_t *)vals[aindex].val9, strlen(vals[aindex].val9), 1, 0, YAML_PLAIN_SCALAR_STYLE);
227  if (!yaml_emitter_emit(emitter, event)){
228  keyerror(event, emitter);
229  return;
230  }
231  }
232  if (keys[aindex].key10[0] !='\0') {
233  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
234  (yaml_char_t *)keys[aindex].key10, strlen(keys[aindex].key10), 1, 0, YAML_PLAIN_SCALAR_STYLE);
235  if (!yaml_emitter_emit(emitter, event)){
236  keyerror(event, emitter);
237  return;
238  }
239  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
240  (yaml_char_t *)vals[aindex].val10, strlen(vals[aindex].val10), 1, 0, YAML_PLAIN_SCALAR_STYLE);
241  if (!yaml_emitter_emit(emitter, event)){
242  keyerror(event, emitter);
243  return;
244  }
245  }
246  if (keys[aindex].key11[0] !='\0') {
247  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
248  (yaml_char_t *)keys[aindex].key11, strlen(keys[aindex].key11), 1, 0, YAML_PLAIN_SCALAR_STYLE);
249  if (!yaml_emitter_emit(emitter, event)){
250  keyerror(event, emitter);
251  return;
252  }
253  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
254  (yaml_char_t *)vals[aindex].val11, strlen(vals[aindex].val11), 1, 0, YAML_PLAIN_SCALAR_STYLE);
255  if (!yaml_emitter_emit(emitter, event)){
256  keyerror(event, emitter);
257  return;
258  }
259  }
260  if (keys[aindex].key12[0] !='\0') {
261  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
262  (yaml_char_t *)keys[aindex].key12, strlen(keys[aindex].key12), 1, 0, YAML_PLAIN_SCALAR_STYLE);
263  if (!yaml_emitter_emit(emitter, event)){
264  keyerror(event, emitter);
265  return;
266  }
267  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
268  (yaml_char_t *)vals[aindex].val12, strlen(vals[aindex].val12), 1, 0, YAML_PLAIN_SCALAR_STYLE);
269  if (!yaml_emitter_emit(emitter, event)){
270  keyerror(event, emitter);
271  return;
272  }
273  }
274  if (keys[aindex].key13[0] !='\0') {
275  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
276  (yaml_char_t *)keys[aindex].key13, strlen(keys[aindex].key13), 1, 0, YAML_PLAIN_SCALAR_STYLE);
277  if (!yaml_emitter_emit(emitter, event)){
278  keyerror(event, emitter);
279  return;
280  }
281  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
282  (yaml_char_t *)vals[aindex].val13, strlen(vals[aindex].val13), 1, 0, YAML_PLAIN_SCALAR_STYLE);
283  if (!yaml_emitter_emit(emitter, event)){
284  keyerror(event, emitter);
285  return;
286  }
287  }
288  if (keys[aindex].key14[0] !='\0') {
289  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
290  (yaml_char_t *)keys[aindex].key14, strlen(keys[aindex].key14), 1, 0, YAML_PLAIN_SCALAR_STYLE);
291  if (!yaml_emitter_emit(emitter, event)){
292  keyerror(event, emitter);
293  return;
294  }
295  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
296  (yaml_char_t *)vals[aindex].val14, strlen(vals[aindex].val14), 1, 0, YAML_PLAIN_SCALAR_STYLE);
297  if (!yaml_emitter_emit(emitter, event)){
298  keyerror(event, emitter);
299  return;
300  }
301  }
302  if (keys[aindex].key15[0] !='\0') {
303  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
304  (yaml_char_t *)keys[aindex].key15, strlen(keys[aindex].key15), 1, 0, YAML_PLAIN_SCALAR_STYLE);
305  if (!yaml_emitter_emit(emitter, event)){
306  keyerror(event, emitter);
307  return;
308  }
309  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
310  (yaml_char_t *)vals[aindex].val15, strlen(vals[aindex].val15), 1, 0, YAML_PLAIN_SCALAR_STYLE);
311  if (!yaml_emitter_emit(emitter, event)){
312  keyerror(event, emitter);
313  return;
314  }
315  }
316  if (keys[aindex].key16[0] !='\0') {
317  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
318  (yaml_char_t *)keys[aindex].key16, strlen(keys[aindex].key16), 1, 0, YAML_PLAIN_SCALAR_STYLE);
319  if (!yaml_emitter_emit(emitter, event)){
320  keyerror(event, emitter);
321  return;
322  }
323  yaml_scalar_event_initialize(event, NULL, (yaml_char_t *)YAML_STR_TAG,
324  (yaml_char_t *)vals[aindex].val16, strlen(vals[aindex].val16), 1, 0, YAML_PLAIN_SCALAR_STYLE);
325  if (!yaml_emitter_emit(emitter, event)){
326  keyerror(event, emitter);
327  return;
328  }
329  }
330 
331 return ;
332 }
333 /* \description Writes a YAML.
334  * In this function, the YAML can have one key per "level" that has an array of keys.
335  * If a struct has a level2key, then that key is written as a sequence. If level2key is empty, no second level is written.
336  * If a key is null, then the kay/value pair is not written.
337  * Users must pass in the size of each struct array for level 2 or 3.
338  * L3 arrays are essentially 2D arrays in 1D and the number of elements can change between each instance, so the user must pass
339  * the array `neach` which has the number of elements per instance.
340  * The top level size must be 1 (for now).
341  * \param yamlname The name of the output yaml file
342  * \param asize The size of the top level array (must be 1)
343  * \param topkeys The Keys for the top level of the yaml
344  * \param topvals The values corresponding to the topkeys
345  * \param a2size The size of the second level arrays and n3each
346  * \param l2keys The keys for the second level of the yaml
347  * \param l2vals The values corresponding to l2keys
348  * \param a3size The full size of the l3 arrays
349  * \param n3each Array that has the number of elements for each l2 array's third level elements
350  * \param l3keys The keys for the third level of the yaml, any lvl2 keys will not be printed
351  * \param l3vals The values corresponding to l3keys
352  * \param lvl2keyeach array to indicate how many structs to print per level2key for the top level keys, should be the size of LVL2KEY_NUM
353  */
354 void write_yaml_from_struct_3 (char *yamlname, int asize, struct fmsyamloutkeys *topkeys, struct fmsyamloutvalues *topvals, int a2size, struct fmsyamloutkeys *l2keys,
355  struct fmsyamloutvalues *l2vals, int a3size, int * n3each, struct fmsyamloutkeys *l3keys, struct fmsyamloutvalues *l3vals,
356  int* lvl2keyeach){
357  yaml_emitter_t emitter; /* libyaml emitter */
358  yaml_event_t event; /* libyaml event for the output yaml */
359  int s2count = 0; /* A counter to keep track of the number of level 2 arrays output */
360  int s3count = 0; /* A counter to keep track of the number of level 3 arrays output */
361  FILE * yamlout; /* The file for the YAML output. */
362  int i_n3 = 0;/* index for the n3each argument*/
363 
364  // trim any trailing whitespace
365  int ws_ind = strlen(yamlname)-1;
366  while(*(yamlname+ws_ind) == ' ') ws_ind--;
367  if( ws_ind != strlen(yamlname)-1) yamlname[ws_ind+1] = '\0';
368 
369  /* open the yaml output file. Only 1 core should do this */
370  yamlout = fopen(yamlname,"w");
371  /* Start the emmitter */
372  yaml_emitter_initialize(&emitter);
373  yaml_emitter_set_output_file(&emitter, yamlout);
374  yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
375  if (!yaml_emitter_emit(&emitter, &event)){
376  error(yamlname, &event, &emitter, yamlout);
377  return;
378  }
379 
380  yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
381  if (!yaml_emitter_emit(&emitter, &event)){
382  error(yamlname, &event, &emitter, yamlout);
383  return;
384  }
385  /* start the event (top level) */
386  yaml_mapping_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_MAP_TAG,
387  1, YAML_ANY_MAPPING_STYLE);
388  if (!yaml_emitter_emit(&emitter, &event)){
389  error(yamlname, &event, &emitter, yamlout);
390  return;
391  }
392 
393  /* write the top level */
394  write_keys_vals_yaml (&emitter, &event , 0, topkeys, topvals);
395  char* curr_topkey = topkeys->level2key;
396 
397  /* loop through the top level 2 keys */
398  int top_ind;
399  for (top_ind=0; top_ind < topkeys->level2key_offset; top_ind++) {
400  /* Start the secodn level event */
401  yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
402  (yaml_char_t *)curr_topkey, strlen(curr_topkey), 1, 0,
403  YAML_PLAIN_SCALAR_STYLE);
404  if (!yaml_emitter_emit(&emitter, &event)){
405  error(yamlname, &event, &emitter, yamlout);
406  return;
407  }
408  /* Start the sequencing */
409  yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG,
410  1, YAML_ANY_SEQUENCE_STYLE);
411  if (!yaml_emitter_emit(&emitter, &event)){
412  error(yamlname, &event, &emitter, yamlout);
413  return;
414  }
415  /* loop through the structs for this key*/
416  int s2;
417  for (s2 = 0 ; s2 < lvl2keyeach[top_ind]; s2++){
418  yaml_mapping_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_MAP_TAG,
419  1, YAML_ANY_MAPPING_STYLE);
420  if (!yaml_emitter_emit(&emitter, &event)){
421  error(yamlname, &event, &emitter, yamlout);
422  return;
423  }
424  /* call the write function */
425  write_keys_vals_yaml (&emitter, &event , s2count, l2keys, l2vals);
426 
427  /* Next level keys */
428  char * curr_l2key = (&l2keys[s2count])->level2key;
429  int l2_ind;
430  for (l2_ind = 0; l2_ind < (&l2keys[s2count])->level2key_offset; l2_ind++) {
431  /* Start the third level event */
432  yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
433  (yaml_char_t *)curr_l2key, strlen(curr_l2key), 1, 0,
434  YAML_PLAIN_SCALAR_STYLE);
435  if (!yaml_emitter_emit(&emitter, &event)){
436  error(yamlname, &event, &emitter, yamlout);
437  return;
438  }
439  /* Start the sequencing */
440  yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG,
441  1, YAML_ANY_SEQUENCE_STYLE);
442  if (!yaml_emitter_emit(&emitter, &event)){
443  error(yamlname, &event, &emitter, yamlout);
444  return;
445  }
446  /* loop through the structs */
447  int s3start = s3count;
448  int s3end = s3start + n3each[i_n3];
449  i_n3++;
450  int s3;
451  for (s3 = s3start ; s3 < s3end ; s3++){
452  yaml_mapping_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_MAP_TAG,
453  1, YAML_ANY_MAPPING_STYLE);
454  if (!yaml_emitter_emit(&emitter, &event)){
455  error(yamlname, &event, &emitter, yamlout);
456  return;
457  }
458  /* call the write function */
459  write_keys_vals_yaml (&emitter, &event , s3, l3keys, l3vals);
460  yaml_mapping_end_event_initialize(&event);
461  if(!yaml_emitter_emit(&emitter, &event)){
462  error(yamlname, &event, &emitter, yamlout);
463  return;
464  }
465  s3count ++;
466  } // for s3
467  yaml_sequence_end_event_initialize(&event);
468  if (!yaml_emitter_emit(&emitter, &event)){
469  error(yamlname, &event, &emitter, yamlout);
470  return;
471  }
472  curr_l2key = (&l2keys[s2count])->level2key + ((l2_ind+1) * KEY_STR_LEN);
473  } /* for l2_ind */
474  yaml_mapping_end_event_initialize(&event);
475  if (!yaml_emitter_emit(&emitter, &event)){
476  error(yamlname, &event, &emitter, yamlout);
477  return;
478  }
479 
480  s2count++;
481  }/* for s2 loop */
482 
483  yaml_sequence_end_event_initialize(&event);
484  if (!yaml_emitter_emit(&emitter, &event)){
485  error(yamlname, &event, &emitter, yamlout);
486  return;
487  }
488  curr_topkey = topkeys->level2key + ((top_ind+1) * KEY_STR_LEN);
489  }/* for top_ind */
490 
491  /* end the emitter */
492  yaml_mapping_end_event_initialize(&event);
493  if (!yaml_emitter_emit(&emitter, &event)){
494  error(yamlname, &event, &emitter, yamlout);
495  return;
496  }
497 
498  yaml_document_end_event_initialize(&event, 0);
499  if (!yaml_emitter_emit(&emitter, &event)){
500  error(yamlname, &event, &emitter, yamlout);
501  return;
502  }
503  yaml_stream_end_event_initialize(&event);
504  if (!yaml_emitter_emit(&emitter, &event)){
505  error(yamlname, &event, &emitter, yamlout);
506  return;
507  }
508  yaml_emitter_delete(&emitter);
509  fclose(yamlout);
510  return;
511 }
512 /// @brief Adds a key to the level2key character array in the struct.
513 /// Uses an offset to store multiple keys, size(amount of strings) is set by LVL2KEY_NUM (avoids c to fortran 2d array issues)
514 /// @param key_name name of level 2 key to add
515 /// @param key_length string length of key_name
516 /// @param keys key struct to add level 2 key to
517 void add_level2key(int key_length, char* key_name, struct fmsyamloutkeys* keys){
518 
519  // local fixed length copy to try to mitigate any fortran to c string weirdness
520  char kname_loc[key_length + 1];
521  //memset(kname_loc, '\0', sizeof(kname_loc));
522  strncpy(kname_loc, key_name, key_length);
523  kname_loc[key_length] = '\0';
524  // error checking
525  if ( strlen(kname_loc) > KEY_STR_LEN){
526  fprintf(stderr, "WARNING: YAML_OUTPUT: invalid level two key passed to add_level2key. Max string size is %d, passed in string: %s", KEY_STR_LEN, key_name);
527  fprintf(stdout, "WARNING: YAML_OUTPUT: invalid level two key passed to add_level2key. Max string size is %d, passed in string: %s", KEY_STR_LEN, key_name);
528  }
529  if( keys->level2key_offset >= LVL2KEY_NUM ){
530  fprintf(stderr, "WARNING: YAML_OUTPUT: max amount of level 2 keys (%d) has been exceeded", LVL2KEY_NUM);
531  fprintf(stdout, "WARNING: YAML_OUTPUT: max amount of level 2 keys (%d) has been exceeded", LVL2KEY_NUM);
532  }
533  // check if string is set to initialize offset count
534  if ( keys->level2key[0] == '\0'){
535  keys->level2key_offset = 0;
536  }
537  // calculate offset and copy into the level2key array
538  int offset = keys->level2key_offset * KEY_STR_LEN;
539  char* curr_key;
540  curr_key = keys->level2key + offset;
541  strcpy(curr_key, kname_loc);
542 
543  keys->level2key_offset++;
544 
545  if (DEBUG) {
546  printf("key length: %d \n key_name:", key_length);
547  printf(key_name);
548  printf("\n");
549  printf("offset: %d \n", offset);
550  printf("kname_loc:");
551  printf(kname_loc);
552  printf("\n*l2key:");
553  printf(keys->level2key);
554  printf("\nl2key+offset:");
555  printf(keys->level2key + offset);
556  printf("\n");
557  }
558 }
559 
560 #endif
561 
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:43
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
Definition: mpp_util.inc:51