aboutsummaryrefslogtreecommitdiff
path: root/pkg/xtools/dttext.x
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /pkg/xtools/dttext.x
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/xtools/dttext.x')
-rw-r--r--pkg/xtools/dttext.x698
1 files changed, 698 insertions, 0 deletions
diff --git a/pkg/xtools/dttext.x b/pkg/xtools/dttext.x
new file mode 100644
index 00000000..387d8654
--- /dev/null
+++ b/pkg/xtools/dttext.x
@@ -0,0 +1,698 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <time.h>
+include <ctype.h>
+include <ctotok.h>
+include <error.h>
+include <fset.h>
+include <pkg/dttext.h>
+
+.help dttext May85 "Simple Text Database Tools"
+.ih
+DESCRIPTION
+
+The database created, accessed, and modified by these procedures is
+a simple text file. The purpose of these tools is to act as
+an interum database facility until the sophisticated IRAF database
+package is available. The database model consists of
+comment lines which begin with a #, records, and fields within records.
+Records and fields (except array fields) have the same format, a keyword
+followed by data and terminated by a newline. Records have the keyword
+'begin' and the data is any following text. Thus a record can be identified
+by anything from a single character to an entire string. A record contains
+all the following lines until the next record or the end of the file.
+Whitespace before and after the keyword is ignored. The user is responsible
+for adding indentation to clarify the structure
+of the database. However, the user can create a database with any
+style of whitespace that satisfies the keyword/value syntax.
+
+The array fields have a slightly different format. The field begins just
+like an integer valued field; keyword followed by an integer. The integer
+value is the number of array elements. The following lines
+contain the array values, one per line. Because the field name
+line has the same structure as an integer valued field the array
+length can be determined before reading the array values by reading
+the field as integer valued.
+
+For arrays with more than one column per line the dtscan procedure is
+used to scan a line and then the FMTIO garg procedures are used to
+decode the columns. The user read the array field as an integer to get
+the number of lines and to position FIO to start reading the lines.
+
+There are four types of fields currently supported. These are integer
+valued fields, real valued fields, string valued fields, and real arrays.
+It is up to the user to know the type of value for each field. Note
+that the integer and real fields may be accessed as string valued.
+
+Records are referenced by a record number. When a database is mapped
+each record which is unique is given a sequential record number.
+When more than one record has the same record identifier then only
+the last record is mapped.
+
+There are limitations imposed by the text file format. A database
+may only be read or appended. To update a record a new record must
+be written. A later record with the same name takes precedence.
+
+Errors are handled through the standard error handling system of IRAF.
+Thus, uncaught errors will terminate the task with a message. If it
+is possible that a field will not be present then the task can catch
+the error and take appropriate action.
+.ih
+DATABASE MAPPING
+
+When a database is mapped READ_ONLY then the records in the database
+are found and a structure created. The structure is given in the file
+"dttext.h". The important elements of the structure are:
+
+.nf
+
+ DT(dt) # Database FIO channel
+ DT_NRECS(dt) # Number of records
+ DT_NAME(dt, rec) # Record name
+ DT_OFFSET(dt, rec) # FIO offset
+.fi
+.ih
+PROCEDURES
+
+The procedures separate into three types, procedures to map and unmap
+the database, procedures to access the database, and procedures to make
+entries in the database. The access routines reference a particular
+record. To access a record by name the procedure dtlocate returns
+the record number or EOF. The put routines write to the end of
+the database. It is important to enter a record because otherwise
+added fields will be associated with the preceding record. The put
+time command puts a comment line with the time.
+
+.nf
+ dt = dtmap (database, mode) # NEW_FILE, READ_ONLY or APPEND
+ dt = dtmap1 (database, name, mode) # Use a directory as a database
+ dtremap (dt, database, name,mode) # Remap a database
+ dtunmap (dt)
+
+ record = dtlocate (dt, recname)
+
+ dtgstr (dt, record, field, str, maxchar)
+ value = dtget[ird] (dt, record, field)
+ dtgar (dt, record, field, array, len_array, npts)
+
+ dtptime (dt)
+ dtput (dt, format)
+.fi
+.ih
+EXAMPLES
+
+The following is an example record from a database.
+
+.nf
+# Fri 15:13:13 05-Apr-85 Example
+begin NGC1952 B
+ title NGC1952 B filter centered
+ ra 12:40:20
+ dec +5:20:15
+ flags 4
+ 3.1
+ 9.2
+ 1
+ 4
+ exp 3600
+.fi
+
+
+The following example reads the example record and writes a new record.
+
+.nf
+ iferr {
+ dt = dtmap (database, READ_ONLY)
+ record = dtlocate (dt, "NGC1952 B")
+ call dtgstr (dt, record, "title", title, SZ_TITLE)
+ ra = dtgetr (dt, record, "RA")
+ dec = dtgetr (dt, record, "DEC")
+
+ # Get length of array for dynamic allocation.
+ nflags = dtgeti (dt, record, "flags")
+ call salloc (flags, nflags, TY_REAL)
+ call dtgar (dt, record, "flags", Memr[flags], nflags, nflags)
+ }
+
+ dt = dtmap (database, APPEND)
+ call dtptime (dt)
+ call dtput (dt, "begin\tNGC1952 Objects\n")
+ call dtput (dt, "\tobjects\t10\n)
+ do i = 1, 10 {
+ call dtput (dt, "\t\t%g\n")
+ call pargr (objects[i])
+ }
+ call dtclose (dt)
+.fi
+
+The following is a database entry for a list which is read by the code below.
+
+.nf
+# Fri 15:13:13 05-Apr-85 Example
+begin Table 1
+ 1 apples 10 macintosh
+ 2 oranges 8 valencia
+ 3 potatoes 3 idaho
+
+
+ # Code to read database table.
+
+ record = dtlocate (dt, "Table 1")
+ call seek (DT(dt), DT_OFFSET(dt, record))
+ while (scan (DT(dt)) != EOF) {
+ call gargi (n)
+ call gargwrd (fruit[1, n])
+ call gargi (number[n])
+ call gargstr (comment[1, n])
+ }
+
+To read sequentially through a database:
+
+ # Code to read sequentially through a database.
+
+ do i = 1, DB_NRECS(db) {
+ call printf ("%s\n")
+ call pargstr (DB_NAME(db, i))
+ }
+.fi
+.ih
+SEE ALSO
+Source code
+.endhelp
+
+
+# DTMAP -- Map a database.
+
+pointer procedure dtmap (database, mode)
+
+char database[ARB] # Database file
+int mode # FIO mode
+
+int i, nrec
+int dt_alloc1, dt_alloc2
+pointer dt, str
+
+int open(), fscan(), strlen()
+bool streq()
+long note()
+errchk delete, open
+
+begin
+ if (mode == NEW_FILE)
+ iferr (call delete (database))
+ ;
+
+ i = open (database, mode, TEXT_FILE)
+
+ call calloc (dt, DT_LEN, TY_STRUCT)
+ DT(dt) = i
+
+ if (mode != READ_ONLY)
+ return (dt)
+
+ dt_alloc1 = DT_ALLOC
+ dt_alloc2 = DT_ALLOC * SZ_LINE
+ call malloc (DT_OFFSETS(dt), dt_alloc1, TY_LONG)
+ call malloc (DT_NAMES(dt), dt_alloc1, TY_INT)
+ call malloc (DT_MAP(dt), dt_alloc2, TY_CHAR)
+ call malloc (str, SZ_LINE, TY_CHAR)
+
+ nrec = 1
+ DT_NRECS(dt) = 0
+ DT_NAMEI(dt, nrec) = 0
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (DT_NAME(dt, nrec), SZ_LINE)
+
+ if (streq (DT_NAME(dt, nrec), "begin")) {
+ call gargstr (Memc[str], SZ_LINE)
+ for (i=str; IS_WHITE(Memc[i]); i=i+1)
+ ;
+ call strcpy (Memc[i], DT_NAME(dt,nrec), SZ_LINE)
+
+ for (i = 1; i < nrec; i = i + 1)
+ if (streq (DT_NAME(dt, i), DT_NAME(dt, nrec)))
+ break
+
+ if (i < nrec)
+ DT_OFFSET(dt, i) = note (DT(dt))
+ else {
+ DT_NRECS(dt) = nrec
+ DT_OFFSET(dt, nrec) = note (DT(dt))
+ DT_NAMEI(dt, nrec+1) = DT_NAMEI(dt, nrec) +
+ strlen (DT_NAME(dt, nrec)) + 1
+ nrec = nrec + 1
+ }
+
+ if (nrec == dt_alloc1) {
+ dt_alloc1 = dt_alloc1 + DT_ALLOC
+ call realloc (DT_OFFSETS(dt), dt_alloc1, TY_LONG)
+ call realloc (DT_NAMES(dt), dt_alloc1, TY_INT)
+ }
+ if (DT_NAMEI(dt, nrec) + SZ_LINE >= dt_alloc2) {
+ dt_alloc2 = dt_alloc2 + DT_ALLOC * SZ_LINE
+ call realloc (DT_MAP(dt), dt_alloc2, TY_CHAR)
+ }
+ }
+ }
+
+ call realloc (DT_MAP(dt), DT_NAMEI(dt, nrec), TY_CHAR)
+ call realloc (DT_OFFSETS(dt), DT_NRECS(dt), TY_LONG)
+ call realloc (DT_NAMES(dt), DT_NRECS(dt), TY_INT)
+ call mfree (str, TY_CHAR)
+
+ return (dt)
+end
+
+
+# DTCLOSE -- Close database.
+
+procedure dtunmap (dt)
+
+pointer dt # Database file descriptor
+
+begin
+ if (dt == NULL)
+ return
+ call close (DT(dt))
+ call mfree (DT_MAP(dt), TY_CHAR)
+ call mfree (DT_OFFSETS(dt), TY_LONG)
+ call mfree (DT_NAMES(dt), TY_INT)
+ call mfree (dt, TY_STRUCT)
+end
+
+
+# DTLOCATE -- Locate a database record.
+
+int procedure dtlocate (dt, name)
+
+pointer dt # DTTEXT pointer
+char name[ARB] # Record name
+
+int i
+
+bool streq()
+
+begin
+ do i = 1, DT_NRECS(dt) {
+ if (streq (name, DT_NAME(dt, i)))
+ return (i)
+ }
+
+# call printf ("Record = %s\n")
+# call pargstr (name)
+# call flush (STDOUT)
+ call error (0, "Database record not found")
+end
+
+
+# DTGSTR -- Get a string field
+
+procedure dtgstr (dt, record, field, str, maxchar)
+
+pointer dt # Database file descriptor
+int record # Database index
+char field[ARB] # Database field
+char str[maxchar] # String value
+int maxchar # Maximum characters for string
+
+char name[SZ_LINE]
+int i, fscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > DT_NRECS(dt)))
+ call error (0, "Database record request out of bounds")
+
+ call seek (DT(dt), DT_OFFSET(dt, record))
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargstr (str, maxchar)
+ for (i=1; IS_WHITE(str[i]); i=i+1)
+ ;
+ if (i > 1)
+ call strcpy (str[i], str, maxchar)
+ return
+ }
+ }
+
+ call error (0, "Database field not found")
+end
+
+
+# DTGETI -- Get an integer field
+
+int procedure dtgeti (dt, record, field)
+
+pointer dt # DTTEXT pointer
+int record # Database index
+char field[ARB] # Database field
+
+int ival # Field value
+char name[SZ_LINE]
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > DT_NRECS(dt)))
+ call error (0, "Database record request out of bounds")
+
+ call seek (DT(dt), DT_OFFSET(dt, record))
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (ival)
+ if (nscan() == 2)
+ return (ival)
+ else
+ call error (0, "Error in database field value")
+ }
+ }
+
+ call error (0, "Database field not found")
+end
+
+
+# DTGETR -- Get an real field
+
+real procedure dtgetr (dt, record, field)
+
+pointer dt # DTTEXT pointer
+int record # Database index
+char field[ARB] # Database field
+
+real rval
+char name[SZ_LINE]
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > DT_NRECS(dt)))
+ call error (0, "Database record request out of bounds")
+
+ call seek (DT(dt), DT_OFFSET(dt, record))
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargr (rval)
+ if (nscan() == 2)
+ return (rval)
+ else
+ call error (0, "Error in database field value")
+ }
+ }
+
+ call error (0, "Database field not found")
+end
+
+
+# DTGETD -- Get a doubel precision field.
+
+double procedure dtgetd (dt, record, field)
+
+pointer dt # DTTEXT pointer
+int record # Database index
+char field[ARB] # Database field
+
+double dval
+char name[SZ_LINE]
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > DT_NRECS(dt)))
+ call error (0, "Database record request out of bounds")
+
+ call seek (DT(dt), DT_OFFSET(dt, record))
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargd (dval)
+ if (nscan() == 2)
+ return (dval)
+ else
+ call error (0, "Error in database field value")
+ }
+ }
+
+ call error (0, "Database field not found")
+end
+
+
+# DTGAR -- Get a real array field
+
+procedure dtgar (dt, record, field, array, len_array, npts)
+
+pointer dt # DTTEXT pointer
+int record # Database index
+char field[ARB] # Database field
+real array[len_array] # Array values
+int len_array # Length of array
+int npts # Number of points in the array
+
+char name[SZ_LINE]
+int i
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > DT_NRECS(dt)))
+ call error (0, "Database record request out of bounds")
+
+ call seek (DT(dt), DT_OFFSET(dt, record))
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (npts)
+ if (nscan() != 2)
+ call error (0, "Error in database field value")
+
+ npts = min (npts, len_array)
+ for (i = 1; i <= npts; i = i + 1) {
+ if (fscan (DT(dt)) == EOF)
+ call error (0, "Error in database field value")
+
+ call gargr (array[i])
+ if (nscan() != 1)
+ call error (0, "Error in database field value")
+ }
+ return
+ }
+ }
+
+ call error (0, "Database field not found")
+end
+
+
+# DTGAD -- Get a double array field
+
+procedure dtgad (dt, record, field, array, len_array, npts)
+
+pointer dt # DTTEXT pointer
+int record # Database index
+char field[ARB] # Database field
+double array[len_array] # Array values
+int len_array # Length of array
+int npts # Number of points in the array
+
+char name[SZ_LINE]
+int i
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > DT_NRECS(dt)))
+ call error (0, "Database record request out of bounds")
+
+ call seek (DT(dt), DT_OFFSET(dt, record))
+
+ while (fscan (DT(dt)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (npts)
+ if (nscan() != 2)
+ call error (0, "Error in database field value")
+
+ npts = min (npts, len_array)
+ for (i = 1; i <= npts; i = i + 1) {
+ if (fscan (DT(dt)) == EOF)
+ call error (0, "Error in database field value")
+
+ call gargd (array[i])
+ if (nscan() != 1)
+ call error (0, "Error in database field value")
+ }
+ return
+ }
+ }
+
+ call error (0, "Database field not found")
+end
+
+
+# DTPTIME -- Put a time string with a comment
+
+procedure dtptime (dt)
+
+pointer dt # DTTEXT pointer
+
+char timestr[SZ_TIME]
+long time, clktime()
+
+begin
+ time = clktime (0)
+ call cnvtime (time, timestr, SZ_TIME)
+ call fprintf (DT(dt), "# %s\n")
+ call pargstr (timestr)
+end
+
+
+# DTPUT -- Print to database.
+
+procedure dtput (dt, format)
+
+pointer dt # DTTEXT pointer
+char format[ARB] # String format
+
+begin
+ call fprintf (DT(dt), format)
+end
+
+# DTSCAN -- Scan database.
+
+int procedure dtscan (dt)
+
+pointer dt # DTTEXT pointer
+
+int fscan()
+
+begin
+ return (fscan (DT(dt)))
+end
+
+
+include <finfo.h>
+
+# DTMAP1 -- Map database.
+#
+# The database name may be a regular file or a directory. If it is a
+# directory a database file with the name given by key is read or appended.
+
+pointer procedure dtmap1 (database, key, mode)
+
+char database[ARB] # Database
+char key[ARB] # Key
+int mode # Mode
+
+pointer sp, dbfile, dt
+
+int isdirectory(), access(), stridxs()
+pointer dtmap()
+
+errchk dtmap()
+
+begin
+ call smark (sp)
+ call salloc (dbfile, SZ_PATHNAME + SZ_FNAME, TY_CHAR)
+
+ # Check if the database does not exist create it as a directory.
+
+ if (access (database, READ_ONLY, DIRECTORY_FILE) == NO)
+ if ((mode == APPEND) || (mode == NEW_FILE)) {
+ if (stridxs (".", database) != 0)
+ call error (0,
+ "Periods not allowed in database directory name")
+ iferr (call fmkdir (database))
+ call error (0, "Can't make database directory")
+ }
+
+ if (isdirectory (database, Memc[dbfile], SZ_PATHNAME + SZ_FNAME) > 0)
+ call strcat (key, Memc[dbfile], SZ_PATHNAME + SZ_FNAME)
+ else
+ call strcpy (database, Memc[dbfile], SZ_PATHNAME + SZ_FNAME)
+
+ dt = dtmap (Memc[dbfile], mode)
+ call strcpy (database, DT_DNAME(dt), DT_SZFNAME)
+ call strcpy (key, DT_FNAME(dt), DT_SZFNAME)
+ DT_MODE(dt) = mode
+
+ call sfree (sp)
+ return (dt)
+end
+
+
+# DTREMAP -- Check if database needs to be remapped.
+#
+# If the pointer is null simply map the database.
+# If the pointer is not null check if the requested database is the same
+# as the current one and if not close the current database and map the
+# new one. Note that remapping between read and append will not update
+# the entry data structure to include any information written.
+
+procedure dtremap (dt, dname, fname, mode)
+
+pointer dt # Database pointer
+char dname[ARB] # Directory name
+char fname[ARB] # File name
+int mode # Mode
+
+int i, open()
+bool strne()
+pointer dbfile, dtmap1()
+errchk dtmap1, dtunmap
+
+begin
+ if (dt != NULL) {
+ if (strne (dname, DT_DNAME(dt)) || strne (fname, DT_FNAME(dt))) {
+ call dtunmap (dt)
+ } else if (mode != DT_MODE(dt)) {
+ i = SZ_PATHNAME + SZ_FNAME
+ call malloc (dbfile, i, TY_CHAR)
+ call fstats (DT(dt), F_FILENAME, Memc[dbfile], i)
+ call close (DT(dt))
+ iferr (i = open (Memc[dbfile], mode, TEXT_FILE)) {
+ DT(dt) = NULL
+ call dtunmap (dt)
+ call mfree (dbfile, TY_CHAR)
+ call erract (EA_ERROR)
+ }
+ DT(dt) = i
+ DT_MODE(dt) = mode
+ call mfree (dbfile, TY_CHAR)
+ }
+ }
+
+ if (dt == NULL) {
+ i = dtmap1 (dname, fname, mode)
+ dt = i
+ }
+end