;+
;NAME:
; struct2ascii
;PURPOSE:
; given an IDL structure, print it out, if a logical unit is supplied,
; print to that unit, else print to the screen, called recursively for
; nested structures. Note that there is no formatting, numerical
; values are printed out in whatever the default output format is.
; Objects are not handled correctly here at all -- pointers eventually
; will be.
;CALLING SEQUENCE:
; struct2ascii, structure, lun=lun
;INPUT:
; structure =  a structure
;OUTPUT:
; None, the structure is printed to the given unit
;KEYWORDS:
; lun = a logical unit numnber for output, the default is to print to
;       the screen.
;HISTORY:
; 23-apr-2007, jmm, jimm@ssl.berkeley.edu
;
;$LastChangedBy$
;$LastChangedDate$
;$LastChangedRevision$
;$URL$
;-
Pro struct2ascii, structure, lun = lun, _extra = _extra

;Well, is the input a structure?
  If(is_struct(structure) Eq 0) Then Begin
    message, /info, 'Input is not a structure'
    Return
  Endif
  have_lun = keyword_set(lun)

  n0 = n_elements(structure)
  sz0 = size(structure, /struct)
  If(is_string(sz0.structure_name) Eq 0) Then strn0 = 'ANONYMOUS' $
  Else strn0 = sz0.structure_name
  If(have_lun) Then Begin
    printf, lun, 'Structure Name: ', strn0
    If(sz0.n_dimensions Eq 0) Then Begin ;oops, a scalar
      printf, lun, 'Structure dimensions: 0'
    Endif Else printf, lun, 'Structure dimensions: ', $
      sz0.dimensions[0:sz0.n_dimensions-1]
  Endif Else Begin
    print, 'Structure Name: ', strn0
    If(sz0.n_dimensions Eq 0) Then Begin ;oops, a scalar
      print, 'Structure dimensions: 0'
    Endif Else print, 'Structure dimensions: ', $
      sz0.dimensions[0:sz0.n_dimensions-1]
  Endelse
  nnn = tag_names(structure)
  lll = n_tags(structure)
  If(have_lun) Then printf, lun, 'Structure n_tags: ', lll $
  Else print, 'Structure n_tags: ', lll
  For n = 0, n0-1 Do Begin
    For j = 0, lll-1 Do Begin
      If(have_lun) Then Begin
        printf, lun, 'Tag Name: ', nnn[j]
      Endif Else print, 'Tag Name: ', nnn[j]
      sz = size(structure[n].(j), /struct)
      If(is_struct(structure[n].(j))) Then Begin
        If(have_lun) Then Begin
          printf, lun, 'Tag type_name: ', sz.type_name
        Endif Else print, 'Tag type_name: ', sz.type_name
        struct2ascii, structure[n].(j), lun = lun
      Endif Else Begin
;You need the type of data, and the dimensions, so that you can read it
;back in
        If(have_lun) Then Begin
          printf, lun, 'Tag type_name: ', sz.type_name
          printf, lun, 'Tag type: ', sz.type
          printf, lun, 'Tag n_dimensions: ', sz.n_dimensions
          If(sz.n_dimensions Eq 0) Then Begin ;oops, a scalar
            printf, lun, 'Tag dimensions: 0'
          Endif Else printf, lun, 'Tag dimensions: ', $
            sz.dimensions[0:sz.n_dimensions-1]
          printf, lun, 'Tag Values: '
          If(sz.type Eq 5 or sz.type Eq 9) Then Begin
            printf, lun, structure[n].(j), format = '(5e22.14)'
          Endif Else printf, lun, structure[n].(j)
        Endif Else Begin
          print, 'Tag type_name: ', sz.type_name
          print, 'Tag type: ', sz.type
          print, 'Tag n_dimensions: ', sz.n_dimensions
          If(sz.n_dimensions Eq 0) Then Begin ;oops, a scalar
            print, 'Tag dimensions: 0'
          Endif Else print, 'Tag dimensions: ', $
            sz.dimensions[0:sz.n_dimensions-1]
          print, 'Tag Values: '
          If(sz.type Eq 5 or sz.type Eq 9) Then Begin
            print, structure[n].(j), format = '(5e22.14)'
          Endif Else print, structure[n].(j)
        Endelse
      Endelse
      If(have_lun) Then Begin
        printf, lun, 'End Tag: ', nnn[j]
      Endif Else print, 'End Tag: ', nnn[j]
    Endfor
    If(have_lun) Then Begin
      printf, lun, 'End Structure: ', strn0
    Endif Else print, 'End Structure: ', strn0
  Endfor
  Return
End