1 /*
2  * This file is part of the Alliance CAD System
3  * Copyright (C) Laboratoire LIP6 - D�partement ASIM
4  * Universite Pierre et Marie Curie
5  *
6  * Home page          : http://www-asim.lip6.fr/alliance/
7  * E-mail             : mailto:alliance-users@asim.lip6.fr
8  *
9  * This library is free software; you  can redistribute it and/or modify it
10  * under the terms  of the GNU Library General Public  License as published
11  * by the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * Alliance VLSI  CAD System  is distributed  in the hope  that it  will be
15  * useful, but WITHOUT  ANY WARRANTY; without even the  implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy  of the GNU General Public License along
20  * with the GNU C Library; see the  file COPYING. If not, write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * Purpose : services functions and global variables
26  * Date    : 06/03/92
27  * Author  : Frederic Petrot <Frederic.Petrot@lip6.fr>
28  * Modified by Czo <Olivier.Sirol@lip6.fr> 1997,98
29  */
30 
31 #ident "$Id: mbk_util.c,v 1.8 2012/05/14 14:20:23 alliance Exp $"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <signal.h>
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 
42 #include "mut.h"
43 #include "mbk_util.h"
44 
45 
46 /* Normally defined in values.h, but not available on all systems */
47 #ifndef BITS
48 #define  BITS(type)  (8 * (int)sizeof(type))
49 #endif
50 
51 /*******************************************************************************
52 * global variables                                                             *
53 *******************************************************************************/
54 chain_list *HEAD_CHAIN = NULL;                 /* chain buffer head           */
55 chain_list *HEAD_BLOCK_CHAIN = NULL;
56 ptype_list *HEAD_PTYPE = NULL;                 /* ptype buffer head           */
57 num_list *HEAD_NUM = NULL;                     /* num   buffer head           */
58 char TRACE_MODE  = 'N';                        /* trace if 'Y'                */
59 int  TRACE_FILE  = 0;                          /* trace if >0                 */
60 int  TRACE_GETENV  = 0;                          /* trace if >0                 */
61 char DEBUG_MODE  = 'N';                        /* debug if 'Y'                */
62 char FAST_MODE   = 'N';                        /* no consistency check if 'Y' */
63 char SEPAR  = '.';                             /* char used in concatenation  */
64 char *WORK_LIB = NULL;                         /* working directory           */
65 char **CATA_LIB = NULL;                        /* read only directories       */
66 char *CATAL = NULL;                            /* catalog file                */
67 char IN_LO[5] = "al";                          /* input logical format        */
68 char IN_PH[5] = "ap";                          /* input physical format       */
69 char OUT_LO[5] = "al";                         /* output logical format       */
70 char OUT_PH[5] = "ap";                         /* output physical format      */
71 long SCALE_X = 100;                            /* distance scale definition   */
72 long MBK_X_GRID             = 5;
73 long MBK_Y_GRID             = 5;
74 long MBK_Y_SLICE            = 50;
75 long MBK_WIDTH_VSS          = 6;
76 long MBK_WIDTH_VDD          = 6;
77 long MBK_TRACK_WIDTH_ALU1   = 2;
78 long MBK_TRACK_WIDTH_ALU2   = 2;
79 long MBK_TRACK_WIDTH_ALU3   = 2;
80 long MBK_TRACK_WIDTH_ALU4   = 2;
81 long MBK_TRACK_WIDTH_ALU5   = 2;
82 long MBK_TRACK_WIDTH_ALU6   = 2;
83 long MBK_TRACK_WIDTH_ALU7   = 2;
84 long MBK_TRACK_WIDTH_ALU8   = 0;
85 long MBK_TRACK_SPACING_ALU1 = 3;
86 long MBK_TRACK_SPACING_ALU2 = 3;
87 long MBK_TRACK_SPACING_ALU3 = 3;
88 long MBK_TRACK_SPACING_ALU4 = 3;
89 long MBK_TRACK_SPACING_ALU5 = 8;
90 long MBK_TRACK_SPACING_ALU6 = 8;
91 long MBK_TRACK_SPACING_ALU7 = 8;
92 long MBK_TRACK_SPACING_ALU8 = 0;
93 char PARSER_INFO[100] = "nothing yet";         /* version number, and so on   */
94 char *VDD = NULL;                              /* user name for power high    */
95 char *VSS = NULL;                              /* user name for power ground  */
96 char *CK = NULL;                               /* user name for clock         */
97 char *IN_FILTER = NULL ;
98 char *OUT_FILTER = NULL ;
99 char *FILTER_SFX = NULL ;
100 /* table de hash de namealloc() et namefind() */
101 static chain_list *NAME_HASHTABLE[HASHVAL];
102 static char buffer[BUFSIZ];                    /* buffer for namealloc strcpy */
103 static char str[BUFSIZ];                       /* buffer for concatname       */
104 static char tolowertable[1 << BITS(char)];     /* number of chars             */
105 static char touppertable[1 << BITS(char)];     /* number of chars             */
106 /*
107 ** Added by Ludovic Jacomme (The slave)
108 ** in order to "trap" exit with Graal/Dreal etc ...
109 */
110  void (*MBK_EXIT_FUNCTION)() = 0;
111 
112 static void dflhandler(int);
113 static void loadcatalog(char ***table, int *size, char type);
114 static void read_lib(void);
115 
116 /*******************************************************************************
117 * fonction handler()                                                           *
118 *******************************************************************************/
dflhandler(int sig)119 static void dflhandler(int sig)
120 {
121    exit(100);
122 }
123 
124 /*******************************************************************************
125 * fonction mbkwaitpid()                                                        *
126 * Verifie parmis les processus fils termines si pid en fait partie. Si status  *
127 * est non nul, le code de retour est place dans cette variable. si mode vaut   *
128 * 1, cet appel est bloquant, sinon il est non bloquant.                        *
129 *******************************************************************************/
mbkwaitpid(int pid,int mode,int * status)130 int mbkwaitpid( int pid, int mode, int *status )
131 {
132   endchld_list *scan, *prev;
133 
134   while(1)
135   {
136     prev = NULL;
137     for( scan = HEAD_ENDCHLD ; scan ; scan = scan->NEXT )
138     {
139       if( scan->PID == pid )
140       {
141         if( status )
142           *status = scan->STATUS;
143 
144         if( prev )
145           prev->NEXT = scan->NEXT;
146         else
147           HEAD_ENDCHLD = scan->NEXT;
148 
149         mbkfreeendchld( scan );
150         return( 1 );
151       }
152       prev = scan;
153     }
154 
155     if( mode != 1 )
156       return( 0 );
157 
158     sleep(3600); /* le sleep est interruptible : on ne perd rien */
159   }
160 
161   return( 0 );
162 }
163 
164 /*******************************************************************************
165 * fonction mbkenv()                                                            *
166 *******************************************************************************/
mbkenv(void)167 void mbkenv(void)
168 {
169 char *str;
170 long nchar;
171 
172 static char MBK_RAND_SEED[] = { 0x62,
173   0x37, 0x34, 0x30, 0x30, 0x32, 0x31, 0x38, 0x61, 0x31, 0x37, 0x34,
174   0x64, 0x34, 0x64, 0x36, 0x36, 0x65, 0x32, 0x35, 0x38, 0x30, 0x34, 0x63,
175   0x31, 0x36, 0x32, 0x38, 0x34, 0x65, 0x37, 0x61 } ;
176 
177 
178    str = mbkgetenv("MBK_TRACE_GETENV");
179    if (str != NULL)
180    {
181       if( !strcmp(str, "yes" ) )
182          TRACE_GETENV = 1;
183       else if (!strcmp(str,"Y"))
184          TRACE_GETENV = 1;
185    }
186 
187    read_lib(); /* read the contents of MBK_WORK_LIB and MBK_CATA_LIB */
188 
189    str = mbkgetenv("MBK_DEBUG_MODE");
190    if (str != NULL)
191       if (!strcmp(str,"yes"))
192          DEBUG_MODE = 'Y';
193 
194    str = mbkgetenv("MBK_TRACE_MODE");
195    if (str != NULL)
196       if (!strcmp(str,"yes"))
197          TRACE_MODE = 'Y';
198 
199    str = mbkgetenv("MBK_TRACE_FILE");
200    if (str != NULL)
201    {
202       if( !strcmp(str, "true" ) )
203          TRACE_FILE = 3;
204       else if (!strcmp(str,"yes"))
205          TRACE_FILE = 2;
206       else if( !strcmp(str, "Y" ) )
207          TRACE_FILE = 1;
208       else if( !strcmp(str, "all" ) )
209          TRACE_FILE = 1;
210    }
211 
212    str = mbkgetenv("MBK_FAST_MODE");
213    if (str != NULL)
214       if (!strcmp(str,"yes"))
215          FAST_MODE = 'Y';
216 
217    str = mbkgetenv("MBK_SCALE_X");
218    if (str != NULL)
219       SCALE_X = (long)atoi(str);
220 
221    str = mbkgetenv("MBK_X_GRID");
222    if (str != NULL)
223       MBK_X_GRID = (long)atoi(str);
224 
225    str = mbkgetenv("MBK_Y_GRID");
226    if (str != NULL)
227       MBK_Y_GRID = (long)atoi(str);
228 
229    str = mbkgetenv("MBK_Y_SLICE");
230    if (str != NULL)
231       MBK_Y_SLICE = (long)atoi(str);
232 
233    str = mbkgetenv("MBK_WIDTH_VSS");
234    if (str != NULL)
235       MBK_WIDTH_VSS = (long)atoi(str);
236 
237    str = mbkgetenv("MBK_WIDTH_VDD");
238    if (str != NULL)
239       MBK_WIDTH_VDD = (long)atoi(str);
240 
241    str = mbkgetenv("MBK_TRACK_WIDTH_ALU1");
242    if (str != NULL)
243       MBK_TRACK_WIDTH_ALU1 = (long)atoi(str);
244 
245    str = mbkgetenv("MBK_TRACK_WIDTH_ALU2");
246    if (str != NULL)
247       MBK_TRACK_WIDTH_ALU2 = (long)atoi(str);
248 
249    str = mbkgetenv("MBK_TRACK_WIDTH_ALU3");
250    if (str != NULL)
251       MBK_TRACK_WIDTH_ALU3 = (long)atoi(str);
252 
253    str = mbkgetenv("MBK_TRACK_WIDTH_ALU4");
254    if (str != NULL)
255       MBK_TRACK_WIDTH_ALU4 = (long)atoi(str);
256 
257    str = mbkgetenv("MBK_TRACK_WIDTH_ALU5");
258    if (str != NULL)
259       MBK_TRACK_WIDTH_ALU5 = (long)atoi(str);
260 
261    str = mbkgetenv("MBK_TRACK_WIDTH_ALU6");
262    if (str != NULL)
263       MBK_TRACK_WIDTH_ALU6 = (long)atoi(str);
264 
265    str = mbkgetenv("MBK_TRACK_WIDTH_ALU7");
266    if (str != NULL)
267       MBK_TRACK_WIDTH_ALU7 = (long)atoi(str);
268 
269    str = mbkgetenv("MBK_TRACK_WIDTH_ALU8");
270    if (str != NULL)
271       MBK_TRACK_WIDTH_ALU8 = (long)atoi(str);
272 
273    str = mbkgetenv("MBK_TRACK_SPACING_ALU1");
274    if (str != NULL)
275       MBK_TRACK_SPACING_ALU1 = (long)atoi(str);
276 
277    str = mbkgetenv("MBK_TRACK_SPACING_ALU2");
278    if (str != NULL)
279       MBK_TRACK_SPACING_ALU2 = (long)atoi(str);
280 
281    str = mbkgetenv("MBK_TRACK_SPACING_ALU3");
282    if (str != NULL)
283       MBK_TRACK_SPACING_ALU3 = (long)atoi(str);
284 
285    str = mbkgetenv("MBK_TRACK_SPACING_ALU4");
286    if (str != NULL)
287       MBK_TRACK_SPACING_ALU4 = (long)atoi(str);
288 
289    str = mbkgetenv("MBK_TRACK_SPACING_ALU5");
290    if (str != NULL)
291       MBK_TRACK_SPACING_ALU5 = (long)atoi(str);
292 
293    str = mbkgetenv("MBK_TRACK_SPACING_ALU6");
294    if (str != NULL)
295       MBK_TRACK_SPACING_ALU6 = (long)atoi(str);
296 
297    str = mbkgetenv("MBK_TRACK_SPACING_ALU7");
298    if (str != NULL)
299       MBK_TRACK_SPACING_ALU7 = (long)atoi(str);
300 
301    str = mbkgetenv("MBK_TRACK_SPACING_ALU8");
302    if (str != NULL)
303       MBK_TRACK_SPACING_ALU8 = (long)atoi(str);
304 
305    srand((unsigned int) MBK_RAND_SEED);
306 
307    str = mbkgetenv("MBK_IN_LO");
308    if (str != NULL) {
309       if (!strcmp(str, "hns"))
310          (void)strcpy(IN_LO, "hns");
311       else if (!strcmp(str, "fne"))
312          (void)strcpy(IN_LO, "fne");
313       else if (!strcmp(str, "hdn"))
314          (void)strcpy(IN_LO, "hdn");
315       else if (!strcmp(str, "fdn"))
316          (void)strcpy(IN_LO, "fdn");
317       else if (!strcmp(str, "al" ))
318          (void)strcpy(IN_LO, "al");
319       else if (!strcmp(str, "alx"))
320          (void)strcpy(IN_LO, "alx");
321       else if (!strcmp(str, "spi"))
322          (void)strcpy(IN_LO, "spi");
323       else if (!strcmp(str, "sp"))
324          (void)strcpy(IN_LO, "sp");
325       else if (!strcmp(str, "cir"))
326          (void)strcpy(IN_LO, "cir");
327       else if (!strcmp(str, "edi"))
328          (void)strcpy(IN_LO, "edi");
329       else if (!strcmp(str, "vst"))
330          (void)strcpy(IN_LO, "vst");
331       else {
332          (void)fflush(stdout);
333          (void)fprintf(stderr,"*** mbk error ***\n");
334          (void)fprintf(stderr,"netlist input format '%s' not supported\n",str);
335          EXIT(1);
336       }
337    }
338 
339    str = mbkgetenv("MBK_OUT_LO");
340    if (str != NULL) {
341       if (!strcmp(str, "hns"))
342          (void)strcpy(OUT_LO, "hns");
343       else if (!strcmp(str, "fne"))
344          (void)strcpy(OUT_LO, "fne");
345       else if (!strcmp(str, "hdn"))
346          (void)strcpy(OUT_LO, "hdn");
347       else if (!strcmp(str, "fdn"))
348          (void)strcpy(OUT_LO, "fdn");
349       else if (!strcmp(str, "al" ))
350          (void)strcpy(OUT_LO, "al");
351       else if (!strcmp(str, "alx"))
352          (void)strcpy(OUT_LO, "alx");
353       else if (!strcmp(str, "spi"))
354          (void)strcpy(OUT_LO, "spi");
355       else if (!strcmp(str, "sp"))
356          (void)strcpy(OUT_LO, "sp");
357       else if (!strcmp(str, "cir"))
358          (void)strcpy(OUT_LO, "cir");
359       else if (!strcmp(str, "edi"))
360          (void)strcpy(OUT_LO, "edi");
361       else if (!strcmp(str, "vst"))
362          (void)strcpy(OUT_LO, "vst");
363       else if (!strcmp(str, "cct"))
364          (void)strcpy(OUT_LO, "cct");
365                 else if (!strcmp(str, "vlg"))
366                       (void)strcpy(OUT_LO, "vlg");
367       else {
368          (void)fflush(stdout);
369          (void)fprintf(stderr,"*** mbk error ***\n");
370          (void)fprintf(stderr,"netlist output format '%s' not supported\n",str);
371          EXIT(1);
372       }
373    }
374 
375    str = mbkgetenv("MBK_IN_PH");
376    if (str != NULL) {
377       if (!strcmp(str, "cp"))
378          (void)strcpy(IN_PH, "cp");
379       else if (!strcmp(str, "ap"))
380          (void)strcpy(IN_PH, "ap");
381       else if (!strcmp(str, "mg"))
382          (void)strcpy(IN_PH, "mg");
383       else {
384          (void)fflush(stdout);
385          (void)fprintf(stderr,"*** mbk error ***\n");
386          (void)fprintf(stderr,"layout input format '%s' not supported\n",str);
387          EXIT(1);
388       }
389    }
390 
391    str = mbkgetenv("MBK_OUT_PH");
392    if (str != NULL) {
393       if (!strcmp(str, "cp"))
394          (void)strcpy(OUT_PH, "cp");
395       else if (!strcmp(str, "ap"))
396          (void)strcpy(OUT_PH, "ap");
397       else if (!strcmp(str, "mg"))
398          (void)strcpy(OUT_PH, "mg");
399       else {
400          (void)fflush(stdout);
401          (void)fprintf(stderr,"*** mbk error ***\n");
402          (void)fprintf(stderr,"layout output format '%s' not supported\n",str);
403          EXIT(1);
404       }
405    }
406 
407    str = mbkgetenv("MBK_CATAL_NAME");
408    if (str != NULL)
409       CATAL = str;
410    else /* default value for catalog name */
411       CATAL = "CATAL";
412 
413    str = mbkgetenv("MBK_SEPAR");
414    if (str != NULL)
415       SEPAR = *str;
416 
417    str = mbkgetenv("MBK_VDD");
418    if (str != NULL)
419       VDD = str;
420    else /* default value for power high */
421       VDD = "vdd";
422 
423    str = mbkgetenv("MBK_VSS");
424    if (str != NULL)
425       VSS = str;
426    else /* default value for power high */
427       VSS = "vss";
428 
429    str = mbkgetenv("MBK_CK");
430    if (str != NULL)
431       CK = str;
432    else /* default value for clock */
433       CK = "ck";
434 
435    str = mbkgetenv( "MBK_IN_FILTER" );
436    if( str )
437      IN_FILTER = str;
438    else
439      IN_FILTER = NULL;
440 
441    str = mbkgetenv( "MBK_OUT_FILTER" );
442    if( str )
443      OUT_FILTER = str;
444    else
445      OUT_FILTER = NULL;
446 
447    str = mbkgetenv( "MBK_FILTER_SFX" );
448    if( str )
449      FILTER_SFX = str;
450    else
451      FILTER_SFX = NULL;
452 
453    /* EXIT shall produce a real exit if not trapped */
454    signal(SIGTERM, dflhandler);
455 
456    /* Initialize a table of lower case characters for the machine encoding */
457    for (nchar = 0; nchar < sizeof(tolowertable); nchar++)
458       tolowertable[nchar] = isupper(nchar) ? tolower(nchar) : nchar;
459 
460    /* Initialize a table of upper case characters for the machine encoding */
461    for (nchar = 0; nchar < sizeof(touppertable); nchar++)
462       touppertable[nchar] = islower(nchar) ? toupper(nchar) : nchar;
463 
464    mbkinitendchld();
465    mbkinitautoackchld();
466    /* Sous Solaris, certaines fonctions de haut niveau (fgets...) sont
467     * interruptible par la reception d'un signal. Ceci n'a jamais ete pris
468     * en compte auparavant : on conserve donc explicitement le comportement
469     * "normal" qui est que ces fonctions ne sont normalement pas
470     * interruptible. D'ou le SA_RESTART.
471     */
472 
473    #ifndef AUTO_HAS_SA_RESTART
474      signal( SIGCHLD, mbkackchld );
475    #else
476      sigemptyset( &ens );
477      sgct.sa_handler  = mbkackchld;
478      sgct.sa_mask     = ens;
479      sgct.sa_flags    = SA_RESTART;
480      sigaction( SIGCHLD, &sgct , NULL );
481    #endif
482 }
483 
484 /*******************************************************************************
485 * function nameindex()                                                         *
486 * return a string that is the concatenation of the name argument, the mbk      *
487 * separator, and an index                                                      *
488 *******************************************************************************/
nameindex(char * name,long index)489 char *nameindex(char *name, long index)
490 {
491 char str[100];
492 
493    (void)sprintf(str,"%s%c%ld", name, SEPAR, index);
494    return namealloc(str);
495 }
496 
497 /*******************************************************************************
498 * fonction addnum()                                                            *
499 * num list specialized allocator to avoid too many mallocs                     *
500 *******************************************************************************/
addnum(num_list * ptnum,long data)501 num_list *addnum(num_list *ptnum, long data)
502 {
503 num_list *pt;
504 register int i;
505 
506    if (HEAD_NUM == NULL) {
507       HEAD_NUM = (num_list *)mbkalloc(BUFSIZE*sizeof(num_list));
508       pt = HEAD_NUM;
509       for (i = 1; i < BUFSIZE; i++) {
510          pt->NEXT = pt + 1;
511          pt++;
512       }
513       pt->NEXT = NULL;
514    }
515 
516    pt = HEAD_NUM;
517    HEAD_NUM = HEAD_NUM->NEXT;
518    pt->NEXT = ptnum;
519    pt->DATA = data;
520    return pt;
521 }
522 
523 /*******************************************************************************
524 * function freenum()                                                           *
525 * gives back freed block to the num memory allocator                           *
526 *******************************************************************************/
freenum(num_list * pt)527 void freenum(num_list *pt)
528 {
529    HEAD_NUM = (num_list *)append((chain_list *)pt, (chain_list *)HEAD_NUM);
530 }
531 
532 /*******************************************************************************
533 * function addchain()                                                          *
534 * chain list specialized allocator to avoid too many mallocs                   *
535 *******************************************************************************/
536 #ifdef DEBUGCHAIN
fnaddchain(chain_list * pthead,void * ptdata,int line,char * file)537 chain_list *fnaddchain(chain_list *pthead, void *ptdata, int line, char *file)
538 #else
539 chain_list *addchain(chain_list *pthead, void *ptdata)
540 #endif
541 {
542 #ifdef DEBUGCHAIN
543 chain_list *block;
544 #endif
545 chain_list *pt;
546 register int i;
547 
548    if (HEAD_CHAIN == NULL) {
549       pt = (chain_list *)mbkalloc(BUFSIZE*sizeof(chain_list));
550 
551 #ifdef DEBUGCHAIN
552       block = (chain_list*)mbkalloc(sizeof(chain_list));
553       block->DATA = pt;
554       block->NEXT = HEAD_BLOCK_CHAIN;
555       HEAD_BLOCK_CHAIN = block;
556 #endif
557 
558       HEAD_CHAIN = pt;
559       for (i = 1; i < BUFSIZE; i++) {
560          pt->NEXT = pt + 1;
561 #ifdef DEBUGCHAIN
562          pt->LINE = 0;
563 #endif
564          pt++;
565       }
566       pt->NEXT = NULL;
567 #ifdef DEBUGCHAIN
568       pt->LINE = 0;
569 #endif
570    }
571 
572    pt = HEAD_CHAIN;
573    HEAD_CHAIN = HEAD_CHAIN->NEXT;
574    pt->NEXT = pthead;
575    pt->DATA = ptdata;
576 #ifdef DEBUGCHAIN
577    pt->LINE = line;
578    pt->FILE = file;
579 #endif
580    return pt;
581 }
582 
583 /*******************************************************************************
584 * function freechain()                                                         *
585 * gives back freed block or blocks to the chain_list memory allocator          *
586 *******************************************************************************/
freechain(chain_list * pt)587 void freechain(chain_list *pt)
588 {
589 #ifdef DEBUGCHAIN
590    chain_list *scanchain;
591    for( scanchain = pt ; scanchain ; scanchain = scanchain->NEXT )
592      scanchain->LINE=0;
593 #endif
594    HEAD_CHAIN = append(pt, HEAD_CHAIN);
595 }
596 
597 /*******************************************************************************
598 * function delchain()                                                          *
599 * delete a single element of a chain_list and gives it back to freechain       *
600 *******************************************************************************/
delchain(chain_list * pthead,chain_list * ptdel)601 chain_list *delchain(chain_list *pthead, chain_list *ptdel)
602 {
603 chain_list *pt;
604 chain_list *ptsav = NULL; /* To make gcc -Wall silent */
605 
606    if (pthead == NULL || ptdel == NULL) {
607       (void)fflush(stdout);
608       (void)fprintf(stderr,"*** mbk error ***");
609       (void)fprintf(stderr,"  delchain() impossible : pointer = NULL !\n");
610       EXIT(1);
611    }
612 
613    if (ptdel == pthead) {
614       pt = pthead->NEXT;
615       pthead->NEXT = NULL;
616       freechain(pthead);
617       return pt;
618    } else {
619       for (pt = pthead; pt; pt = pt->NEXT) {
620          if (pt == ptdel)
621             break;
622          ptsav = pt;
623       }
624       if (pt != NULL) {
625          ptsav->NEXT = pt->NEXT;
626          ptdel->NEXT = NULL;
627          freechain(ptdel);
628          return pthead;
629       } else
630          return NULL;
631    }
632 }
633 
634 /*******************************************************************************
635 * function addptype()                                                          *
636 *******************************************************************************/
testchain(void)637 void testchain(void)
638 {
639 #ifdef DEBUGCHAIN
640   chain_list *scanchain;
641   int i;
642   for( scanchain = HEAD_BLOCK_CHAIN ; scanchain ; scanchain = scanchain->NEXT )
643   {
644     for( i = 0 ; i < BUFSIZE ; i++)
645       if( ((chain_list*)(scanchain->DATA))[i].LINE != 0 )
646         printf( "%50s : %5d\n", ((chain_list*)(scanchain->DATA))[i].FILE,
647                                 ((chain_list*)(scanchain->DATA))[i].LINE
648               );
649   }
650 #endif
651 }
652 
653 /*******************************************************************************
654 * function addptype()                                                          *
655 *******************************************************************************/
addptype(ptype_list * pthead,long type,void * ptdata)656 ptype_list *addptype(ptype_list *pthead, long type, void *ptdata)
657 {
658 ptype_list *pt;
659 register int i;
660 
661    if (HEAD_PTYPE == NULL) {
662       pt = (ptype_list *)mbkalloc(BUFSIZE * sizeof(ptype_list));
663       HEAD_PTYPE = pt;
664       for (i = 1; i < BUFSIZE; i++) {
665          pt->NEXT = pt + 1;
666          pt++;
667       }
668       pt->NEXT = NULL;
669    }
670 
671    pt = HEAD_PTYPE;
672    HEAD_PTYPE = HEAD_PTYPE->NEXT;
673    pt->NEXT = pthead;
674    pt->DATA = ptdata;
675    pt->TYPE = type;
676    return pt;
677 }
678 
679 /*******************************************************************************
680 * function delptype()                                                          *
681 *******************************************************************************/
delptype(ptype_list * pthead,long type)682 ptype_list *delptype(ptype_list *pthead, long type)
683 {
684 ptype_list *pt;
685 ptype_list *ptsav = NULL; /* To make gcc -Wall silent */
686 
687    if (pthead == NULL) {
688       (void)fflush(stdout);
689       (void)fprintf(stderr,"*** mbk error ***\n");
690       (void)fprintf(stderr,"delptype() impossible : pthead = NULL !\n");
691       EXIT(1);
692    }
693 
694    if (pthead->TYPE == type) {
695       pt = pthead->NEXT;
696       pthead->NEXT = NULL;
697       freeptype(pthead);
698       return pt;
699    } else {
700       for (pt = pthead; pt; pt = pt->NEXT) {
701          if (pt->TYPE == type)
702             break;
703          ptsav = pt;
704       }
705       if (pt != NULL) {
706          ptsav->NEXT = pt->NEXT;
707          pt->NEXT = NULL;
708          freeptype(pt);
709          return pthead;
710       } else
711          return NULL;
712    }
713 }
714 
715 /*******************************************************************************
716 * function freeptype()                                                         *
717 *******************************************************************************/
freeptype(ptype_list * pt)718 void freeptype(ptype_list  *pt)
719 {
720    HEAD_PTYPE = (ptype_list *)append((chain_list *)pt,(chain_list *)HEAD_PTYPE);
721 }
722 
723 /*******************************************************************************
724 * function getptype()                                                          *
725 *******************************************************************************/
getptype(ptype_list * pthead,long type)726 ptype_list *getptype(ptype_list *pthead, long type)
727 {
728 ptype_list  *pt;
729 
730    for (pt = pthead; pt; pt = pt->NEXT)
731       if (pt->TYPE == type)
732          return pt;
733    return NULL;
734 }
735 
736 /*******************************************************************************
737 * function append()                                                            *
738 *******************************************************************************/
append(chain_list * pt1,chain_list * pt2)739 chain_list *append(chain_list *pt1, chain_list *pt2)
740 {
741 chain_list *pt;
742 
743    if (pt1 == NULL)
744       return pt2;
745    else {
746       for (pt = pt1; pt->NEXT; pt = pt->NEXT);
747       pt->NEXT = pt2; /* append the list 2 at the end of list 1 */
748       return pt1;
749    }
750 }
751 
752 /*******************************************************************************
753 * Dictonnary related functions                                                 *
754 *******************************************************************************/
755 
756 /* Random hash function due to Don. E. Knuth, The Stanford Graph Base.
757  * Truly better than the previous one from my own experimentations. */
758 #define HASH_MULT 314159
759 #define HASH_PRIME 516595003
760 
761 #define HASH_FUNC(inputname, name, code)                                     \
762    do {                                                                      \
763       while (*inputname) {                                                   \
764          *name = tolower((int)*inputname++);                            \
765          code += (code ^ (code >> 1)) + HASH_MULT * (unsigned char) *name++; \
766          while (code >= HASH_PRIME)                                          \
767             code -= HASH_PRIME;                                              \
768       }                                                                      \
769       *name = '\0';                                                          \
770       code %= HASHVAL;                                                       \
771    } while (0)
772 
773 /*******************************************************************************
774 * function namealloc()                                                         *
775 *******************************************************************************/
namealloc(const char * inputname)776 char *namealloc(const char *inputname)
777 {
778 chain_list *pt;
779 char *name = buffer; /* ensure no modification of parameter string */
780 int code = 0;
781 static char *lastname;
782 
783    if (inputname == NULL)
784       return NULL;
785 
786    if (inputname == lastname)
787       return lastname; /* To make const acceptable, strange */
788 
789    /* Beware, that's a define, ... */
790    HASH_FUNC(inputname, name, code);
791 
792    for (pt = NAME_HASHTABLE[code]; pt; pt = pt->NEXT)
793       if (!strcmp(buffer, (char *)pt->DATA))
794          return (char *)pt->DATA;
795 
796    name = (char *)mbkalloc((unsigned int)(strlen(buffer) + 1));
797    (void)strcpy(name, buffer);
798    NAME_HASHTABLE[code] = addchain(NAME_HASHTABLE[code], (void *)name);
799 #ifdef DEBUGCHAIN
800    NAME_HASHTABLE[code]->LINE=0; /* pas de trace de debuggage dessus */
801 #endif
802    lastname = (char *)(NAME_HASHTABLE[code]->DATA);
803    return lastname;
804 }
805 
806 
807 /*******************************************************************************
808 * function namefind()                                                         *
809 *******************************************************************************/
namefind(const char * inputname)810 char *namefind(const char *inputname)
811 {
812 chain_list *pt;
813 char *name = buffer; /* ensure no modification of parameter string */
814 register int code = 0;
815 
816    if (inputname == NULL)
817       return NULL;
818 
819    HASH_FUNC(inputname, name, code);
820 
821    for (pt = NAME_HASHTABLE[code]; pt; pt = pt->NEXT)
822       if (!strcmp(buffer, (char *)pt->DATA))
823          return (char *)pt->DATA;
824 
825    return NULL ;
826 }
827 
828 /*******************************************************************************
829 * function downstr()                                                           *
830 *******************************************************************************/
downstr(const char * s,char * t)831 void downstr(const char *s, char *t)
832 {
833    for (; *s; s++, t++)
834       *t = tolowertable[(int)*s];
835    *t = *s;
836 }
837 
838 /*******************************************************************************
839 * function upstr()                                                             *
840 *******************************************************************************/
upstr(const char * s,char * t)841 void upstr(const char *s, char *t)
842 {
843    for (; *s; s++, t++)
844       *t = touppertable[(int)*s];
845    *t = *s;
846 }
847 
848 /*******************************************************************************
849 * function isck()                                                              *
850 *******************************************************************************/
isck(char * name)851 int  isck(char *name)
852 {
853     if (!name || !CK)
854         return 0;
855     else
856         if (!strcmp(name, CK))
857             return 1;
858         else
859             return 0;
860 }
861 
862 /*******************************************************************************
863 * function instr() : about strstr, but some systems don't have it              *
864 *******************************************************************************/
instr(char * s,const char * find,char separ)865 char *instr(char *s, const char *find, char separ)
866 {
867 char *t, c, sc;
868 int len;
869 
870    if (!s || !find)
871       return NULL;
872    if (separ) {
873       t = s;
874       if ((s = strrchr(s, separ)) == NULL)
875          s = t;
876       else
877          s++; /* skip the separator itself */
878    }
879    if ((c = *find++) != 0) {
880       len = strlen(find);
881       do {
882          do {
883             if ((sc = *s++) == 0)
884                return NULL;
885          } while (sc != c);
886       } while (strncmp(s, find, len) != 0);
887       s--;
888    }
889    return s;
890 }
891 
892 /*******************************************************************************
893 * function vectorize : builds a legal mbk vector from a name and an index      *
894 *******************************************************************************/
vectorize(const char * radical,long index)895 char *vectorize(const char *radical, long index)
896 {
897   (void)sprintf(str,"%s %ld", radical, index);
898   return namealloc(str);
899 }
900 
901 /*******************************************************************************
902 * function vectorradical : returns the radical of an mbk vector                *
903 *******************************************************************************/
vectorradical(char * name)904 char *vectorradical(char *name)
905 {
906 char *s;
907 
908    strcpy(str, name);
909    s = strchr(str, ' ');
910 
911    if (!s)
912       return name;
913 
914    *s = '\0';
915    return namealloc(str);
916 }
917 
918 /*******************************************************************************
919 * function vectorindex : returns the index of an mbk vector                    *
920 *******************************************************************************/
vectorindex(const char * name)921 int vectorindex(const char *name)
922 {
923 char *s = strchr(name, ' ');
924 
925    if (!s)
926       return -1;
927 
928    return atoi(s);
929 }
930 
931 /*******************************************************************************
932 *  generic compaison function :                                                *
933 *  unlike strcmp, ensure that 10 > 2 for vectorized strings.                   *
934 *  first, check strings, then check numerical values as numbers, not strings.  *
935 *******************************************************************************/
naturalstrcmp(const char * s,const char * t)936 int naturalstrcmp(const char *s, const char *t)
937 {
938 char *spt, *tpt;
939 const char *st = s, *tt = t;
940 int u, ls, lt;
941 
942    spt = buffer, tpt = str;
943 
944    while ((!isspace((int)*st)) && *st)
945       *spt++ = *st++;
946    *spt = '\0';
947 
948    while ((!isspace((int)*tt)) && *tt)
949       *tpt++ = *tt++;
950    *tpt = '\0';
951 
952    if ((u = strcmp(buffer, str)) != 0)
953       return u;
954 
955    if ((ls = strlen(s)) == (lt = strlen(t)))
956       return strcmp(s, t);
957 
958    return ls - lt;
959 }
960 
961 /*******************************************************************************
962 * function concatname()                                                        *
963 *******************************************************************************/
concatname(const char * name1,const char * name2)964 char *concatname(const char *name1, const char *name2)
965 {
966   (void)sprintf(str,"%s%c%s", name1, SEPAR, name2);
967   return namealloc(str);
968 }
969 
970 /*******************************************************************************
971 * mbkstrdup : since brain damaged system we aim at do not have it              *
972 *******************************************************************************/
mbkstrdup(const char * s)973 char *mbkstrdup(const char *s)
974 {
975   char *t;
976 
977   if (s == NULL)
978     return NULL;
979 
980   t = (char *)mbkalloc((size_t)(strlen(s) + 1));
981   return strcpy(t, s);
982 }
983 
984 /*******************************************************************************
985 * function reverse                                                             *
986 *******************************************************************************/
reverse(chain_list * head)987 chain_list *reverse(chain_list *head)
988 {
989 chain_list *p;
990 chain_list *q = (chain_list *)NULL;
991 
992    if (!head)
993       return NULL;
994    while ((p = head->NEXT)) {
995       head->NEXT = q;
996       q = head;
997       head = p;
998    }
999    head->NEXT = q;
1000    return head;
1001 }
1002 
1003 /*******************************************************************************
1004 * function pstrcmp                                                             *
1005 * used for qsort and bsearch use for catalog sorting and acessing              *
1006 *******************************************************************************/
pstrcmp(const void * s,const void * t)1007 static int pstrcmp(const void *s, const void *t)
1008 {
1009    return strcmp(*(const char **)s, *(const char **)t);
1010 }
1011 
1012 /*******************************************************************************
1013 * function incatalogfeed                                                       *
1014 * tests if a model is present in the catalog with the F attribut               *
1015 *******************************************************************************/
incatalogfeed(const char * figname)1016 int incatalogfeed(const char *figname)
1017 {
1018 static int size;
1019 static char **table;
1020 
1021    if (!size)
1022       loadcatalog(&table, &size, 'F');
1023    return size ?
1024             (long)bsearch(&figname, table, size, sizeof(char *), pstrcmp) : 0;
1025 }
1026 
1027 /*******************************************************************************
1028 * function incataloggds                                                        *
1029 * tests if a model is present in the catalog with the G attribut               *
1030 ******************************************************************************/
incataloggds(const char * figname)1031 int incataloggds(const char *figname)
1032 {
1033 static int size;
1034 static char **table;
1035 
1036    if (!size)
1037       loadcatalog(&table, &size, 'G');
1038    return size ?
1039             (long)bsearch(&figname, table, size, sizeof(char *), pstrcmp) : 0;
1040 }
1041 
1042 /*******************************************************************************
1043 * function incatalog                                                           *
1044 * tests if a model is present in the catalog with the C attribut               *
1045 *******************************************************************************/
incatalog(const char * figname)1046 int incatalog(const char *figname)
1047 {
1048 static int size;
1049 static char **table;
1050 
1051    if (!size)
1052       loadcatalog(&table, &size, 'C');
1053    return size ?
1054             (long)bsearch(&figname, table, size, sizeof(char *), pstrcmp) : 0;
1055 }
1056 
1057 /*******************************************************************************
1058 * function incatalogdelete                                                     *
1059 * tests if a model is present in the catalog with the D attribut               *
1060 *******************************************************************************/
incatalogdelete(const char * figname)1061 int incatalogdelete(const char *figname)
1062 {
1063 static int size;
1064 static char **table;
1065 
1066    if (!size)
1067       loadcatalog(&table, &size, 'D');
1068    return size ?
1069             (long)bsearch(&figname, table, size, sizeof(char *), pstrcmp) : 0;
1070 }
1071 
1072 /*******************************************************************************
1073 * function loadcatalog                                                         *
1074 * read the catalog from disk checking the given type                           *
1075 *******************************************************************************/
1076 
loadcatalog(char *** table,int * size,char type)1077 static void loadcatalog(char ***table, int *size, char type)
1078 {
1079 void *pt;
1080 char attrib;
1081 int nb;
1082 int nb_input;
1083 int i = 0;
1084 chain_list *files = (chain_list *)NULL;
1085 /* Tables for quick cell search :
1086    The catalog file is read only once, and sorted for speed.
1087    The later calls to loadcatalog only return the approriate table. */
1088 static chain_list *cells[4];
1089 static char **tabs[4];
1090 static int sizes[4];
1091 static int read;
1092 
1093    if (!read) {
1094       read++;
1095       (void)sprintf(buffer, "%s/%s", WORK_LIB, CATAL ? CATAL : "CATAL");
1096       files = addchain(files, (void *)fopen(buffer, READ_TEXT));
1097       while (CATA_LIB[i]) {
1098          (void)sprintf(buffer, "%s/CATAL", CATA_LIB[i++]);
1099          files = addchain(files, (void *)fopen(buffer, READ_TEXT));
1100       }
1101       /* error message :
1102          To avoid malloc/free on file name, the error message is output
1103          relatively to its order. */
1104       files = reverse(files);
1105       for (i = 0, pt = (void *)files; pt;
1106             pt = (void *)((chain_list *)pt)->NEXT, i++) {
1107          if (!((chain_list *)pt)->DATA)
1108             continue;
1109          nb = 0;
1110          while (!feof((FILE *)((chain_list *)pt)->DATA)) {
1111             nb++; /* count lines */
1112             nb_input = fscanf((FILE *)((chain_list *)pt)->DATA, "%4096s %c\n",
1113                               buffer, &attrib);
1114             if (nb_input == 0) /* skip white lines */
1115                continue;
1116             if (nb_input != 2) {
1117                (void)fflush(stdout);
1118                (void)fprintf(stderr, "*** mbk error ***\n");
1119                (void)fprintf(stderr, "loadcatalog syntax error line %d ", nb);
1120                if (i == 0)
1121                   (void)fprintf(stderr, "in file %s/%s\n", WORK_LIB, CATAL);
1122                else
1123                   (void)fprintf(stderr, "in file %s/CATAL\n", CATA_LIB[i - 1]);
1124                EXIT(1);
1125             }
1126             attrib = islower((int)attrib) ? (char)toupper((int)attrib) : attrib;
1127             switch (attrib) {
1128                case 'C' :
1129                   cells[0] = addchain(cells[0], namealloc(buffer));
1130                   sizes[0]++;
1131                   break;
1132                case 'G' :
1133                   cells[1] = addchain(cells[1], namealloc(buffer));
1134                   sizes[1]++;
1135                   break;
1136                case 'F' :
1137                   cells[2] = addchain(cells[2], namealloc(buffer));
1138                   sizes[2]++;
1139                   break;
1140                case 'D' :
1141                   cells[3] = addchain(cells[3], namealloc(buffer));
1142                   sizes[3]++;
1143                   break;
1144                default :
1145                   (void)fflush(stdout);
1146                   (void)fprintf(stderr, "*** mbk error ***\n");
1147                   (void)fprintf(stderr, "loadcatalog syntax error line %d ",
1148                                  nb);
1149                   if (i == 0)
1150                      (void)fprintf(stderr, "in file %s/%s\n", WORK_LIB, CATAL);
1151                   else
1152                      (void)fprintf(stderr, "in file %s/CATAL\n",
1153                                     CATA_LIB[i - 1]);
1154                   (void)fprintf(stderr,"unknown attribut %c\n", attrib);
1155                   EXIT(1);
1156             }
1157          }
1158          (void)fclose((FILE *)((chain_list *)pt)->DATA);
1159       }
1160       for (nb = 0; nb < 4; nb++) {
1161          if (sizes[nb]) {
1162             tabs[nb] = (char **)mbkalloc(sizes[nb] * sizeof(char *));
1163             for (i = 0, pt = (void *)cells[nb]; pt;
1164                   pt = (void *)((chain_list *)pt)->NEXT, i++)
1165                tabs[nb][i] = (char *)((chain_list *)pt)->DATA;
1166             qsort(tabs[nb], sizes[nb], sizeof(char *), pstrcmp);
1167             freechain(cells[nb]);
1168          }
1169       }
1170    }
1171 
1172    switch (type) {
1173       case 'C' :
1174          *table = tabs[0];
1175          *size = sizes[0];
1176          break;
1177       case 'G' :
1178          *table = tabs[1];
1179          *size = sizes[1];
1180          break;
1181       case 'F' :
1182          *table = tabs[2];
1183          *size = sizes[2];
1184          break;
1185       case 'D' :
1186          *table = tabs[3];
1187          *size = sizes[3];
1188          break;
1189    }
1190 }
1191 
1192 /*******************************************************************************
1193 * function read_lib()                                                          *
1194 * fills an array of char * in order to have a list of names as CATA_LIB        *
1195 *******************************************************************************/
read_lib(void)1196 static void read_lib(void)
1197 {
1198 char *str, *s, *stc, *c;
1199 int argc = 0;
1200 
1201    str = mbkgetenv("MBK_WORK_LIB");
1202    if (str != NULL) {
1203       WORK_LIB =
1204          (char *)mbkalloc((unsigned int)(strlen(str) + 1) * sizeof(char));
1205       (void)strcpy(WORK_LIB, str);
1206    } else { /* no specific path is given */
1207       WORK_LIB = (char *)mbkalloc((unsigned int)2 * sizeof(char));
1208       (void)strcpy(WORK_LIB, ".");
1209    }
1210 
1211    str = mbkgetenv("MBK_CATA_LIB");
1212    if(str != NULL) {
1213       s = (char *)mbkalloc((unsigned int)(strlen(str) + 1) * sizeof(char));
1214       (void)strcpy(s, str);
1215       str = s;   /* let's not modify the environement values */
1216       stc = str; /* for counting purposes */
1217       while (1) {
1218          if ((c = strchr(stc, ':')) == NULL)
1219             break;
1220          argc++;
1221          stc = ++c;
1222       }
1223       CATA_LIB = (char **)mbkalloc((unsigned int)(argc + 2) * sizeof(char *));
1224       argc = 0;
1225       while (1) {
1226          if ((s = strchr(str, ':')) == NULL)
1227             break;
1228          *(s++) = '\0';
1229          CATA_LIB[argc++] = str; /* no allocation necessary */
1230          str = s;
1231       }
1232       if (s == NULL)
1233          CATA_LIB[argc++] = str == NULL || *str == '\0' ? NULL : str;
1234       CATA_LIB[argc] = NULL;
1235    } else { /* no specific path is given */
1236       CATA_LIB = (char **)mbkalloc((unsigned int)2 * sizeof(char *));
1237       CATA_LIB[0] = ".";
1238       CATA_LIB[1] = NULL;
1239    }
1240 }
1241 /*******************************************************************************
1242 * Hash tables management functions, contributed to by Luc Burgun on 20/06/92   *
1243 *******************************************************************************/
1244 static void reallocht(ht *pTable);
1245 /*******************************************************************************
1246 * dilution function for the table accesses                                     *
1247 *******************************************************************************/
hash(void * p)1248 static unsigned long hash(void *p)
1249 {
1250    return abs((long)p * ((long)p >> 5) >> 4);
1251 }
1252 
1253 /*******************************************************************************
1254 * function addht, create a hash table                                          *
1255 *******************************************************************************/
addht(unsigned long len)1256 ht *addht(unsigned long len)
1257 {
1258 ht *pTable;
1259 htitem *pEl;
1260 int i;
1261 
1262    if (len == 0) {
1263       fflush(stdout);
1264       (void)fprintf(stderr, "*** mbk error ***\n");
1265       (void)fprintf(stderr, "addht impossible : hash table size is '0'\n");
1266       EXIT(1);
1267    }
1268    pTable = (ht *)mbkalloc(sizeof(struct htable));
1269    pTable->length = len;
1270    pEl = (htitem *)mbkalloc(len * (sizeof(struct htitem)));
1271    pTable->pElem = pEl;
1272    for (i = 0; i < len; i++) {
1273       pEl[i].key = NULL;
1274       pEl[i].value = EMPTYHT;
1275    }
1276    pTable->count = 0;
1277    return pTable;
1278 }
1279 
1280 /*******************************************************************************
1281 * function delht, delete a hash table                                          *
1282 *******************************************************************************/
delht(ht * pTable)1283 void delht(ht *pTable)
1284 {
1285 htitem * pEl;
1286 
1287    pEl = pTable->pElem;
1288    mbkfree(pEl);
1289    mbkfree(pTable);
1290 }
1291 
1292 /*******************************************************************************
1293 * function gethtitem, get an element in a hash table                            *
1294 *******************************************************************************/
gethtitem(ht * pTable,void * key)1295 long gethtitem(ht *pTable, void *key)
1296 {
1297 long co = 0;
1298 long indice = 0;
1299 htitem * pEl;
1300 
1301    indice = hash(key) % pTable->length;
1302    do {
1303       if (co++ > HMAX_CALLS) {
1304          reallocht(pTable);
1305          return gethtitem(pTable, key);
1306       }
1307 
1308       pEl = (pTable->pElem) + indice;
1309       if (pEl->value != EMPTYHT && pEl->value != DELETEHT) {
1310          if ((long) key == (long) pEl->key)
1311             return pEl->value;
1312       } else if (pEl->value == EMPTYHT)
1313          return EMPTYHT;
1314       indice = (indice + 1) % pTable->length;
1315    } while (1);
1316 }
1317 
1318 /*******************************************************************************
1319 * function addhtitem, get an element in a hash table                            *
1320 *******************************************************************************/
addhtitem(ht * pTable,void * key,long value)1321 long addhtitem(ht *pTable, void *key, long value)
1322 {
1323 int indice = 0;
1324 htitem *pEl;
1325 int co = 0;
1326 
1327    if (value == EMPTYHT || value == DELETEHT) {
1328       fflush(stdout);
1329       (void)fprintf(stderr, "*** mbk error ***\n");
1330       (void)fprintf(stderr, "addhtitem impossible : value is EMPTYHT or DELETEHT\n");
1331       EXIT(1);
1332    }
1333    if (pTable->count++ > (pTable->length) * 8 / 10) {
1334       reallocht(pTable);
1335       return addhtitem(pTable, key, value);
1336    }
1337 
1338    indice = hash(key) % pTable->length;
1339    do {
1340       if (co++ > HMAX_CALLS) {
1341          reallocht(pTable);
1342          return addhtitem(pTable, key, value);
1343       }
1344       pEl = (pTable->pElem) + indice;
1345       if (pEl->value == EMPTYHT || pEl->value == DELETEHT) {
1346          pEl->value = value;
1347          pEl->key = key;
1348          return value;
1349       } else if ((long) pEl->key == (long) key) {
1350          pTable->count--;
1351          pEl->value = value;
1352          return value;
1353       }
1354       indice = (indice + 1) % pTable->length;
1355    } while (1);
1356 }
1357 
1358 /*******************************************************************************
1359 * function sethtitem, test if an element exists in a hash table,                *
1360 * adds it anyway, and returns 1 if it used to exist, 0 else.                   *
1361 *******************************************************************************/
sethtitem(ht * pTable,void * key,long value)1362 long sethtitem(ht *pTable, void *key, long value)
1363 {
1364 int indice = 0;
1365 htitem *pEl;
1366 int co = 0;
1367 
1368    if (value == EMPTYHT || value == DELETEHT) {
1369       fflush(stdout);
1370       (void)fprintf(stderr, "*** mbk error ***\n");
1371       (void)fprintf(stderr, "sethtitem impossible : value is EMPTYHT or DELETEHT\n");
1372       EXIT(1);
1373    }
1374    if (pTable->count++ > (pTable->length) * 8 / 10) {
1375       reallocht(pTable);
1376       return sethtitem(pTable, key, value);
1377    }
1378 
1379    indice = hash(key) % pTable->length;
1380    do {
1381       if (co++ > HMAX_CALLS) {
1382          reallocht(pTable);
1383          return sethtitem(pTable, key, value);
1384       }
1385       pEl = (pTable->pElem) + indice;
1386       if (pEl->value == EMPTYHT || pEl->value == DELETEHT) {
1387          pEl->value = value;
1388          pEl->key = key;
1389          return 0;
1390       } else if ((long) pEl->key == (long) key) {
1391          pTable->count--;
1392          pEl->value = value;
1393          return 1;
1394       }
1395       indice = (indice + 1) % pTable->length;
1396    } while (1);
1397 }
1398 
1399 /*******************************************************************************
1400 * function delhtitem, delete an element in a hash table                         *
1401 *******************************************************************************/
delhtitem(ht * pTable,void * key)1402 long delhtitem(ht *pTable, void *key)
1403 {
1404 int indice = 0;
1405 htitem *pEl;
1406 int co = 0;
1407 
1408    indice = hash(key) % pTable->length;
1409    do {
1410       if (co++ > HMAX_CALLS) {
1411          reallocht(pTable);
1412          return delhtitem(pTable, key);
1413       }
1414       pEl = (pTable->pElem) + indice;
1415       if (pEl->value != EMPTYHT && pEl->value != DELETEHT) {
1416          if ((long) key == (long)pEl->key) {
1417             pTable->count--;
1418             pEl->value = DELETEHT;
1419             return pEl->value;
1420          }
1421       } else if (pEl->value == EMPTYHT)
1422          return EMPTYHT;
1423       indice = (indice + 1) % pTable->length;
1424    } while (1);
1425 }
1426 
1427 /*******************************************************************************
1428 * display contents of an hash table                                            *
1429 *******************************************************************************/
viewht(ht * pTable,char * (* pout)(void *))1430 void viewht(ht *pTable, char *(*pout)(void *))
1431 {
1432 long i;
1433 htitem *pEl = pTable->pElem;
1434 
1435    (void)printf("================== viewht ================\n");
1436    (void)printf("length = %ld\t     count = %ld\n",
1437                   pTable->length, pTable->count);
1438    (void)printf("==========================================\n");
1439    for (i = 0; i < pTable->length; i++) {
1440       if (pEl->value != EMPTYHT && pEl->value != DELETEHT) {
1441          printf("index  %ld\t", i);
1442          printf("key    %s\t", pout(pEl->key));
1443          printf("value  %ld \n", pEl->value);
1444       }
1445       pEl++;
1446    }
1447 }
1448 
1449 /*******************************************************************************
1450 * realloc space to adapt hash table size to number of entries                  *
1451 *******************************************************************************/
reallocht(ht * pTable)1452 static void reallocht(ht *pTable)
1453 {
1454 ht *tabBis;
1455 htitem *pEl;
1456 int i;
1457 
1458    pEl = pTable->pElem;
1459    tabBis = addht((pTable->length) * 5);
1460    for (i = 0; i < pTable->length; i++) {
1461       if (pEl->value != EMPTYHT && pEl->value != DELETEHT)
1462          addhtitem(tabBis, pEl->key, pEl->value);
1463       pEl++;
1464    }
1465    mbkfree(pTable->pElem);
1466    pTable->length = tabBis->length;
1467    pTable->pElem = tabBis->pElem;
1468    pTable->count = tabBis->count;
1469    mbkfree(tabBis);
1470 }
1471 
1472 /*******************************************************************************
1473 * All that needed for a cute banner, by Frederic Petrot                        *
1474 * Used to be a standalone library                                              *
1475 *******************************************************************************/
1476 #include <time.h>
1477 #define WINDOW_SIZE 81
1478 #define LINES 15
1479 #define ASCENT 13
1480 static char screen[LINES][WINDOW_SIZE];
1481 
indx(char c)1482 static int indx(char c)
1483 {
1484    return c >= '0' && c <= '9' ? (int)c - '0'
1485                               : isupper((int)c) ? (int)10 + c - 'A'
1486                               : islower((int)c) ? (int)11 + 'Z' - 'A' + c - 'a'
1487                               : -1;
1488 }
1489 
banner(const char * s,const char * police[][62],int nl)1490 static void banner(const char *s, const char *police[][62], int nl)
1491 {
1492 int i, j, k, l, m;
1493 const char *line;
1494 
1495    /* rince off :
1496       the buffer is filled with nul characteres. */
1497    for (j = 0; j < nl; j++)
1498       for (i = 0; i < WINDOW_SIZE; i++)
1499          screen[j][i] = '\0';
1500    /* first :
1501       filling the buffer with direct table output. */
1502    while (*s) {
1503       for (i = 0; i < nl; i++) {
1504          if ((j = indx(*s)) == -1) {
1505             fprintf(stderr,
1506                "alliancebanner: Error: Character out of [0-9A-Za-z] range\n");
1507             exit(1);
1508          }
1509          line = police[j][i];
1510          if (strlen(line) + strlen(screen[i]) >= WINDOW_SIZE) {
1511             fprintf(stderr,
1512    "alliancebanner: Error: Resulting size bigger than %d columns not allowed\n",
1513                               WINDOW_SIZE - 1);
1514             exit(1);
1515          }
1516          strcat(screen[i], line);
1517          if (*(s + 1) != '\0')
1518             strcat(screen[i], " ");
1519       }
1520       s++;
1521    }
1522    for (m = l = -1, j = 0; j < nl; j++)
1523       for (i = 0; i < WINDOW_SIZE; i++)
1524          if (screen[j][i] == '@') {
1525             if (m == -1)
1526                m = j;
1527             l = j;
1528             break;
1529          }
1530    k = strlen(screen[0]);
1531    /* banner :
1532       output on stdout. */
1533    putc('\n', stdout);
1534    for (j = m; j <= l; j++) {
1535       for (i = 0; i < (WINDOW_SIZE - k) / 2; i++)
1536          putc(' ', stdout);
1537       for (i = 0; i < k; i++)
1538          putc(screen[j][i], stdout);
1539       putc('\n', stdout);
1540    }
1541 }
1542 
cartouche(const char * tool,const char * tv,const char * comment,const char * date,const char * av,const char * authors,const char * contrib)1543 static void cartouche(const char *tool, const char *tv, const char *comment, const char *date, const char *av, const char *authors, const char *contrib)
1544 {
1545 int i, j, k, l;
1546 static char *msg[6] = {
1547    "%s",
1548    "Alliance CAD System %s,\"%s %s",
1549    "Copyright (c) %s-%d,\"ASIM/LIP6/UPMC",
1550    "Author(s):\"%s",
1551    "Contributor(s):\"%s",
1552    "E-mail        :\"alliance-users@asim.lip6.fr"
1553 };
1554 int msgl[6];
1555 char *str;
1556 time_t timer;
1557 char day[4], month[4];
1558 int year, nday, hour, minute, second;
1559 
1560    (void)time(&timer);
1561    (void)sscanf(ctime(&timer), "%3s %3s %11d %11d:%11d:%11d %11d",
1562                        day, month, &nday, &hour, &minute, &second, &year);
1563    /* rince off :
1564       the buffer is filled with nul characteres. */
1565    for (j = 0; j < 12; j++)
1566       for (i = 0; i < WINDOW_SIZE; i++)
1567          screen[j][i] = '\0';
1568    i = strlen(tool);
1569    str = mbkstrdup(tool);
1570    for (k = 0; k < i; k++)
1571       str[k] = isupper((int)tool[k]) ? tolower((int)tool[k]) : tool[k];
1572    sprintf(screen[0], msg[0], comment);
1573    sprintf(screen[1], msg[1], av, str, tv);
1574    mbkfree(str);
1575    sprintf(screen[2], msg[2], date, year);
1576    if (authors != (char *)0 )
1577     sprintf(screen[3], msg[3],authors);
1578    else
1579     screen[3][0] = '\0';
1580    if (contrib != (char *)0 )
1581     sprintf(screen[4], msg[4],contrib);
1582    else
1583     screen[4][0] = '\0';
1584 
1585    strcat(screen[5], msg[5]);
1586 
1587    for (i = 1; i < 6; i++) {
1588       msgl[i] = strlen(screen[i]);
1589       j = j < msgl[i] ? msgl[i] : j;
1590    }
1591    for (i = 1; i < 6; i++)
1592       for (l = 0, k = 0; k < WINDOW_SIZE; k++) {
1593          if (screen[i][k] == '\0') {
1594             screen[i + 6][k + l] = '\0';
1595             break;
1596          }
1597          if (screen[i][k] == '"') { /* only once per line */
1598             for (; l <= j - msgl[i]; l++)
1599                screen[i + 6][k + l] = ' ';
1600             continue;
1601          }
1602          screen[i + 6][k + l] = screen[i][k];
1603       }
1604    /* cartouche :
1605       output on stdout. */
1606    i = strlen(comment);
1607    putc('\n', stdout);
1608    for (k = 0; k < (WINDOW_SIZE - i) / 2; k++)
1609       putc(' ', stdout);
1610    puts(screen[0]);
1611    putc('\n', stdout);
1612    for (i = 1; i < 6; i++) {
1613       if (screen[i][0]=='\0') continue;
1614       for (k = 0; k < (WINDOW_SIZE - j) / 2; k++)
1615          putc(' ', stdout);
1616       for (k = 0; k <= j; k++)
1617          if (screen[i + 6][k] != 0) /* not so nice, but */
1618             putc(screen[i + 6][k], stdout);
1619       putc('\n', stdout);
1620    }
1621    putc('\n', stdout);
1622 }
1623 
alliancebanner_with_contrib(const char * tool,const char * tv,const char * comment,const char * date,const char * av,const char * authors,const char * contrib)1624 void alliancebanner_with_contrib(const char *tool, const char *tv, const char *comment, const char *date, const char *av, const char *authors, const char *contrib)
1625 {
1626   banner(tool, Unknown_Bold_Normal_14, 15);
1627   cartouche(tool, tv, comment, date, av, authors,contrib);
1628 }
1629 
alliancebanner_with_authors(const char * tool,const char * tv,const char * comment,const char * date,const char * av,const char * authors)1630 void alliancebanner_with_authors(const char *tool, const char *tv, const char *comment, const char *date, const char *av, const char *authors)
1631 {
1632   alliancebanner_with_contrib( tool, tv, comment, date, av, authors, NULL );
1633 }
1634 
1635 
alliancebanner(const char * tool,const char * tv,const char * comment,const char * date,const char * av)1636 void alliancebanner(const char *tool, const char *tv, const char *comment, const char *date, const char *av)
1637 {
1638   alliancebanner_with_contrib( tool, tv, comment, date, av, NULL, NULL );
1639 }
1640 
1641 /******************
1642 * Contributed to by Ludovic Jacomme
1643 **************************/
1644 ptype_list *HEAD_MBKDEBUG = NULL;
1645 char        MBK_DEBUG_ON  = 0;
1646 
trapdebug(int dummy)1647 static void trapdebug(int dummy)
1648 {
1649   ptype_list *ScanDebug;
1650 
1651   for ( ScanDebug  = HEAD_MBKDEBUG;
1652         ScanDebug != (ptype_list *)NULL;
1653         ScanDebug  = ScanDebug->NEXT )
1654   {
1655     fprintf( stdout, "mbkdebug: file %s line %ld\n",
1656              (char *)ScanDebug->DATA, ScanDebug->TYPE );
1657   }
1658 
1659   fflush( stdout );
1660 
1661   signal( SIGQUIT, trapdebug );
1662   signal( SIGSEGV, SIG_DFL      );
1663   signal( SIGBUS , SIG_DFL      );
1664   signal( SIGILL , SIG_DFL      );
1665 }
1666 
mbkdebug(void)1667 void mbkdebug(void)
1668 {
1669   signal( SIGSEGV, trapdebug );
1670   signal( SIGBUS,  trapdebug );
1671   signal( SIGILL,  trapdebug );
1672   signal( SIGQUIT, trapdebug );
1673 
1674   MBK_DEBUG_ON = 1;
1675 }
1676 
1677 /*
1678 ** Added by Ludovic Jacomme (The slave)
1679 ** in order to "trap" exit with Graal/Dreal etc ...
1680 */
1681 
mbkexit(int ExitValue)1682 void mbkexit( int ExitValue )
1683 {
1684   if ( MBK_EXIT_FUNCTION != NULL )
1685   {
1686     (*MBK_EXIT_FUNCTION)( ExitValue );
1687   }
1688 
1689   kill( getpid(), SIGTERM );
1690 }
1691 
1692 
1693 /* To compile with gcc under SunOS */
1694 #ifdef SunOS
dlopen(char * path,int mode)1695 void *dlopen(char *path, int mode)
1696 {
1697 }
dlsym(void * handle,char * symbol)1698 void *dlsym(void *handle, char *symbol)
1699 {
1700 }
dlerror(void)1701 char *dlerror(void)
1702 {
1703 }
dlclose(void * handle)1704 int dlclose(void *handle)
1705 {
1706 }
1707 #endif
1708