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