MISR Toolkit  1.5.1
wrtlabel.c
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  WriteLabel: Writes a PDS label in the Object Description Language
4  to the specified file.
5 
6  Input:
7  output_file - File pointer to output file.
8 
9  base_node - Pointer to aggregate node of the ODL tree with which
10  writing is to begin. This node, and all aggregates
11  beneath it will be written.
12 
13  Output: There are no output parameters and no function value is returned.
14  The label is written to the file using output routine ODLWriteStmt.
15 
16  Author: Randy Davis, University of Colorado LASP
17 
18  Creation Date: 11 October 1990
19  Last Modified: 18 May 1991
20 
21  History:
22 
23  Creation - This routine was introduced in Version 1.0 of the ODLC library
24  and upgraded significantly in Version 2.0.
25 
26  Version 2.1 - 13 March 1991 - Randy Davis, U. of Colorado LASP
27  a) Now prints out comments associated with an aggregate or parameter.
28  b) Eliminated use of the 'level' field, which has been deleted
29  from aggregate nodes.
30  c) Modified so that if both a name and class are specified for an
31  object, they are printed out in the PDS standard format, ie:
32 
33  OBJECT = class
34  NAME = name
35  ... other parameters ...
36  END_OBJECT = class
37 
38  If an object class is not given, then the old-style is used:
39 
40  OBJECT = name
41  ... parameters ...
42  END_OBJECT
43 
44  The latter style is always used for groups, since they don't have
45  a class.
46 
47  Version 2.2 - 18 May 1991 - M. DeMore, Jet Propulsion Laboratory
48  Removed include statements that were Unix specific and placed them
49  in odldef.h. Removed ODL function prototypes and included file
50  odlinter.h.
51 
52  Version 2.3 - 13 October 1991 - M. DeMore, Jet Propulsion Laboratory
53  Modified to handle new argument list to ODLFormatString, in order
54  to handle backslashes in DOS file names. Added check of pds_finish_label
55  for Toolbox use.
56 
57  14-MAY-1995 Alward Siyyid Changed line 432 from
58  while (old_node != base_node)
59  to
60  while (old_node != base_node->parent)
61  so that END_GROUP or END_OBJECT line
62  for the base_node is also written out.
63  Otherwise if file is read again, the
64  odl parser complains about the missing
65  line.
66 
67  14-MAY-1995 Alward Siyyid Modified so that if both a name and
68  class are specified for an object, they
69  are printed out in the PGS standard
70  format, ie:
71  OBJECT = name
72  CLASS = class
73  ... other parameters ...
74  END_OBJECT = name
75 
76  20-JUL-1995 Alward Siyyid cancelled the change on 14-MAY-1995 regarding
77  line 432
78 
79  26-OCT-1996 Alward Siyyid Changed the value for MAXLABLINE from 70
80  to 317 to allow for long words in a string
81 
82  06-DEC-1997 Carol Tsai Changed the value for MAXLABLINE from255
83  to 300 to allow for long words in a string
84 
85  27-MAR-1998 G. Khalsa Replaced variable "char stmt[ODLMAXSTMT]" with
86  variable "char* stmt" (the space for which is
87  allocated dynamically in the body of the function).
88  This was done because ODLMAXSTMT had to increased
89  to a very large number and allocating the required
90  space off the stack was causing problems).
91 
92  ****************************************************************************/
93 
94 #include "odldef.h"
95 #include "odlinter.h"
96 #include "stdio.h"
97 #include "stdlib.h"
98 
99 /* The following define the maximum number of characters in a label line, the
100  number of characters to indent on the left margin for each step up in
101  aggregate nesting level, and the minimum spacing for a parameter name */
102 
103 #define MAXLABLINE 300
104 #define INDENTSIZE 2
105 #define MINAMESIZE 20
106 
107 #ifdef PDS_TOOLBOX
108 
109 extern int pds_finish_label;
110 
111 #endif
112 
113 /* The following macro is used to space in properly from the left margin */
114 
115 #define indentf(X) for (i=0 ; i < X ; i++) stmt[len++] = ' '
116 
117 
119  FILE *output_file,
120  AGGREGATE base_node)
121 {
122 
123  AGGREGATE node; /* Pointer to current node */
124  AGGREGATE old_node; /* Pointer to previous node */
125  PARAMETER parameter; /* Pointer to current parameter node */
126  VALUE data; /* Pointer to current parameter value */
127  int i; /* Loop index */
128  int ip; /* Number of parens to print for sequence */
129  int ncol; /* Current output line column number */
130  int nindent; /* Indentation for parameter names */
131  int nl; /* Length of current parameter name */
132  int nlv; /* Length of current value */
133  int no; /* Alignment on OBJECT/END_OBJECT lines */
134  int ns; /* Alignment for parameter assignments */
135  int nv; /* Alignment for parameter values */
136  int vindent; /* Indentation for values */
137  int col_count; /* Count of array columns processed */
138  char* stmt; /* Pointer to buffer to hold each statement */
139  int len; /* Number of characters in output statement */
140 
141  if (base_node == NULL)
142  {
143  return;
144  }
145 
146  /* allocate space for statement buffer */
147 
148  stmt = (char*) malloc(ODLMAXSTMT);
149  if (stmt == NULL)
150  {
151  return;
152  }
153 
154  stmt[0] = '\0';
155 
156  /* Process the base node first and then all the nodes beneath it */
157 
158  old_node = base_node->parent;
159  node = base_node;
160  nindent = 0;
161 
162  while (node != NULL)
163  {
164  /* Put out any END_OBJECTs or END_GROUPs that are needed */
165 
166  if (node != base_node && node->parent == old_node)
167  {
168  /* The new object or group belongs to the old node. We defer the
169  END_OBJECT or END_GROUP for the old node until we're done
170  processing all of its dependent nodes, so we don't do anything
171  here except put a blank line before the OBJECT or GROUP line
172  if we're not going to put out a comment first */
173 
174  if (node->comment == NULL)
175  {
176  ODLWriteStmt (output_file, "\n");
177  }
178  }
179  else
180  {
181  /* The new object or group is at the same or lower level than the old
182  object or group. Put out the END_OBJECT or END_GROUP for the
183  old node and all of its ancestors, up to and including the node
184  at the same level as the new node */
185 
186  while (node->parent != old_node)
187  {
188  len = 0;
189  nindent -= INDENTSIZE;
190  indentf (nindent);
191  no = MINAMESIZE + INDENTSIZE;
192 
193  if (old_node->kind == KA_OBJECT &&
194  old_node->objClass != NULL && old_node->objClass[0] != '\0')
195  {
196  sprintf (&stmt[len], "%-*s = %s\n\n",
197  no,
198  "END_OBJECT",
199  old_node->name);
200  }
201  else
202  {
203  sprintf (&stmt[len], "%-*s = %s\n\n",
204  no,
205  (old_node->kind==KA_OBJECT)?"END_OBJECT":"END_GROUP",
206  old_node->name);
207  }
208 
209  ODLWriteStmt (output_file, stmt);
210  old_node = ParentAggregate (old_node);
211  }
212  }
213 
214  /* Put out the comment, if any associated with the new aggregate node */
215 
216  if (node->comment != NULL)
217  {
218  ODLFormatComment (stmt, node->comment, nindent+1, MAXLABLINE);
219  ODLWriteStmt (output_file, stmt);
220  }
221 
222  /* Put in the OBJECT = name or GROUP = name line for the new node,
223  unless this is a root node */
224 
225  if (node->parent != NULL)
226  {
227  len = 0;
228  indentf (nindent);
229  nindent += INDENTSIZE;
230  no = MINAMESIZE + INDENTSIZE;
231 
232  if (node->kind == KA_OBJECT &&
233  node->objClass != NULL && node->objClass[0] != '\0')
234  {
235  sprintf (&stmt[len], "%-*s = %s\n",
236  no,
237  "OBJECT",
238  node->name);
239  len = strlen (stmt);
240 
241  /* No need to do this anymore because the Class statement is one of the parameters
242  Alward Siyyid, 14the of may 1995 */
243 /*
244  indentf (nindent);
245  sprintf (&stmt[len], "%-*s = %s\n",
246  MINAMESIZE,
247  "CLASS",
248  node->objClass);
249 */
250  }
251  else
252  {
253  sprintf (&stmt[len], "%-*s = %s\n",
254  no,
255  (node->kind == KA_OBJECT) ? "OBJECT" : "GROUP",
256  node->name);
257  }
258 
259  ODLWriteStmt (output_file, stmt);
260  }
261 
262  /* Generate the attribute and pointer assignment statements for
263  the current object or group */
264 
265  parameter = FirstParameter (node);
266 
267  while (parameter != NULL)
268  {
269  /* Print out the comment associated with the parameter, if any */
270 
271  if (parameter->comment != NULL)
272  {
273  ODLFormatComment (stmt, parameter->comment, nindent+1, MAXLABLINE);
274  ODLWriteStmt (output_file, stmt);
275  }
276 
277  len = 0;
278 
279  /* Determine the padding necessary to make the equal sign and
280  values for this assignment line up nicely */
281 
282  ns = (parameter->node_kind==KP_POINTER) ? MINAMESIZE-1 : MINAMESIZE;
283 
284  /* Calculate the indentation to the start of the value for this
285  assignment. This amount of indentation will be applied if
286  the value continues onto second and subsequent lines so that
287  values will line up better */
288 
289  nl = strlen (parameter->name);
290  nv = ((nl > ns)? nl : ns) + 3;
291  vindent = nindent + nv;
292 
293  /* Write out the parameter name with appropriate indentation and
294  padding */
295 
296  indentf (nindent);
297 
298  if (parameter->node_kind == KP_POINTER)
299  {
300  stmt[len++] = '^';
301  }
302 
303  sprintf (&stmt[len], "%-*s = ",
304  ns,
305  parameter->name);
306  len += nv;
307 
308  /* Perform value-kind dependent formatting */
309 
310  switch (parameter->value_kind)
311  {
312  case KV_SEQUENCE:
313  ip = (parameter->rows > 0)? parameter->rows : 1;
314  if (ip > 2) ip = 2;
315  for (i=0; (i < ip); i++)
316  {
317  stmt[len++] = '(';
318  vindent++;
319  }
320  break;
321 
322  case KV_SET:
323  stmt[len++] = '{';
324  vindent++;
325  break;
326 
327  default:
328  break;
329  }
330 
331  /* Process every value for this assignment */
332 
333  col_count = 0;
334  ncol = vindent;
335 
336  data = FirstValue (parameter);
337 
338  while (data != NULL)
339  {
340  if (data->item.type != TV_STRING)
341  {
342  /* Determine the number of character spaces the new value
343  will occupy on the current line */
344 
345  nlv = data->item.length;
346  if (data->item.type == TV_SYMBOL && data->item.format == 0)
347  {
348  /* This is a quoted symbolic literal: account for the
349  space occupied by the delimiting apostrophes */
350 
351  nlv += 2;
352  }
353 
354  ncol += nlv;
355 
356  if (ncol >= MAXLABLINE)
357  {
358  /* Adding the new value would overflow the current line,
359  so start a new line */
360 
361  stmt[len++] = '\n';
362  indentf (vindent);
363  ncol = vindent + nlv;
364  }
365  }
366 
367  /* Format the data value, according to its data type */
368 
369  switch (data->item.type)
370  {
371  case TV_INTEGER:
372  len += ODLFormatInteger (&stmt[len], &data->item);
373  break;
374 
375  case TV_REAL:
376  len += ODLFormatReal (&stmt[len], &data->item);
377  break;
378 
379  case TV_SYMBOL:
380  len += ODLFormatSymbol (&stmt[len], &data->item);
381  break;
382 
383  case TV_STRING:
384  if (parameter->node_kind == KP_POINTER)
385  {
386  len += ODLFormatString (&stmt[len], &data->item, &ncol,
387  nindent+2*INDENTSIZE, MAXLABLINE-2, 1, 1);
388  }
389  else
390  {
391  len += ODLFormatString (&stmt[len], &data->item, &ncol,
392  nindent+2*INDENTSIZE, MAXLABLINE-2, 1, 0);
393  }
394  break;
395 
396  case TV_DATE:
397  len += ODLFormatDate (&stmt[len], &data->item);
398  break;
399 
400  case TV_TIME:
401  len += ODLFormatTime (&stmt[len], &data->item);
402  break;
403 
404  case TV_DATE_TIME:
405  len += ODLFormatDateTime (&stmt[len], &data->item);
406  break;
407  }
408 
409  /* Get the next data value for this assignment, if any */
410 
411  data = NextValue (data);
412 
413  /* Add any formatting that might be necessary to separate
414  values */
415 
416  if (data != NULL)
417  {
418  switch (parameter->value_kind)
419  {
420  case KV_SEQUENCE:
421  col_count++;
422  if (col_count >= parameter->columns)
423  {
424  stmt[len++] = ')';
425  stmt[len++] = '\n';
426  indentf (vindent-1);
427  stmt[len++] = '(';
428  ncol = vindent;
429  col_count = 0;
430  }
431  else
432  {
433  stmt[len++] = ',';
434  stmt[len++] = ' ';
435  ncol += 2;
436  }
437  break;
438 
439  default:
440  stmt[len++] = ',';
441  stmt[len++] = ' ';
442  ncol += 2;
443  break;
444  }
445  }
446  }
447 
448  /* We've processed all the values for this assignment. Put
449  out any necessary end-of-assignment formatting */
450 
451  switch (parameter->value_kind)
452  {
453  case KV_SEQUENCE:
454  for (i=0; (i < ip); i++)
455  {
456  stmt[len++] = ')';
457  }
458  break;
459 
460  case KV_SET:
461  stmt[len++] = '}';
462  break;
463 
464  default:
465  break;
466  }
467 
468  stmt[len++] = '\n';
469  stmt[len] = '\0';
470  ODLWriteStmt (output_file, stmt);
471 
472  /* Get the next parameter for this object, if any */
473 
474  parameter = NextParameter (parameter);
475  }
476 
477  /* Get the next object or group node, if any */
478 
479  old_node = node;
480  node = NextSubAggregate (base_node, node);
481  }
482 
483  /* Print out any END_OBJECTs or END_GROUPs that we have pending */
484 
485  while (old_node != base_node)
486  {
487  len = 0;
488  nindent -= INDENTSIZE;
489  indentf (nindent);
490  sprintf (&stmt[len], "%-*s = %s\n\n",
491  no,
492  (old_node->kind == KA_OBJECT) ? "END_OBJECT" : "END_GROUP",
493  old_node->name);
494  ODLWriteStmt (output_file, stmt);
495  old_node = ParentAggregate (old_node);
496  }
497 
498  /* Print out the terminating END statement */
499 
500 #ifdef PDS_TOOLBOX
501  if (pds_finish_label)
502  ODLWriteStmt (output_file, "END\n");
503 #else
504  ODLWriteStmt (output_file, "END\n");
505 #endif
506 
507  free(stmt);
508 
509  return;
510 }
AGGREGATE ParentAggregate(AGGREGATE base_node)
Definition: a_nodesa.c:295
#define MINAMESIZE
Definition: wrtlabel.c:105
HDFFCLIBAPI intf * len
char format
Definition: odldef.h:215
if((msg=H5E_create_msg(cls, H5E_MAJOR, "Dataset"))==NULL) if((H5E_DATASET_g
Definition: odldef.h:97
int ODLFormatString(char stmt[], VALUE_DATA *item, int *column, int left_margin, int right_margin, int format_flag, int is_pointer)
Definition: fmtvalue.c:636
PARAMETER FirstParameter()
Definition: odldef.h:97
#define MAXLABLINE
Definition: wrtlabel.c:103
char * name
Definition: odldef.h:138
int ODLFormatSymbol(char *stmt, VALUE_DATA *item)
Definition: fmtvalue.c:355
short length
Definition: odldef.h:217
char * comment
Definition: odldef.h:139
char * comment
Definition: odldef.h:114
AGGREGATE_KIND kind
Definition: odldef.h:115
int ODLFormatDateTime(char *stmt, VALUE_DATA *item)
Definition: fmtvalue.c:582
int ns
Definition: misr_init.c:6
Definition: odldef.h:96
int ODLFormatDate(char *stmt, VALUE_DATA *item)
Definition: fmtvalue.c:409
#define INDENTSIZE
Definition: wrtlabel.c:104
#define ODLMAXSTMT
Definition: odldef.h:74
int ODLFormatReal(char *stmt, VALUE_DATA *item)
Definition: fmtvalue.c:181
short rows
Definition: odldef.h:144
int ODLFormatInteger(char stmt[], VALUE_DATA *item)
Definition: fmtvalue.c:80
struct Value_Data item
Definition: odldef.h:229
struct Aggregate_Node * parent
Definition: odldef.h:118
#define indentf(X)
Definition: wrtlabel.c:115
VALUE_TYPE type
Definition: odldef.h:213
char * objClass
Definition: odldef.h:113
int ODLFormatTime(char *stmt, VALUE_DATA *item)
Definition: fmtvalue.c:484
void WriteLabel(FILE *output_file, AGGREGATE base_node)
Definition: wrtlabel.c:118
HDFFCLIBAPI void * data
void ODLWriteStmt()
PARAMETER NextParameter()
VALUE FirstValue()
int ODLFormatComment(char *stmt, char *comment, int left_margin, int right_margin)
Definition: fmtvalue.c:854
VALUE NextValue()
Definition: odldef.h:93
VALUE_KIND value_kind
Definition: odldef.h:141
PARAMETER_KIND node_kind
Definition: odldef.h:140
short columns
Definition: odldef.h:143
AGGREGATE NextSubAggregate(AGGREGATE base_node, AGGREGATE start_node)
Definition: a_nodesa.c:410
char * name
Definition: odldef.h:112

MISR Toolkit - Copyright © 2005 - 2020 Jet Propulsion Laboratory
Generated on Fri Jun 19 2020 22:49:51