1 /*
2 fitskey.c
3
4 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 *
6 * Part of: The LDAC Tools
7 *
8 * Author: E.BERTIN, DeNIS/LDAC
9 *
10 * Contents: Functions related to the management of keys.
11 *
12 * Last modify: 15/08/2003
13 *
14 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "fitscat_defs.h"
26 #include "fitscat.h"
27
28 /****** add_key ****************************************************************
29 PROTO int add_key(keystruct *key, tabstruct *tab, int pos)
30 PURPOSE Copy a key from one table to another.
31 INPUT Pointer to the key,
32 Pointer to the table,
33 Pointer to the destination table,
34 Position (1= first, <=0 = at the end)
35 OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
36 NOTES A preexisting key in the destination table yields a RETURN_ERROR.
37 AUTHOR E. Bertin (IAP & Leiden observatory)
38 VERSION 26/03/96
39 ***/
add_key(keystruct * key,tabstruct * tab,int pos)40 int add_key(keystruct *key, tabstruct *tab, int pos)
41
42 {
43
44 /*Check if a similar key doesn't already exist in the dest. cat */
45 if (name_to_key(tab, key->name))
46 return RETURN_ERROR;
47
48 /*Update links (portion of code similar to that of copy_key below) */
49 if ((key->nextkey = pos_to_key(tab, pos)))
50 {
51 (key->prevkey = key->nextkey->prevkey)->nextkey = key;
52 key->nextkey->prevkey = key;
53 /*--the first place has a special meaning*/
54 if (pos==1)
55 tab->key = key;
56 }
57 else
58 /*There was no no key before*/
59 tab->key = key->nextkey = key->prevkey = key;
60
61 tab->nkey++;
62
63 return RETURN_OK;
64 }
65
66
67 /****** blank_keys *************************************************************
68 PROTO int blank_keys(tabstruct *tab)
69 PURPOSE Put the array pointers from all keys in a table to NULL.
70 INPUT Pointer to the table.
71 OUTPUT RETURN_OK if keys were found, and RETURN_ERROR otherwise.
72 Notes: -.
73 AUTHOR E. Bertin (IAP & Leiden observatory)
74 VERSION 25/04/97
75 ***/
blank_keys(tabstruct * tab)76 int blank_keys(tabstruct *tab)
77
78 {
79 keystruct *key;
80 int k;
81
82 if (!(key = tab->key))
83 return RETURN_ERROR;
84
85 for (k=tab->nkey; k--;)
86 {
87 key->ptr = NULL;
88 key = key->nextkey;
89 }
90
91 return RETURN_OK;
92 }
93
94
95 /****** copy_key ***************************************************************
96 PROTO int copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos)
97 PURPOSE Copy a key from one table to another.
98 INPUT Pointer to the original table,
99 Name of the key,
100 Pointer to the destination table,
101 Position (1= first, <=0 = at the end)
102 OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
103 NOTES A preexisting key in the destination table yields a RETURN_ERROR,
104 the ptr member is NOT COPIED.
105 AUTHOR E. Bertin (IAP & Leiden observatory)
106 VERSION 19/08/96
107 ***/
copy_key(tabstruct * tabin,char * keyname,tabstruct * tabout,int pos)108 int copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos)
109
110 {
111 keystruct *keyin, *keyout;
112
113 /*Convert the key name to a pointer*/
114 if (!(keyin = name_to_key(tabin, keyname)))
115 return RETURN_ERROR;
116
117 /*Check if a similar key doesn't already exist in the dest. cat */
118 if (name_to_key(tabout, keyname))
119 return RETURN_ERROR;
120
121 tabout->nkey++;
122
123 /*First, allocate memory and copy data */
124 QCALLOC(keyout, keystruct, 1);
125 *keyout = *keyin;
126 keyout->ptr = NULL;
127 if (keyin->naxis)
128 QMEMCPY(keyin->naxisn, keyout->naxisn, int, keyin->naxis);
129
130 /*Then, update the links */
131 if ((keyout->nextkey = pos_to_key(tabout, pos)))
132 {
133 (keyout->prevkey = keyout->nextkey->prevkey)->nextkey = keyout;
134 keyout->nextkey->prevkey = keyout;
135 /*--the first place has a special meaning*/
136 if (pos==1)
137 tabout->key = keyout;
138 }
139 else
140 /*There was no no key before*/
141 tabout->key = keyout->nextkey = keyout->prevkey = keyout;
142
143 return RETURN_OK;
144 }
145
146
147 /****** free_key ***************************************************************
148 PROTO void free_key(keystruct *key)
149 PURPOSE Free memory associated to a key ptr.
150 INPUT Pointer to the key.
151 OUTPUT -.
152 NOTES -.
153 AUTHOR E. Bertin (IAP & Leiden observatory)
154 VERSION 19/08/96
155 ***/
free_key(keystruct * key)156 void free_key(keystruct *key)
157
158 {
159 free(key->naxisn);
160 free(key->ptr);
161 free(key);
162
163 return;
164 }
165
166
167 /****** new_key ****************************************************************
168 PROTO keystruct *new_key(char *keyname)
169 PURPOSE Create a new key.
170 INPUT Name of the key.
171 OUTPUT A pointer to the new keystruct.
172 NOTES This function is only provided as a counterpart to new_tab() and
173 new_cat(): in order to be usable, other key parameters MUST be
174 handled by the user.
175 AUTHOR E. Bertin (IAP & Leiden observatory)
176 VERSION 26/03/96
177 ***/
new_key(char * keyname)178 keystruct *new_key(char *keyname)
179
180 {
181 keystruct *key;
182
183 QCALLOC(key, keystruct, 1);
184 strcpy(key->name, keyname);
185
186 return key;
187 }
188
189
190 /****** read_key ***************************************************************
191 PROTO keystruct *read_key(tabstruct *tab, char *keyname)
192 PURPOSE Read one simple column from a FITS binary table.
193 INPUT pointer to the table,
194 name of the key,
195 OUTPUT A pointer to the relevant key, or NULL if the desired key is not
196 found in the table.
197 NOTES If key->ptr is not NULL, the function doesn't do anything.
198 AUTHOR E. Bertin (IAP & Leiden observatory)
199 E.R. Deul (Sterrewacht Leiden) (Added open_cat error checking)
200 VERSION 18/02/2000
201 ***/
read_key(tabstruct * tab,char * keyname)202 keystruct *read_key(tabstruct *tab, char *keyname)
203
204 {
205 catstruct *cat;
206 keystruct *key;
207 char *buf, *ptr, *fptr,*fptr0;
208 int i,j, larray,narray,size;
209 int esize;
210
211 if (!(key = name_to_key(tab, keyname)))
212 return NULL;
213
214 /*If ptr is not NULL, there is already something loaded there: let's free mem */
215 QFREE(key->ptr);
216
217 /*!! It is not necessarily the original table */
218 tab = key->tab;
219 cat = tab->cat;
220
221 /*We are expecting a 2D binary-table, and nothing else*/
222 if ((tab->naxis != 2)
223 || (tab->bitpix!=8)
224 || (tab->tfields == 0)
225 || strncmp(tab->xtension, "BINTABLE", 8))
226 error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename);
227
228 /*Size and number of lines in the binary table*/
229 larray = tab->naxisn[0];
230 narray = tab->naxisn[1];
231
232 /*Positioning to the first element*/
233 if (open_cat(cat, READ_ONLY) == RETURN_ERROR)
234 error(EXIT_FAILURE, "*Error*: opening catalog ",cat->filename);
235 QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename);
236
237 /*allocate memory for the buffer where we put one line of data*/
238 QMALLOC(buf, char, larray);
239
240 fptr0 = buf+key->pos;
241 size = key->nbytes;
242
243 /*allocate memory for the array*/
244 QMALLOC(ptr, char, size*narray);
245 key->ptr = ptr;
246
247 /*read line by line*/
248 for (i=narray; i--;)
249 {
250 QFREAD(buf, larray, cat->file, cat->filename);
251 fptr = fptr0;
252 if (bswapflag)
253 {
254 esize = t_size[key->ttype];
255 swapbytes(fptr0, esize, size/esize);
256 }
257 for (j = size; j--;)
258 *(ptr++) = *(fptr++);
259 }
260
261 free(buf);
262 return key;
263 }
264
265
266 /****** read_keys **************************************************************
267 PURPOSE Read several columns from a FITS binary table.
268 INPUT pointer to the table,
269 pointer to an array of char *,
270 pointer to an array of keystruct * (memory must have been allocated),
271 number of keys to read,
272 an optional mask pointer.
273 OUTPUT -.
274 NOTES The array of pointers pointed by keys is filled with pointers
275 to the relevant keys (a NULL means NO key with such name was found).
276 A NULL keys pointer can be given (no info returned of course).
277 A NULL keynames pointer means read ALL keys belonging to the table.
278 A NULL mask pointer means NO selection for reading.
279 AUTHOR E. Bertin (IAP & Leiden observatory)
280 VERSION 18/02/2000
281 ***/
read_keys(tabstruct * tab,char ** keynames,keystruct ** keys,int nkeys,BYTE * mask)282 void read_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys,
283 BYTE *mask)
284
285 {
286 catstruct *cat;
287 keystruct *key, **ckeys;
288 BYTE *mask2;
289 char *buf, *ptr, *fptr;
290 int i,j,k,n, larray,narray, nb, kflag = 0, size;
291 int esize;
292
293 /*!! It is not necessarily the original table */
294 tab = tab->key->tab;
295 cat = tab->cat;
296
297 /*We are expecting a 2D binary-table, and nothing else*/
298 if ((tab->naxis != 2)
299 || (tab->bitpix!=8)
300 || (tab->tfields == 0)
301 || strncmp(tab->xtension, "BINTABLE", 8))
302 error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename);
303
304 /*Size and number of lines in the binary table*/
305 larray = tab->naxisn[0];
306 narray = tab->naxisn[1];
307
308 nb = 0;
309 if ((mask2 = mask))
310 {
311 for (i=narray; i--;)
312 if (*(mask2++))
313 nb++;
314 }
315
316 if (!keynames)
317 nkeys = tab->nkey;
318
319 /*Allocate memory to store the list of keys to be read */
320 if (!keys)
321 {
322 QMALLOC(keys, keystruct *, nkeys);
323 kflag = 1;
324 }
325
326 /*allocate memory for the arrays*/
327 ckeys = keys;
328 if (keynames)
329 for (i=nkeys; i--;)
330 {
331 if ((key = name_to_key(tab, *(keynames++))))
332 {
333 QFREE(key->ptr);
334 if (nb)
335 key->nobj = nb;
336 else
337 nb=key->nobj;
338 QMALLOC(key->ptr, char, key->nbytes*nb);
339 *(ckeys++) = key;
340 }
341 else
342 *(ckeys++) = NULL;
343 }
344 else
345 {
346 key = tab->key;
347 for (i=nkeys; i--;)
348 {
349 QFREE(key->ptr);
350 if (nb)
351 key->nobj = nb;
352 else
353 nb=key->nobj;
354 QMALLOC(key->ptr, char, key->nbytes*nb);
355 *(ckeys++) = key;
356 key = key->nextkey;
357 }
358 }
359
360 /*allocate memory for the buffer where we put one line of data*/
361 QMALLOC(buf, char, larray);
362
363 /*Positioning to the first element*/
364 open_cat(cat, READ_ONLY);
365 QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename);
366
367 /*read line by line*/
368 n = 0;
369 mask2 = mask;
370 for (i=narray; i--;)
371 {
372 QFREAD(buf, larray, cat->file, cat->filename);
373 if (!mask || *(mask2++))
374 {
375 ckeys = keys;
376 for (j=nkeys; j--;)
377 if ((key = *(ckeys++)))
378 {
379 fptr = buf+key->pos;
380 ptr = (char *)key->ptr+n*(size=key->nbytes);
381 if (bswapflag)
382 {
383 esize = t_size[key->ttype];
384 swapbytes(fptr, esize, size/esize);
385 }
386 for (k = size; k--;)
387 *(ptr++) = *(fptr++);
388 }
389 n++;
390 }
391 }
392
393 free(buf);
394 if (kflag)
395 free(keys);
396
397 return;
398 }
399
400 /****** remove_key *************************************************************
401 PROTO int remove_key(tabstruct *tab, char *keyname)
402 PURPOSE Remove a key from a table.
403 INPUT Pointer to the table,
404 Name of the key.
405 OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
406 NOTES If keyname = "", the last key from the list is removed.
407 AUTHOR E. Bertin (IAP & Leiden observatory)
408 VERSION 15/01/97
409 ***/
remove_key(tabstruct * tab,char * keyname)410 int remove_key(tabstruct *tab, char *keyname)
411
412 {
413 keystruct *key, *prevkey, *nextkey;
414
415 if (!keyname || !tab->nkey || !tab->key)
416 return RETURN_ERROR;
417
418 if (keyname[0])
419 {
420 /*--Convert the key name to a pointer*/
421 if (!(key = name_to_key(tab, keyname)))
422 return RETURN_ERROR;
423 }
424 else
425 key = tab->key->prevkey;
426
427 prevkey = key->prevkey;
428 /*Free memory*/
429 nextkey = key->nextkey;
430 if (tab->key==key)
431 tab->key = nextkey;
432 free_key(key);
433
434 if (--tab->nkey)
435 {
436 /*--update the links of neighbours*/
437 nextkey->prevkey = prevkey;
438 prevkey->nextkey = nextkey;
439 }
440 else
441 tab->key = NULL;
442
443 return RETURN_OK;
444 }
445
446
447 /****** remove_keys ************************************************************
448 PROTO int remove_keys(tabstruct *tab)
449 PURPOSE Remove all keys from a table.
450 INPUT Pointer to the table.
451 OUTPUT RETURN_OK if keys were found, and RETURN_ERROR otherwise.
452 NOTES -.
453 AUTHOR E. Bertin (IAP & Leiden observatory)
454 VERSION 13/03/99
455 ***/
remove_keys(tabstruct * tab)456 int remove_keys(tabstruct *tab)
457
458 {
459 int k;
460
461 if (!tab->key)
462 return RETURN_ERROR;
463
464 for (k=tab->nkey; k--;)
465 remove_key(tab, "");
466
467 return RETURN_OK;
468 }
469
470
471 /****** name_to_key ************************************************************
472 PROTO keystruct *name_to_key(tabstruct *tab, char *keyname)
473 PURPOSE Name search of a key in a table.
474 INPUT Pointer to the table,
475 Key name.
476 OUTPUT The key pointer if the name was matched, and NULL otherwise.
477 NOTES -.
478 AUTHOR E. Bertin (IAP & Leiden observatory)
479 VERSION 25/04/97
480 ***/
name_to_key(tabstruct * tab,char * keyname)481 keystruct *name_to_key(tabstruct *tab, char *keyname)
482
483 {
484 keystruct *key;
485 int i;
486
487 if (!(key=tab->key))
488 return NULL;
489
490 for (i=tab->nkey; strcmp(keyname, key->name) && i--; key=key->nextkey);
491
492 return i<0? NULL:key;
493 }
494
495 /****** keys_list **************************************************************
496 PROTO char **keys_list(catstruct *tab, int *n)
497 PURPOSE List all keys in a table.
498 INPUT Pointer to the table,
499 Pointer to the number of names in that list.
500 OUTPUT A list of all key names.
501 NOTES -.
502 AUTHOR E.R. Deul (Leiden observatory)
503 VERSION ??/??/96
504 ***/
keys_list(tabstruct * tab,int * n)505 char **keys_list(tabstruct *tab, int *n)
506
507 {
508 keystruct *key;
509 int i;
510 char **names;
511
512 QCALLOC(names, char *, tab->nkey);
513 key = tab->key;
514 for (i=0; i<tab->nkey; i++) {
515 QCALLOC(names[i], char, MAXCHARS);
516 strcpy(names[i],key->name);
517 key = key->nextkey;
518 }
519 *n = tab->nkey;
520 return names;
521 }
522
523
524 /****** pos_to_key *************************************************************
525 PROTO keystruct *pos_to_key(tabstruct *tab, int pos)
526 PURPOSE Position search of a key in a table.
527 INPUT Pointer to the table,
528 Position of the key.
529 OUTPUT The key pointer if a key exists at the given position, and the
530 pointer to the first key otherwise.
531 NOTES pos = 0 or 1 means the first key.
532 AUTHOR E. Bertin (IAP & Leiden observatory)
533 VERSION 20/03/96
534 ***/
pos_to_key(tabstruct * tab,int pos)535 keystruct *pos_to_key(tabstruct *tab, int pos)
536
537 {
538 keystruct *key;
539 int i;
540
541 if (!(key=tab->key))
542 return NULL;
543
544 if ((pos--)==1)
545 return tab->key;
546
547 for (i=0; i!=pos && i<tab->nkey; i++, key=key->nextkey);
548
549 return i<tab->nkey?key:tab->key;
550 }
551
552
553 /****** show_keys **************************************************************
554 PROTO void show_keys(tabstruct *tab, char **keynames,
555 keystruct **keys, int nkeys,
556 BYTE *mask, FILE *stream,
557 int strflag, int banflag, int leadflag,
558 output_type o_type)
559 PURPOSE Convert a binary table to an ASCII file.
560 INPUT pointer to the table,
561 pointer to an array of char *,
562 pointer to an array of keystruct * (memory must have been allocated),
563 number of keys to read,
564 an optional mask pointer,
565 a stream,
566 a flag to indicate if arrays should be displayed (0=NO),
567 a flag to indicate if a banner with keynames should be added (0=NO).
568 a flag to indicate if a leading row number should be added (0=NO).
569 the output type
570 OUTPUT -.
571 NOTES This is approximately the same code as for read_keys.
572 The array of pointers pointed by keys is filled with pointers
573 to the relevant keys (a NULL means NO key with such name was found).
574 A NULL keys pointer can be given (no info returned of course).
575 A NULL keynames pointer means read ALL keys belonging to the table.
576 A NULL mask pointer means NO selection for reading.
577 AUTHOR E. Bertin (IAP & Leiden observatory)
578 VERSION 15/08/2003
579 ***/
show_keys(tabstruct * tab,char ** keynames,keystruct ** keys,int nkeys,BYTE * mask,FILE * stream,int strflag,int banflag,int leadflag,output_type o_type)580 void show_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys,
581 BYTE *mask, FILE *stream,
582 int strflag, int banflag, int leadflag, output_type o_type)
583
584 {
585 catstruct *cat;
586 keystruct *key, **ckeys;
587 BYTE *mask2;
588 char *buf, *rfield, *ptr;
589 int i,j,k,n,c, larray,narray, nb, kflag, maxnbytes, nelem,
590 esize, *key_col;
591 typedef struct structreq_keyname
592 {
593 char oldname[80]; /* Name of the original pipeline key */
594 char newname[80]; /* Name of the skycat required key */
595 } req_keynamestruct;
596
597 req_keynamestruct objectmap[] =
598 {
599 {"SeqNr", "id"},
600 {"Ra", "ra"},
601 {"Dec", "dec"},
602 {"MAG_ISO", "Mag"},
603 {"", ""}
604 };
605 req_keynamestruct *map;
606
607 char skycathead[] = "QueryResult\n\n"
608 "# Config entry for original catalog server:\n"
609 "serv_type: catalog\n"
610 "long_name: ldactoskycat catalog\n"
611 "short_name: ldactoaskycat\n"
612 "symbol: id circle %4.1f\n"
613 "search_cols: mag {Brightest (min)} {Faintest (max)}\n"
614 "# End config entry\n\n";
615
616 char *t, skycattail[] = "";
617
618
619 /* !! It is not necessarily the original table */
620 if (tab->key)
621 tab = tab->key->tab;
622 cat = tab->cat;
623
624 /* We are expecting a 2D binary-table, and nothing else */
625 if ((tab->naxis != 2)
626 || (tab->bitpix!=8)
627 || (tab->tfields == 0)
628 || strncmp(tab->xtension, "BINTABLE", 8))
629 error(EXIT_FAILURE, "*Error*: Not a binary table in ", cat->filename);
630
631 /* Size and number of lines in the binary table */
632 larray = tab->naxisn[0];
633 narray = tab->naxisn[1];
634
635 nb = 0;
636 if ((mask2 = mask))
637 {
638 for (i=narray; i--;)
639 if (*(mask2++))
640 nb++;
641 }
642
643 if (!keynames)
644 nkeys = tab->nkey;
645 QCALLOC(key_col, int, nkeys);
646 if (keynames) {
647 for (i=0;i<nkeys;i++)
648 if ((t=strchr(keynames[i], ')'))!=NULL) {
649 *t='\0';
650 t=strchr(keynames[i], '(');
651 *t='\0';
652 key_col[i] = atoi(++t);
653 }
654 }
655 /* Allocate memory to store the list of keys to be read */
656 kflag = 0;
657 if (!keys)
658 {
659 QMALLOC(keys, keystruct *, nkeys);
660 kflag = 1;
661 }
662
663 n=1;
664 switch (o_type) {
665 case SHOW_ASCII:
666 if (leadflag)
667 fprintf(stream, "# %3d %-15.15s %.47s\n", n++,
668 "(row_pos)", "running row");
669 break;
670 case SHOW_SKYCAT:
671 fprintf(stream, skycathead, 6.0);
672 break;
673 }
674
675 /* Allocate memory for the arrays */
676 maxnbytes = 0;
677 ckeys = keys;
678 if (keynames)
679 for (i=nkeys; i--;)
680 {
681 if ((key = name_to_key(tab, *(keynames++))))
682 {
683 for (map=objectmap; map->oldname[0]&&o_type == SHOW_SKYCAT; map++) {
684 if (strcmp(key->name, map->oldname) == 0) {
685 strcpy(key->name, map->newname);
686 }
687 }
688 *(ckeys++) = key;
689 switch (o_type) {
690 case SHOW_ASCII:
691 if (banflag)
692 {
693 if (*key->unit)
694 fprintf(stream, "# %3d %-19.19s %-47.47s [%s]\n",
695 n, key->name,key->comment, key->unit);
696 else
697 fprintf(stream, "# %3d %-19.19s %.47s\n",
698 n, key->name,key->comment);
699 n += key->nbytes/t_size[key->ttype];
700 }
701 break;
702 case SHOW_SKYCAT:
703 if (key->nbytes/t_size[key->ttype] > 1)
704 for (j=0;j<key->nbytes/t_size[key->ttype];j++)
705 fprintf(stream, "%s(%d)\t", key->name,j+1);
706 else
707 fprintf(stream, "%s\t", key->name);
708 break;
709 }
710 if (key->nbytes>maxnbytes)
711 maxnbytes = key->nbytes;
712 }
713 else
714 *(ckeys++) = NULL;
715 }
716 else
717 {
718 key = tab->key;
719 for (i=nkeys; i--; key = key->nextkey)
720 if (strflag || key->naxis==0)
721 {
722 for (map=objectmap; map->oldname[0]&&o_type == SHOW_SKYCAT; map++) {
723 if (strcmp(key->name, map->oldname) == 0) {
724 strcpy(key->name, map->newname);
725 }
726 }
727 *(ckeys++) = key;
728 switch (o_type) {
729 case SHOW_ASCII:
730 if (banflag)
731 {
732 if (*key->unit)
733 fprintf(stream, "# %3d %-19.19s %-47.47s [%s]\n",
734 n, key->name,key->comment, key->unit);
735 else
736 fprintf(stream, "# %3d %-19.19s %.47s\n",
737 n, key->name,key->comment);
738 n += key->nbytes/t_size[key->ttype];
739 }
740 break;
741 case SHOW_SKYCAT:
742 if (key->nbytes/t_size[key->ttype] > 1)
743 for (j=0;j<key->nbytes/t_size[key->ttype];j++)
744 fprintf(stream, "%s(%d)\t", key->name,j+1);
745 else
746 fprintf(stream, "%s\t", key->name);
747 break;
748 }
749 if (key->nbytes>maxnbytes)
750 maxnbytes = key->nbytes;
751 }
752 else
753 {
754 switch (o_type) {
755 case SHOW_ASCII:
756 if (*key->unit)
757 fprintf(stream, "# %-19.19s %-47.47s [%s]\n",
758 key->name,key->comment, key->unit);
759 else
760 fprintf(stream, "# %-19.19s %.47s\n",
761 key->name,key->comment);
762 break;
763 case SHOW_SKYCAT:
764 break;
765 }
766 *(ckeys++) = NULL;
767 }
768 }
769 if (o_type == SHOW_SKYCAT)
770 fprintf(stream, "\n------------------\n");
771
772 /* Allocate memory for the buffer where we put one line of data */
773 QMALLOC(buf, char, larray);
774
775 /* Allocate memory for the buffer where we put one element */
776 QMALLOC(rfield, char, maxnbytes);
777
778 /* Positioning to the first element */
779 open_cat(cat, READ_ONLY);
780 QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename);
781
782 /*read line by line*/
783 n = 0;
784 mask2 = mask;
785 for (i=narray; i--;)
786 {
787 QFREAD(buf, larray, cat->file, cat->filename);
788 if (!mask || *(mask2++))
789 {
790 ckeys = keys;
791 if (leadflag)
792 {
793 fprintf(stream, "%d", ++n);
794 if (nkeys)
795 putc(' ', stream);
796 }
797 for (k=0; k<nkeys; k++)
798 {
799 if ((key = *(ckeys++)) && (strflag || key->naxis==0))
800 {
801 ptr = memcpy(rfield, buf+key->pos, key->nbytes);
802 esize = t_size[key->ttype];
803 nelem = key->nbytes/esize;
804 if (bswapflag)
805 swapbytes(ptr, esize, nelem);
806 switch(key->ttype)
807 {
808 case T_SHORT:
809 for (j = 0; j<nelem; j++, ptr += esize)
810 {
811 if (key_col[k] == 0 || key_col[k] == j+1) {
812 fprintf(stream, *key->printf?key->printf:"%d",
813 *(short *)ptr);
814 if (j < nelem-1) {
815 switch (o_type) {
816 case SHOW_ASCII:
817 putc(' ', stream);
818 break;
819 case SHOW_SKYCAT:
820 putc('\t', stream);
821 break;
822 }
823 }
824 }
825 }
826 break;
827
828 case T_LONG:
829 for (j = 0; j<nelem; j++,ptr += esize)
830 {
831 if (key_col[k] == 0 || key_col[k] == j+1) {
832 fprintf(stream, *key->printf?key->printf:"%d",
833 *(int *)ptr);
834 if (j < nelem-1) {
835 switch (o_type) {
836 case SHOW_ASCII:
837 putc(' ', stream);
838 break;
839 case SHOW_SKYCAT:
840 putc('\t', stream);
841 break;
842 }
843 }
844 }
845 }
846 break;
847
848 case T_FLOAT:
849 for (j = 0; j<nelem; j++,ptr += esize)
850 {
851 if (key_col[k] == 0 || key_col[k] == j+1) {
852 fprintf(stream, *key->printf?key->printf:"%g",
853 *(float *)ptr);
854 if (j < nelem-1) {
855 switch (o_type) {
856 case SHOW_ASCII:
857 putc(' ', stream);
858 break;
859 case SHOW_SKYCAT:
860 putc('\t', stream);
861 break;
862 }
863 }
864 }
865 }
866 break;
867
868 case T_DOUBLE:
869 for (j = 0; j<nelem; j++,ptr += esize)
870 {
871 if (key_col[k] == 0 || key_col[k] == j+1) {
872 fprintf(stream, *key->printf?key->printf:"%f",
873 *(double *)ptr);
874 if (j < nelem-1) {
875 switch (o_type) {
876 case SHOW_ASCII:
877 putc(' ', stream);
878 break;
879 case SHOW_SKYCAT:
880 putc('\t', stream);
881 break;
882 }
883 }
884 }
885 }
886 break;
887
888 case T_BYTE:
889 if (key->htype==H_BOOL)
890 for (j = 0; j<nelem; j++,ptr += esize)
891 {
892 if (key_col[k] == 0 || key_col[k] == j+1) {
893 if (*(char *)ptr)
894 fprintf(stream, "T");
895 else
896 fprintf(stream, "F");
897 }
898 }
899 else
900 for (j = 0; j<nelem; j++,ptr += esize)
901 {
902 if (key_col[k] == 0 || key_col[k] == j+1) {
903 fprintf(stream, *key->printf?key->printf:"%d",
904 (int)*((unsigned char *)ptr));
905 if (j) {
906 switch (o_type) {
907 case SHOW_ASCII:
908 putc(' ', stream);
909 break;
910 case SHOW_SKYCAT:
911 putc('\t', stream);
912 break;
913 }
914 }
915 }
916 }
917 break;
918
919 case T_STRING:
920 for (j = nelem; j-- && (c=(int)*ptr); ptr += esize)
921 fprintf(stream, "%c", c);
922 break;
923
924 default:
925 error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ",
926 "show_keys()");
927 break;
928 }
929 if (k < nkeys - 1) {
930 switch (o_type) {
931 case SHOW_ASCII:
932 putc(' ', stream);
933 break;
934 case SHOW_SKYCAT:
935 putc('\t', stream);
936 break;
937 }
938 }
939 }
940 }
941 putc('\n', stream);
942 }
943 }
944 free(key_col);
945 free(buf);
946 if (kflag)
947 free(keys);
948 if (o_type == SHOW_SKYCAT)
949 fprintf(stream, skycattail);
950 return;
951 }
952
953