home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume27 / gcom / part04 < prev    next >
Text File  |  1992-01-13  |  43KB  |  1,800 lines

  1. Newsgroups: comp.sources.misc
  2. From: murf@oakhill.sps.mot.com (Steve Murphy)
  3. Subject:  v27i075:  gcom - GEDCOM genealogical database merge utility, v1, Part04/07
  4. Message-ID: <1992Jan13.145532.25538@sparky.imd.sterling.com>
  5. X-Md4-Signature: 45a2e9a9c93634ed8c8f513423dda538
  6. Date: Mon, 13 Jan 1992 14:55:32 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: murf@oakhill.sps.mot.com (Steve Murphy)
  10. Posting-number: Volume 27, Issue 75
  11. Archive-name: gcom/part04
  12. Environment: SunOS
  13.  
  14. ---- Cut Here and unpack ----
  15. #!/bin/sh
  16. # This is part 04 of gcom
  17. if touch 2>&1 | fgrep 'amc' > /dev/null
  18.  then TOUCH=touch
  19.  else TOUCH=true
  20. fi
  21. # ============= keys.gperf ==============
  22. echo "x - extracting keys.gperf (Text)"
  23. sed 's/^X//' << 'SHAR_EOF' > keys.gperf &&
  24. X%{
  25. Xstatic char rcs_stuff[] = "$Id: keys.gperf,v 1.2 1992/01/03 17:49:58 murf Exp $";
  26. X/*
  27. X# Copyright (C) 1992 Steven Michael Murphy
  28. X#
  29. X#
  30. X# This file is part of gcom, the GEDCOM file merging utility for UNIX,
  31. X# 
  32. X# 
  33. X# gcom is free software; you can redistribute it and/or modify
  34. X# it under the terms of the GNU General Public License as published by
  35. X# the Free Software Foundation; either version 2, or (at your option)
  36. X# any later version.
  37. X# 
  38. X# gcom is distributed in the hope that it will be useful,
  39. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  40. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  41. X# GNU General Public License for more details.
  42. X# 
  43. X# You should have received a copy of the GNU General Public License
  44. X# along with gcom; see the file COPYING.  If not, write to
  45. X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  46. X*/
  47. X#include <stdio.h>
  48. X#include "gedcom.b.tab.h"
  49. Xextern int lineno;
  50. Xstatic char buff[300]; /* Actually, 80 may be enough */
  51. Xstatic char *buff_ptr = &buff[0];
  52. X
  53. X
  54. XFILE *yyin;
  55. X%}
  56. Xstruct keyword {    char *name;     int val; };
  57. X%%
  58. XADDR, ADDR
  59. XBAPL, BAPL
  60. XCHAR, CHAR
  61. XCOMM, COMM
  62. XCONT, CONT
  63. XDATE, DATE
  64. XENDL, ENDL
  65. XFILE, FILE9
  66. XFLAG, FLAG
  67. XDEST, DEST
  68. XPHON, PHON
  69. XPLAC, PLAC
  70. XQUAL, QUAL
  71. XREL, REL
  72. XNOTE, NOTE
  73. XSEX, SEX
  74. XSOUR, SOUR
  75. XTEMP, TEMP
  76. XTITL, TITL
  77. XBIC, BIC
  78. XNUMB, NUMB
  79. XREFN, REFN
  80. XBIRT, BIRT
  81. XBURI, BURI
  82. XCHIL, CHIL
  83. XCHR, CHR
  84. XDEAT, DEAT
  85. XFAM, FAM
  86. XNAME, NAME
  87. XFAMC, FAMC
  88. XFAMS, FAMS
  89. XHEAD, HEAD
  90. XHUSB, HUSB
  91. XINDI, INDI
  92. XMARR, MARR
  93. XSTAL, STAL
  94. XTRLR, TRLR
  95. XWIFE, WIFE
  96. XSUBM, SUBM
  97. XSLGC, SLGC
  98. XSLGS, SLGS
  99. X%%
  100. X
  101. X
  102. Xyylex()
  103. X{
  104. X    struct keyword *kw;
  105. X    char *p;
  106. X    int i;
  107. X    
  108. X    if( !(*buff_ptr) )
  109. X    {
  110. X        int lev;
  111. X        if( !fgets(buff,300,yyin) )
  112. X        {
  113. X            return 0; /* end of file */
  114. X        }
  115. X        buff[strlen(buff)-1] = 0; /* blast the newline */
  116. X        lineno++;
  117. X        buff_ptr = &buff[0]; /* get a new line */
  118. X        /* the first thing on a line is the level number, get it */
  119. X        lev = strtol(buff,&p,10);
  120. X        if( p == buff_ptr )
  121. X        {
  122. X            fprintf(stderr,"No level number at the beginning of the line on line %d\n",
  123. X                    lineno);
  124. X            return LEV0;
  125. X        }
  126. X        buff_ptr = p;
  127. X        return LEV0+lev;
  128. X    }
  129. X    else
  130. X    {
  131. X        /* either a type or a reference */
  132. X        while(*buff_ptr &&
  133. X              (*buff_ptr == ' ' || *buff_ptr == '\t') )
  134. X            buff_ptr++;
  135. X        /* collect next token */
  136. X        p = buff_ptr;
  137. X        while( *buff_ptr && (*buff_ptr != ' ' && *buff_ptr != '\t' &&
  138. X                             *buff_ptr != '\n' ) )
  139. X            buff_ptr++;
  140. X        if( *p == '@' )
  141. X        {
  142. X            char x,*y;
  143. X            
  144. X            x = *buff_ptr;
  145. X            *buff_ptr = 0;
  146. X            p++; /* skip the @ stuff and just pass the ref id */
  147. X            yylval.str = (char *)malloc(buff_ptr-p);
  148. X            strncpy(yylval.str,p,buff_ptr-p);
  149. X            yylval.str[buff_ptr-p-1] = 0; /* leave out the '@'s */
  150. X            *buff_ptr = x;
  151. X            return REF;
  152. X        }
  153. X        if( !strncmp(p,"DIV",3) ) /* DIV is a slightly special case ... ? */
  154. X        {
  155. X            if( *(p+4) == 'Y' ) yylval.num = 1;
  156. X            else yylval.num = 0;
  157. X            *buff_ptr = 0; /* we are done here */
  158. X            return DIV;
  159. X        }
  160. X        *buff_ptr = 0;
  161. X        /* then match on the token, and return the rest of the line as
  162. X           the value */
  163. X        /* the tokens are arranged in a ______table. */
  164. X        kw = in_word_set(p,strlen(p));
  165. X        if( kw )
  166. X        {
  167. X            *buff_ptr = ' ';
  168. X            if( *(buff_ptr+1) == '@' )
  169. X            {
  170. X                return kw->val;
  171. X            }
  172. X            setyystr(p);
  173. X            *buff_ptr = 0; /* this will reset the lexer and read in a
  174. X                              new line next time.... */
  175. X            return kw->val;
  176. X        }
  177. X        else
  178. X        {
  179. X            /* else report error */
  180. X            fprintf(stderr,"HEY, '%s' is not a keyword I understand! (line %d)\n",
  181. X                    p, lineno);
  182. X        }
  183. X    }
  184. X}
  185. X
  186. X
  187. Xsetyystr(txt)
  188. Xchar *txt;
  189. X{
  190. X    int x=strlen(txt);
  191. X    char *y = txt;
  192. X    while( *y && *y != ' ' )
  193. X        y++;
  194. X    if( *y )
  195. X    {
  196. X        /* there is a space */
  197. X        x -= (y-txt);
  198. X        y++;
  199. X        yylval.str = (char *)malloc(x);
  200. X        strcpy(yylval.str,y);
  201. X    }
  202. X    else
  203. X        yylval.str = "";
  204. X}
  205. X
  206. SHAR_EOF
  207. $TOUCH -am 0103114992 keys.gperf &&
  208. chmod 0664 keys.gperf ||
  209. echo "restore of keys.gperf failed"
  210. set `wc -c keys.gperf`;Wc_c=$1
  211. if test "$Wc_c" != "3657"; then
  212.     echo original size 3657, current size $Wc_c
  213. fi
  214. # ============= gedmerge.c ==============
  215. echo "x - extracting gedmerge.c (Text)"
  216. sed 's/^X//' << 'SHAR_EOF' > gedmerge.c &&
  217. Xstatic char rcs_stuff[] = "$Id: gedmerge.c,v 1.2 1992/01/03 17:49:55 murf Exp $";
  218. X#include <stdio.h>
  219. X#include "gedcom.h"
  220. X#include <ctype.h>
  221. X/*
  222. X# Copyright (C) 1992 Steven Michael Murphy
  223. X#
  224. X#
  225. X# This file is part of gcom, the GEDCOM file merging utility for UNIX,
  226. X# 
  227. X# 
  228. X# gcom is free software; you can redistribute it and/or modify
  229. X# it under the terms of the GNU General Public License as published by
  230. X# the Free Software Foundation; either version 2, or (at your option)
  231. X# any later version.
  232. X# 
  233. X# gcom is distributed in the hope that it will be useful,
  234. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  235. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  236. X# GNU General Public License for more details.
  237. X# 
  238. X# You should have received a copy of the GNU General Public License
  239. X# along with gcom; see the file COPYING.  If not, write to
  240. X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  241. X*/
  242. X
  243. X/* all the merges will try to take stuff in b and "add it" to a. */
  244. X
  245. Xvoid merge_strings(a,b,what)
  246. Xchar **a,**b,*what;
  247. X{
  248. X    if( *a && *b && strcmp(*a,*b) )
  249. X        fprintf(stderr,"!!!!! %ss differ.... ref=%s, addit=%s\n", 
  250. X                what,*a,*b);
  251. X    else if( !(*a) && (*b) )
  252. X    {
  253. X        *a = *b;
  254. X        *b=0; /* at the same time, take away from b */
  255. X        fprintf(stderr,"added %s to ref (%s)\n", what, *a);
  256. X    }
  257. X}
  258. X
  259. Xvoid merge_datplace(a,b)
  260. Xstruct datplace **a,**b;
  261. X{
  262. X    if( !(*a) && !(*b) ) /* neither has any */
  263. X        return;
  264. X    if( !(*b) ) /* a has something and b does not */
  265. X        return;
  266. X    if( !(*a) && *b)
  267. X    {
  268. X        /* b has some, add to a */
  269. X        *a = Calloc(struct  datplace);
  270. X    }
  271. X    merge_strings(&(*a)->date,&(*b)->date,"date");
  272. X    merge_strings(&(*a)->place,&(*b)->place,"place");
  273. X}
  274. X
  275. Xvoid merge_ordinance(a,b)
  276. Xstruct ordinance **a,**b;
  277. X{
  278. X    if( !(*a) && !(*b) ) /* neither has any */
  279. X        return;
  280. X    if( !(*b) ) /* a has something and b does not */
  281. X        return;
  282. X    if( !(*a) && *b)
  283. X    {
  284. X        /* b has some, add to a */
  285. X        *a = Calloc(struct  ordinance);
  286. X    }
  287. X    merge_strings(&(*a)->date,&(*b)->date,"date");
  288. X    merge_strings(&(*a)->qual,&(*b)->qual,"qualifier");
  289. X    merge_strings(&(*a)->val,&(*b)->val,"temple ord desc");
  290. X    if( (*a)->temp[0] && (*b)->temp[0] && strcmp((*a)->temp,(*b)->temp) )
  291. X        fprintf(stderr,"!!!!! temples differ... ref=%s, addit=%s\n",
  292. X                    (*a)->temp,(*b)->temp);
  293. X}
  294. X
  295. Xvoid merge_notes(a,b)
  296. Xstruct notelist **a,**b;
  297. X{
  298. X    int i,j,k,match;
  299. X    
  300. X    if( !(*a) && !(*b) ) /* neither has any */
  301. X        return;
  302. X    if( !(*b) ) /* a has something and b does not */
  303. X        return;
  304. X    if( !(*a) && *b)
  305. X    {
  306. X        /* b has some, add to a */
  307. X        *a = Calloc(struct  notelist);
  308. X    }
  309. X    /* only copy in notes not an exact duplication of previous
  310. X         notes */
  311. X    for(i=0; i < (*b)->notes; i++)
  312. X    {
  313. X        for(match=0,j=0; j < (*a)->notes; j++)
  314. X        {
  315. X            /* either every comment entry in b matches every
  316. X            comment entry in a or, the note in b can be added to a */
  317. X            if( (*a)->note[j].lines != (*b)->note[i].lines )
  318. X            {
  319. X                continue;
  320. X            }
  321. X                
  322. X            for(k=0; k < (*a)->note[j].lines; k++)
  323. X            {
  324. X                if( strcmp((*a)->note[j].line[k], (*b)->note[i].line[k]))
  325. X                {
  326. X                    match = -1;
  327. X                    break;
  328. X                }
  329. X            }
  330. X            if( !match )
  331. X            {
  332. X                /* I know this is confusing, but the above loop will turn
  333. X                   out a -1 if it sees a non-match. if it sees no non-matches
  334. X                   it will drop out without changing match. This means a
  335. X                   match with match zero. Apply an inverter: */
  336. X                match  = 1;
  337. X                break;
  338. X            }
  339. X        } /* j for loop */
  340. X        if ( !match )
  341. X        {
  342. X            /* no match, so add this morsel of b into a */
  343. X            if( (*a)->notes )
  344. X                (*a)->note = (struct comment *)realloc((*a)->note,
  345. X                                   sizeof(struct comment)*((*a)->notes+1));
  346. X            else
  347. X                (*a)->note = Calloc(struct comment);
  348. X            (*a)->note[(*a)->notes].lines = (*b)->note[i].lines;
  349. X            (*a)->note[(*a)->notes].line = (*b)->note[i].line;
  350. X            /* make the transfer of information complete */
  351. X            (*b)->note[i].lines = 0;
  352. X            fprintf(stderr,"added note to ref database, '%s.....'\n",
  353. X                (*a)->note[(*a)->notes].line[0]);
  354. X            (*a)->notes++;
  355. X        }
  356. X    }
  357. X}
  358. X
  359. Xvoid merge_address(a,b)
  360. Xstruct address **a,**b;
  361. X{
  362. X/* since addresses are only in the submission stuff, 
  363. Xleave it alone */
  364. X}
  365. X
  366. Xvoid merge_stake(a,b)
  367. Xstruct stake **a,**b;
  368. X{
  369. X/* since stake info are only in the submission stuff, leave it */
  370. X}
  371. X
  372. Xvoid merge_comment(a,b)
  373. Xstruct comment **a,**b;
  374. X{
  375. X    int i,j,different;
  376. X    
  377. X    if( !(*a) && !(*b) ) /* neither has any */
  378. X        return;
  379. X    if( !(*b) ) /* a has something and b does not */
  380. X        return;
  381. X    if( !(*a) && *b)
  382. X    {
  383. X        /* b has some, add to a */
  384. X        *a = Calloc(struct  comment);
  385. X    }
  386. X    /* all the lines of a comment match, or the comment in b is
  387. X         added to a */
  388. X    if( (*a)->lines != (*b)->lines )
  389. X        different = 1;
  390. X    else 
  391. X        different = 0;
  392. X    
  393. X}
  394. X
  395. Xvoid upcase(str)
  396. Xchar *str;
  397. X{
  398. X    char *p,toupper();
  399. X    p = str;
  400. X    while( *p )
  401. X    {
  402. X        if( islower(*p) )
  403. X            *p = toupper(*p);
  404. X        p++;
  405. X    }
  406. X}
  407. X
  408. Xint my_strcmp(a,b)
  409. Xchar *a,*b;
  410. X{
  411. X    char buf1[300],buf2[300];
  412. X    
  413. X    strcpy(buf1,a);
  414. X    strcpy(buf2,b);
  415. X    upcase(buf1);
  416. X    upcase(buf2);
  417. X    return(strcmp(buf1,buf2));
  418. X}
  419. X
  420. Xint same_individual(a,b)
  421. Xstruct individ *a,*b;
  422. X{
  423. X    /* this routine is trying to determine if two seperate individuals
  424. X    could be considered to be the same person. */
  425. X    /* the name MUST match -- if not, edit the input files
  426. X          and try again.........!*/
  427. X    if( a->birth && b->birth )
  428. X    {
  429. X        if(a->birth->date && b->birth->date )
  430. X        {
  431. X            if( my_strcmp(a->birth->date, b->birth->date) )
  432. X                return 0;
  433. X        }
  434. X    }
  435. X    else
  436. X        return 0;
  437. X    if( a->title && !b->title || !a->title && b->title )
  438. X        return 0;
  439. X    if( a->title && b->title && my_strcmp(a->title,b->title) )
  440. X        return 0;
  441. X    if( !my_strcmp(a->name, b->name) )
  442. X        return 1;
  443. X    else 
  444. X        return 0;
  445. X}
  446. Xvoid merge_fams(a,b)
  447. Xstruct family *a,*b;
  448. X{
  449. X    fprintf(stderr,"*****Merging data for Family %s...\n", a->ref);
  450. X    merge_datplace(&a->marriage,&b->marriage);
  451. X    merge_ordinance(&a->sealspouse,&b->sealspouse);
  452. X}
  453. X
  454. Xvoid merge_individ(a,b)
  455. Xstruct individ *a,*b;
  456. X{
  457. X    fprintf(stderr,"*****Merging data for %s...\n", a->name);
  458. X    /* it is assumed these individuals are supposed to be the same
  459. X       person. merge the data within each into "a" */
  460. X    merge_strings(&a->name,&b->name,"name");
  461. X    merge_strings(&a->title,&b->title, "title");
  462. X    merge_strings(&a->givenref, &b->givenref,"ref");
  463. X    merge_strings(&a->flag,&b->flag,"flag");
  464. X    merge_notes(&a->notes,&b->notes);
  465. X    merge_datplace(&a->birth,&b->birth);
  466. X    merge_datplace(&a->christen,&b->christen);
  467. X    merge_datplace(&a->death,&b->death);
  468. X    merge_datplace(&a->burial,&b->burial);
  469. X    merge_ordinance(&a->baptism,&b->baptism);
  470. X    merge_ordinance(&a->endow,&b->endow);
  471. X    merge_ordinance(&a->child_to_parent,&b->child_to_parent);
  472. X    if( !a->sex && b->sex )
  473. X        a->sex = b->sex;
  474. X    else if( a->sex != b->sex )
  475. X        fprintf(stderr,"!!!!! He or She? Sex mismatch! ref = %s, addit= %s\n", a->name, b->name);
  476. X}
  477. X
  478. Xmerge_dbs(ged1,ged2)
  479. Xstruct gedfile *ged1,*ged2;
  480. X{
  481. X    int i,overlapi,overlapf,numinds,numfams;
  482. X    struct individ *ind1,*ind2;
  483. X    struct family *fam1,*fam2;
  484. X    overlapi=overlapf=numinds=numfams = 0;
  485. X    
  486. X    for(i=0; i < ged1->indlist->num; i++)
  487. X    {
  488. X        if( ged1->indlist->ind[i]->corr.match_ind )
  489. X        {
  490. X            ind1 = ged1->indlist->ind[i];
  491. X            ind2 = ged2->indlist->ind[ind1->corr.index];
  492. X            merge_individ(ind1,ind2);
  493. X            overlapi++;
  494. X        }
  495. X        numinds++;
  496. X    }
  497. X    for(i=0; i < ged1->famlist->num; i++)
  498. X    {
  499. X        if( ged1->famlist->fam[i]->corr.match_ind )
  500. X        {
  501. X            fam1 = ged1->famlist->fam[i];
  502. X            fam2 = ged2->famlist->fam[fam1->corr.index];
  503. X            merge_fams(fam1,fam2);
  504. X            overlapf++;
  505. X        }
  506. X        numfams++;
  507. X    }
  508. X    fprintf(stderr,"upon completion of data merging, the ref database\n\
  509. Xnow holds %d individuals and %d families, with %d individs and %d fams \n\
  510. Xoverlapping between databases\n", numinds, numfams, overlapi, overlapf);
  511. X}
  512. X
  513. X
  514. SHAR_EOF
  515. $TOUCH -am 0103114992 gedmerge.c &&
  516. chmod 0664 gedmerge.c ||
  517. echo "restore of gedmerge.c failed"
  518. set `wc -c gedmerge.c`;Wc_c=$1
  519. if test "$Wc_c" != "7479"; then
  520.     echo original size 7479, current size $Wc_c
  521. fi
  522. # ============= st.c ==============
  523. echo "x - extracting st.c (Text)"
  524. sed 's/^X//' << 'SHAR_EOF' > st.c &&
  525. Xstatic char rcs_stuff[] = "$Id: st.c,v 1.1.1.1 1992/01/03 17:10:25 murf Exp $";
  526. X/*LINTLIBRARY*/
  527. X/*
  528. X * String Table (Hash) Package
  529. X *
  530. X * Peter Moore
  531. X * University of California, Berkeley
  532. X * 1985
  533. X *  
  534. X * This is a general purpose hash table package.
  535. X */
  536. X
  537. X
  538. X#ifndef OCTTOOLS_COPYRIGHT_H
  539. X#define OCTTOOLS_COPYRIGHT_H
  540. X/*
  541. X * Oct Tools Distribution 3.0
  542. X *
  543. X * Copyright (c) 1988, 1989, Regents of the University of California.
  544. X * All rights reserved.
  545. X *
  546. X * Use and copying of this software and preparation of derivative works
  547. X * based upon this software are permitted.  However, any distribution of
  548. X * this software or derivative works must include the above copyright
  549. X * notice.
  550. X *
  551. X * This software is made available AS IS, and neither the Electronics
  552. X * Research Laboratory or the University of California make any
  553. X * warranty about the software, its performance or its conformity to
  554. X * any specification.
  555. X *
  556. X * Suggestions, comments, or improvements are welcome and should be
  557. X * addressed to:
  558. X *
  559. X *   octtools@eros.berkeley.edu
  560. X *   ..!ucbvax!eros!octtools
  561. X */
  562. X
  563. X#if !defined(lint) && !defined(SABER)
  564. X#ifdef MCC
  565. Xstatic char octtools_copyright[] = "\
  566. XCopyright (C) 1988, 1989, Regents of the University of California.  All rights reserved.\n\
  567. XCopyright (C) 1989, Microelectronics and Computer Technology Corporation. All rights reserved.";
  568. X#else
  569. Xstatic char octtools_copyright[] = "Copyright (c) 1988, 1989, Regents of the University of California.  All rights reserved.";
  570. X#endif /* MCC */
  571. X#endif
  572. X#endif 
  573. X#ifndef PORT_H
  574. X#define PORT_H
  575. X
  576. X#ifdef SABER
  577. X#define volatile
  578. X#endif
  579. X
  580. X/*
  581. X * int32 should be defined as the most economical sized integer capable of
  582. X * holding a 32 bit quantity
  583. X * int16 should be similarly defined
  584. X */
  585. X
  586. X/* XXX hack */
  587. X#ifndef MACHDEP_INCLUDED
  588. X#define MACHDEP_INCLUDED
  589. X#ifdef vax
  590. Xtypedef int int32;
  591. Xtypedef short int16;
  592. X#else
  593. X     /* Ansi-C promises that these definitions should always work */
  594. Xtypedef long int32;
  595. Xtypedef int int16;
  596. X#endif /* vax */
  597. X#endif /* MACHDEP_INCLUDED */
  598. X
  599. X
  600. X#ifndef __STDC__
  601. X#ifndef __DATE__
  602. X#ifdef CUR_DATE
  603. X#define __DATE__    CUR_DATE
  604. X#else
  605. X#define __DATE__    "unknown-date"
  606. X#endif /* CUR_DATE */
  607. X#endif /* __DATE__ */
  608. X
  609. X#ifndef __TIME__
  610. X#ifdef CUR_TIME
  611. X#define __TIME__    CUR_TIME
  612. X#else
  613. X#define __TIME__    "unknown-time"
  614. X#endif /* CUR_TIME */
  615. X#endif /* __TIME__ */
  616. X#endif /* __STDC__ */
  617. X
  618. X#ifdef sun386
  619. X#define PORTAR
  620. X#endif
  621. X
  622. X#include <stdio.h>
  623. X#include <ctype.h>
  624. X#ifdef macintosh
  625. X#include <Types.h>
  626. X#else
  627. X#include <sys/types.h>
  628. X#endif
  629. X#undef HUGE
  630. X#include <math.h>
  631. X#include <signal.h>
  632. X
  633. X#if defined(ultrix)  /* { */
  634. X#if defined(_SIZE_T_) /* { */
  635. X#define ultrix4
  636. X#else             /* } else { */
  637. X#if defined(SIGLOST) /* { */
  638. X#define ultrix3
  639. X#else                /* } else { */
  640. X#define ultrix2
  641. X#endif               /* } */
  642. X#endif               /* } */
  643. X#endif               /* } */
  644. X
  645. X#if defined(ultrix3) && defined(mips)
  646. Xextern double rint();
  647. Xextern double trunc();
  648. X#endif
  649. X
  650. X#if defined(sun) && defined(FD_SETSIZE)
  651. X#define sunos4
  652. X#else
  653. X#define sunos3
  654. X#endif
  655. X
  656. X#if defined(sequent) || defined(news800)
  657. X#define LACK_SYS5
  658. X#endif
  659. X
  660. X#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2)
  661. X#define SIGNAL_FN    void
  662. X#else
  663. X/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */
  664. X#define SIGNAL_FN    int
  665. X#endif
  666. X
  667. X/* Some systems have 'fixed' certain functions which used to be int */
  668. X#if defined(ultrix) || defined(SABER) || defined(hpux) || defined(aiws) || defined(apollo) || defined(__STDC__)
  669. X#define VOID_HACK void
  670. X#else
  671. X#define VOID_HACK int
  672. X#endif
  673. X
  674. X#ifndef NULL
  675. X#define NULL 0
  676. X#endif /* NULL */
  677. X
  678. X/*
  679. X * CHARBITS should be defined only if the compiler lacks "unsigned char".
  680. X * It should be a mask, e.g. 0377 for an 8-bit machine.
  681. X */
  682. X
  683. X#ifndef CHARBITS
  684. X#    define    UNSCHAR(c)    ((unsigned char)(c))
  685. X#else
  686. X#    define    UNSCHAR(c)    ((c)&CHARBITS)
  687. X#endif
  688. X
  689. X#define SIZET int
  690. X
  691. X#ifdef __STDC__
  692. X#define CONST const
  693. X#define VOIDSTAR   void *
  694. X#else
  695. X#define CONST
  696. X#define VOIDSTAR   char *
  697. X#endif /* __STDC__ */
  698. X
  699. X
  700. X/* Some machines fail to define some functions in stdio.h */
  701. X#ifndef __STDC__
  702. Xextern FILE *popen(), *tmpfile();
  703. Xextern int pclose();
  704. X#ifndef clearerr        /* is a macro on many machines, but not all */
  705. Xextern VOID_HACK clearerr();
  706. X#endif /* clearerr */
  707. X#ifndef rewind
  708. X#ifndef macintosh
  709. Xextern VOID_HACK rewind();
  710. X#endif
  711. X#endif /* rewind */
  712. X#endif /* __STDC__ */
  713. X
  714. X
  715. X/* most machines don't give us a header file for these */
  716. X#ifdef __STDC__
  717. X#include <stdlib.h>
  718. X#else
  719. X#ifdef hpux
  720. Xextern int abort();
  721. Xextern void free(), exit(), perror();
  722. X#else
  723. X#ifndef macintosh
  724. Xextern VOID_HACK abort(), free(), exit(), perror();
  725. X#endif
  726. X#endif /* hpux */
  727. Xextern char *getenv(), *malloc(), *realloc(), *calloc();
  728. X#ifdef aiws
  729. Xextern int sprintf();
  730. X#else
  731. X#ifndef macintosh
  732. Xextern char *sprintf();
  733. X#endif
  734. X#endif
  735. Xextern int system();
  736. Xextern double atof();
  737. Xextern long atol();
  738. Xextern int sscanf();
  739. X#endif /* __STDC__ */
  740. X
  741. X
  742. X/* some call it strings.h, some call it string.h; others, also have memory.h */
  743. X#ifdef __STDC__
  744. X#include <string.h>
  745. X#else
  746. X/* ANSI C string.h -- 1/11/88 Draft Standard */
  747. X#if defined(ultrix4)
  748. X#include <strings.h>
  749. X#else
  750. Xextern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror();
  751. Xextern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr();
  752. Xextern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn();
  753. Xextern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset();
  754. Xextern int memcmp(), strcmp();
  755. X#endif /* ultrix4 */
  756. X#endif /* __STDC__ */
  757. X
  758. X#ifdef lint
  759. X#undef putc            /* correct lint '_flsbuf' bug */
  760. X#endif /* lint */
  761. X
  762. X/* a few extras */
  763. Xextern VOID_HACK srandom();
  764. Xextern long random();
  765. X
  766. X#if defined(ultrix3)
  767. Xextern unsigned sleep();
  768. X#else
  769. Xextern VOID_HACK sleep();
  770. X#endif
  771. X
  772. X/* assertion macro */
  773. X
  774. X#ifndef assert
  775. X#ifdef __STDC__
  776. X#include <assert.h>
  777. X#else
  778. X#ifndef NDEBUG
  779. X#define assert(ex) {\
  780. X    if (! (ex)) {\
  781. X    (void) fprintf(stderr, "Assertion failed: file %s, line %d\n",\
  782. X        __FILE__, __LINE__);\
  783. X    (void) fflush(stdout);\
  784. X    abort();\
  785. X    }\
  786. X}
  787. X#else
  788. X#define assert(ex) {;}
  789. X#endif
  790. X#endif
  791. X#endif
  792. X
  793. X/* handle the various limits */
  794. X#if defined(__STDC__) || defined(POSIX)
  795. X#include <limits.h>
  796. X#else
  797. X#define USHRT_MAX    (~ (unsigned short int) 0)
  798. X#define UINT_MAX    (~ (unsigned int) 0)
  799. X#define ULONG_MAX    (~ (unsigned long int) 0)
  800. X#define SHRT_MAX    ((short int) (USHRT_MAX >> 1))
  801. X#define INT_MAX        ((int) (UINT_MAX >> 1))
  802. X#define LONG_MAX    ((long int) (ULONG_MAX >> 1))
  803. X#endif
  804. X
  805. X#endif /* PORT_H */
  806. X
  807. X#include "errtrap.h"
  808. X#ifndef UTILITY_H
  809. X#define UTILITY_H
  810. X
  811. X/*
  812. X *  assumes the memory manager is libmm.a
  813. X *    - allows malloc(0) or realloc(obj, 0)
  814. X *    - catches out of memory (and calls MMout_of_memory())
  815. X *    - catch free(0) and realloc(0, size) in the macros
  816. X */
  817. X#define NIL(type)        ((type *) 0)
  818. X#define ALLOC(type, num)    \
  819. X    ((type *) malloc(sizeof(type) * (num)))
  820. X#define REALLOC(type, obj, num)    \
  821. X    (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
  822. X        ((type *) malloc(sizeof(type) * (num)))
  823. X#define FREE(obj)        \
  824. X    if ((obj)) { (void) free((char *) (obj)); (obj) = 0; }
  825. X
  826. X
  827. Xextern long  util_cpu_time();
  828. Xextern char *util_path_search
  829. X    ARGS((char *program));
  830. Xextern char *util_file_search
  831. X    ARGS((char *file, char *path, char *mode));
  832. Xextern int   util_pipefork
  833. X    ARGS((char **argv, FILE **toCommand, FILE **fromCommand));
  834. Xextern int   util_csystem
  835. X    ARGS((char *command));
  836. Xextern char *util_print_time
  837. X    ARGS((long t));
  838. Xextern char *util_strsav
  839. X    ARGS((char *ptr));
  840. Xextern char *util_tilde_expand
  841. X    ARGS((char *filename));
  842. X
  843. X#ifndef NIL_FN
  844. X#define NIL_FN(type) ((type (*)()) 0)
  845. X#endif /* NIL_FN */
  846. X
  847. X#ifndef MAX
  848. X#define MAX(a,b)    ((a) > (b) ? (a) : (b))
  849. X#endif /* MAX */
  850. X#ifndef MIN
  851. X#define MIN(a,b)    ((a) < (b) ? (a) : (b))
  852. X#endif /* MIN */
  853. X#ifndef ABS
  854. X#define ABS(a)        ((a) > 0 ? (a) : -(a))
  855. X#endif /* ABS */
  856. X
  857. X
  858. X#ifdef lint
  859. X#undef ALLOC            /* allow for lint -h flag */
  860. X#undef REALLOC
  861. X#define ALLOC(type, num)    (((type *) 0) + (num))
  862. X#define REALLOC(type, obj, num)    ((obj) + (num))
  863. X#endif /* lint */
  864. X
  865. X#endif
  866. X
  867. X#include "st.h"
  868. X
  869. X#define ST_NUMCMP(x,y) ((int) (x) - (int) (y))
  870. X#define ST_NUMHASH(x,size) (ABS((int)x)%(size))
  871. X#define ST_PTRHASH(x,size) ((int)((unsigned)(x)>>2)%size)
  872. X#define ST_EQUAL(func, x, y) \
  873. X    ((((func) == st_numcmp) || ((func) == st_ptrcmp)) ?\
  874. X      (ST_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
  875. X
  876. X
  877. X#define do_hash(key, table)\
  878. X    ((table->hash == st_ptrhash) ? ST_PTRHASH((key),(table)->num_bins) :\
  879. X     (table->hash == st_numhash) ? ST_NUMHASH((key), (table)->num_bins) :\
  880. X     (*table->hash)((key), (table)->num_bins))
  881. X
  882. Xchar st_pkg_name[] = "st";
  883. X
  884. X/* Possible error conditions */
  885. Xchar *st_no_mem = "out of memory";
  886. Xchar *st_bad_ret = "bad return code from function passed to st_foreach";
  887. Xchar *st_bad_gen = "null or zero generator";
  888. X
  889. X/* Forward declarations */
  890. Xint st_numhash(), st_ptrhash(), st_numcmp(), st_ptrcmp();
  891. Xstatic void rehash();
  892. X
  893. X
  894. Xst_table *st_init_table_with_params(compare, hash, size, density, grow_factor,
  895. X                    reorder_flag)
  896. Xint (*compare)();
  897. Xint (*hash)();
  898. Xint size;
  899. Xint density;
  900. Xdouble grow_factor;
  901. Xint reorder_flag;
  902. X/* Detailed table allocator */
  903. X{
  904. X    st_table *new;
  905. X
  906. X    new = ALLOC(st_table, 1);
  907. X    if (!new) {
  908. X    errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);
  909. X    /* NOTREACHED */
  910. X    }
  911. X    new->compare = compare;
  912. X    new->hash = hash;
  913. X    new->num_entries = 0;
  914. X    new->max_density = density;
  915. X    new->grow_factor = grow_factor;
  916. X    new->reorder_flag = reorder_flag;
  917. X    if (size <= 0) {
  918. X    size = 1;
  919. X    }
  920. X    new->num_bins = size;
  921. X    new->bins = 
  922. X    (st_table_entry **) calloc((unsigned)size, sizeof(st_table_entry *));
  923. X    if (!new->bins) {
  924. X    free((char *) new);
  925. X    errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);
  926. X    /* NOTREACHED */
  927. X    }
  928. X    return new;
  929. X}
  930. X
  931. Xst_table *st_init_table(compare, hash)
  932. Xint (*compare)();
  933. Xint (*hash)();
  934. X/* Default table allocator */
  935. X{
  936. X    return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
  937. X                     ST_DEFAULT_MAX_DENSITY,
  938. X                     ST_DEFAULT_GROW_FACTOR,
  939. X                     ST_DEFAULT_REORDER_FLAG);
  940. X}
  941. X                 
  942. X
  943. Xvoid
  944. Xst_free_table(table)
  945. Xst_table *table;
  946. X/* Destroy a table */
  947. X{
  948. X    register st_table_entry *ptr, *next;
  949. X    int i;
  950. X
  951. X    for(i = 0; i < table->num_bins ; i++) {
  952. X    ptr = table->bins[i];
  953. X    while (ptr != NIL(st_table_entry)) {
  954. X        next = ptr->next;
  955. X        free((char *) ptr);
  956. X        ptr = next;
  957. X    }
  958. X    }
  959. X    free((char *) table->bins);
  960. X    free((char *) table);
  961. X}
  962. X
  963. X
  964. X#define ST_PTR_NOT_EQUAL(table, ptr, user_key)\
  965. X(ptr != NIL(st_table_entry) && !ST_EQUAL(table->compare, user_key, (ptr)->key))
  966. X
  967. X#define FIND_ENTRY(table, hash_val, key, ptr, last) \
  968. X    (last) = &(table)->bins[hash_val];\
  969. X    (ptr) = *(last);\
  970. X    while (ST_PTR_NOT_EQUAL((table), (ptr), (key))) {\
  971. X    (last) = &(ptr)->next; (ptr) = *(last);\
  972. X    }\
  973. X    if ((ptr) != NIL(st_table_entry) && (table)->reorder_flag) {\
  974. X    *(last) = (ptr)->next;\
  975. X    (ptr)->next = (table)->bins[hash_val];\
  976. X    (table)->bins[hash_val] = (ptr);\
  977. X    }
  978. X
  979. Xint st_lookup(table, key, value)
  980. Xst_table *table;
  981. Xregister char *key;
  982. Xchar **value;
  983. X/* Look up item in table -- return zero if not found */
  984. X{
  985. X    int hash_val;
  986. X    register st_table_entry *ptr, **last;
  987. X
  988. X    hash_val = do_hash(key, table);
  989. X
  990. X    FIND_ENTRY(table, hash_val, key, ptr, last);
  991. X    
  992. X    if (ptr == NIL(st_table_entry)) {
  993. X    return 0;
  994. X    } else {
  995. X    if (value != NIL(char *))  *value = ptr->record; 
  996. X    return 1;
  997. X    }
  998. X}
  999. X
  1000. X#define ADD_DIRECT(table, key, value, hash_val, new)\
  1001. X{\
  1002. X    if (table->num_entries/table->num_bins >= table->max_density) {\
  1003. X    rehash(table);\
  1004. X    hash_val = do_hash(key,table);\
  1005. X    }\
  1006. X    \
  1007. X    new = ALLOC(st_table_entry, 1);\
  1008. X    \
  1009. X    if (new) {\
  1010. X    new->key = key;\
  1011. X    new->record = value;\
  1012. X    new->next = table->bins[hash_val];\
  1013. X    table->bins[hash_val] = new;\
  1014. X    table->num_entries++;\
  1015. X    } else {\
  1016. X    errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);\
  1017. X    /* NOTREACHED */ \
  1018. X    } \
  1019. X}
  1020. X
  1021. Xint st_insert(table, key, value)
  1022. Xregister st_table *table;
  1023. Xregister char *key;
  1024. Xchar *value;
  1025. X/* Insert an item into the table - replacing if it already exists */
  1026. X{
  1027. X    int hash_val;
  1028. X    st_table_entry *new;
  1029. X    register st_table_entry *ptr, **last;
  1030. X
  1031. X    hash_val = do_hash(key, table);
  1032. X
  1033. X    FIND_ENTRY(table, hash_val, key, ptr, last);
  1034. X
  1035. X    if (ptr == NIL(st_table_entry)) {
  1036. X    ADD_DIRECT(table,key,value,hash_val,new);
  1037. X    return 0;
  1038. X    } else {
  1039. X    ptr->record = value;
  1040. X    return 1;
  1041. X    }
  1042. X}
  1043. X
  1044. Xvoid st_add_direct(table, key, value)
  1045. Xst_table *table;
  1046. Xchar *key;
  1047. Xchar *value;
  1048. X/* Add item to table without checking for existing item */
  1049. X{
  1050. X    int hash_val;
  1051. X    st_table_entry *new;
  1052. X    
  1053. X    hash_val = do_hash(key, table);
  1054. X    ADD_DIRECT(table, key, value, hash_val, new);
  1055. X}
  1056. X
  1057. Xint st_find_or_add(table, key, slot)
  1058. Xst_table *table;
  1059. Xchar *key;
  1060. Xchar ***slot;
  1061. X/* Return slot for key - make one if one doesn't exist */
  1062. X{
  1063. X    int hash_val;
  1064. X    st_table_entry *new, *ptr, **last;
  1065. X
  1066. X    hash_val = do_hash(key, table);
  1067. X
  1068. X    FIND_ENTRY(table, hash_val, key, ptr, last);
  1069. X
  1070. X    if (ptr == NIL(st_table_entry)) {
  1071. X    ADD_DIRECT(table, key, (char *)0, hash_val, new);
  1072. X    if (slot != NIL(char **)) *slot = &new->record;
  1073. X    return 0;
  1074. X    } else {
  1075. X    if (slot != NIL(char **)) *slot = &ptr->record;
  1076. X    return 1;
  1077. X    }
  1078. X}
  1079. X
  1080. Xint st_find(table, key, slot)
  1081. Xst_table *table;
  1082. Xchar *key;
  1083. Xchar ***slot;
  1084. X/* Finds an entry in table */
  1085. X{
  1086. X    int hash_val;
  1087. X    st_table_entry *ptr, **last;
  1088. X
  1089. X    hash_val = do_hash(key, table);
  1090. X
  1091. X    FIND_ENTRY(table, hash_val, key, ptr, last);
  1092. X
  1093. X    if (ptr == NIL(st_table_entry)) {
  1094. X    return 0;
  1095. X    } else {
  1096. X    if (slot != NIL(char **)) *slot = &ptr->record;
  1097. X    return 1;
  1098. X    }
  1099. X}
  1100. X
  1101. Xstatic void rehash(table)
  1102. Xregister st_table *table;
  1103. X/* Grows table */
  1104. X{
  1105. X    register st_table_entry *ptr, *next, **old_bins = table->bins;
  1106. X    int i, old_num_bins = table->num_bins, hash_val;
  1107. X
  1108. X    table->num_bins = table->grow_factor*old_num_bins;
  1109. X    
  1110. X    if (table->num_bins%2 == 0) {
  1111. X    table->num_bins += 1;
  1112. X    }
  1113. X    
  1114. X    table->bins = 
  1115. X      (st_table_entry **) calloc((unsigned) table->num_bins,
  1116. X        sizeof(st_table_entry *));
  1117. X
  1118. X    if (!table->bins) {
  1119. X    /* If out of memory: don't resize */
  1120. X          table->bins = old_bins;
  1121. X    table->num_bins = old_num_bins;
  1122. X    return;
  1123. X    }
  1124. X    
  1125. X    table->num_entries = 0;
  1126. X
  1127. X    for(i = 0; i < old_num_bins ; i++) {
  1128. X    ptr = old_bins[i];
  1129. X    while (ptr != NIL(st_table_entry)) {
  1130. X        next = ptr->next;
  1131. X        hash_val = do_hash(ptr->key, table);
  1132. X        ptr->next = table->bins[hash_val];
  1133. X        table->bins[hash_val] = ptr;
  1134. X        table->num_entries++;
  1135. X        ptr = next;
  1136. X    }
  1137. X    }
  1138. X    free((char *) old_bins);
  1139. X}
  1140. X
  1141. Xst_table *st_copy(old_table)
  1142. Xst_table *old_table;
  1143. X{
  1144. X    st_table *new_table;
  1145. X    st_table_entry *ptr, *new;
  1146. X    int i, num_bins = old_table->num_bins;
  1147. X
  1148. X    new_table = ALLOC(st_table, 1);
  1149. X    if (new_table == NIL(st_table)) {
  1150. X    errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);
  1151. X    /* NOTREACHED */
  1152. X    }
  1153. X    
  1154. X    *new_table = *old_table;
  1155. X    new_table->bins = 
  1156. X      (st_table_entry **) calloc((unsigned) num_bins, sizeof(st_table_entry *));
  1157. X    
  1158. X    if (new_table->bins == NIL(st_table_entry *)) {
  1159. X    free((char *) new_table);
  1160. X    errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);
  1161. X    /* NOTREACHED */
  1162. X    }
  1163. X
  1164. X    for(i = 0; i < num_bins ; i++) {
  1165. X    new_table->bins[i] = NIL(st_table_entry);
  1166. X    ptr = old_table->bins[i];
  1167. X    while (ptr != NIL(st_table_entry)) {
  1168. X        new = ALLOC(st_table_entry, 1);
  1169. X        if (new == NIL(st_table_entry)) {
  1170. X        free((char *) new_table->bins);
  1171. X        free((char *) new_table);
  1172. X        errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);
  1173. X        /* NOTREACHED */
  1174. X        }
  1175. X        *new = *ptr;
  1176. X        new->next = new_table->bins[i];
  1177. X        new_table->bins[i] = new;
  1178. X        ptr = ptr->next;
  1179. X    }
  1180. X    }
  1181. X    return new_table;
  1182. X}
  1183. X
  1184. Xint st_delete(table, keyp, value)
  1185. Xregister st_table *table;
  1186. Xregister char **keyp;
  1187. Xchar **value;
  1188. X{
  1189. X    int hash_val;
  1190. X    char *key = *keyp;
  1191. X    register st_table_entry *ptr, **last;
  1192. X
  1193. X    hash_val = do_hash(key, table);
  1194. X
  1195. X    FIND_ENTRY(table, hash_val, key, ptr ,last);
  1196. X    
  1197. X    if (ptr == NIL(st_table_entry)) {
  1198. X    return 0;
  1199. X    }
  1200. X
  1201. X    *last = ptr->next;
  1202. X    if (value != NIL(char *)) *value = ptr->record;
  1203. X    *keyp = ptr->key;
  1204. X    free((char *) ptr);
  1205. X    table->num_entries--;
  1206. X    return 1;
  1207. X}
  1208. X
  1209. Xint st_foreach(table, func, arg)
  1210. Xst_table *table;
  1211. Xenum st_retval (*func)();
  1212. Xchar *arg;
  1213. X{
  1214. X    st_table_entry *ptr, **last;
  1215. X    enum st_retval retval;
  1216. X    int i;
  1217. X
  1218. X    for(i = 0; i < table->num_bins; i++) {
  1219. X    last = &table->bins[i]; ptr = *last;
  1220. X    while (ptr != NIL(st_table_entry)) {
  1221. X        retval = (*func)(ptr->key, ptr->record, arg);
  1222. X        switch (retval) {
  1223. X        case ST_CONTINUE:
  1224. X        last = &ptr->next; ptr = *last;
  1225. X        break;
  1226. X        case ST_STOP:
  1227. X        return 0;
  1228. X        case ST_DELETE:
  1229. X        *last = ptr->next;
  1230. X        free((char *) ptr);
  1231. X        ptr = *last;
  1232. X        break;
  1233. X        default:
  1234. X        errRaise(st_pkg_name, ST_BAD_RET, st_bad_ret);
  1235. X        /* NOTREACHED */
  1236. X        }
  1237. X    }
  1238. X    }
  1239. X    return 1;
  1240. X}
  1241. X
  1242. Xint st_strhash(string, modulus)
  1243. Xregister char *string;
  1244. Xint modulus;
  1245. X{
  1246. X    register int val = 0;
  1247. X    register int c;
  1248. X    
  1249. X    while ((c = *string++) != '\0') {
  1250. X    val = val*997 + c;
  1251. X    }
  1252. X
  1253. X    return ((val < 0) ? -val : val)%modulus;
  1254. X}
  1255. X
  1256. Xint st_numhash(x, size)
  1257. Xchar *x;
  1258. Xint size;
  1259. X{
  1260. X    return ST_NUMHASH(x, size);
  1261. X}
  1262. X
  1263. Xint st_ptrhash(x, size)
  1264. Xchar *x;
  1265. Xint size;
  1266. X{
  1267. X    return ST_PTRHASH(x, size);
  1268. X}
  1269. X
  1270. Xint st_numcmp(x, y)
  1271. Xchar *x;
  1272. Xchar *y;
  1273. X{
  1274. X    return ST_NUMCMP(x, y);
  1275. X}
  1276. X
  1277. Xint st_ptrcmp(x, y)
  1278. Xchar *x;
  1279. Xchar *y;
  1280. X{
  1281. X    return ST_NUMCMP(x, y);
  1282. X}
  1283. X
  1284. Xst_generator *
  1285. Xst_init_gen(table)
  1286. Xst_table *table;
  1287. X/* Initializes generation of items in table */
  1288. X{
  1289. X    st_generator *gen;
  1290. X
  1291. X    gen = ALLOC(st_generator, 1);
  1292. X    if (!gen) {
  1293. X    errRaise(st_pkg_name, ST_NO_MEM, st_no_mem);
  1294. X    /* NOTREACHED */
  1295. X    }
  1296. X    gen->table = table;
  1297. X    gen->entry = NIL(st_table_entry);
  1298. X    gen->indx = 0;
  1299. X    return gen;
  1300. X}
  1301. X
  1302. X
  1303. Xint 
  1304. Xst_gen(gen, key_p, value_p)
  1305. Xst_generator *gen;
  1306. Xchar **key_p;
  1307. Xchar **value_p;
  1308. X/* Generates next item in generation sequence */
  1309. X{
  1310. X    register int i;
  1311. X
  1312. X    if (!gen) {
  1313. X    errRaise(st_pkg_name, ST_BAD_GEN, st_bad_gen);
  1314. X    /* NOTREACHED */
  1315. X    }
  1316. X    
  1317. X    if (gen->entry == NIL(st_table_entry)) {
  1318. X    /* try to find next entry */
  1319. X    for(i = gen->indx; i < gen->table->num_bins; i++) {
  1320. X        if (gen->table->bins[i] != NIL(st_table_entry)) {
  1321. X        gen->indx = i+1;
  1322. X        gen->entry = gen->table->bins[i];
  1323. X        break;
  1324. X        }
  1325. X    }
  1326. X    if (gen->entry == NIL(st_table_entry)) {
  1327. X        return 0;        /* that's all folks ! */
  1328. X    }
  1329. X    }
  1330. X    *key_p = gen->entry->key;
  1331. X    if (value_p != 0) *value_p = gen->entry->record;
  1332. X    gen->entry = gen->entry->next;
  1333. X    return 1;
  1334. X}
  1335. X
  1336. X
  1337. Xvoid
  1338. Xst_free_gen(gen)
  1339. Xst_generator *gen;
  1340. X{
  1341. X    if (gen) {
  1342. X    free((char *) gen);
  1343. X    } else {
  1344. X    errRaise(st_pkg_name, ST_BAD_GEN, st_bad_gen);
  1345. X    /* NOTREACHED */
  1346. X    }
  1347. X}
  1348. SHAR_EOF
  1349. $TOUCH -am 0103111092 st.c &&
  1350. chmod 0664 st.c ||
  1351. echo "restore of st.c failed"
  1352. set `wc -c st.c`;Wc_c=$1
  1353. if test "$Wc_c" != "18207"; then
  1354.     echo original size 18207, current size $Wc_c
  1355. fi
  1356. # ============= st.h ==============
  1357. echo "x - extracting st.h (Text)"
  1358. sed 's/^X//' << 'SHAR_EOF' > st.h &&
  1359. X/*  $Id: st.h,v 1.1.1.1 1992/01/03 17:10:26 murf Exp $ */
  1360. X
  1361. X#ifndef ANSI_H
  1362. X#define ANSI_H
  1363. X
  1364. X/* Function prototypes */
  1365. X#ifdef __STDC__
  1366. X#define ARGS(args)    args
  1367. X#else
  1368. X#define ARGS(args)    ()
  1369. X#endif
  1370. X
  1371. X#endif
  1372. X#ifndef ST_INCLUDED
  1373. X#define ST_INCLUDED
  1374. X
  1375. X
  1376. Xextern char st_pkg_name[];
  1377. X
  1378. X/* Fatal error codes */
  1379. X#define ST_NO_MEM    0
  1380. X#define ST_BAD_RET    1
  1381. X#define ST_BAD_GEN    2
  1382. X
  1383. Xtypedef struct _st_table_entry st_table_entry;
  1384. Xstruct _st_table_entry {
  1385. X    char *key;
  1386. X    char *record;
  1387. X    st_table_entry *next;
  1388. X};
  1389. X
  1390. Xtypedef struct _st_table st_table;
  1391. Xstruct _st_table {
  1392. X    int (*compare)();
  1393. X    int (*hash)();
  1394. X    int num_bins;
  1395. X    int num_entries;
  1396. X    int max_density;
  1397. X    int reorder_flag;
  1398. X    double grow_factor;
  1399. X    st_table_entry **bins;
  1400. X};
  1401. X
  1402. Xtypedef struct _st_generator st_generator;
  1403. Xstruct _st_generator {
  1404. X    st_table *table;
  1405. X    st_table_entry *entry;
  1406. X    int indx;
  1407. X};
  1408. X
  1409. X#define st_is_member(table,key) st_lookup(table,key,(char **) 0)
  1410. X#define st_count(table) ((table)->num_entries)
  1411. X
  1412. Xenum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
  1413. X
  1414. Xextern st_table *st_init_table_with_params
  1415. X  ARGS((int (*compare)(), int (*hash)(), int size, int density,
  1416. X    double grow_factor, int reorder_flag));
  1417. X
  1418. Xextern st_table *st_init_table
  1419. X  ARGS((int (*compare)(), int (*hash)()));
  1420. X
  1421. Xextern void st_free_table
  1422. X  ARGS((st_table *table));
  1423. X
  1424. Xextern int st_lookup
  1425. X  ARGS((st_table *table, char *key, char **value));
  1426. X
  1427. Xextern int st_insert
  1428. X  ARGS((st_table *table, char *key, char *value));
  1429. X
  1430. Xextern void st_add_direct
  1431. X  ARGS((st_table *table, char *key, char *value));
  1432. X
  1433. Xextern int st_find_or_add
  1434. X  ARGS((st_table *table, char *key, char ***slot));
  1435. X
  1436. Xextern int st_find
  1437. X  ARGS((st_table *table, char *key, char ***slot));
  1438. X
  1439. Xextern st_table *st_copy
  1440. X  ARGS((st_table *old_table));
  1441. X
  1442. Xextern int st_delete
  1443. X  ARGS((st_table *table, char **keyp, char **value));
  1444. X
  1445. Xextern int st_foreach
  1446. X  ARGS((st_table *table, enum st_retval (*func)(), char *arg));
  1447. X
  1448. Xextern int st_strhash
  1449. X  ARGS((char *string, int modulus));
  1450. X
  1451. Xextern int st_numhash
  1452. X  ARGS((char *x, int size));
  1453. X
  1454. Xextern int st_ptrhash
  1455. X  ARGS((char *x, int size));
  1456. X
  1457. Xextern int st_numcmp
  1458. X  ARGS((char *x, char *y));
  1459. X
  1460. Xextern int st_ptrcmp
  1461. X  ARGS((char *x, char *y));
  1462. X
  1463. Xextern st_generator *st_init_gen
  1464. X  ARGS((st_table *table));
  1465. X
  1466. Xextern int st_gen
  1467. X  ARGS((st_generator *gen, char **key_p, char **value_p));
  1468. X
  1469. Xextern void st_free_gen
  1470. X  ARGS((st_generator *gen));
  1471. X
  1472. X#define ST_DEFAULT_MAX_DENSITY 5
  1473. X#define ST_DEFAULT_INIT_TABLE_SIZE 11
  1474. X#define ST_DEFAULT_GROW_FACTOR 2.0
  1475. X#define ST_DEFAULT_REORDER_FLAG 0
  1476. X
  1477. X#define st_foreach_item(table, gen, key_p, value_p) \
  1478. X    for(gen=st_init_gen(table); st_gen(gen,key_p,value_p) || (st_free_gen(gen),0);)
  1479. X
  1480. X#endif /* ST_INCLUDED */
  1481. SHAR_EOF
  1482. $TOUCH -am 0103111092 st.h &&
  1483. chmod 0664 st.h ||
  1484. echo "restore of st.h failed"
  1485. set `wc -c st.h`;Wc_c=$1
  1486. if test "$Wc_c" != "2655"; then
  1487.     echo original size 2655, current size $Wc_c
  1488. fi
  1489. # ============= errtrap.c ==============
  1490. echo "x - extracting errtrap.c (Text)"
  1491. sed 's/^X//' << 'SHAR_EOF' > errtrap.c &&
  1492. X#ifndef OCTTOOLS_COPYRIGHT_H
  1493. X#define OCTTOOLS_COPYRIGHT_H
  1494. X/*
  1495. X * Oct Tools Distribution 3.0
  1496. X *
  1497. X * Copyright (c) 1988, 1989, Regents of the University of California.
  1498. X * All rights reserved.
  1499. X *
  1500. X * Use and copying of this software and preparation of derivative works
  1501. X * based upon this software are permitted.  However, any distribution of
  1502. X * this software or derivative works must include the above copyright
  1503. X * notice.
  1504. X *
  1505. X * This software is made available AS IS, and neither the Electronics
  1506. X * Research Laboratory or the University of California make any
  1507. X * warranty about the software, its performance or its conformity to
  1508. X * any specification.
  1509. X *
  1510. X * Suggestions, comments, or improvements are welcome and should be
  1511. X * addressed to:
  1512. X *
  1513. X *   octtools@eros.berkeley.edu
  1514. X *   ..!ucbvax!eros!octtools
  1515. X */
  1516. X/* $Id: errtrap.c,v 1.1.1.1 1992/01/03 17:10:25 murf Exp $ */
  1517. X#if !defined(lint) && !defined(SABER)
  1518. Xstatic char octtools_copyright[] = "Copyright (c) 1988, 1989, Regents of the University of California.  All rights reserved.";
  1519. X#endif
  1520. X#endif 
  1521. X#ifdef macintosh
  1522. X#include <StdArg.h>
  1523. X#else
  1524. X#include <varargs.h>
  1525. X#endif
  1526. X#include "uprintf.h"
  1527. X#include "errtrap.h"
  1528. X
  1529. X/*LINTLIBRARY*/
  1530. X
  1531. X#define ERR_BUF_SIZE    4096
  1532. X
  1533. X#define STACK_SIZE    100
  1534. X
  1535. X/* error handler stack */
  1536. Xstatic void (*handlerList[STACK_SIZE])();
  1537. Xstatic int numHandlers = 0;
  1538. Xstatic int curHandlerIdx = -1;
  1539. X
  1540. X/* information given to errRaise */
  1541. Xstatic char *errPkg = (char *) 0;
  1542. Xstatic int errCode = 0;
  1543. Xstatic char errMessage[ERR_BUF_SIZE];
  1544. Xstatic char *errProgName = "\t\t*** ATTENTION ***\n\
  1545. X    The writer of this program failed to register the name of the program\n\
  1546. X    by calling `errProgramName'.  Consequently, the name of program that\n\
  1547. X    failed cannot be determined by the error handling package.\n\n<unknown>";
  1548. Xstatic int errCoreFlag = 0;
  1549. X
  1550. Xvoid errProgramName(name)
  1551. Xchar *name;
  1552. X{
  1553. X    errProgName = name;
  1554. X}
  1555. X
  1556. Xvoid errCore(flag)
  1557. Xint flag;
  1558. X{
  1559. X    errCoreFlag = flag;
  1560. X}
  1561. X
  1562. Xvoid errPushHandler(func)
  1563. Xvoid (*func)();
  1564. X{
  1565. X    if (numHandlers >= STACK_SIZE) {
  1566. X    errRaise(ERR_PKG_NAME, 0,
  1567. X        "errPushHandler:  can't push error handler -- stack is full");
  1568. X    }
  1569. X    handlerList[numHandlers++] = func;
  1570. X}
  1571. X
  1572. Xvoid errPopHandler()
  1573. X{
  1574. X    if (numHandlers < 1) {
  1575. X    errRaise(ERR_PKG_NAME, 0,
  1576. X        "errPopHandler:  can't pop error handler -- stack is empty");
  1577. X    }
  1578. X    numHandlers--;
  1579. X}
  1580. X
  1581. X#ifdef lint
  1582. X/*ARGSUSED*/
  1583. X/*VARARGS3*/
  1584. X
  1585. Xvoid errRaise(pkg, code, fmt, va_alist)
  1586. Xchar *pkg;
  1587. Xint code;
  1588. Xchar *fmt;
  1589. Xva_dcl
  1590. X
  1591. X#else    /*LINT*/
  1592. X#ifdef macintosh
  1593. Xvoid errRaise(char *pkg, ... )
  1594. X#else
  1595. Xvoid errRaise(va_alist)
  1596. Xva_dcl
  1597. X#endif
  1598. X#endif    /*LINT*/
  1599. X
  1600. X{
  1601. X    va_list ap;
  1602. X    char *format;
  1603. X    static void defaultHandler();
  1604. X#ifdef macintosh
  1605. X    va_start(ap, pkg);
  1606. X    errPkg = pkg;
  1607. X#else
  1608. X    va_start(ap);
  1609. X    errPkg = va_arg(ap, char *);
  1610. X#endif
  1611. X    errCode = va_arg(ap, int);
  1612. X    format = va_arg(ap, char *);
  1613. X    if (format != errMessage) {
  1614. X    (void) uprintf(errMessage, format, &ap);
  1615. X    }
  1616. X    va_end(ap);
  1617. X
  1618. X    curHandlerIdx = numHandlers;
  1619. X    while (curHandlerIdx > 0) {
  1620. X    (*handlerList[--curHandlerIdx])(errPkg, errCode, errMessage);
  1621. X    }
  1622. X    defaultHandler(errPkg, errCode, errMessage);
  1623. X}
  1624. X
  1625. Xstatic void defaultHandler(pkgName, code, mesg)
  1626. Xchar *pkgName;
  1627. Xint code;
  1628. Xchar *mesg;
  1629. X{
  1630. X    (void) fprintf(stderr,
  1631. X        "%s: unexpected fatal error detected by %s (code %d):\n\t%s\n",
  1632. X        errProgName, pkgName, code, mesg);
  1633. X    if (errCoreFlag) {
  1634. X    abort();
  1635. X    } else {
  1636. X    exit(1);
  1637. X    }
  1638. X}
  1639. X
  1640. X#ifdef lint
  1641. X/*ARGSUSED*/
  1642. X/*VARARGS1*/
  1643. X
  1644. Xvoid errPass(fmt, va_alist)
  1645. Xchar *fmt;
  1646. Xva_dcl
  1647. X
  1648. X#else    /*LINT*/
  1649. X#ifdef macintosh
  1650. Xvoid errPass(char *fmt, ... )
  1651. X#else
  1652. Xvoid errPass(va_alist)
  1653. Xva_dcl
  1654. X#endif
  1655. X#endif    /*LINT*/
  1656. X
  1657. X{
  1658. X    va_list ap;
  1659. X    char *format;
  1660. X    static char tmpBuffer[ERR_BUF_SIZE];
  1661. X    static void defaultHandler();
  1662. X
  1663. X#ifdef macintosh
  1664. X    va_start(ap,fmt);
  1665. X    format = fmt;
  1666. X#else
  1667. X    va_start(ap);
  1668. X    format = va_arg(ap, char *);
  1669. X#endif
  1670. X    (void) uprintf(tmpBuffer, format, &ap);
  1671. X    (void) strcpy(errMessage, tmpBuffer);
  1672. X    va_end(ap);
  1673. X
  1674. X    /* this should have been set by errRaise, but make sure it's possible */
  1675. X    if (curHandlerIdx > numHandlers) curHandlerIdx = numHandlers;
  1676. X
  1677. X    while (curHandlerIdx > 0) {
  1678. X    (*handlerList[--curHandlerIdx])(errPkg, errCode, errMessage);
  1679. X    }
  1680. X
  1681. X    defaultHandler(errPkg, errCode, errMessage);
  1682. X}
  1683. X
  1684. Xjmp_buf errJmpBuf;
  1685. X
  1686. Xstatic jmp_buf jmpBufList[STACK_SIZE];
  1687. Xstatic numJmpBufs = 0;
  1688. X
  1689. Xvoid errIgnPush()
  1690. X{
  1691. X    static void ignoreHandler();
  1692. X
  1693. X    /* don't need to check for overflow, since errPushHandler will */
  1694. X    errPushHandler(ignoreHandler);
  1695. X    (void) memcpy((char *) jmpBufList[numJmpBufs++], (char *) errJmpBuf,
  1696. X                sizeof(jmp_buf));
  1697. X
  1698. X    /* so errStatus can tell if something trapped */
  1699. X    errPkg = (char *) 0;
  1700. X}
  1701. X
  1702. Xvoid errIgnPop()
  1703. X{
  1704. X    if (numJmpBufs <= 0) {
  1705. X    errRaise(ERR_PKG_NAME, 0, "errIgnPop called before errIgnPush");
  1706. X    }
  1707. X    errPopHandler();
  1708. X    numJmpBufs--;
  1709. X}
  1710. X
  1711. X/*ARGSUSED*/
  1712. Xstatic void ignoreHandler(pkgName, code, message)
  1713. Xchar *pkgName;
  1714. Xint code;
  1715. Xchar *message;
  1716. X{
  1717. X    if (numJmpBufs <= 0) {
  1718. X    errRaise(ERR_PKG_NAME, 0,
  1719. X    "errtrap internal error:  ERR_IGNORE handler called with no jmp_buf");
  1720. X    }
  1721. X    longjmp(jmpBufList[numJmpBufs - 1], 1);
  1722. X}
  1723. X
  1724. Xint errStatus(pkgNamePtr, codePtr, messagePtr)
  1725. Xchar **pkgNamePtr;
  1726. Xint *codePtr;
  1727. Xchar **messagePtr;
  1728. X{
  1729. X    if (errPkg) {
  1730. X    *pkgNamePtr = errPkg;
  1731. X    *codePtr = errCode;
  1732. X    *messagePtr = errMessage;
  1733. X    return(1);
  1734. X    }
  1735. X    return(0);
  1736. X}
  1737. SHAR_EOF
  1738. $TOUCH -am 0103111092 errtrap.c &&
  1739. chmod 0664 errtrap.c ||
  1740. echo "restore of errtrap.c failed"
  1741. set `wc -c errtrap.c`;Wc_c=$1
  1742. if test "$Wc_c" != "5301"; then
  1743.     echo original size 5301, current size $Wc_c
  1744. fi
  1745. # ============= errtrap.h ==============
  1746. echo "x - extracting errtrap.h (Text)"
  1747. sed 's/^X//' << 'SHAR_EOF' > errtrap.h &&
  1748. X#ifndef ANSI_H
  1749. X#define ANSI_H
  1750. X/* $Id: errtrap.h,v 1.1.1.1 1992/01/03 17:10:25 murf Exp $ */
  1751. X
  1752. X/* Function prototypes */
  1753. X#ifdef __STDC__
  1754. X#define ARGS(args)    args
  1755. X#else
  1756. X#define ARGS(args)    ()
  1757. X#endif
  1758. X
  1759. X#endif
  1760. X#ifndef ERRTRAP_H
  1761. X#define ERRTRAP_H
  1762. X
  1763. X#include <setjmp.h>
  1764. X#include <stdio.h>
  1765. X
  1766. X#define ERR_PKG_NAME    "errtrap"
  1767. X
  1768. Xextern void errProgramName( /* char *progName */ );
  1769. Xextern void errCore( /* int flag */ );
  1770. Xextern void errPushHandler( /* void (*handler)() */ );
  1771. Xextern void errPopHandler();
  1772. Xextern void errRaise( /* char *pkgName, int code, char *format, ... */ );
  1773. Xextern void errPass( /* char *format, ... */ );
  1774. X
  1775. X#define ERR_IGNORE(expr)    \
  1776. X    {                    \
  1777. X    if ( ! setjmp(errJmpBuf)) {    \
  1778. X        errIgnPush();        \
  1779. X        expr;            \
  1780. X    }                \
  1781. X    errIgnPop();            \
  1782. X    }
  1783. Xextern jmp_buf errJmpBuf;
  1784. Xextern void errIgnPush(), errIgnPop();
  1785. Xextern int errStatus();
  1786. X
  1787. X#endif /* ERRTRAP_H */
  1788. SHAR_EOF
  1789. $TOUCH -am 0103111092 errtrap.h &&
  1790. chmod 0664 errtrap.h ||
  1791. echo "restore of errtrap.h failed"
  1792. set `wc -c errtrap.h`;Wc_c=$1
  1793. if test "$Wc_c" != "861"; then
  1794.     echo original size 861, current size $Wc_c
  1795. fi
  1796. echo "End of part 4, continue with part 5"
  1797. exit 0
  1798.  
  1799. exit 0 # Just in case...
  1800.