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
|
include <imio.h>
include <imhdr.h>
include <mii.h>
include <fset.h>
include <mach.h>
include <syserr.h>
include "fxf.h"
define MIN_BUFSIZE 2880
# FXF_EXPANDH -- Routine to expand all the headers of a MEF file. The calling
# routine only requires that extension 'group' be expanded but when dealing
# with large MEF files with many extensions this procedure can take a long
# time if the application code wants to expand more than one header.
# fxf_expandh will expand all the headers in the file so they will have at
# least 'nlines' blank cards.
procedure fxf_expandh (in_fd, out_fd, nlines, group, nbks, hdroff, pixoff)
int in_fd #I input file descriptor
int out_fd #I output file descriptor
int nlines #I minimum number of blank cards
int group #I group that initiated the expansion
int nbks #I numbers of blocks to expand group 'group'
int hdroff #O new offset for beginning of 'group'
int pixoff #0 new offset for beginning of data
pointer hd, ip, op, buf
char line[80], endl[80]
int gn, newc, k, nchars, nbk, hsize
int fxf_xaddl(), read()
int bufsize, psize, rem, hoffset, poffset
int note(), fstati()
errchk malloc, read, write
begin
# In case nlines is zero set a minimum > 0.
nlines = max (nlines, 10)
# Initialize a blank line.
call amovks (" ", line, LEN_CARD)
# Initialize END card image.
call amovc ("END", endl, 3)
call amovks (" ", endl[4], LEN_CARD-3)
call fseti (in_fd, F_ADVICE, SEQUENTIAL)
call fseti (out_fd, F_ADVICE, SEQUENTIAL)
bufsize = max (MIN_BUFSIZE, fstati (in_fd, F_BUFSIZE))
call malloc (buf, bufsize, TY_CHAR)
gn = 0
hd = buf
repeat {
hd = buf
if (group == gn)
hdroff = note(out_fd)
# Read and write header information. The last block must
# have the END card and is output from this routine.
iferr (call fxf_xhrd (in_fd, out_fd, Memc[buf], bufsize, hoffset,
poffset, hsize))
break
# Determine the number of cards to expand. newc is in blocks
# of 36 cards. 0, 36, 72, ...
newc = fxf_xaddl (buf, hsize, nlines)
# expand the given group at least one block
if (newc == 0 && nbks > 0 && group == gn)
newc = nbks * 36
# OP points to the top of the last block read, IP to the bottom.
op = buf + hsize - FITS_BLOCK_BYTES
ip = buf + hsize
if (newc == 0) {
# Leave space for the END card.
ip = ip - 80
} else {
# Write current buffer before writing blanks.
call miipak (Memc[op], Memc[op], FITS_BLOCK_BYTES,
TY_CHAR,MII_BYTE)
call write (out_fd, Memc[op], FITS_BLOCK_CHARS)
# Use the same buffer space since we are using blanks
ip = ip - FITS_BLOCK_BYTES
op = ip
}
# Write the blank cards.
do k = 1, newc-1 {
call amovc (line, Memc[ip], LEN_CARD)
ip = ip + LEN_CARD
if (mod (k,36) == 0) {
# We have more than one block of blanks.
call miipak (Memc[op], Memc[op], nchars, TY_CHAR, MII_BYTE)
call write (out_fd, Memc[op], FITS_BLOCK_CHARS)
# Notice we used the same buffer space
ip = ip - FITS_BLOCK_BYTES
op = ip
}
}
# Finally the END card.
call amovc (endl, Memc[ip], LEN_CARD)
nchars = 2880
call miipak (Memc[op], Memc[op], nchars, TY_CHAR, MII_BYTE)
call write (out_fd, Memc[op], nchars/2)
# Get the number of blocks of pixel data to copy. We are not
# changing anything; it is straight copy.
psize = (hoffset - poffset)
nbk = psize / bufsize
rem = mod(psize,bufsize)
if (group == gn)
pixoff = note(out_fd)
do k = 1, nbk {
nchars = read (in_fd, Memc[buf], bufsize)
call write (out_fd, Memc[buf], bufsize)
}
if (rem > 0) {
nchars = read (in_fd, Memc[buf], rem)
call write (out_fd, Memc[buf], rem)
}
gn = gn + 1
}
call mfree (buf, TY_CHAR)
end
# FXF_XHRD -- Procedure to read 2880 bytes blocks of header from 'in'
# and copy them to 'out'. The last block read contains the END card
# and is pass to the calling routine which will write it out to 'out.
procedure fxf_xhrd (in, out, buf, bufsize, hoffset, poffset, hsize)
int in #I Input file descriptor
int out #I output file descriptor
char buf[ARB] #I Working buffer
int bufsize #I Workign buffer size
int hoffset #O Header offset for next group
int poffset #O Data offset for current group
int hsize #O Number of cards read in header
pointer sp, hb
int nblks, totpix, i, j, ip, nchars
int strncmp(), note(), read()
bool end_card, fxf_xn_decode_blk1()
include "fxfcache.com"
errchk syserr, read, write
begin
call smark (sp)
call salloc (hb, 1440, TY_CHAR)
hoffset = note (in)
# Read first block of header.
nchars = read (in, Memc[hb], FITS_BLOCK_CHARS)
if (nchars == EOF) {
call sfree (sp)
call syserr (SYS_FXFRFEOF)
}
call miiupk (Memc[hb], buf, FITS_BLOCK_BYTES, MII_BYTE,TY_CHAR)
end_card = fxf_xn_decode_blk1 (buf, totpix)
if (!end_card) {
call miipak (buf, Memc[hb], FITS_BLOCK_BYTES, TY_CHAR, MII_BYTE)
call write (out, Memc[hb], FITS_BLOCK_CHARS)
}
ip = FITS_BLOCK_BYTES + 1
nblks = 1
if (!end_card) {
# Continue reading header until the block with END
# which is the last before the data block.
while (read (in, Memc[hb], FITS_BLOCK_CHARS) != EOF) {
call miiupk (Memc[hb], buf[ip], FITS_BLOCK_BYTES,
MII_BYTE,TY_CHAR)
# Look for the END card
do i = 0, 35 {
j = ip + i*LEN_CARD
if (buf[j] == 'E') {
if (strncmp (buf[j], "END ", 8) == 0)
end_card = true
}
}
nblks = nblks + 1
if (end_card)
break
call miipak (buf[ip], Memc[hb], FITS_BLOCK_BYTES,
TY_CHAR, MII_BYTE)
call write (out, Memc[hb], FITS_BLOCK_CHARS)
ip = ip + FITS_BLOCK_BYTES
# If the header is really big we can run out of
# buffer space. Revert back to the beginning.
if (ip > bufsize) {
ip = 1
nblks = 1
}
}
}
hsize = nblks * 36 * LEN_CARD
# We are at the beginning of the pixel area.
poffset = note (in)
# Get the beginnning of the next header.
hoffset = poffset + totpix
call sfree (sp)
end
# FXF_XN_DECODE_BLK1 -- Function that return true if the 1st block of a header
# contains the END card. The size of the pixel are is also returned.
bool procedure fxf_xn_decode_blk1 (buf, datalen)
char buf[ARB] #I header data buffer
int datalen #O length of data area in chars
char card[LEN_CARD]
int totpix, nbytes, index, k, i, pcount, bitpix, naxis, ip
int len_axis[7]
int fxf_ctype()
bool end_card
errchk syserr, syserrs
begin
# Read successive lines of the 1st header block
pcount = 0
end_card = false
do k = 0, 35 {
ip = k*LEN_CARD + 1
# Copy into a one line buffer, we need to EOS mark.
call strcpy (buf[ip], card, LEN_CARD)
switch (fxf_ctype (card, index)) {
case KW_END:
end_card = true
break
case KW_PCOUNT:
call fxf_geti (card, pcount)
case KW_BITPIX:
call fxf_geti (card, bitpix)
case KW_NAXIS:
if (index == 0) {
call fxf_geti (card, naxis)
if (naxis < 0 )
call syserr (SYS_FXFRFBNAXIS)
} else
call fxf_geti (card, len_axis[index])
default:
;
}
}
# Calculate the length of the data area of the current extension,
# measured in SPP chars and rounded up to an integral number of FITS
# logical blocks.
if (naxis != 0) {
totpix = len_axis[1]
do i = 2, naxis
totpix = totpix * len_axis[i]
# Compute the size of the data area (pixel matrix plus PCOUNT)
# in bytes. Be careful not to overflow a 32 bit integer.
nbytes = (totpix + pcount) * (abs(bitpix) / NBITS_BYTE)
# Round up to fill the final 2880 byte FITS logical block.
nbytes = ((nbytes + 2880-1) / 2880) * 2880
datalen = nbytes / SZB_CHAR
} else
datalen = 0
return (end_card)
end
# FXF_XADDL -- Algorithm to find the number of blank cards stored in the
# input buffer. This is the number from the end of the buffer up to the
# last non blank card (excluding the END card). The function returns the
# number of extra header cards (in multiple of 36) that is necessary to
# add to the current header.
int procedure fxf_xaddl (hd, ncua, nlines)
pointer hd #U header area pointer
int ncua #I number of characters in the user area
int nlines #I minimum number of header lines to be added
int ip, nbc, k, ncards, nkeyw
int strncmp()
begin
# Go to the end of buffer and get last line pointer
ip = hd + ncua - LEN_CARD
# See if line is blank.
nbc = 0
while (ip > hd) {
# Check for nonblank card
do k = 0, LEN_CARD-1
if (Memc[ip+k] != ' ')
break
# Since we are counting from the bottom, the first keyword
# (except END) would end counting.
if (k != LEN_CARD && k != 0) # nonblank keyw card reached
break
else if (k == 0) {
# Just bypass END and continue looking for blank cards
if (strncmp ("END ", Memc[ip], 8) == 0) {
# Clear this card as it will be written at the
# end of the output header.
call amovkc (" ", Memc[ip], LEN_CARD)
ip = ip - LEN_CARD
next
} else
break
} else
nbc = nbc + 1
ip = ip - LEN_CARD
}
# Calculate the number of keywords right before the last blank
# card and right after the last non-blank keyword, excluding the
# END card
nkeyw = (ip-hd)/80 + 1
ncards = ncua / LEN_CARD
# Calculate the complement with respect to 36
ncards = ((ncards + 35)/36)*36 - ncards
nbc = nbc + ncards
if (nbc < nlines) {
# Lets add nlines-nbc cards to the header
ncards = nlines - nbc
# Adjust to a 36 cards boundary.
ncards = 36 - mod (ncards, 36) + ncards
} else
ncards = 0
return (ncards)
end
|