Understanding the Synergy symbol table API

The Synergy symbol table API provides runtime maintenance of sets of names, along with ancillary information associated with those names. These names are simply text strings of up to 255 characters. The ancillary information associated with each name can be up to 100 characters.

Each entry within a symbol table has three components: a name, an access code, and user‑defined data. Each entry is added to two lists: an access list (see Access list) and a search list (see Search list). As entries are added to a symbol table, memory is expanded as required. Deleting an item from a symbol table reclaims the memory associated with that item immediately.

Requirements

The file DBLDIR:namspc.def defines the macros and constants required by the symbol table API. You must include this file in your program using the .INCLUDE compiler directive.

All programs that use the symbol table API must be built using the compiler options ‑T (which trims trailing null arguments from XCALLs and function references) and ‑X (which automatically declares all undefined function references as external ^VAL functions).

Access list

The access list is a user‑configurable list. The access code for an entry is that entry’s position within the access list. An entry is initially added at the end of the access list but can subsequently be moved anywhere within the list using %NSPC_MOVE.

Search list

The search list maintains an alphabetical order of the entries by name. This allows for high‑speed lookups of entry names. This list cannot be reordered by the user.

Sample program

The following example is two functions and a subroutine that the user must call. One reads an .ini file and populates the symbol table, and the other does a search to see if a particular entry is there.

;=======================================================================
; Module:               prcini.dbl
;
; Description:          Process an .INI file
;=======================================================================
function prcini_file   ,^val  ,reentrant

; Description: Read an .ini file. Returns ID of the loaded symbol table.
    a_file              ,a
; Notes: This routine parses an .ini file and stores the initialization
; settings into a symbol table for future retrieval.
.include "DBLDIR:namspc.def"
.define MAXITM          ,10             ;The maximum parse tokens we'll need
.define MAXSECLEN    ,64                 ;Maximum length of a section identifier
.define LINLEN          ,100            ;Line size
stack record
    chn                 ,i4             ;Input processing channel
    new_id              ,i4             ;New entry id
    nsid                ,i4             ;The symbol table ID
    icnt                ,i4             ;Loaded item count
    linsiz              ,i4             ;Input line length
    ndx                 ,i4             ;Item index
    ipos                ,[MAXITM]i4     ;Item positions
    ilen                ,[MAXITM]i4     ;Item lengths
    ityp                ,[MAXITM]i4     ;Item types
    pos                 ,i4             ;Same as the arrays for a given entry
    len                 ,i4
    typ                 ,i4
    ix                  ,i4             ;A scratch integer
    group ident         ,a              ;Item storage
     id1                ,[MAXSECLEN]a1
    endgroup
    group line          ,a              ;Input line
     ln1                ,[LINLEN]a1
    endgroup
    secnam              ,a(MAXSECLEN)   ;The saved section name
    tagnam              ,a(MAXSECLEN)   ;The current tag name
proc
    clear nsid, chn                             ;Init fields
    chn = %syn_freechn
    open(chn,i,a_file) [err=nofile]             ;Open the .ini file
    repeat                                      ;Skip to the first section
      begin
        call nextline
        if (linsiz .eq. 0)
          goto done
        if (id1 .eq. '[')
          exitloop
      end
    nsid = %nspc_open(D_NSPC_CASE,LINLEN,,MAXSECLEN*2)
    repeat
      begin
        call nextitem                           ;Get the section's name
        if ((ndx.gt.icnt) .or. (typ .ne. I_IDENT))
          nextloop
        secnam = ident
        upcase secnam
        repeat
          begin
            call nextline                       ;Get next nonblank line
            if (linsiz .eq. 0)
              goto done
            if (id1 .eq. '[')                   ;Process another section
              exitloop
            tagnam = ident                      ;Get the tag name
            upcase tagnam
            pos = %instr(1,line,'=') + 1
            new_id = %nspc_add(nsid,%atrim(secnam)+ "!" + %atrim(tagnam),
  &                  line(pos,linsiz))
          end
      end
done, 
    close chn                                   ;Close the channel and return 
    freturn nsid                                ; with success flagged
    
nofile, 
    freturn 0                                   ;Return with error flagged

; Get next nonblank line.  If at EOF, linsiz will be zero.
nextline,
    repeat
      begin
        reads(chn,line,eof)                     ;Get the next line
        if ((%rdlen .eq. 0) .or. (%atrim(line) .eq. " "))
          nextloop                              ;Ignore empty lines
        linsiz = %trim(line)
        xcall s_parse(line(1:linsiz), 1, MAXITM, ipos, ilen, ityp, icnt, 
  &           ndx)
        clear ndx                               ;Get the first item
        call nextitem
        if ((ndx .le. icnt) .and. (id1 .ne. ';'))
                                                ;Exit if not an empty line
          return
      end
eof,
    clear linsiz                                ;Signal EOF
    return
; Get the next parsed item on the line
nextitem,
    len = ilen[ndx += 1]                        ;Move to the next item
    pos = ipos[ndx]
    using (typ = ityp[ndx]) select
 (I_SPACE),
      goto nextitem                             ;Ignore spaces
 (I_ANUM,I_IDENT),
      begin
        ident = line(pos:len)                   ;Get case–sensitive identifier
        typ = I_IDENT                           ;Map ANUM to IDENT
      end
 (I_SPECIAL),
      id1 = ln1(pos)                            ;Get the special character
 (),
      clear id1
    endusing
    return
endfunction
subroutine prcini_close

; Close the symbol table
    a_nsid              ,n                      ;ID of .ini file's symbol table

proc
    xcall nspc_close(a_nsid)
    xreturn
endsubroutine
function prcini_find ,^val ,reentrant

; Find an .ini file entry
    a_nsid              ,n                      ;ID of .ini file's symbol table
    a_section           ,a                      ;The section name
    a_entry             ,a                      ;The entry tag
    a_result            ,a                      ;Returned found entry
; Return Value:  TRUE if the entry was found
record
    result              ,i4
    section             ,a(MAXSECLEN)
    entry_tag           ,a(MAXSECLEN)
proc
    clear section, entry_tag
    if (^passed(a_section) .and. a_section)
      begin
        section = a_section
        upcase section
      end
    if (^passed(a_entry) .and. a_entry)
      entry_tag = a_entry
    upcase entry_tag
    result = %nspc_find(a_nsid,%atrim(section)+"!"+%atrim(entry_tag),
  &          a_result)
    freturn(result)
endfunction