function create_index,a,nrec,update=update,outfile=outfile

   ; These constants should be changed in coordination with ARCHIVE
   nbytperentry = 38
   ; NB: This list should be of even number.  If it is not, add a zero to the end.
   template_codes = [!SEGM.GPARM, !SEGM.TPCAL,!SEGM.AMPCAL,$
                     !SEGM.PHZCAL,!SEGM.EPHEM,!SEGM.TPUPD]

   n_templ = n_elements(template_codes)

   ; As a precaution, check that there is not already an INDEX segment
   rec = (find_index(a,nrec) - 1)[0]

   indrec = nrec
   if (keyword_set(update) and rec ne -2) then begin
      indrec = rec     ; INDEX segment exists, but we want to update it
   endif else begin
      if (rec ne -2) then return,rec+1   ; INDEX segment already exists, so return its rec #
   endelse

   ; It did not already exist, so try to create one
   ; First open file for update and try to append an empty record, to see if it is
   ; possible to write to the file (it may be on read-only media).
   ; Get the file name associated with ASSOC variable A (note it is dangerous
   ; to parse the HELP command output like this...)
   help,a,output=afile
   afile = afile[0]
   bra = strpos(afile,'<')+1
   ket = strpos(afile,'>')
   filename = strmid(afile,bra,ket-bra)

   ; If the OUTVAR is not set, then we are writing the INDEX record to the existing
   ; file, so take care of some things for this case.
   if (not keyword_set(outfile)) then begin
      ; Check if this is a readonly file, in which case we cannot add or
      ; update the INDEX records.
      if (is_rd_only(filename)) then goto,skip

      if (indrec eq nrec) then begin
         ; Check if the last record of the file is an EOF record (a few were written
         ; with EOF = 100, now EOF = 17).  If so, decrement NREC so that the EOF will
         ; be overwritten.
         tls = tl_decode(a(nrec-1))
         if (tls.segmentcode eq !SEGM.EOF or tls.segmentcode eq 100) then nrec = nrec-1
         indrec = nrec
      endif

      ; Seems to have worked, so it is worthwhile to create the index record
      ; Index record number will be just NREC+1
      openu,lun,/get_lun,filename
      b = assoc(lun,intarr(1024))   ; Associate a second variable B to the file
   endif else begin
      ; OUTFILE is set, so we are writing to a new file.
      openw,olun,/get_lun,outfile
      b = assoc(olun,intarr(1024))
      indrec = 0
   endelse

   ; Generate the T/L field and the template for the scan entries
   data = a(0)
   tls = tl_decode(data)
   tls.segmentcode = 16   ; INDEX segment
   tls.scancode = 1       ; TEST scan (scan number is not defined for INDEX)
   tls.nrc = indrec+1       ; Current record number
   tls.nro = 0            ; Original record number (not defined)
   tls.nrs = 1            ; Which record of the segment this is (1st)
   ; Encode changed T/L field back to binary data
   tlsdat = tl_encode(tls)

   ; Create blank record and start filling it in
   data = intarr(1024)
   data[0:11] = tlsdat
   data[12] = uint(ishft(n_templ,8) + nbytperentry)
   ; Fill in template bytes
   for i = 0, n_templ-1, 2 do begin
      data[13+i/2] = uint(ishft(template_codes[i+1],8) + template_codes[i])
   endfor

   ; Pointer to start of next INDEX entry
   inext = 13+n_templ/2
   ; Save "boiler plate" info that gets written to each record
   bplate = data[12:inext-1]

   ; Get the list of scan headers and segments not in a scan
   seglist = get_segments(a,nrec)
   ntot = findsegentries(seglist,ihed,iseg)
   nhed = n_elements(ihed)
   nseg = n_elements(iseg)

   recs = intarr(n_templ)  ; Template record numbers

   id = progmeter(/init)
   ; Loop over scan headers
   for i = 0, nhed-1 do begin
      res = progmeter(id,i*1.0/ntot)
      if (ihed[i] ne -1) then begin
         ; Get info from each scan for index entries
         ; Get start and end record numbers
         reads,seglist[ihed[i]],srec,erec,format='(13X,I5,1X,I5)'
         ; Get start and end date and time
         tdata = a(srec-1)
         scansegcodes = tdata[2]
         tlsnew = tl_decode(tdata)
         syr = tlsnew.year
         sday = tlsnew.day
         smsec = tlsnew.msec
         tdata = a(erec-1)
         tlsnew = tl_decode(tdata)
         eyr = tlsnew.year
         eday = tlsnew.day
         emsec = tlsnew.msec
         ; Get TRAJECTORY segment for source name and pointing offsets
         trec = findseg(a,srec,nrec,!SEGM.TRAJ)
         if (trec eq -1) then begin
            ; No TRAJECTORY structure, so fill in with nominal.
            bytsrcnam = byte('<UNKNOWN>   ')
            srcnamdat = uintarr(6)
            ; Pack 2-byte data with byte-character data from sourcename
            for j = 0, 5 do begin
               srcnamdat[j] = ishft(uint(bytsrcnam[j*2+1]),8) + uint(bytsrcnam[j*2])
            endfor
            hao  = 0
            deco = 0
         endif else begin
            tdata = a(trec-1)
            srcnamdat = tdata[12:17]
            traj = decode(tdata,!SEGM.TRAJ)
            hao  = uint((*traj.pha)[ 0]) ; HA offset  [mdeg]
            deco = uint((*traj.pdec)[0]) ; Dec offset [mdeg]
         endelse
         ; Get the start records of the appropriate segments from the template.
         ; If no appropriate record is found within the scan, FINDSEG returns
         ; -1, in which case the next earlier relevant record number is used.
         for j = 0, n_templ-1 do recs[j] = recs[j] > findseg(a,srec,nrec,template_codes[j])

         ; Finally have all of the info, so create the INDEX entry for this scan
         data[inext] = scansegcodes
         data[inext+1] = srec
         data[inext+2] = erec
         data[inext+3] = syr
         data[inext+4] = sday
         data[inext+5:inext+6] = [uint(smsec),ishft(smsec,-16)]
         data[inext+7] = eyr
         data[inext+8] = eday
         data[inext+9:inext+10] = [uint(emsec),ishft(emsec,-16)]
         data[inext+11:inext+16] = srcnamdat
         data[inext+17] = hao
         data[inext+18] = deco
         for j = 0, n_templ-1 do data[inext+19+j] = recs[j]

         ; That INDEX entry is complete.  Advance the pointer for the next
         ; INDEX entry and check that it has not filled the current record
         inext = inext+nbytperentry/2+n_templ
         if (inext + nbytperentry/2 + n_templ gt 1024) then begin
            ; The next entry is not going to fit into this record, so
            ; write it to the file and prepare a new one
            b(indrec) = data         ; Write out current record
            indrec = indrec + 1        ; Increment total number of records
            tls.nrc = indrec+1       ; Current record number
            tls.nro = 0            ; Original record number (not defined)
            tls.nrs = tls.nrs+1    ; Which record of the segment this is
            ; Encode changed T/L field back to binary data
            tlsdat = tl_encode(tls)
            data = intarr(1024)    ; Zero the next record
            data[0:11] = tlsdat    ; Entry T/L Field
            inext = 13+n_templ/2   ; Starting pointer for this record
            data[12:inext-1] = bplate  ; Insert "boiler plate" info
         endif
      endif
   endfor
   res = progmeter(id,nhed*1.0/ntot)

   nstarted = tls.nrs
   ; Scans are all done.  Write out blank records to a total of 9
   for i = 0, 9-nstarted do begin
      b(indrec) = data         ; Write out current (partially filled) record
      indrec = indrec + 1        ; Increment total number of records
      tls.nrc = indrec+1       ; Current record number
      tls.nro = 0            ; Original record number (not defined)
      tls.nrs = tls.nrs+1    ; Which record of the segment this is
      ; Encode changed T/L field back to binary data
      tlsdat = tl_encode(tls)
      data = intarr(1024)    ; Zero the next record
      data[0:11] = tlsdat    ; Entry T/L Field
      inext = 13+n_templ/2   ; Starting pointer for this record
      data[12:inext-1] = bplate  ; Insert "boiler plate" info
   endfor

   ; Now at the last (10th) INDEX segment record.  Enter info for special segments
   for i = 0, nseg-1 do begin
      res = progmeter(id,(i+nhed)*1.0/ntot)
      if (iseg[i] ne -1) then begin
         ; Get info from each scan for index entries
         ; Get start record number
         reads,seglist[iseg[i]],srec,format='(13X,I5)'
         ; Get start date and time
         tdata = a(srec-1)
         tlsnew = tl_decode(tdata)
         segcode = tlsnew.segmentcode
         syr = tlsnew.year
         sday = tlsnew.day
         smsec = tlsnew.msec
         ; Finally have all of the info, so create the INDEX entry for this segment
         data[inext] = segcode
         data[inext+1] = srec
         data[inext+2] = syr
         data[inext+3] = sday
         data[inext+4:inext+5] = [uint(smsec),ishft(smsec,-16)]
         ; That INDEX entry is complete.  Advance the pointer for the next
         ; INDEX entry and check that it has not filled the current record
         inext = inext+6
      endif
   endfor
   b(indrec) = data
   indrec = indrec+1
   if (n_elements(lun) ne 0) then free_lun,lun
   if (n_elements(olun) ne 0) then free_lun,olun

   res = progmeter(id,/destroy)
   return,indrec
skip:
   ; There was an error opening or writing the file
   ON_IOERROR,NULL
   if (n_elements(lun) ne 0) then free_lun,lun
   if (n_elements(olun) ne 0) then free_lun,olun

   ans = dialog_message(['CREATE_INDEX: An error occurred in trying to write the',$
                         'INDEX segment.  The file may be on read-only media.'],/error)

return,-1
en