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