/* Set the current_value field of pf. This does not perform any range * checking. Such checking should be performed by the calling routine. * This way, the min,max fields will not be parsed and if any parse error * occurs, it occurs because of the value. * * If the PF_CURRENT_VALUE bit is not set upon return, the current_value * is not set and must be queried by the calling routine. This routine * does not query. * * TODO: fix this for list types */ static int _pf_get_current_value (Param_File_Type *p, Param_Type *pf) { char *value; if (pf->flags & PF_CURRENT_VALUE) return 0; if (NULL == pf->value) return 0; if (pf->flags & PF_INDIRECT_VALUE) { if (-1 == _pf_get_indirect_value (p, pf->value, &value)) return -1; if (value == NULL) return 0; } else value = pf->value; if (-1 == parse_string_according_to_type (value, pf->type & 0xFF, &pf->current_value.ival, &pf->current_value.dval, &pf->current_value.sval)) { if (pf->flags & PF_INDIRECT_VALUE) SLFREE (value); return -1; } pf->flags |= PF_CURRENT_VALUE; if (pf->flags & PF_INDIRECT_VALUE) SLFREE (value); return 0; }
static void free_group_scores (void) { while (Group_Score_Root != NULL) { Group_Score_Type *gnext = Group_Score_Root->next; PScore_Type *pst = Group_Score_Root->pst; Group_Score_Name_Type *gsnt; gsnt = Group_Score_Root->gsnt.next; while (gsnt != NULL) { Group_Score_Name_Type *next = gsnt->next; SLFREE (gsnt); gsnt = next; } while (pst != NULL) { PScore_Type *pnext = pst->next; free_psrt (pst->pregexp_list); slrn_free ((char *) pst->description); SLFREE (pst); pst = pnext; } SLFREE (Group_Score_Root); Group_Score_Root = gnext; } }
static void free_bintable (JDFits_Header_Type *fh) /*{{{*/ { JDFits_Bintable_Type *bt = fh->ext.bintable; if (bt == NULL) return; if (bt->finfo != NULL) SLFREE (bt->finfo); SLFREE (bt); fh->ext.bintable = NULL; }
/* This function simply reads the header at the current position of the file * pointer. It makes no attempt to parse it. The current header attached * to the @JDFits_Type@ structure is freed. If the calling routine wants to * save it, it should set the @ft->header@ field to NULL. When the routine * returns, it sets the fields @ft->header@, @ft->header->num_keywords@ * and @ft->header->header_data@ structure fields appropriately. * It returns 0 upon success and -1 upon failure. */ static int jdfits_read_raw_header (JDFits_Type *ft) { unsigned char *buf, *bufp, *bufp_max; unsigned int nrecords, ncards; unsigned char *header_data_buf; /* free up the current header */ if (ft->header != NULL) free_fits_header (ft); if ((NULL == (ft->header = (JDFits_Header_Type *) jdfits_malloc (sizeof (JDFits_Header_Type)))) || (NULL == (buf = (unsigned char *) jdfits_malloc (JDFITS_RECORD_SIZE)))) { if (ft->header != NULL) SLFREE (ft->header); ft->header = NULL; jdfits_error ("jdfits_read_header: Memory allocation failure."); return -1; } memset ((char *) ft->header, 0, sizeof (JDFits_Header_Type)); nrecords = 0; bufp = buf; ncards = 0; while (1) { if (-1 == jdfits_read_record (ft, bufp)) { if (nrecords != 0) jdfits_error ("jdfits_read_header: Error reading record."); SLFREE (buf); return -1; } nrecords++; /* check to see if this has an end card. */ bufp_max = bufp + JDFITS_RECORD_SIZE; while (bufp < bufp_max) { if (!strncmp ((char *) bufp, "END ", 8)) break; ncards++; bufp += JDFITS_CARD_SIZE; } if (bufp < bufp_max) { bufp += 8; while (bufp < bufp_max) { if (*bufp != ' ') { jdfits_warning ("\ The record following the END card is not padded with blanks as required."); break; } bufp++; } break; /* END found */ }
void SLdebug_free (SLFUTURE_VOID *p) { if (p == NULL) return; if (-1 == check_memory ((unsigned char *) p, "FREE")) return; SLFREE ((char*)p - Chunk); }
/* If the object in the location pointed to by sval is non-NULL, it will be * freed. */ static int parse_string_according_to_type (char *str, unsigned int type, int *ival, double *dval, char **sval) { switch (type) { case PF_UINT_TYPE: case PF_INTEGER_TYPE: return _pf_parse_single_number (str, ival, NULL); case PF_BOOLEAN_TYPE: return _pf_parse_boolean (str, ival); case PF_REAL_TYPE: case PF_DOUBLE_TYPE: return _pf_parse_single_number (str, NULL, dval); case PF_STRING_TYPE: case PF_FILE_TYPE: /* This is easy */ if (*sval != NULL) SLFREE (*sval); if (NULL == (*sval = _pf_create_string (str))) return -1; return 0; default: pf_error ("type %d not implemented.", type); PF_Errno = PF_NOT_IMPLEMENTED; } return -1; }
void _pf_free_param_file (Param_File_Type *p) { Param_Type *pf, *pf_next; if (p == NULL) return; pf = p->pf; while (pf != NULL) { pf_next = pf->next; free_param_type (pf); pf = pf_next; } if (p->input_filename != NULL) SLFREE (p->input_filename); if (p->output_filename != NULL) SLFREE (p->output_filename); SLFREE (p); }
static int enumerated_value_check (Param_Type *pf, char *list) { unsigned int type; int ival; double dval; char *value; unsigned int nth = 0; type = pf->type & 0xFF; while (NULL != (value = _pf_extract_string_element (list, "|", &nth))) { if (*value == 0) { SLFREE (value); continue; } switch (type) { case PF_UINT_TYPE: (void) _pf_parse_single_number (value, &ival, NULL); SLFREE (value); if ((unsigned int) ival == pf->current_value.uval) return 0; break; case PF_INTEGER_TYPE: (void) _pf_parse_single_number (value, &ival, NULL); SLFREE (value); if (ival == pf->current_value.ival) return 0; break; case PF_REAL_TYPE: case PF_DOUBLE_TYPE: (void) _pf_parse_single_number (value, NULL, &dval); SLFREE (value); if (dval == pf->current_value.dval) return 0; break; case PF_STRING_TYPE: case PF_FILE_TYPE: if (!strcmp (value, pf->current_value.sval)) { SLFREE (value); return 0; } SLFREE (value); break; default: SLFREE (value); return 0; } } PF_Errno = PF_RANGE_ERROR; return -1; }
static void free_srt (Score_Regexp_Type *srt) { while (srt != NULL) { Score_Regexp_Type *srt_next = srt->next; if ((srt->header_type == SCORE_SUB_AND) || (srt->header_type == SCORE_SUB_OR)) free_srt (srt->search.srt); SLFREE (srt); srt = srt_next; } }
static int update_value (Param_Type *pf) { char buf[PF_MAX_LINE_LEN]; char *b; if ((pf->flags & PF_CURRENT_VALUE) == 0) return 0; if (pf->flags & PF_INDIRECT_VALUE) return 0; if (pf->type & PF_LIST_TYPE) return 0; b = buf; switch (pf->type & 0xFF) { case PF_INTEGER_TYPE: sprintf (buf, "%d", pf->current_value.ival); break; case PF_UINT_TYPE: sprintf (buf, "%u", pf->current_value.uval); break; case PF_REAL_TYPE: case PF_DOUBLE_TYPE: sprintf (buf, "%.16g", pf->current_value.dval); break; case PF_FILE_TYPE: case PF_STRING_TYPE: b = pf->current_value.sval; if (strlen (b) >= PF_MAX_LINE_LEN) { pf_error ("String value is too long for parameter file."); PF_Errno = PF_BAD_ARGUMENT; return -1; } break; case PF_BOOLEAN_TYPE: strcpy (buf, (pf->current_value.ival ? "yes" : "no")); break; default: pf_error ("update_value: Type %c is not supported", pf->type & 0xFF); PF_Errno = PF_NOT_IMPLEMENTED; return -1; } if (pf->value != NULL) SLFREE (pf->value); if (NULL == (pf->value = _pf_create_string (b))) return -1; return 0; }
static void free_psrt (PScore_Regexp_Type *r) { while (r != NULL) { PScore_Regexp_Type *rnext = r->next; if ((r->header_type == SCORE_SUB_AND) || (r->header_type == SCORE_SUB_OR)) free_psrt (r->ireg.psrt); else if ((r->flags & USE_INTEGER) == 0) slrn_free ((char *) r->ireg.regexp_str); SLFREE (r); r = rnext; } }
static Param_File_Type *create_param_file_type (char *file) { Param_File_Type *p; if (NULL == (p = (Param_File_Type *) _pf_malloc (sizeof (Param_File_Type)))) return NULL; if (NULL == (p->input_filename = _pf_create_string (file))) { SLFREE (p); return NULL; } return p; }
/* This routine free all memory associated with pf. */ static void free_param_type (Param_Type *pf) { if (pf->name != NULL) SLFREE (pf->name); if (pf->prompt != NULL) SLFREE (pf->prompt); if (pf->value != NULL) SLFREE (pf->value); if (pf->min != NULL) SLFREE (pf->min); if (pf->max != NULL) SLFREE (pf->max); if ((((pf->type & 0xFF) == PF_STRING_TYPE) || ((pf->type & 0xFF) == PF_FILE_TYPE)) && (pf->flags & PF_CURRENT_VALUE) && (pf->current_value.sval != NULL)) SLFREE (pf->current_value.sval); SLFREE (pf); }
static void free_group_chain (void) { Score_Regexp_Type *srt; while (Score_Root != NULL) { Score_Type *next = Score_Root->next; srt = &Score_Root->regexp_list; /* first not malloced; free subscores only: */ if ((srt->header_type == SCORE_SUB_AND) || (srt->header_type == SCORE_SUB_OR)) free_srt (srt->search.srt); free_srt (srt->next); SLFREE (Score_Root); Score_Root = next; } Score_Tail = NULL; }
static void compile_function_list(char *order, sort_function_type **Functions) /*{{{*/ { char buf[256]; unsigned int nth=0; while (*Functions != NULL) { sort_function_type *next = (*Functions)->next; SLFREE (*Functions); *Functions = next; } if ((order == NULL) || !(*order)) return; while (-1 != SLextract_list_element (order, nth, ',', buf, sizeof(buf))) { if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Subject")) add_sort_function(Functions, header_subject_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Score")) add_sort_function(Functions, header_score_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Highscore")) add_sort_function(Functions, header_highscore_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Date")) add_sort_function(Functions, header_date_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Author")) add_sort_function(Functions, header_author_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Lines")) add_sort_function(Functions, header_lines_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Number")) add_sort_function(Functions, header_num_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Id")) add_sort_function(Functions, header_msgid_cmp, isupper(buf[0])); else if (! slrn_case_strcmp((unsigned char*)buf, (unsigned char*)"Body")) add_sort_function(Functions, header_has_body_cmp, isupper(buf[0])); else /* Nonexistant sorting method */ { slrn_error(_("Can't sort according to `%s'"), buf); } nth++; } /* while (...) */ }
static int parse_headers (JDFits_Header_Type *ht) { unsigned char *p, ch; unsigned int i; unsigned int n = ht->num_keywords; int naxis; int bitpix; JDFits_Keyword_Type *kwt; off_t naxis_product; kwt = (JDFits_Keyword_Type *) SLCALLOC (n, sizeof (JDFits_Keyword_Type)); if (kwt == NULL) { jdfits_error ("parse_headers: Memory allocation error."); return -1; } ht->keys = kwt; p = ht->header_data_buf; for (i = 0; i < n; i++) { unsigned char *p1 = p + 8, *nextp = p + JDFITS_CARD_SIZE; kwt->name = (char *) p; ch = *p1; *p1-- = 0; while ((p1 >= p) && (*p1 == ' ')) *p1-- = 0; if ((ch == '=') && (0 == is_commentary_keyword (kwt->name))) { /* value */ if (p1 + 1 == p) { jdfits_warning ("Card %d appears corrupt.", i); } p1 = p + 9; while ((p1 < nextp) && (*p1 == ' ')) p1++; if ((p1 == nextp) || (*p1 == '/')) { jdfits_warning ("Card %d (%s) has no value.", i, kwt->name); kwt->type = JDFITS_UNPARSED_TYPE | JDFITS_STRING_TYPE; } else switch (*p1) { case '\'': kwt->type = JDFITS_STRING_TYPE | JDFITS_UNPARSED_TYPE; break; case 'F': case 'T': kwt->type = JDFITS_BOOL_TYPE | JDFITS_UNPARSED_TYPE; if (p1 == p + 29) break; if (*p1 != 'F') { jdfits_warning ("Boolean card %d (%s) has value in wrong column.", i, kwt->name); break; } /* Drop */ case 'A': case 'a': case 'B': case 'b': case 'C': case 'c': case 'D': case 'd': case 'E': case 'e': case 'f': /* we can have integers, floats or decimals. * Anything else? */ case '-': case '+': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': kwt->type = JDFITS_NUMBER_MASK | JDFITS_UNPARSED_TYPE; break; default: jdfits_warning ("Card %d (%s) appears corrupt. Assuming a string.", i, kwt->name); kwt->type = JDFITS_STRING_TYPE | JDFITS_UNPARSED_TYPE; } kwt->v.sval = (char *)p1; kwt->comment = (char *) nextp; /* for unparsed cards, this * field points to the end */ } /* END of VALUE CARDS */ else { /* According to the 1990 FITS User's Guide, any thing else is a * comment card */ kwt->type = JDFITS_COMMENT_TYPE; p[8] = ch; kwt->v.sval = kwt->comment = (char *)p + 8; kwt->comment_len = (int) ((char *)nextp - kwt->comment); } p = nextp + 1; kwt++; } /* End of for loop */ /* Do a minimial parse so that the data size and name of the header or * extension can be determined. According to the 1993 NOST 100-1.0 * definition of the FITS format, the header must begin with the keywords: * @ SIMPLE * @ BITPIX * @ NAXIS * @ NAXIS[n], n = 1..NAXIS * @ EXTEND (presence not required) * The size of the primary header is: * @ abs(BITPIX) * NAXIS[1] * ... * NAXIS[n] * If the header represents an extension, it looks like: * @ XTENSION * @ BITPIX * @ NAXIS * @ NAXIS[n], n = 1..NAXIS * @ (zero or more other keywords including:) * @ PCOUNT * @ GCOUNT * The size of the extension is: * @ abs(BITPIX) * GCOUNT * (PCOUNT + NAXIS[1] * ... * NAXIS[n]) */ kwt = ht->keys; ht->name = NULL; if ((kwt->type & JDFITS_STRING_TYPE) && !strcmp (kwt->name, "XTENSION")) { ht->type = JDFITS_EXTENSION_HEADER; if (0 == parse_string (kwt)) { ht->name = kwt->v.sval; if (!strcmp ((char *) ht->name, "BINTABLE")) ht->type = JDFITS_BINTABLE_HEADER; } } else if ((kwt->type & JDFITS_BOOL_TYPE) && !strcmp(kwt->name, "SIMPLE")) { ht->type = JDFITS_SIMPLE_HEADER; (void) parse_bool (kwt); } else { jdfits_error ("Header is not a fits header. Expected to see SIMPLE or XTENSION."); goto error_return; } if ((0 == (kwt[1].type & JDFITS_NUMBER_MASK)) || strcmp (kwt[1].name, "BITPIX") || (-1 == parse_int (kwt + 1))) { jdfits_error ("BITPIX keyword missing or has a bad value."); goto error_return; } ht->bitpix = bitpix = kwt[1].v.ival; if ((bitpix != 8) && (bitpix != 16) && (bitpix != 32) && (bitpix != -32) && (bitpix != -64)) jdfits_warning ("The BITPIX keyword has a non-standard value: %d", bitpix); if ((0 == (kwt[2].type & JDFITS_NUMBER_MASK)) || strcmp (kwt[2].name, "NAXIS") || (-1 == parse_int (kwt + 2)) || ((naxis = kwt[2].v.ival) < 0)) { jdfits_error ("NAXIS keyword missing or has a bad value."); goto error_return; } ht->naxis = naxis; if (naxis) naxis_product = 1; else naxis_product = 0; kwt += 3; for (i = 1; i <= (unsigned int) naxis; i++) { char naxis_str[9]; sprintf (naxis_str, "NAXIS%d", i); if ((0 == (kwt->type & JDFITS_NUMBER_MASK)) || strcmp (kwt->name, naxis_str) || (-1 == parse_int (kwt)) || ((naxis_product = naxis_product * kwt->v.ival) < 0)) { jdfits_error ("NAXIS keyword missing or has a bad value."); goto error_return; } kwt++; } if (naxis) { ht->kw_naxis1 = kwt - naxis; } else ht->kw_naxis1 = NULL; /* Now if this is an extension header, look for the PCOUNT and GCOUNT * fields. The reference makes it seem that PCOUNT comes first. However, * other documentation is not as explicit. */ if (ht->type != JDFITS_SIMPLE_HEADER) { JDFits_Keyword_Type *kwmax = ht->keys + ht->num_keywords; ht->pcount = ht->gcount = -1; while (kwt < kwmax) { if (kwt->type & JDFITS_NUMBER_MASK) { if ((ht->pcount == -1) && !strcmp (kwt->name, "PCOUNT")) { if ((-1 == parse_int (kwt)) || ((ht->pcount = kwt->v.ival) < 0)) { jdfits_error ("PCOUNT card is defective."); goto error_return; } if (ht->gcount != -1) break; } else if ((ht->gcount == -1) && !strcmp (kwt->name, "GCOUNT")) { if ((-1 == parse_int (kwt)) || ((ht->gcount = kwt->v.ival) <= 0)) { jdfits_error ("GCOUNT card is defective."); goto error_return; } if (ht->pcount != -1) break; } } kwt++; } if (ht->pcount == -1) { jdfits_warning ("PCOUNT card is missing. Assuming a value of zero."); ht->pcount = 0; } if (ht->gcount == -1) { jdfits_warning ("GCOUNT card is missing. Assuming a value of one."); ht->gcount = 1; } } else { ht->pcount = 0; ht->gcount = 1; } ht->size = ht->gcount * (ht->pcount + naxis_product); ht->size *= abs (bitpix) / 8; /* convert to 8 bit BYTES */ return 0; error_return: SLFREE (ht->keys); ht->keys = NULL; ht->name = NULL; ht->type = 0; return -1; }
int jdfits_bintable_parse_headers (JDFits_Type *ft) /*{{{*/ { JDFits_Header_Type *h = NULL; JDFits_Keyword_Type *kwt = NULL; JDFits_Bintable_Type *bt = NULL; JDFits_Bintable_Field_Type *bft = NULL; int tfields, i; /* Check to make sure this is a bintable */ if ((ft == NULL) || (NULL == (h = ft->header))) { jdfits_error ("jdfits_bintable_parse_headers: header is NULL."); return -1; } if (h->type == JDFITS_EXTENSION_HEADER) { if ((h->name != NULL) && !strcmp ((char *) h->name, "BINTABLE")) h->type = JDFITS_BINTABLE_HEADER; } if (h->type != JDFITS_BINTABLE_HEADER) { jdfits_error ("jdfits_bintable_parse_headers: Not a BINTABLE header."); return -1; } /* Check to make sure the header meets the other basic requirements. */ if ((h->bitpix != 8) || (h->naxis != 2) || (h->gcount != 1)) { jdfits_error ("jdfits_bintable_parse_headers: Header does not meet bintable requirements."); return -1; } if (h->ext.bintable != NULL) return 0; /* already parsed */ /* Now look for the tfields header. */ if ((NULL == (kwt = jdfits_parse_keyword (h, "TFIELDS", JDFITS_INT_TYPE))) || ((tfields = kwt->v.ival) < 0) || (tfields > 999)) { jdfits_error ("jdfits_bintable_parse_headers: Bad or missing TFIELDS entry."); goto free_error; } if (NULL == (bt = (JDFits_Bintable_Type *) SLMALLOC (sizeof (JDFits_Bintable_Type)))) { jdfits_error ("jdfits_bintable_parse_headers: Malloc Error."); goto free_error; } memset ((char *) bt, 0, sizeof (JDFits_Bintable_Type)); if (0 != tfields) { bft = (JDFits_Bintable_Field_Type *) SLCALLOC (tfields, sizeof (JDFits_Bintable_Field_Type)); if (bft == NULL) { jdfits_error ("jdfits_bintable_parse_headers: Calloc Error."); goto free_error; } } bt->finfo = bft; bt->tfields = tfields; if (NULL != (kwt = jdfits_parse_keyword (h, "EXTNAME", JDFITS_STRING_TYPE))) bt->extname = (char *) kwt->v.sval; for (i = 1; i <= tfields; i++) { char buf[9], *b; unsigned char ch; unsigned int repeat, type, size; char *fmt, *default_format; JDFits_Bintable_Field_Type *bfti = bft + (i - 1); sprintf (buf, "TFORM%d", i); kwt = jdfits_parse_keyword (h, buf, JDFITS_STRING_TYPE); if (kwt == NULL) { jdfits_error ("jdfits_bintable_parse_headers: Bad or missing %s entry.", buf); goto free_error; } b = (char *) kwt->v.sval; ch = *b; /* Some files produced by ftools use spaces like: " 1J " */ while (ch == ' ') { b++; ch = *b; } if (isdigit (ch) == 0) repeat = 1; else { repeat = 0; while (((ch = (unsigned char) *b) != 0) && isdigit (ch)) { repeat = 10 * repeat + (ch - '0'); b++; } } bfti->repeat = repeat; default_format = "% 16.9E"; type = 0; pointer_type_label: switch (ch) { case 'L': type |= JDFITS_BOOL_TYPE; size = 8; fmt = "%d"; break; case 'X': switch (repeat) { /* FIXME: I need to use hex formats, but that requires * proper parsing of the format string in the dump function. */ case 8: type |= JDFITS_BYTE_TYPE; bfti->repeat = 1; size = 8; fmt = "%d"; break; case 16: type |= JDFITS_INT16_TYPE; bfti->repeat = 1; size = 16; fmt = JDFITS_FMT_16; break; case 32: type |= JDFITS_INT32_TYPE; bfti->repeat = 1; size = 32; fmt = JDFITS_FMT_32; break; default: type |= JDFITS_BIT_TYPE; size = 1; fmt = "%X"; break; } break; case 'B': type |= JDFITS_BYTE_TYPE; size = 8; fmt = "%c"; break; case 'I': type |= JDFITS_INT16_TYPE; size = 16; fmt = JDFITS_FMT_16; break; case 'P': /* variable length array */ if (repeat > 1) { jdfits_error ("jdfits_bintable_parse_headers: The repeat count must be 0 or 1 for P type."); goto free_error; } if (repeat) repeat = 2; bfti->repeat = repeat; b++; ch = *b; type = JDFITS_POINTER_FLAG; goto pointer_type_label; case 'J': type |= JDFITS_INT32_TYPE; size = 32; fmt = JDFITS_FMT_32; break; case 'A': type |= JDFITS_STRING_TYPE; size = 8; fmt = "%s"; break; case 'E': type |= JDFITS_FLOAT32_TYPE; fmt = "% 15.7E"; size = 32; break; case 'D': type |= JDFITS_FLOAT64_TYPE; size = 64; fmt = "% 16.9E"; break; case 0: ch = '0'; /* drop */ case 'C': /* complex */ case 'M': /* double precision complex */ default: jdfits_error ("jdfits_bintable_parse_headers: Field type '%c' is not implemented. (%s)", ch, buf); goto free_error; } bfti->size = size; bfti->type = type; /* Now pick up the remaining indexed keywords. */ if (NULL == (kwt = bt_parse_index_kw (h, "TTYPE", i, JDFITS_STRING_TYPE))) bfti->ttype = NULL; else bfti->ttype = kwt->v.sval; if (NULL == (kwt = bt_parse_index_kw (h, "TUNIT", i, JDFITS_STRING_TYPE))) bfti->tunit = NULL; else bfti->tunit = kwt->v.sval; if (NULL == (kwt = bt_parse_index_kw (h, "TDIM", i, JDFITS_STRING_TYPE))) bfti->tdim = NULL; else bfti->tdim = kwt->v.sval; if (NULL == (kwt = bt_parse_index_kw (h, "TNULL", i, JDFITS_INT_TYPE))) bfti->tnull = 0; else bfti->tnull = kwt->v.ival; bfti->has_scaling = 0; if (NULL == (kwt = bt_parse_index_kw (h, "TSCAL", i, JDFITS_FLOAT64_TYPE))) { bfti->tscal = 1.0; } else { bfti->tscal = kwt->v.dval; bfti->has_scaling = 1; } if (NULL == (kwt = bt_parse_index_kw (h, "TZERO", i, JDFITS_FLOAT64_TYPE))) bfti->tzero = 0.0; else { bfti->tzero = kwt->v.dval; bfti->has_scaling = 1; } if (NULL == (kwt = bt_parse_index_kw (h, "TCRPX", i, JDFITS_FLOAT64_TYPE))) bfti->tcrpx = 0.0; else { bfti->tcrpx = kwt->v.dval; bfti->has_scaling = 1; } if (NULL == (kwt = bt_parse_index_kw (h, "TCRVL", i, JDFITS_FLOAT64_TYPE))) bfti->tcrvl = 0.0; else { bfti->tcrvl = kwt->v.dval; bfti->has_scaling = 1; } if (NULL == (kwt = bt_parse_index_kw (h, "TCDLT", i, JDFITS_FLOAT64_TYPE))) bfti->tcdlt = 1.0; else { bfti->tcdlt = kwt->v.dval; bfti->has_scaling = 1; } #if 0 /* We do not yet handled the unsigned int hack. So avoid float format */ if (bfti->has_scaling) fmt = default_format; #endif if ((NULL == (kwt = bt_parse_index_kw (h, "TDISP", i, JDFITS_STRING_TYPE))) || (-1 == jdfits_ffmt_to_cfmt (kwt->v.sval, bfti->tdisp))) strcpy ((char *) bfti->tdisp, fmt); } h->ext.bintable = bt; h->free_routine = free_bintable; /* Now set up the remaining fields. Note that the positions of * naxis1 and naxis2 are fixed. */ bt->naxis1 = h->keys[3].v.ival; bt->naxis2 = h->keys[4].v.ival; return 0; /* Only get here if something goes wrong. Here all malloced items in this * function are freed. */ free_error: h->ext.bintable = NULL; if (bt != NULL) SLFREE (bt); if (bft != NULL) SLFREE (bft); return -1; }
static int get_indirect_object (Param_File_Type *p, char *name, char **val, int what) { char *file, *parm; Param_File_Type *new_p; Param_Type *pf; int ret; char *value; int is_file_indirect; if (*name != ')') { PF_Errno = PF_INDIRECT_ERROR; return -1; } name++; /* ))Shell Command */ if (*name == ')') return do_indirect_shell_cmd (name + 1, val); /* Note: The CXC parameter file library appears to support an indirection * of the form ")FILE.PARM", which means to use the value of PARM from FILE. * (note added Oct-30-2001) */ is_file_indirect = 0; if (*name == '*') { is_file_indirect = 1; name++; } if (NULL != _pf_strchr (name, '.')) /* HACK!!! Undocumented CXC parmeter file behavior. */ is_file_indirect = 1; if (is_file_indirect) { if (NULL == (parm = _pf_strchr (name, '.'))) { pf_error ("Indirection does not point to a parameter."); PF_Errno = PF_CORRUPT_FIELD; return -1; } file = _pf_create_nstring (name, (unsigned int) (parm - name)); if (file == NULL) return -1; parm++; /* skip . */ new_p = p = pf_open_parameter_file (file, "r"); if (p == NULL) { pf_error ("Unable to open indirect file %s.", file); SLFREE (file); PF_Errno = PF_INDIRECT_ERROR; return -1; } SLFREE (file); name = parm; } else new_p = NULL; if (NULL == (pf = _pf_locate_param_by_type (p, name, 0))) { if (new_p != NULL) pf_close_parameter_file (new_p); pf_error ("Bad indirect: %s", name); PF_Errno = PF_INDIRECT_ERROR; return -1; } ret = 0; if (what == 0) value = pf->value; else if (what == 1) value = pf->min; else value = pf->max; if (pf->flags & PF_DOING_INDIRECT) { pf_error ("Indirection loop found."); PF_Errno = PF_INDIRECT_ERROR; ret = -1; } else if (value == NULL) *val = NULL; else if (*value == ')') { pf->flags |= PF_DOING_INDIRECT; ret = get_indirect_object (p, value, val, what); pf->flags &= ~PF_DOING_INDIRECT; } else { if (NULL == (*val = _pf_create_string (value))) ret = -1; } if (new_p != NULL) pf_close_parameter_file (new_p); return ret; }
static int phrase_score_file (char *file, FILE *fp, Score_Context_Type *c, unsigned int *linenum, PScore_Regexp_Type *sub_psrt) { char line[1024]; PScore_Regexp_Type *psrt; char *description = NULL; while (fgets (line, sizeof (line) - 1, fp)) { unsigned char *lp; int ret, not_flag; (*linenum)++; psrt = NULL; if (0 == SLprep_line_ok (line, &c->pt)) continue; lp = (unsigned char *) slrn_skip_whitespace (line); if ((*lp == '#') || (*lp == '%') || (*lp <= ' ')) continue; if (sub_psrt == NULL) { if ((0 == slrn_case_strncmp (lp, (unsigned char *) "include", 7)) && ((lp[7] == ' ') || (lp[7] == '\t'))) { if (0 == handle_include_line (file, (char *)lp + 7, c)) continue; score_error (_("Error handling INCLUDE line"), line, *linenum, file); slrn_free (description); return -1; } if (*lp == '[') { unsigned char *g, *gmax, ch; g = c->group; gmax = g + sizeof (c->group); lp++; lp = (unsigned char *) slrn_skip_whitespace ((char *)lp); c->gnt_not_flag = 0; if (*lp == '~') { c->gnt_not_flag = 1; lp = (unsigned char *) slrn_skip_whitespace ((char *)lp + 1); } while (((ch = *lp++) != 0) && (ch != ']') && (g < gmax)) *g++ = ch; if ((ch != ']') || (g == gmax)) { score_error (_("Syntax Error."), line, *linenum, file); slrn_free (description); return -1; } *g = 0; c->start_new_group = 1; c->score_has_expired = 0; c->start_new_score = 0; continue; } if (!slrn_case_strncmp (lp, (unsigned char *)"Score:", 6)) { unsigned char *lpp = lp + 6, *eol; c->pscore_flags = 0; if (*lpp == ':') { lpp++; c->pscore_flags |= SCORE_IS_OR_TYPE; } lpp = (unsigned char *) slrn_skip_whitespace ((char *) lpp); if (*lpp == '=') { c->pscore_flags |= RETURN_THIS_SCORE; lpp++; } c->score = atoi ((char *)lpp); c->start_new_score = 1; if (description != NULL) { slrn_free (description); description = NULL; } eol = (unsigned char *) slrn_strchr ((char *)lpp, '#'); if (eol == NULL) lpp = (unsigned char *) slrn_strchr ((char *)lpp, '%'); else lpp = eol; if (lpp != NULL) { lpp = (unsigned char *) slrn_skip_whitespace ((char *)lpp + 1); eol = lpp + strlen ((char*)lpp) - 1; while ((eol >= lpp) && (*eol <= 32)) *eol-- = '\0'; description = slrn_safe_strmalloc ((char *)lpp); } continue; } if (c->start_new_score) { if (!slrn_case_strncmp (lp, (unsigned char *) "Expires:", 8)) { ret = has_score_expired (lp + 8, c->today); if (ret == -1) { score_error (_("Expecting 'Expires: MM/DD/YYYY' or 'Expires: DD-MM-YYYY'"), line, *linenum, file); slrn_free (description); return -1; } if (ret) { slrn_message (_("%s has expired score on line %d"), file, *linenum); #ifndef SLRNPULL_CODE Slrn_Saw_Warning = 1; #endif c->start_new_score = 0; c->score_has_expired = 1; } else c->score_has_expired = 0; continue; } if (NULL == (c->pst = create_new_score (c->group, c->start_new_group, c->gnt_not_flag, c->score, c->pscore_flags, file, *linenum, description))) { score_error (_("Bad group regular expression."), line, *linenum, file); slrn_free (description); return -1; } c->start_new_group = 0; c->start_new_score = 0; c->score_has_expired = 0; if (description != NULL) { slrn_free (description); description = NULL; } } if (c->score_has_expired) continue; if (c->pst == NULL) { score_error (_("Expecting Score keyword."), line, *linenum, file); return -1; } } /*if (sub_psrt==null) */ slrn_free (description); if (*lp == '~') { not_flag = 1; lp++; } else not_flag = 0; ret = -1; psrt = (PScore_Regexp_Type *) slrn_safe_malloc (sizeof (PScore_Regexp_Type)); /* Otherwise the line is a kill one */ if (!slrn_case_strncmp (lp, (unsigned char *)"Subject:", 8)) ret = add_group_regexp (psrt, lp + 7, lp, SCORE_SUBJECT, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"From:", 5)) ret = add_group_regexp (psrt, lp + 4, lp, SCORE_FROM, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Xref:", 5)) ret = add_group_regexp (psrt, lp + 4, lp, SCORE_XREF, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Newsgroup:", 10)) ret = add_group_regexp (psrt, lp + 9, lp, SCORE_NEWSGROUP, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"References:", 11)) ret = add_group_regexp (psrt, lp + 10, lp, SCORE_REFERENCES, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Lines:", 6)) ret = add_group_regexp (psrt, lp + 5, lp, SCORE_LINES, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Date:", 5)) ret = add_group_regexp (psrt, lp + 4, lp, SCORE_DATE, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Age:", 4)) ret = add_group_regexp (psrt, lp + 3, lp, SCORE_AGE, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Bytes:", 6)) ret = add_group_regexp (psrt, lp + 5, lp, SCORE_BYTES, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Has-Body:", 9)) ret = add_group_regexp (psrt, lp + 8, lp, SCORE_HAS_BODY, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"Message-Id:", 11)) ret = add_group_regexp (psrt, lp + 10, lp, SCORE_MESSAGE_ID, not_flag); else if (!slrn_case_strncmp (lp, (unsigned char *)"{:", 2)) { if (lp[2] ==':') { ret = add_group_regexp (psrt, lp + 1, lp, SCORE_SUB_OR, not_flag); } else { ret = add_group_regexp (psrt, lp + 1, lp, SCORE_SUB_AND, not_flag); } if (phrase_score_file(file, fp, c, linenum, psrt)) return -1; } else if (!slrn_case_strncmp (lp, (unsigned char *)"}", 1)) { SLFREE (psrt); if (sub_psrt != NULL) return 0; else { score_error (_("Missing COLON."), line, *linenum, file); return -1; } } else { unsigned char *lpp = lp; while (*lpp && (*lpp != ':')) lpp++; if (*lpp != ':') { SLFREE (psrt); score_error (_("Missing COLON."), line, *linenum, file); return -1; } ret = add_group_regexp (psrt, lpp, lp, SCORE_GENERIC, not_flag); } if (ret == -1) { score_error (_("No regular expression given."), line, *linenum, file); return -1; } if (sub_psrt == NULL) { if (c->pst->pregexp_list == NULL) { c->pst->pregexp_list = psrt; } else { PScore_Regexp_Type *last = c->pst->pregexp_list; while (last->next != NULL) last = last->next; last->next = psrt; } } else { if (sub_psrt->ireg.psrt == NULL) { sub_psrt->ireg.psrt = psrt; } else { PScore_Regexp_Type *last = sub_psrt->ireg.psrt; while (last->next != NULL) last = last->next; last->next = psrt; } } } /*while (fgets (line, sizeof (line) - 1, fp))*/ if (sub_psrt == NULL) return 0; else { score_error (_("Missing '}' for subscore"), line, *linenum, file); return -1; } }
int jdfits_bintable_read_data (JDFits_Type *ft) /*{{{*/ { unsigned int tfields, i, j; unsigned int rows; JDFits_Bintable_Type *fbt; fbt = ft->header->ext.bintable; rows = fbt->naxis2; tfields = (unsigned int) fbt->tfields; for (i = 0; i < tfields; i++) { unsigned int nelements; unsigned int type; JDFits_Bintable_Field_Type *finfo; JDFits_Data_Array_Type *fdat; finfo = &fbt->finfo[i]; nelements = rows * finfo->repeat; type = finfo->type; fdat = &(finfo->data_array); fdat->nelements = nelements; fdat->type = type; if (NULL == (fdat->v.sval = _jdfits_allocate_bytes_of_type (type, nelements))) goto close_error; } /* Now data arrays are malloced, so read in the data. There is no scaling * performed. */ if (-1 == jdfits_read_open_data (ft)) goto close_error; for (i = 0; i < rows; i++) { for (j = 0; j < tfields; j++) { JDFits_Bintable_Field_Type *finfo; JDFits_Data_Array_Type *fdat; unsigned int repeat; unsigned int offset; finfo = &fbt->finfo[j]; fdat = &(finfo->data_array); repeat = finfo->repeat; offset = i * repeat; switch (fdat->type) { case JDFITS_INT16_TYPE: if (repeat != jdfits_read_int16 (ft, fdat->v.hval + offset, repeat)) { jdfits_error ("Read error."); goto close_error; } break; case JDFITS_INT32_TYPE: if (repeat != jdfits_read_int32 (ft, fdat->v.lval + offset, repeat)) { jdfits_error ("Read error."); goto close_error; } break; case JDFITS_FLOAT32_TYPE: if (repeat != jdfits_read_float32 (ft, fdat->v.fval + offset, repeat)) { jdfits_error ("Read error."); goto close_error; } break; case JDFITS_FLOAT64_TYPE: if (repeat != jdfits_read_float64 (ft, fdat->v.dval + offset, repeat)) { jdfits_error ("Read error."); goto close_error; } break; case JDFITS_STRING_TYPE: case JDFITS_BOOL_TYPE: case JDFITS_BIT_TYPE: case JDFITS_BYTE_TYPE: default: jdfits_error ("jdfits_bintable_read_data: Field type '%d' is not implemented.", fdat->type); goto close_error; } } } jdfits_read_close_data (ft); return 0; close_error: jdfits_read_close_data (ft); for (i = 0; i < tfields; i++) { if (fbt->finfo[i].data_array.v.ival != NULL) { SLFREE (fbt->finfo[i].data_array.v.ival); fbt->finfo[i].data_array.v.ival = NULL; } } return -1; }
int JDMread_column_fdata (char *file, float **data, int *cindex, unsigned int n, unsigned int *num_read) { char buf[512]; unsigned int space = 1024; unsigned int nread = 0; int do_close; unsigned int i; #define MAX_COLUMNS 20 float dum[MAX_COLUMNS]; FILE *fp; *num_read = 0; if (n > MAX_COLUMNS) { JDMath_Error = JDMATH_INVALID_PARAMETER; JDMmsg_error ("JDMread_column_fdata"); return -1; } if (file == NULL) { fp = stdin; do_close = 0; file = "<stdin>"; } else { if (NULL == (fp = fopen (file, "r"))) { JDMath_Error = JDMATH_FILE_OPEN_ERROR; JDMmsg_error2 ("JDMread_column_fdata", file); return -1; } do_close = 1; } /* initialize everything to NULL */ for (i = 0; i < n; i++) data[i] = NULL; for (i = 0; i < n; i++) { float *ptr; if (cindex[i] == 0) continue; ptr = (float *) SLMALLOC (space * sizeof (float)); if (ptr == NULL) goto return_error; data[i] = ptr; } while (NULL != fgets (buf, sizeof (buf) - 1, fp)) { if ((int)n > sscanf (buf, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", dum+0, dum+1, dum+2, dum+3, dum+4, dum+5, dum+6, dum+7, dum+8, dum+9, dum+10, dum+11, dum+12, dum+13, dum+14, dum+15, dum+16, dum+17, dum+18, dum+19 )) continue; if (nread == space) { space += 1024; for (i = 0; i < n; i++) { float *ptr; if (cindex[i] == 0) continue; ptr = (float *) SLREALLOC (data[i], space * sizeof (float)); if (ptr == NULL) goto return_error; data[i] = ptr; } } for (i = 0; i < n; i++) { if (cindex[i] == 0) continue; data[i][nread] = dum[i]; } nread++; } if (nread == 0) { JDMath_Error = JDMATH_CORRUPT_FILE_ERROR; JDMmsg_error2 ("JDMread_column_fdata", file); goto read_error; } if (file != NULL) fclose (fp); *num_read = nread; return 0; return_error: JDMath_Error = JDMATH_MALLOC_ERROR; read_error: if (do_close) fclose (fp); JDMmsg_error2 ("JDMread_column_fdata", file); for (i = 0; i < n; i++) { if (data[i] != NULL) SLFREE (data[i]); } return -1; }
/* Find articles with the same subject and put them into the same thread. */ static void link_same_subjects (void) /*{{{*/ { Slrn_Header_Type **header_list, *h; unsigned int i, nparents; int use_hook = 0; void (*qsort_fun) (char *, unsigned int, unsigned int, int (*)(Slrn_Header_Type **, Slrn_Header_Type **)); /* This is a silly hack to make up for braindead compilers and the lack of * uniformity in prototypes for qsort. */ qsort_fun = (void (*)(char *, unsigned int, unsigned int, int (*)(Slrn_Header_Type **, Slrn_Header_Type **))) qsort; /* Count number of threads we might want to link. */ h = Slrn_First_Header; nparents = 0; while (h != NULL) { if (h->parent == NULL) nparents++; h = h->real_next; } if (nparents < 2) return; /* Allocate an array for them, fill and qsort() it. */ if (NULL == (header_list = (Slrn_Header_Type **) SLCALLOC (sizeof (Slrn_Header_Type *), nparents))) { slrn_error (_("link_same_subjects: memory allocation failure.")); return; } h = Slrn_First_Header; i = 0; while (i < nparents) { if (h->parent == NULL) header_list[i++] = h; h = h->real_next; } (*qsort_fun) ((char *) header_list, nparents, sizeof (Slrn_Header_Type *), qsort_subject_cmp); if (0 != slrn_is_hook_defined(HOOK_SUBJECT_COMPARE)) use_hook = 1; h = header_list[0]; for (i = 1; i < nparents; i++) { Slrn_Header_Type *h1 = header_list[i]; int differ; differ = _art_subject_cmp (h->subject, h1->subject); if (differ && use_hook) { int rslt; (void) slrn_run_hooks (HOOK_SUBJECT_COMPARE, 2, h->subject, h1->subject); if (-1 != SLang_pop_integer (&rslt)) differ = rslt; } if (differ == 0) { /* h and h1 have the same subject. Now make h1 a (faked) child of h. */ insert_fake_child (h, h1); if (h1->flags & FAKE_CHILDREN) { /* h1 has fake children, we have to link them up to the new * parent. That is, h1 will become their sister. So, * extract the adopted children of h1 and make them the sister, */ Slrn_Header_Type *child = h1->child, *last_child; last_child = child; /* child CANNOT be NULL here!! (the parent claims to have * children) */ child = child->sister; while ((child != NULL) && ((child->flags & FAKE_PARENT) == 0)) { last_child = child; child = child->sister; } if (last_child->flags & FAKE_PARENT) /* h1 has only fake children */ { child = last_child; h1->child = NULL; } else last_child->sister = NULL; last_child = child; while (last_child != NULL) { child = last_child->sister; insert_fake_child (h, last_child); last_child = child; } h1->flags &= ~FAKE_CHILDREN; } /* if (h1 had faked children) */ } /* if (found same subject) */ else h = h1; } /* traversing the array */ SLFREE (header_list); }
/* Find articles whose References header starts with the same Message-Id * and put them into the same thread. */ static void link_lost_relatives (void) /*{{{*/ { unsigned int n, i, j; Slrn_Header_Type *h; Relative_Type *relatives; /* Count the number of possible lost relatives */ n = 0; h = Slrn_First_Header; while (h != NULL) { if ((h->parent == NULL) && (h->refs != NULL) && (*h->refs != 0)) n++; h = h->real_next; } if (n < 2) return; /* Allocate an array for them and fill it, remembering a hash value of the * first Message-ID in the References header line. */ relatives = (Relative_Type *) slrn_malloc (sizeof (Relative_Type) * n, 0, 0); if (relatives == NULL) return; n = 0; h = Slrn_First_Header; while (h != NULL) { if ((h->parent == NULL) && (h->refs != NULL) && (*h->refs != 0)) { unsigned char *r, *ref_begin; r = (unsigned char *) h->refs; while (*r && (*r != '<')) r++; if (*r) { ref_begin = r; while (*r && (*r != '>')) r++; if (*r) r++; relatives[n].ref_hash = slrn_compute_hash (ref_begin, r); relatives[n].h = h; n++; } } h = h->real_next; } /* Walk through the array and mark all headers with the same hash value * as relatives. */ for (i = 0; i < n; i++) { unsigned long ref_hash; Relative_Type *ri = relatives + i; Slrn_Header_Type *rih; ref_hash = ri->ref_hash; rih = ri->h; for (j = i + 1; j < n; j++) { if (relatives[j].ref_hash == ref_hash) { Slrn_Header_Type *rjh = relatives[j].h; if ((Slrn_New_Subject_Breaks_Threads & 1) && (rih->subject != NULL) && (rjh->subject != NULL) && (0 != _art_subject_cmp (rih->subject, rjh->subject))) continue; if (rih->parent != NULL) { /* rih has a parent, so make rjh also a faked child of rih->parent */ insert_fake_child (rih->parent, rjh); } else /* make rjh a faked child of rih */ { insert_fake_child (rih, rjh); } break; } /* if (found same hash value) */ } } SLFREE (relatives); }
/* This function is called to sort the headers in article mode. */ void slrn_sort_headers (void) /*{{{*/ { Slrn_Header_Type **header_list, *h; unsigned int i, nheaders; static char *prev_sort_order = NULL; char *sort_order; int do_threading; void (*qsort_fun) (char *, unsigned int, unsigned int, int (*)(Slrn_Header_Type **, Slrn_Header_Type **)); /* This is a silly hack to make up for braindead compilers and the lack of * uniformity in prototypes for qsort. */ qsort_fun = (void (*)(char *, unsigned int, unsigned int, int (*)(Slrn_Header_Type **, Slrn_Header_Type **))) qsort; /* Maybe we must (re-)compile Sort_Functions first */ sort_order = get_current_sort_order (&do_threading); if ((sort_order != NULL) && ((prev_sort_order == NULL) || (strcmp (prev_sort_order, sort_order)))) { slrn_free (prev_sort_order); prev_sort_order = slrn_safe_strmalloc (sort_order); recompile_sortorder (sort_order); } /* Pre-sort by thread / server number */ if (do_threading) sort_by_threads (); else _art_sort_by_server_number(); /* sort_by_threads already did the sorting inside of the threads; what's * left to us is the sorting of headers that don't have parents. * First, count their number and get memory for an array of them. */ nheaders = 0; h = Slrn_First_Header; while (h != NULL) { if (h->parent == NULL) nheaders++; h = h->real_next; } if (nheaders < 2) goto cleanup_screen_and_return; if (NULL == (header_list = (Slrn_Header_Type **) SLCALLOC (sizeof (Slrn_Header_Type *), nheaders + 1))) { slrn_error (_("slrn_sort_headers(): memory allocation failure.")); goto cleanup_screen_and_return; } /* Now, fill the array and call qsort on it; use our header_initial_cmp function * to do the comparison. */ h = Slrn_First_Header; nheaders = 0; while (h != NULL) { if (h->parent == NULL) header_list[nheaders++] = h; h = h->real_next; } header_list[nheaders] = NULL; (*qsort_fun) ((char *) header_list, nheaders, sizeof (Slrn_Header_Type *), header_initial_cmp); /* What we do now depends on the threading state. If the headers are * unthreaded, simply link them in the order returned by qsort. */ if (!do_threading) { header_list[0]->next = header_list[1]; header_list[0]->prev = NULL; for (i = 1; i < nheaders; i++) { h = header_list[i]; h->next = header_list[i + 1]; h->prev = header_list[i - 1]; } } else { /* If the headers are threaded, we have sorted parents. Always link * them with the last child of the previous thread. */ h = NULL; for (i = 0; i <= nheaders; i++) { Slrn_Header_Type *h1 = header_list[i]; if (h != NULL) { h->sister = h1; while (h->child != NULL) { h = h->child; while (h->sister != NULL) h = h->sister; } h->next = h1; } if (h1 != NULL) h1->prev = h; h = h1; } } /* Finally, free the array and clean up the screen. */ _art_Headers = header_list[0]; SLFREE (header_list); cleanup_screen_and_return: _art_find_header_line_num (); Slrn_Full_Screen_Update = 1; if (!Slrn_Uncollapse_Threads) slrn_collapse_threads (1); }
void _JDMfree (void *s) { if (s != NULL) SLFREE (s); }