pro create_struct, struct, strname, tagnames, tag_descript, DIMEN = dimen, $
              CHATTER = chatter, NODELETE = nodelete
;-------------------------------------------------------------------------------

 compile_opt idl2
 if N_params() LT 4 then begin
   print,'Syntax - CREATE_STRUCT, STRUCT, strname, tagnames, tag_descript,' 
   print,'                  [ DIMEN = , /CHATTER, /NODELETE ]'
   return
 endif

 if ~keyword_set( chatter) then chatter = 0        ;default is 0
 if (N_elements(dimen) eq 0) then dimen = 1            ;default is 1

 if (dimen lt 1) then begin
  print,' Number of dimensions must be >= 1. Returning.'
  return
 endif

; For anonymous structure, strname = ''
  anonymous = 0b
  if (strlen( strtrim(strname,2)) EQ 0 ) then anonymous = 1b

 good_fmts = [ 'A', 'B', 'I', 'L', 'F', 'E', 'D', 'J','C','M', 'K' ]
 fmts = ["' '",'0B','0','0B','0.0','0.0','0.0D0','0L','complex(0)', $
           'dcomplex(0)', '0LL']
 arrs = [ 'strarr', 'bytarr', 'intarr', 'bytarr', 'fltarr', 'fltarr', $
          'dblarr', 'lonarr','complexarr','dcomplexarr','lon64arr']
 ngoodf = N_elements( good_fmts )

; If tagname is a scalar string separated by commas, convert to a string array

 if size(tagnames,/N_dimensions) EQ 0 then begin
            tagname = strsplit(tagnames,',',/EXTRACT) 
 endif else tagname = tagnames

 Ntags = N_elements(tagname)

; Make sure supplied tag names are valid.
 
 tagname = idl_validname( tagname, /convert_all )

;  If user supplied a scalar string descriptor then we want to break it up
;  into individual items.    This is somewhat complicated because the string
;  delimiter is not always a comma, e.g. if 'F,F(2,2),I(2)', so we need
;  to check positions of parenthesis also.

 sz = size(tag_descript)
 if sz[0] EQ 0 then begin
      tagvar = strarr( Ntags)
      temptag = tag_descript
      for i = 0, Ntags - 1 do begin
         comma = strpos( temptag, ',' )
         lparen = strpos( temptag, '(' )
         rparen = strpos( temptag, ')' )
            if ( comma GT lparen ) and (comma LT Rparen) then pos = Rparen+1 $
                                                         else pos = comma 
             if pos EQ -1 then begin
                 if i NE Ntags-1 then message, $
         'WARNING - could only parse ' + strtrim(i+1,2) + ' string descriptors'
                 tagvar[i] = temptag 
                 goto, DONE
             endif else begin
                    tagvar[i] = strmid( temptag, 0, pos )
                    temptag = strmid( temptag, pos+1)
              endelse
             endfor
             DONE:
            
 endif else tagvar = tag_descript

; create string array for IDL statements, to be written into 
; 'temp_'+strname+'.pro'

 pro_string = strarr (ntags + 2) 

 if (dimen EQ 1) then begin

   pro_string[0] = "struct =  { " + strname + " $"
   pro_string[ntags+1] = " } "

 endif else begin

   dimen = long(dimen)                ;Changed to LONG from FIX Mar 95
   pro_string[0] = "struct "   + " = replicate ( { " + strname + " $"
   pro_string[ntags+1] = " } , " + string(dimen) + ")"

 endelse

 tagvar = strupcase(tagvar) 

 for i = 0, ntags-1 do begin

   goodpos = -1
   for j = 0,ngoodf-1 do begin
         fmt_pos = strpos( tagvar[i], good_fmts[j] )
         if ( fmt_pos GE 0 ) then begin
              goodpos = j
              break
         endif
   endfor

  if goodpos EQ -1 then begin 
      print,' Format not recognized: ' + tagvar[i]
      print,' Allowed formats are :',good_fmts
      stop,' Redefine tag format (' + string(i) + ' ) or quit now'
  endif 


    if fmt_pos GT 0 then begin

           repeat_count = strmid( tagvar[i], 0, fmt_pos )
           if strnumber( repeat_count, value ) then begin
                fmt = arrs[ goodpos ] + '(' + strtrim(fix(value), 2) + ')'
           endif else begin 
                print,' Format not recognized: ' + tagvar[i]
                stop,' Redefine tag format (' + string(i) + ' ) or quit now'
           endelse

    endif else  begin

; Break up the tag descriptor into a format and a dimension
    tagfmts = strmid( tagvar[i], 0, 1)
    tagdim = strtrim( strmid( tagvar[i], 1, 80),2)
    if strmid(tagdim,0,1) NE '(' then tagdim = ''
    fmt = (tagdim EQ '') ? fmts[goodpos] : arrs[goodpos] + tagdim 
    endelse

  if anonymous and ( i EQ 0 ) then comma = '' else comma = " , "

      pro_string[i+1] = comma + tagname[i] + ": " + fmt + " $"      

 endfor

; Check that this structure definition is OK (if chatter set to 1)
 
 if keyword_set ( Chatter )  then begin
   ans = ''
   print,' Structure ',strname,' will be defined according to the following:'
   temp = repchr( pro_string, '$', '')
   print, temp
   read,' OK to continue? (Y or N)  ',ans
   if strmid(strupcase(ans),0,1) eq 'N' then begin
      print,' Returning at user request.'
     return
   endif
 endif 

; --- Determine if a file already exists with same name as temporary file

 tempfile = 'temp_' + strlowcase( strname )
 while file_test( tempfile + '.pro' ) do tempfile = tempfile + 'x'
 
; ---- open temp file and create procedure
; ---- If problems writing into the current directory, try the HOME directory

 cd,current= prodir 
 cdhome = 0
 openw, unit, tempfile +'.pro', /get_lun, ERROR = err
 if (err LT 0)  then begin
      prodir = getenv('HOME')
      tempfile = prodir + path_sep() + tempfile
      while file_test( tempfile + '.pro' ) do tempfile = tempfile + 'x'
      openw, unit, tempfile +'.pro', /get_lun, ERROR = err
      if err LT 0 then message,'Unable to create a temporary .pro file'
      cdhome = 1
  endif
 name = file_basename(tempfile)
 printf, unit, 'pro ' +  name + ', struct'
 printf,unit,'compile_opt hidden'
 for j = 0,N_elements(pro_string)-1 do $
        printf, unit, strtrim( pro_string[j] )
 printf, unit, 'return'
 printf, unit, 'end'
 free_lun, unit

; If using the HOME directory, it needs to be included in the IDL !PATH

 if cdhome then cd,getenv('HOME'),curr=curr
  resolve_routine, name
  Call_procedure, name, struct
 if cdhome then cd,curr

 if keyword_set( NODELETE ) then begin
    message,'Created temporary file ' + tempfile + '.pro',/INF
    return
 endif else file_delete, tempfile + '.pro'
  
  return
  end         ;pro create_struct