1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <syserr.h>
include <error.h>
include <mach.h>
include <fset.h>
include <plset.h>
include "qpoe.h"
include "qpex.h"
include "qpio.h"
# QPIO_OPEN -- Open the named event list parameter for event i/o. Since event
# lists can only be read and written sequentially, there are only two useful
# i/o modes, namely, READ_ONLY and NEW_FILE. Filtering is permitted only
# when reading an event list; when writing to a new event list, the events
# are merely copied out as they are received.
pointer procedure qpio_open (qp, paramex, mode)
pointer qp #I QPOE descriptor
char paramex[ARB] #I event-list parameter plus expression list
int mode #I access mode
bool newlist
pointer sp, io, dd, eh, op, oo, flist, deffilt, defmask, maskname
pointer param, expr, filter, filter_text, mask, umask, psym, dsym, name
int sz_filter, szb_page, nwords, nchars, junk, fd, ip, i, j
pointer qp_gpsym(), qpex_open(), stname(), strefstab()
int qp_popen(), qp_lenf(), read(), pl_l2pi(), fstati()
int qp_geti(), qp_gstr(), qp_parsefl(), qpio_parse(), qpex_modfilter()
errchk qp_bind, qp_geti, qpio_parse, qp_gpsym, qp_addf, qp_gstr
errchk qp_parsefl, qp_popen, qpex_open, qpio_loadmask, qpex_modfilter
errchk stname, calloc, malloc, realloc, read, syserrs
string s_deffilt DEF_FILTER
string s_defmask DEF_MASK
define done_ 91
begin
call smark (sp)
call salloc (deffilt, SZ_FNAME, TY_CHAR)
call salloc (defmask, SZ_FNAME, TY_CHAR)
call salloc (maskname, SZ_FNAME, TY_CHAR)
call salloc (umask, SZ_FNAME, TY_CHAR)
if (QP_ACTIVE(qp) == NO)
call qp_bind (qp)
newlist = (mode == NEW_FILE || mode == APPEND)
if (QP_DEBUG(qp) > 0) {
call eprintf ("qpio_open (%xX, `%s', %d)\n")
call pargi (qp)
call pargstr (paramex)
call pargi (mode)
}
# Allocate and initialize the QPIO descriptor.
call calloc (io, LEN_IODES, TY_STRUCT)
call calloc (IO_DD(io), LEN_DDDES, TY_STRUCT)
call calloc (IO_PARAM(io), SZ_FNAME, TY_CHAR)
call calloc (IO_MASK(io), SZ_FNAME, TY_CHAR)
IO_QP(io) = qp
IO_MODE(io) = mode
IO_DEBUG(io) = QP_DEBUG(qp)
IO_XBLOCK(io) = QP_XBLOCK(qp)
IO_YBLOCK(io) = QP_YBLOCK(qp)
IO_NODEFFILT(io) = QP_NODEFFILT(qp)
IO_NODEFMASK(io) = QP_NODEFMASK(qp)
IO_OPTBUFSIZE(io) = QP_OPTBUFSIZE(qp)
IO_ACTIVE(io) = NO
dd = IO_DD(io)
param = IO_PARAM(io)
mask = IO_MASK(io)
filter = NULL
iferr {
# Get the image dimensions.
IO_NCOLS(io) = qp_geti (qp, "axlen[1]")
IO_NLINES(io) = qp_geti (qp, "axlen[2]")
# Parse the parameter expression into the parameter name and
# expression qualifier fields. Possible variations on the input
# syntax are "" (null string, default everything), "param" (parameter
# name only), "param[expr]" (parameter name plus expression), and
# "[expr]" or "expr" (expression only), where the parameter name may
# be specified as in "[param=value,...]", i.e., as a term in the
# expression (allowing it to be input by the user to override the
# default).
op = param
for (ip=1; paramex[ip] != EOS && paramex[ip] != '['; ip=ip+1) {
Memc[op] = paramex[ip]
op = op + 1
}
expr = ip
# Parse the expression qualifier field to set the i/o parameters,
# e.g., region mask, event attribute filter, blocking factor,
# coordinate system, etc. All QPIO parameters are removed, returning
# the filter expression (if any) to be passed on to QPEX for event
# attribute filtering. The `filter' buffer is passed by pointer so
# that it may be reallocated if more space is needed.
sz_filter = DEF_SZEXPRBUF
call malloc (filter, sz_filter, TY_CHAR)
if (qpio_parse (io, paramex[expr],
filter, sz_filter, Memc[mask], SZ_FNAME) == ERR)
call eprintf ("QPIO warning: error parsing options expression\n")
# If no event list parameter was named, use the default.
if (Memc[param] == EOS)
call strcpy (DEF_EVENTPARAM, Memc[param], SZ_FNAME)
# Verify the parameter's type if it already exists, or create a new
# parameter of the default type if the mode is newfile or append.
psym = qp_gpsym (qp, Memc[param])
if (psym != NULL) {
if (S_DTYPE(psym) != TY_USER || S_DSYM(psym) == NULL)
call syserrs (SYS_QPNEVPAR, Memc[param])
else if (newlist && S_NELEM(psym) > 0)
call syserrs (SYS_QPCLOBBER, Memc[param])
} else if (mode == READ_ONLY) {
call syserrs (SYS_QPUKNPAR, Memc[param])
} else {
call qp_addf (qp, Memc[param], DEF_EVENTTYPE, 0, "", 0)
psym = qp_gpsym (qp, Memc[param])
}
# Get the field list for the user defined event structure. This
# defines the size of an event struct, lists the offset and type
# of each field, and indicates which fields are to be used for X
# and Y in positional accesses (unless already set in the paramex).
dsym = strefstab (QP_ST(qp), S_DSYM(psym))
nchars = S_NELEM(dsym)
name = stname (QP_ST(qp), dsym)
call salloc (flist, nchars, TY_CHAR)
if (qp_gstr (qp, Memc[name], Memc[flist], nchars) < nchars)
call syserrs (SYS_QPBADVAL, Memc[name])
if (qp_parsefl (qp, Memc[flist], IO_DD(io)) <= 0)
call syserrs (SYS_QPINVDD, Memc[name])
else if (IO_EVXOFF(io) == NULL && IO_EVYOFF(io) == NULL) {
i = DD_XFIELD(dd)
j = DD_YFIELD(dd)
if (i == 0 || j == 0)
call syserrs (SYS_QPNOXYF, Memc[name])
switch (DD_FTYPE(dd,i)) {
case TY_SHORT, TY_INT, TY_LONG, TY_REAL, TY_DOUBLE:
IO_EVXTYPE(io) = DD_FTYPE(dd,i)
default:
call syserrs (SYS_QPXYFNS, Memc[name])
}
switch (DD_FTYPE(dd,j)) {
case TY_SHORT, TY_INT, TY_LONG, TY_REAL, TY_DOUBLE:
IO_EVYTYPE(io) = DD_FTYPE(dd,j)
default:
call syserrs (SYS_QPXYFNS, Memc[name])
}
IO_EVXOFF(io) = DD_FOFFSET(dd,i)
IO_EVYOFF(io) = DD_FOFFSET(dd,j)
}
IO_EVENTLEN(io) = DD_STRUCTLEN(dd) * SZ_STRUCT / SZ_SHORT
# Open the lfile used to store the event list.
IO_FD(io) = qp_popen (qp, Memc[param], mode, BINARY_FILE)
IO_LF(io) = S_LFILE(psym)
IO_CHAN(io) = fstati (IO_FD(io), F_CHANNEL)
IO_PSYM(io) = psym
# The rest of the initialization is performed in the first call to
# qpio_putev if we are writing a new event list.
if (newlist) # EXIT if new event list
goto done_ # -----------------------
fd = IO_FD(io)
szb_page = QP_FMPAGESIZE(qp)
nchars = szb_page / SZB_CHAR
call salloc (eh, szb_page / (SZ_STRUCT*SZB_CHAR), TY_STRUCT)
call aclri (Memi[eh], szb_page / (SZ_STRUCT*SZB_CHAR))
# Read event list header.
if (read (fd, Memi[eh], nchars) < nchars)
call syserrs (SYS_QPNOEH, Memc[param])
IO_NEVENTS(io) = EH_NEVENTS(eh)
IO_EVENTLEN(io) = EH_EVENTLEN(eh)
IO_SZBBUCKET(io)= EH_SZBBUCKET(eh)
IO_BUCKETLEN(io)= EH_BUCKETLEN(eh)
IO_FBOFF(io) = EH_FBOFF(eh)
IO_EVMINOFF(io) = EH_EVMINOFF(eh)
IO_EVMAXOFF(io) = EH_EVMAXOFF(eh)
IO_INDEXLEN(io) = EH_INDEXLEN(eh)
IO_YOFFVOFF(io) = EH_YOFFVOFF(eh)
IO_YOFFVLEN(io) = EH_YOFFVLEN(eh)
IO_YLENVOFF(io) = EH_YLENVOFF(eh)
IO_YLENVLEN(io) = EH_YLENVLEN(eh)
IO_IXXOFF(io) = EH_IXXOFF(eh)
IO_IXYOFF(io) = EH_IXYOFF(eh)
IO_IXXTYPE(io) = EH_IXXTYPE(eh)
IO_IXYTYPE(io) = EH_IXYTYPE(eh)
# Copy the MINEVL event struct into the QPIO descriptor.
nwords = IO_EVENTLEN(io)
call malloc (IO_MINEVL(io), nwords, TY_SHORT)
call amovs (Memi[eh+EH_MINEVLOFF(eh)], Mems[IO_MINEVL(io)],
IO_EVENTLEN(io))
# Copy the MAXEVL event struct into the QPIO descriptor.
call malloc (IO_MAXEVL(io), nwords, TY_SHORT)
call amovs (Memi[eh+EH_MAXEVLOFF(eh)], Mems[IO_MAXEVL(io)],
IO_EVENTLEN(io))
if (IO_DEBUG(io) > 0) {
call eprintf ("%s: nev=%d, szbk=%d, bklen=%d+2, ixlen=%d\n")
call pargstr (Memc[param])
call pargi (IO_NEVENTS(io))
call pargi (IO_SZBBUCKET(io))
call pargi (IO_BUCKETLEN(io))
call pargi (IO_INDEXLEN(io))
}
# Get compressed event list index, if any.
if (IO_INDEXLEN(io) > 0) {
call salloc (oo, IO_INDEXLEN(io) * 2, TY_SHORT)
call malloc (IO_YOFFVP(io), IO_INDEXLEN(io), TY_INT)
call malloc (IO_YLENVP(io), IO_INDEXLEN(io), TY_INT)
nchars = IO_YOFFVLEN(io) * SZ_SHORT
call seek (fd, IO_YOFFVOFF(io))
if (read (fd, Mems[oo], nchars) < nchars)
call syserrs (SYS_QPBADIX, Memc[param])
junk = pl_l2pi (Mems[oo], 1, Memi[IO_YOFFVP(io)], IO_INDEXLEN(io))
nchars = IO_YLENVLEN(io) * SZ_SHORT
call seek (fd, IO_YLENVOFF(io))
if (read (fd, Mems[oo], nchars) < nchars)
call syserrs (SYS_QPBADIX, Memc[param])
junk = pl_l2pi (Mems[oo], 1, Memi[IO_YLENVP(io)], IO_INDEXLEN(io))
}
# We won't need the file buffer any more, so free it.
call fseti (fd, F_BUFSIZE, 0)
# Compile the event attribute filter (EAF). Always open the default
# filter if one is provided with the datafile. If the user has also
# specified a filter, this will modify the default filter.
if (IO_NODEFFILT(io) != YES) {
# Check for "deffilt.<evl>" first, then "deffilt".
call sprintf (Memc[deffilt], SZ_FNAME, "%s.%s")
call pargstr (s_deffilt)
call pargstr (Memc[param])
nchars = qp_lenf (qp, Memc[deffilt])
if (nchars <= 0) {
call strcpy (s_deffilt, Memc[deffilt], SZ_FNAME)
nchars = qp_lenf (qp, Memc[deffilt])
}
# Open the default filter if one was found.
if (nchars > 0) {
call salloc (filter_text, nchars, TY_CHAR)
if (qp_gstr(qp,Memc[deffilt],Memc[filter_text],nchars) < nchars)
call syserrs (SYS_QPBADVAL, Memc[deffilt])
IO_EX(io) = qpex_open (qp, Memc[filter_text])
IO_EXCLOSE(io) = YES
}
}
# Fold in the user specified filter if one was given.
if (Memc[filter] != EOS) {
if (IO_EX(io) != NULL) {
if (qpex_modfilter (IO_EX(io), Memc[filter]) == ERR)
call fprintf (STDERR,
"Warning: error compiling QPIO filter\n")
} else {
IO_EX(io) = qpex_open (qp, Memc[filter])
IO_EXCLOSE(io) = YES
}
if (IO_DEBUG(io) > 0) {
call eprintf ("event attribute filter: %s\n")
call pargstr (Memc[filter])
}
}
# Open the region mask. This may be specified (named) in the parameter
# expression, else we try to open a default mask. If a mask is named,
# the name may be the name of a header parameter containing the mask
# as the stored array value (TY_OPAQUE parameter), the name of a header
# parameter containing the name of the mask (TY_CHAR), or the name of
# a mask storage file (.pl extension).
# Make a copy of the user mask name, as qpio_loadmask will clobber it.
call strcpy (Memc[mask], Memc[umask], SZ_FNAME)
if (IO_NODEFMASK(io) != YES) {
# Check for "defmask.<evl>" first, then "defmask".
call sprintf (Memc[defmask], SZ_FNAME, "%s.%s")
call pargstr (s_defmask)
call pargstr (Memc[param])
nchars = qp_lenf (qp, Memc[defmask])
if (nchars <= 0) {
call strcpy (s_defmask, Memc[defmask], SZ_FNAME)
nchars = qp_lenf (qp, Memc[defmask])
}
if (nchars > 0)
if (qp_gstr (qp, Memc[defmask], Memc[maskname], SZ_FNAME) > 0)
call qpio_loadmask (io, Memc[maskname], NO)
}
# Load user specified mask.
if (Memc[umask] != EOS)
call qpio_loadmask (io, Memc[umask], YES)
else if (IO_INDEXLEN(io) > 0)
call malloc (IO_RL(io), RL_LENELEM*2, TY_INT)
# Allocate the bucket buffer.
call malloc (IO_BP(io), IO_SZBBUCKET(io)/SZB_CHAR/SZ_SHORT, TY_SHORT)
done_
# If no default rect was specified, set default bounding box for
# reading to be the entire image.
if (IO_BBUSED(io) == NO) {
IO_VSDEF(io,1) = 1; IO_VSDEF(io,2) = 1
IO_VEDEF(io,1) = IO_NCOLS(io); IO_VEDEF(io,2) = IO_NLINES(io)
}
# Initialize the active BB to the default.
call amovi (IO_VSDEF(io,1), IO_VS(io,1), NDIM)
call amovi (IO_VEDEF(io,1), IO_VE(io,1), NDIM)
} then {
# We branch here if any nasty errors occur above. Cleanup and free
# the partially opened descriptor and pass the error on to whoever
# called us.
if (IO_BP(io) != NULL)
call mfree (IO_BP(io), TY_SHORT)
if (IO_RL(io) != NULL)
call mfree (IO_RL(io), TY_INT)
if (IO_PL(io) != NULL && IO_PLCLOSE(io) == YES)
call pl_close (IO_PL(io))
if (IO_EX(io) != NULL)
call qpex_close (IO_EX(io))
if (IO_YLENVP(io) != NULL)
call mfree (IO_YLENVP(io), TY_INT)
if (IO_YOFFVP(io) != NULL)
call mfree (IO_YOFFVP(io), TY_INT)
if (IO_MINEVL(io) != NULL)
call mfree (IO_MINEVL(io), TY_SHORT)
if (IO_MAXEVL(io) != NULL)
call mfree (IO_MAXEVL(io), TY_SHORT)
if (IO_FD(io) != NULL)
call close (IO_FD(io))
if (IO_MASK(io) != NULL)
call mfree (IO_MASK(io), TY_CHAR)
if (IO_PARAM(io) != NULL)
call mfree (IO_PARAM(io), TY_CHAR)
if (IO_DD(io) != NULL)
call mfree (IO_DD(io), TY_STRUCT)
if (filter != NULL)
call mfree (filter, TY_CHAR)
if (io != NULL)
call mfree (io, TY_STRUCT)
call erract (EA_ERROR)
}
# The filter can be regenerated, so don't keep the input expr around.
call mfree (filter, TY_CHAR)
# Normal exit for read-only access.
call sfree (sp)
return (io)
end
|