📄 rt-mt.c
字号:
if (num < 0 || num >= total.author) { /*error("invalid author in thread file: %d [%ld]\n", num, art_num);*/ invalid_data = TRUE; return Nullch; } return savestr(author_array[num]);}/* Our parent/sibling information is a relative offset in the article array.** zero for none. Child values are always found in the very next array** element if child_cnt is non-zero.*/static ARTICLE *the_article(relative_offset, num)WORD relative_offset;int num;{ union { ARTICLE *ap; int num; } uni; if (!relative_offset) return Nullart; num += relative_offset; if (num < 0 || num >= total.article) { /*error("invalid article offset in thread file.\n");*/ invalid_data = TRUE; return Nullart; } uni.num = num+1; return uni.ap; /* slip them an offset in disguise */}/* Read the articles into their trees. Point everything everywhere. */static intread_articles(){ register int count; register ARTICLE *article, **art_ptr; int ret; /* Build an array to interpret interlinkages of articles. */ article_array = (ARTICLE**)safemalloc(total.article * sizeof (ARTICLE*)); art_ptr = article_array; invalid_data = FALSE; for (count = 0; count < total.article; count++) {#ifdef USE_XTHREAD ret = nntp_read((char*)&p_article, (long)sizeof (PACKED_ARTICLE));#else ret = fread((char*)&p_article, 1, sizeof (PACKED_ARTICLE), fp);#endif if (ret != sizeof (PACKED_ARTICLE)) { /*error("failed article read -- %d bytes instead of %d.\n", ret, sizeof (PACKED_ARTICLE));*/ return 0; } lp_bmap(&p_article.num, 2); wp_bmap(&p_article.subject, 8); article = *art_ptr++ = allocate_article(p_article.num); article->date = p_article.date;#ifndef DBM_XREFS if (olden_days < 2 && !(p_article.flags & HAS_XREFS)) article->xrefs = nullstr;#endif article->from = the_author(p_article.author); article->parent = the_article(p_article.parent, count); article->child1 = the_article(p_article.child_cnt ? 1 : 0, count); article->sibling = the_article(p_article.sibling, count); article->subj = the_subject(p_article.subject); if (invalid_data) { /* (Error already logged.) */ return 0; } /* This is ok because parent articles precede their children */ if (article->parent) { union { ARTICLE *ap; int num; } uni; uni.ap = article->parent; article->parent = article_array[uni.num-1]; } if (article->subj) { if (!(article->flags & AF_MISSING)) { article->flags |= AF_FROMTRUNCED | AF_THREADED | ((p_article.flags & ROOT_ARTICLE)? 0 : AF_HAS_RE); } /* Give this subject to any faked parent articles */ while (article->parent && !article->parent->subj) { article->parent->subj = article->subj; article = article->parent; } } else article->flags |= AF_FAKE; } /* We're done with most of the pointer arrays at this point. */ safefree((char**)&subject_array); safefree((char**)&author_array); safefree(&strings); return 1;}/* Read the message-id strings and attach them to each article. The data** format consists of the mushed-together null-terminated strings (a domain** name followed by all its unique-id prefixes) and then the article offsets** to which they belong. The first domain name was omitted, as it is a null** domain for those truly weird message-id's without '@'s.*/static intread_ids(){ register ARTICLE *article; register char *string_ptr; register int i, count, len, len2; if (!read_item(&strings, (MEM_SIZE)total.string2) || !read_item((char**)&ids, (MEM_SIZE)(total.article+total.domain+1) * sizeof (WORD))) { return 0; } wp_bmap(ids, total.article + total.domain + 1); string_ptr = strings; string_end = string_ptr + total.string2; if (string_end[-1] != '\0') { /*error("second string table is invalid.\n");*/ return 0; } for (i = 0, count = total.domain + 1; count--; i++) { if (i) { if (string_ptr >= string_end) { /*error("error unpacking domain strings.\n");*/ return 0; } sprintf(buf, "@%s", string_ptr); len = strlen(string_ptr) + 1; string_ptr += len; } else { *buf = '\0'; len = 0; } if (ids[i] != -1) { if (ids[i] < 0 || ids[i] >= total.article) { /*error("error in id array.\n");*/ return 0; } article = article_array[ids[i]]; for (;;) { if (string_ptr >= string_end) { /*error("error unpacking domain strings.\n");*/ return 0; } len2 = strlen(string_ptr); article->msgid = safemalloc(len2 + len + 2 + 1); sprintf(article->msgid, "<%s%s>", string_ptr, buf); string_ptr += len2 + 1; if (msgid_hash) { HASHDATUM data; if ((article->flags & AF_TMPMEM) == AF_TMPMEM) { data.dat_ptr = (char*)article; data.dat_len = 0; } else { data.dat_ptr = Nullch; data.dat_len = article_num(article); } hashstore(msgid_hash, article->msgid, len2+len+2, data); } if (++i >= total.article + total.domain + !count) { /*error("overran id array unpacking domains.\n");*/ return 0; } if (ids[i] != -1) { if (ids[i] < 0 || ids[i] >= total.article) return 0; article = article_array[ids[i]]; } else break; } } } safefree((char**)&ids); safefree(&strings); return 1;}/* And finally, turn all the links into real pointers and mark missing** articles as read.*/static voidtweak_data(){ register int count; register ARTICLE *ap, **art_ptr; register SUBJECT *sp; register ART_NUM i; union { ARTICLE *ap; int num; } uni; for (sp = first_subject; sp; sp = sp->next) { uni.ap = sp->thread; sp->thread = article_array[uni.num]; sp->thread->subj->flags |= SF_THREAD; } art_ptr = article_array; for (count = total.article; count--; ) { ap = *art_ptr++; if (ap->child1) { uni.ap = ap->child1; ap->child1 = article_array[uni.num-1]; } if (ap->sibling) { uni.ap = ap->sibling; ap->sibling = article_array[uni.num-1]; } if (!(ap->flags & AF_MISSING)) cache_article(ap); } /* Mark any missing articles as read */ for (i = absfirst, ap = article_ptr(i); i <= total.last; i++, ap++) { if ((ap->flags & (AF_CACHED|AF_MISSING)) == AF_CACHED) check_poster(ap); else onemissing(ap); } safefree((char**)&article_array);}/* A shorthand for reading a chunk of the file into a malloc'ed array.*/static intread_item(dest, len)char **dest;MEM_SIZE len;{ long ret; *dest = safemalloc(len);#ifdef USE_XTHREAD ret = nntp_read(*dest, (long)len);#else ret = fread(*dest, 1, (int)len, fp);#endif if (ret != len) { free(*dest); *dest = Nullch; return 0; } putchar('.'), fflush(stdout); return 1;}/* Free some memory if it hasn't already been freed.*/static voidsafefree(pp)char **pp;{ if (*pp) { free(*pp); *pp = Nullch; }}/* Determine this machine's byte map for WORDs and LONGs. A byte map is an** array of BYTEs (sizeof (WORD) or sizeof (LONG) of them) with the 0th BYTE** being the byte number of the high-order byte in my <type>, and so forth.*/static voidmybytemap(map)BMAP *map;{ union { BYTE b[sizeof (LONG)]; WORD w; LONG l; } u; register BYTE *mp; register int i, j; mp = &map->w[sizeof (WORD)]; u.w = 1; for (i = sizeof (WORD); i > 0; i--) { for (j = 0; j < sizeof (WORD); j++) { if (u.b[j] != 0) break; } if (j == sizeof (WORD)) goto bad_news; *--mp = j; while (u.b[j] != 0 && u.w) u.w <<= 1; } mp = &map->l[sizeof (LONG)]; u.l = 1; for (i = sizeof (LONG); i > 0; i--) { for (j = 0; j < sizeof (LONG); j++) { if (u.b[j] != 0) break; } if (j == sizeof (LONG)) { bad_news: /* trouble -- set both to *something* consistent */ for (j = 0; j < sizeof (WORD); j++) map->w[j] = j; for (j = 0; j < sizeof (LONG); j++) map->l[j] = j; return; } *--mp = j; while (u.b[j] != 0 && u.l) u.l <<= 1; }}/* Transform each WORD's byte-ordering in a buffer of the designated length.*/static voidwp_bmap(buf, len)WORD *buf;int len;{ union { BYTE b[sizeof (WORD)]; WORD w; } in, out; register int i; if (word_same) return; while (len--) { in.w = *buf; for (i = 0; i < sizeof (WORD); i++) out.b[my_bmap.w[i]] = in.b[mt_bmap.w[i]]; *buf++ = out.w; }}/* Transform each LONG's byte-ordering in a buffer of the designated length.*/static voidlp_bmap(buf, len)LONG *buf;int len;{ union { BYTE b[sizeof (LONG)]; LONG l; } in, out; register int i; if (long_same) return; while (len--) { in.l = *buf; for (i = 0; i < sizeof (LONG); i++) out.b[my_bmap.l[i]] = in.b[mt_bmap.l[i]]; *buf++ = out.l; }}#endif /* USE_MT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -