FORM  4.3
minos.c
Go to the documentation of this file.
1 
7 /* #[ License : */
8 /*
9  * Copyright (C) 1984-2022 J.A.M. Vermaseren
10  * When using this file you are requested to refer to the publication
11  * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
12  * This is considered a matter of courtesy as the development was paid
13  * for by FOM the Dutch physics granting agency and we would like to
14  * be able to track its scientific use to convince FOM of its value
15  * for the community.
16  *
17  * This file is part of FORM.
18  *
19  * FORM is free software: you can redistribute it and/or modify it under the
20  * terms of the GNU General Public License as published by the Free Software
21  * Foundation, either version 3 of the License, or (at your option) any later
22  * version.
23  *
24  * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
25  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
26  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
27  * details.
28  *
29  * You should have received a copy of the GNU General Public License along
30  * with FORM. If not, see <http://www.gnu.org/licenses/>.
31  */
32 /* #] License : */
33 /*
34  #[ Includes :
35 
36  File contains the lowlevel routines for the management of primitive
37  database-like files. The structures are explained in the file manage.h
38  Original file for minos made by J.Vermaseren, april-1994.
39 
40  Note: the minos primitives for writing are never invoked in parallel.
41 */
42 
43 #include "form3.h"
44 #include "minos.h"
45 int withoutflush = 0;
46 
47 /*
48  #] Includes :
49  #[ Variables :
50 */
51 
52 static INDEXBLOCK scratchblock;
53 static NAMESBLOCK scratchnamesblock;
54 
55 #define CFD(y,s,type,x,j) for(x=0,j=0;j<((int)sizeof(type));j++) \
56  x=(x<<8)+((*s++)&0x00FF); y=x;
57 #define CTD(y,s,type,x,j) x=y;for(j=sizeof(type)-1;j>=0;j--){s[j]=x&0xFF; \
58  x>>=8;} s += sizeof(type);
59 
60 /*
61  #] Variables :
62  #[ Utilities :
63  #[ minosread :
64 */
65 
66 int minosread(FILE *f,char *buffer,MLONG size)
67 {
68  MLONG x;
69  while ( size > 0 ) {
70  x = fread(buffer,sizeof(char),size,f);
71  if ( x <= 0 ) return(-1);
72  buffer += x;
73  size -= x;
74  }
75  return(0);
76 }
77 
78 /*
79  #] minosread :
80  #[ minoswrite :
81 */
82 
83 int minoswrite(FILE *f,char *buffer,MLONG size)
84 {
85  MLONG x;
86  while ( size > 0 ) {
87  x = fwrite(buffer,sizeof(char),size,f);
88  if ( x <= 0 ) return(-1);
89  buffer += x;
90  size -= x;
91  }
92  if ( withoutflush == 0 ) fflush(f);
93  return(0);
94 }
95 
96 /*
97  #] minoswrite :
98  #[ str_dup :
99 */
100 
101 char *str_dup(char *str)
102 {
103  char *s, *t;
104  int i;
105  s = str;
106  while ( *s ) s++;
107  i = s - str + 1;
108  if ( ( s = (char *)Malloc1((size_t)i,"a string copy") ) == 0 ) return(0);
109  t = s;
110  while ( *str ) *t++ = *str++;
111  *t = 0;
112  return(s);
113 }
114 
115 /*
116  #] str_dup :
117  #[ convertblock :
118 */
119 
120 void convertblock(INDEXBLOCK *in,INDEXBLOCK *out,int mode)
121 {
122  char *s,*t;
123  MLONG i, x;
124  int j;
125  OBJECTS *obj;
126  switch ( mode ) {
127  case TODISK:
128  s = (char *)out;
129  CTD(in->flags,s,MLONG,x,j)
130  CTD(in->previousblock,s,MLONG,x,j)
131  CTD(in->position,s,MLONG,x,j)
132  for ( i = 0, obj = in->objects; i < NUMOBJECTS; i++, obj++ ) {
133  CTD(obj->position,s,MLONG,x,j)
134  CTD(obj->size,s,MLONG,x,j)
135  CTD(obj->date,s,MLONG,x,j)
136  CTD(obj->tablenumber,s,MLONG,x,j)
137  CTD(obj->uncompressed,s,MLONG,x,j)
138  CTD(obj->spare1,s,MLONG,x,j)
139  CTD(obj->spare2,s,MLONG,x,j)
140  CTD(obj->spare3,s,MLONG,x,j)
141  t = obj->element;
142  for ( j = 0; j < ELEMENTSIZE; j++ ) *s++ = *t++;
143  }
144  break;
145  case FROMDISK:
146  s = (char *)in;
147  CFD(out->flags,s,MLONG,x,j)
148  CFD(out->previousblock,s,MLONG,x,j)
149  CFD(out->position,s,MLONG,x,j)
150  for ( i = 0, obj = out->objects; i < NUMOBJECTS; i++, obj++ ) {
151  CFD(obj->position,s,MLONG,x,j)
152  CFD(obj->size,s,MLONG,x,j)
153  CFD(obj->date,s,MLONG,x,j)
154  CFD(obj->tablenumber,s,MLONG,x,j)
155  CFD(obj->uncompressed,s,MLONG,x,j)
156  CFD(obj->spare1,s,MLONG,x,j)
157  CFD(obj->spare2,s,MLONG,x,j)
158  CFD(obj->spare3,s,MLONG,x,j)
159  t = obj->element;
160  for ( j = 0; j < ELEMENTSIZE; j++ ) *t++ = *s++;
161  }
162  break;
163  }
164 }
165 
166 /*
167  #] convertblock :
168  #[ convertnamesblock :
169 */
170 
171 void convertnamesblock(NAMESBLOCK *in,NAMESBLOCK *out,int mode)
172 {
173  char *s;
174  MLONG x;
175  int j;
176  switch ( mode ) {
177  case TODISK:
178  s = (char *)out;
179  CTD(in->previousblock,s,MLONG,x,j)
180  CTD(in->position,s,MLONG,x,j)
181  for ( j = 0; j < NAMETABLESIZE; j++ ) out->names[j] = in->names[j];
182  break;
183  case FROMDISK:
184  s = (char *)in;
185  CFD(out->previousblock,s,MLONG,x,j)
186  CFD(out->position,s,MLONG,x,j)
187  for ( j = 0; j < NAMETABLESIZE; j++ ) out->names[j] = in->names[j];
188  break;
189  }
190 }
191 
192 /*
193  #] convertnamesblock :
194  #[ convertiniinfo :
195 */
196 
197 void convertiniinfo(INIINFO *in,INIINFO *out,int mode)
198 {
199  char *s;
200  MLONG i, x, *y;
201  int j;
202  switch ( mode ) {
203  case TODISK:
204  s = (char *)out; y = (MLONG *)in;
205  for ( i = sizeof(INIINFO)/sizeof(MLONG); i > 0; i-- ) {
206  CTD(*y,s,MLONG,x,j)
207  y++;
208  }
209  break;
210  case FROMDISK:
211  s = (char *)in; y = (MLONG *)out;
212  for ( i = sizeof(INIINFO)/sizeof(MLONG); i > 0; i-- ) {
213  CFD(*y,s,MLONG,x,j)
214  y++;
215  }
216  break;
217  }
218 }
219 
220 /*
221  #] convertiniinfo :
222  #[ LocateBase :
223 */
224 
225 FILE *LocateBase(char **name, char **newname)
226 {
227  FILE *handle;
228  int namesize, i;
229  UBYTE *s, *to, *u1, *u2, *indir;
230  if ( ( handle = fopen(*name,"r+b") ) != 0 ) {
231  *newname = (char *)strDup1((UBYTE *)(*name),"LocateBase");
232  return(handle);
233  }
234  namesize = 2; s = (UBYTE *)(*name);
235  while ( *s ) { s++; namesize++; }
236  indir = AM.IncDir;
237  if ( indir ) {
238  s = indir; i = 0;
239  while ( *s ) { s++; i++; }
240  *newname = (char *)Malloc1(namesize+i,"LocateBase");
241  s = indir; to = (UBYTE *)(*newname);
242  while ( *s ) *to++ = *s++;
243  if ( to > (UBYTE *)(*newname) && to[-1] != SEPARATOR ) *to++ = SEPARATOR;
244  s = (UBYTE *)(*name);
245  while ( *s ) *to++ = *s++;
246  *to = 0;
247  if ( ( handle = fopen(*newname,"r+b") ) != 0 ) {
248  return(handle);
249  }
250  M_free(*newname,"LocateBase, incdir/file");
251  }
252  if ( AM.Path ) {
253  u1 = AM.Path;
254  while ( *u1 ) {
255  u2 = u1; i = 0;
256  while ( *u1 && *u1 != ':' ) {
257  if ( *u1 == '\\' ) u1++;
258  u1++; i++;
259  }
260  *newname = (char *)Malloc1(namesize+i,"LocateBase");
261  s = u2; to = (UBYTE *)(*newname);
262  while ( s < u1 ) {
263  if ( *s == '\\' ) s++;
264  *to++ = *s++;
265  }
266  if ( to > (UBYTE *)(*newname) && to[-1] != SEPARATOR ) *to++ = SEPARATOR;
267  s = (UBYTE *)(*name);
268  while ( *s ) *to++ = *s++;
269  *to = 0;
270  if ( ( handle = fopen(*newname,"r+b") ) != 0 ) {
271  return(handle);
272  }
273  M_free(*newname,"LocateBase Path/file");
274  if ( *u1 ) u1++;
275  }
276  }
277 /* Error1("LocateBase: Cannot find file",*name); */
278  return(0);
279 }
280 
281 /*
282  #] LocateBase :
283  #] Utilities :
284  #[ ReadIndex :
285 */
286 
287 int ReadIndex(DBASE *d)
288 {
289  MLONG i;
290  INDEXBLOCK **ib;
291  NAMESBLOCK **ina;
292  MLONG position, size;
293 /*
294  Allocate the pieces one by one (makes it easier to give it back)
295 */
296  if ( d->info.numberofindexblocks <= 0 ) return(0);
297 #ifndef WORDSIZE32
298  if ( sizeof(INDEXBLOCK)*d->info.numberofindexblocks > MAXINDEXSIZE ) {
299  MesPrint("We need more than %ld bytes for the index.\n",MAXINDEXSIZE);
300  MesPrint("The file %s may not be a proper database\n",d->name);
301  return(-1);
302  }
303 #endif
304  size = sizeof(INDEXBLOCK *)*d->info.numberofindexblocks;
305  if ( ( ib = (INDEXBLOCK **)Malloc1(size,"tb,index") ) == 0 ) return(-1);
306  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
307  if ( ( ib[i] = (INDEXBLOCK *)Malloc1(sizeof(INDEXBLOCK),"index block") ) == 0 ) {
308  for ( --i; i >= 0; i-- ) M_free(ib[i],"tb,indexblock");
309  M_free(ib,"tb,index");
310  return(-1);
311  }
312  }
313  size = sizeof(NAMESBLOCK *)*d->info.numberofnamesblocks;
314  if ( ( ina = (NAMESBLOCK **)Malloc1(size,"tb,indexnames") ) == 0 ) return(-1);
315  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
316  if ( ( ina[i] = (NAMESBLOCK *)Malloc1(sizeof(NAMESBLOCK),"index names block") ) == 0 ) {
317  for ( --i; i >= 0; i-- ) M_free(ina[i],"index names block");
318  M_free(ina,"tb,indexnames");
319  for ( i = 0; i < d->info.numberofindexblocks; i++ ) M_free(ib[i],"tb,indexblock");
320  M_free(ib,"tb,index");
321  return(-1);
322  }
323  }
324 /*
325  Read the index blocks, from the back to the front. The links are only
326  reliable that way.
327 */
328  position = d->info.lastindexblock;
329  for ( i = d->info.numberofindexblocks - 1; i >= 0; i-- ) {
330  fseek(d->handle,position,SEEK_SET);
331  if ( minosread(d->handle,(char *)(&scratchblock),sizeof(INDEXBLOCK)) ) {
332  MesPrint("Error while reading file %s\n",d->name);
333 thisiswrong:
334  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) M_free(ina[i],"index names block");
335  M_free(ina,"tb,indexnames");
336  for ( i = 0; i < d->info.numberofindexblocks; i++ ) M_free(ib[i],"tb,indexblock");
337  M_free(ib,"tb,index");
338  return(-1);
339  }
340  convertblock(&scratchblock,ib[i],FROMDISK);
341  if ( ib[i]->position != position ||
342  ( ib[i]->previousblock <= 0 && i > 0 ) ) {
343  MesPrint("File %s has inconsistent contents\n",d->name);
344  goto thisiswrong;
345  }
346  position = ib[i]->previousblock;
347  }
348  d->info.firstindexblock = ib[0]->position;
349  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
350  ib[i]->flags &= MCLEANFLAG;
351  }
352 /*
353  Read the names blocks, from the back to the front. The links are only
354  reliable that way.
355 */
356  position = d->info.lastnameblock;
357  for ( i = d->info.numberofnamesblocks - 1; i >= 0; i-- ) {
358  fseek(d->handle,position,SEEK_SET);
359  if ( minosread(d->handle,(char *)(&scratchnamesblock),sizeof(NAMESBLOCK)) ) {
360  MesPrint("Error while reading file %s\n",d->name);
361  goto thisiswrong;
362  }
363  convertnamesblock(&scratchnamesblock,ina[i],FROMDISK);
364  if ( ina[i]->position != position ||
365  ( ina[i]->previousblock <= 0 && i > 0 ) ) {
366  MesPrint("File %s has inconsistent contents\n",d->name);
367  goto thisiswrong;
368  }
369  position = ina[i]->previousblock;
370  }
371  d->info.firstnameblock = ina[0]->position;
372 /*
373  Give the old info back to the system.
374 */
375  if ( d->iblocks ) {
376  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
377  if ( d->iblocks[i] ) M_free(d->iblocks[i],"d->iblocks[i]");
378  }
379  M_free(d->iblocks,"d->iblocks");
380  }
381  if ( d->nblocks ) {
382  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
383  if ( d->nblocks[i] ) M_free(d->nblocks[i],"d->nblocks[i]");
384  }
385  M_free(d->nblocks,"d->nblocks");
386  }
387 /*
388  And substitute the new blocks
389 */
390  d->iblocks = ib;
391  d->nblocks = ina;
392  return(0);
393 }
394 
395 /*
396  #] ReadIndex :
397  #[ WriteIndexBlock :
398 */
399 
400 int WriteIndexBlock(DBASE *d,MLONG num)
401 {
402  if ( num >= d->info.numberofindexblocks ) {
403  MesPrint("Illegal number specified for number of index blocks\n");
404  return(-1);
405  }
406  fseek(d->handle,d->iblocks[num]->position,SEEK_SET);
407  convertblock(d->iblocks[num],&scratchblock,TODISK);
408  if ( minoswrite(d->handle,(char *)(&scratchblock),sizeof(INDEXBLOCK)) ) {
409  MesPrint("Error while writing an index block in file %s\n",d->name);
410  MesPrint("File may be unreliable now\n");
411  return(-1);
412  }
413  return(0);
414 }
415 
416 /*
417  #] WriteIndexBlock :
418  #[ WriteNamesBlock :
419 */
420 
421 int WriteNamesBlock(DBASE *d,MLONG num)
422 {
423  if ( num >= d->info.numberofnamesblocks ) {
424  MesPrint("Illegal number specified for number of names blocks\n");
425  return(-1);
426  }
427  fseek(d->handle,d->nblocks[num]->position,SEEK_SET);
428  convertnamesblock(d->nblocks[num],&scratchnamesblock,TODISK);
429  if ( minoswrite(d->handle,(char *)(&scratchnamesblock),sizeof(NAMESBLOCK)) ) {
430  MesPrint("Error while writing a names block in file %s\n",d->name);
431  MesPrint("File may be unreliable now\n");
432  return(-1);
433  }
434  return(0);
435 }
436 
437 /*
438  #] WriteNamesBlock :
439  #[ WriteIndex :
440 
441  Problem here is to get the links right.
442 */
443 
444 int WriteIndex(DBASE *d)
445 {
446  MLONG i, position;
447  if ( d->iblocks == 0 ) return(0);
448  if ( d->nblocks == 0 ) return(0);
449  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
450  if ( d->iblocks[i] == 0 ) {
451  MesPrint("Error: unassigned index blocks. Cannot write\n");
452  return(-1);
453  }
454  }
455  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
456  if ( d->nblocks[i] == 0 ) {
457  MesPrint("Error: unassigned names blocks. Cannot write\n");
458  return(-1);
459  }
460  }
461  d->info.lastindexblock = -1;
462  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
463  position = d->iblocks[i]->position;
464  if ( position <= 0 ) {
465  fseek(d->handle,0,SEEK_END);
466  position = ftell(d->handle);
467  d->iblocks[i]->position = position;
468  if ( i <= 0 ) d->iblocks[i]->previousblock = -1;
469  else d->iblocks[i]->previousblock = d->iblocks[i-1]->position;
470  }
471  else fseek(d->handle,position,SEEK_SET);
472  convertblock(d->iblocks[i],&scratchblock,TODISK);
473  if ( minoswrite(d->handle,(char *)(&scratchblock),sizeof(INDEXBLOCK)) ) {
474  MesPrint("Error while writing index of file %s",d->name);
475  d->iblocks[i]->position = -1;
476  return(-1);
477  }
478  d->info.lastindexblock = position;
479  }
480  d->info.lastnameblock = -1;
481  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
482  position = d->nblocks[i]->position;
483  if ( position <= 0 ) {
484  fseek(d->handle,0,SEEK_END);
485  position = ftell(d->handle);
486  d->nblocks[i]->position = position;
487  if ( i <= 0 ) d->nblocks[i]->previousblock = -1;
488  else d->nblocks[i]->previousblock = d->nblocks[i-1]->position;
489  }
490  else fseek(d->handle,position,SEEK_SET);
491  convertnamesblock(d->nblocks[i],&scratchnamesblock,TODISK);
492  if ( minoswrite(d->handle,(char *)(&scratchnamesblock),sizeof(NAMESBLOCK)) ) {
493  MesPrint("Error while writing index of file %s",d->name);
494  d->nblocks[i]->position = -1;
495  return(-1);
496  }
497  d->info.lastnameblock = position;
498  }
499  return(0);
500 }
501 
502 /*
503  #] WriteIndex :
504  #[ WriteIniInfo :
505 */
506 
507 int WriteIniInfo(DBASE *d)
508 {
509  INIINFO inf;
510  fseek(d->handle,0,SEEK_SET);
511  convertiniinfo(&(d->info),&inf,TODISK);
512  if ( minoswrite(d->handle,(char *)(&inf),sizeof(INIINFO)) ) {
513  MesPrint("Error while writing masterindex of file %s",d->name);
514  return(-1);
515  }
516  return(0);
517 }
518 
519 /*
520  #] WriteIniInfo :
521  #[ ReadIniInfo :
522 */
523 
524 int ReadIniInfo(DBASE *d)
525 {
526  INIINFO inf;
527  fseek(d->handle,0,SEEK_SET);
528  if ( minosread(d->handle,(char *)(&inf),sizeof(INIINFO)) ) {
529  MesPrint("Error while reading masterindex of file %s",d->name);
530  return(-1);
531  }
532  convertiniinfo(&inf,&(d->info),FROMDISK);
533  if ( d->info.entriesinindex < 0
534  || d->info.numberofindexblocks < 0
535  || d->info.lastindexblock < 0 ) {
536  MesPrint("The file %s is not a proper database\n",d->name);
537  return(-1);
538  }
539  return(0);
540 }
541 
542 /*
543  #] ReadIniInfo :
544  #[ GetDbase :
545 */
546 
547 DBASE *GetDbase(char *filename)
548 {
549  FILE *f;
550  DBASE *d;
551  char *newname;
552  if ( ( f = LocateBase(&filename,&newname) ) == 0 ) {
553 
554  return(NewDbase(filename,0));
555  }
556 /* setbuf(f,0); */
557  d = (DBASE *)From0List(&(AC.TableBaseList));
558  d->mode = 0;
559  d->tablenamessize = 0;
560  d->topnumber = 0;
561  d->tablenamefill = 0;
562  d->iblocks = 0;
563  d->nblocks = 0;
564  d->tablenames = 0;
565 
566  d->info.entriesinindex = 0;
567  d->info.numberofindexblocks = 0;
568  d->info.firstindexblock = 0;
569  d->info.lastindexblock = 0;
570  d->info.numberoftables = 0;
571  d->info.numberofnamesblocks = 0;
572  d->info.firstnameblock = 0;
573  d->info.lastnameblock = 0;
574 
575  d->name = str_dup(filename); /* For the moment just for the error messages */
576  d->handle = f;
577  if ( ReadIniInfo(d) || ReadIndex(d) ) { M_free(d,"index-d"); fclose(f); return(0); }
578  if ( ComposeTableNames(d) < 0 ) { FreeTableBase(d); fclose(f); return(0); }
579  d->name = str_dup(filename);
580  d->fullname = newname;
581  return(d);
582 }
583 
584 /*
585  #] GetDbase :
586  #[ NewDbase :
587 
588  Creates a new database with 'number' entries in the index.
589 */
590 
591 DBASE *NewDbase(char *name,MLONG number)
592 {
593  FILE *f;
594  DBASE *d;
595  MLONG numblocks, numnameblocks, i;
596  char *s;
597 /*----------change 10-feb-2003 */
598  int j, jj;
599  MLONG t = (MLONG)(time(0));
600 /*-----------------------------*/
601  if ( number < 0 ) number = 0;
602  if ( ( f = fopen(name,"w+b") ) == 0 ) {
603  MesPrint("Could not create a new file with name %s\n",name);
604  return(0);
605  }
606  numblocks = (number+NUMOBJECTS-1)/NUMOBJECTS;
607  numnameblocks = 1;
608  if ( numblocks <= 0 ) numblocks = 1;
609  if ( numnameblocks <= 0 ) numnameblocks = 1;
610  d = (DBASE *)From0List(&(AC.TableBaseList));
611  if ( ( d->iblocks = (INDEXBLOCK **)Malloc1(numblocks*sizeof(INDEXBLOCK *),
612  "new database") ) == 0 ) {
613  NumTableBases--;
614  return(0);
615  }
616  d->tablenames = 0;
617  d->tablenamessize = 0;
618  d->topnumber = 0;
619  d->tablenamefill = 0;
620 
621  d->mode = 0;
622  if ( ( d->nblocks = (NAMESBLOCK **)Malloc1(sizeof(NAMESBLOCK *)*numnameblocks,
623  "new database") ) == 0 ) {
624  M_free(d->iblocks,"new database");
625  NumTableBases--;
626  return(0);
627  }
628  if ( ( f = fopen(name,"w+b") ) == 0 ) {
629  MesPrint("Could not create new file %s\n",name);
630  NumTableBases--;
631  return(0);
632  }
633 /* setbuf(f,0); */
634  d->name = str_dup(name);
635  d->fullname = str_dup(name);
636  d->handle = f;
637 
638  d->info.entriesinindex = number;
639  d->info.numberofindexblocks = numblocks;
640  d->info.numberofnamesblocks = numnameblocks;
641  d->info.firstindexblock = 0;
642  d->info.lastindexblock = 0;
643  d->info.numberoftables = 0;
644  d->info.firstnameblock = 0;
645  d->info.lastnameblock = 0;
646 
647  if ( WriteIniInfo(d) ) {
648 getout:
649  fclose(f);
650  remove(d->fullname);
651  if ( d->name ) { M_free(d->name,"name tablebase"); d->name = 0; }
652  if ( d->fullname ) { M_free(d->fullname,"fullname tablebase"); d->fullname = 0; }
653  M_free(d->nblocks,"new database");
654  M_free(d->iblocks,"new database");
655  NumTableBases--;
656  return(0);
657  }
658  for ( i = 0; i < numblocks; i++ ) {
659  if ( ( d->iblocks[i] = (INDEXBLOCK *)Malloc1(sizeof(INDEXBLOCK),
660  "index blocks of new database") ) == 0 ) {
661  while ( --i >= 0 ) M_free(d->iblocks[i],"index blocks of new database");
662  goto getout;
663  }
664  if ( i > 0 ) d->iblocks[i]->previousblock = d->iblocks[i-1]->position;
665  else d->iblocks[i]->previousblock = -1;
666  d->iblocks[i]->position = ftell(f);
667 /*----------change 10-feb-2003 */
668 /*
669  Zero things properly. We don't want garbage in the file.
670 */
671  for ( j = 0; j < NUMOBJECTS; j++ ) {
672  d->iblocks[i]->objects[j].date = t;
673  d->iblocks[i]->objects[j].size = 0;
674  d->iblocks[i]->objects[j].position = -1;
675  d->iblocks[i]->objects[j].tablenumber = 0;
676  d->iblocks[i]->objects[j].uncompressed = 0;
677  d->iblocks[i]->objects[j].spare1 = 0;
678  d->iblocks[i]->objects[j].spare2 = 0;
679  d->iblocks[i]->objects[j].spare3 = 0;
680  for ( jj = 0; jj < ELEMENTSIZE; jj++ ) d->iblocks[i]->objects[j].element[jj] = 0;
681  }
682  convertblock(d->iblocks[i],&scratchblock,TODISK);
683  if ( minoswrite(d->handle,(char *)(&scratchblock),sizeof(INDEXBLOCK)) ) {
684  MesPrint("Error while writing new index blocks\n");
685  goto getout;
686  }
687  }
688  for ( i = 0; i < numnameblocks; i++ ) {
689  if ( ( d->nblocks[i] = (NAMESBLOCK *)Malloc1(sizeof(NAMESBLOCK),
690  "names blocks of new database") ) == 0 ) {
691  while ( --i >= 0 ) { M_free(d->nblocks[i],"names blocks of new database"); }
692  for ( i = 0; i < numblocks; i++ ) M_free(d->iblocks[i],"index blocks of new database");
693  goto getout;
694  }
695  if ( i > 0 ) d->nblocks[i]->previousblock = d->nblocks[i-1]->position;
696  else d->nblocks[i]->previousblock = -1;
697  d->nblocks[i]->position = ftell(f);
698  s = d->nblocks[i]->names;
699  for ( j = 0; j < NAMETABLESIZE; j++ ) *s++ = 0;
700  convertnamesblock(d->nblocks[i],&scratchnamesblock,TODISK);
701  if ( minoswrite(d->handle,(char *)(&scratchnamesblock),sizeof(NAMESBLOCK)) ) {
702  MesPrint("Error while writing new names blocks\n");
703  for ( i = 0; i < numnameblocks; i++ ) M_free(d->nblocks[i],"names blocks of new database");
704  for ( i = 0; i < numblocks; i++ ) M_free(d->iblocks[i],"index blocks of new database");
705  goto getout;
706  }
707  }
708  d->info.firstindexblock = d->iblocks[0]->position;
709  d->info.lastindexblock = d->iblocks[numblocks-1]->position;
710  d->info.firstnameblock = d->nblocks[0]->position;
711  d->info.lastnameblock = d->nblocks[numnameblocks-1]->position;
712  if ( WriteIniInfo(d) ) {
713  for ( i = 0; i < numnameblocks; i++ ) M_free(d->nblocks[i],"names blocks of new database");
714  for ( i = 0; i < numblocks; i++ ) M_free(d->iblocks[i],"index blocks of new database");
715  goto getout;
716  }
717  return(d);
718 }
719 
720 /*
721  #] NewDbase :
722  #[ FreeTableBase :
723 */
724 
725 void FreeTableBase(DBASE *d)
726 {
727  int i, j, *old, *newL;
728  LIST *L;
729  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) M_free(d->nblocks[i],"nblocks[i]");
730  for ( i = 0; i < d->info.numberofindexblocks; i++ ) M_free(d->iblocks[i],"iblocks[i]");
731  M_free(d->nblocks,"nblocks");
732  M_free(d->iblocks,"iblocks");
733  if ( d->tablenames ) M_free(d->tablenames,"d->tablenames");
734  if ( d->name ) M_free(d->name,"d->name");
735  if ( d->fullname ) M_free(d->fullname,"d->fullname");
736  i = d - tablebases;
737  if ( i < ( NumTableBases - 1 ) ) {
738  L = &(AC.TableBaseList);
739  j = ( ( NumTableBases - i - 1 ) * L->size ) / sizeof(int);
740  old = (int *)d; newL = (int *)(d+1);
741  while ( --j >= 0 ) *newL++ = *old++;
742  j = L->size / sizeof(int);
743  while ( --j >= 0 ) *newL++ = 0;
744  }
745  NumTableBases--;
746  M_free(d,"tb,d");
747 }
748 
749 /*
750  #] FreeTableBase :
751  #[ ComposeTableNames :
752 
753  The nameblocks are supposed to be in memory.
754  Hence we have to go through them
755 */
756 
757 int ComposeTableNames(DBASE *d)
758 {
759  MLONG nsize = 0;
760  int i, j, k;
761  char *s, *t, *ss;
762  d->topnumber = 0;
763  i = 0; s = d->nblocks[i]->names; j = NAMETABLESIZE;
764  while ( *s ) {
765  if ( *s ) d->topnumber++;
766  for ( k = 0; k < 2; k++ ) { /* name and argtail */
767  while ( *s ) {
768  j--;
769  if ( j <= 0 ) {
770  i++; if ( i >= d->info.numberofnamesblocks ) goto gotall;
771  s = d->nblocks[i]->names; j = NAMETABLESIZE;
772  }
773  else s++;
774  }
775  j--;
776  if ( j <= 0 ) {
777  i++; if ( i >= d->info.numberofnamesblocks ) goto gotall;
778  s = d->nblocks[i]->names; j = NAMETABLESIZE;
779  }
780  else s++;
781  }
782  }
783 gotall:;
784  nsize = (d->info.numberofnamesblocks-1)*NAMETABLESIZE +
785  (s-d->nblocks[i]->names)+1;
786  if ( ( d->tablenames = (char *)Malloc1((2*nsize+30)*sizeof(char),"tablenames") )
787  == 0 ) { return(-1); }
788  t = d->tablenames;
789  d->tablenamessize = 2*nsize+30;
790  d->tablenamefill = nsize-1;
791  for ( k = 0; k < i; k++ ) {
792  ss = d->nblocks[k]->names;
793  for ( j = 0; j < NAMETABLESIZE; j++ ) *t++ = *ss++;
794  }
795  ss = d->nblocks[i]->names;
796  while ( ss < s ) *t++ = *ss++;
797  *t = 0;
798  return(0);
799 }
800 
801 /*
802  #] ComposeTableNames :
803  #[ OpenDbase :
804 */
805 
806 DBASE *OpenDbase(char *filename)
807 {
808  FILE *f;
809  DBASE *d;
810  char *newname;
811  if ( ( f = LocateBase(&filename,&newname) ) == 0 ) {
812  MesPrint("Cannot open file %s\n",filename);
813  return(0);
814  }
815 /* setbuf(f,0); */
816  d = (DBASE *)From0List(&(AC.TableBaseList));
817  d->name = filename; /* For the moment just for the error messages */
818  d->handle = f;
819  if ( ReadIniInfo(d) || ReadIndex(d) ) { M_free(d,"OpenDbase"); fclose(f); return(0); }
820  if ( ComposeTableNames(d) ) {
821  FreeTableBase(d);
822  fclose(f);
823  return(0);
824  }
825  d->name = str_dup(filename);
826  d->fullname = newname;
827  return(d);
828 }
829 
830 /*
831  #] OpenDbase :
832  #[ AddTableName :
833 
834  Adds a name of a table. Writes the namelist to disk.
835  Returns the number of this tablename in the database.
836  If the name was already in the table we return its value in negative.
837  Zero is an error!
838 */
839 
840 MLONG AddTableName(DBASE *d,char *name,TABLES T)
841 {
842  char *s, *t, *tt;
843  int namesize, tailsize;
844  MLONG newsize, i, num;
845 /*
846  First search for the name in what we have already
847 */
848  if ( d->tablenames ) {
849  num = 0;
850  s = d->tablenames;
851  while ( *s ) {
852  num++;
853  t = name;
854  while ( ( *s == *t ) && *t ) { s++; t++; }
855  if ( *s == *t ) { return(-num); }
856  while ( *s ) s++;
857  s++;
858  while ( *s ) s++;
859  s++;
860  }
861  }
862 /*
863  This name has to be added
864 */
865  MesPrint("We add the name %s\n",name);
866  t = name;
867  while ( *t ) { t++; }
868  namesize = t-name;
869  if ( ( t = (char *)(T->argtail) ) != 0 ) {
870  while ( *t ) { t++; }
871  tailsize = t - (char *)(T->argtail);
872  }
873  else { tailsize = 0; }
874  if ( d->tablenames == 0 ) {
875  if ( ComposeTableNames(d) ) {
876  FreeTableBase(d);
877  M_free(d,"AddTableName");
878  return(0);
879  }
880  }
881  d->info.numberoftables++;
882  while ( ( d->tablenamefill+namesize+tailsize+3 > d->tablenamessize )
883  || ( d->tablenames == 0 ) ) {
884  newsize = 2*d->tablenamessize + 2*namesize + 2*tailsize + 6;
885  if ( ( t = (char *)Malloc1(newsize*sizeof(char),"AddTableName") ) == 0 )
886  return(0);
887  tt = t;
888  if ( d->tablenames ) {
889  s = d->tablenames;
890  for ( i = 0; i < d->tablenamefill; i++ ) *t++ = *s++;
891  *t = 0;
892  M_free(d->tablenames,"d->tablenames");
893  }
894  d->tablenames = tt;
895  d->tablenamessize = newsize;
896  }
897  s = d->tablenames + d->tablenamefill;
898  t = name;
899  while ( *t ) *s++ = *t++;
900  *s++ = 0;
901  t = (char *)(T->argtail);
902  while ( *t ) *s++ = *t++;
903  *s++ = 0;
904  *s = 0;
905  d->tablenamefill = s - d->tablenames;
906  d->topnumber++;
907 /*
908  Now we have to synchronize
909 */
910  if ( PutTableNames(d) ) return(0);
911  return(d->topnumber);
912 }
913 
914 /*
915  #] AddTableName :
916  #[ GetTableName :
917 
918  Gets a name of a table.
919  Returns the number of this tablename in the database.
920  Zero -> error
921 */
922 
923 MLONG GetTableName(DBASE *d,char *name)
924 {
925  char *s, *t;
926  MLONG num;
927 /*
928  search for the name in what we have
929 */
930  if ( d->tablenames ) {
931  num = 0;
932  s = d->tablenames;
933  while ( *s ) {
934  num++;
935  t = name;
936  while ( ( *s == *t ) && *t ) { s++; t++; }
937  if ( *s == *t ) { return(num); }
938  while ( *s ) s++;
939  s++;
940  while ( *s ) s++;
941  s++;
942  }
943  }
944  return(0);
945 }
946 
947 /*
948  #] GetTableName :
949  #[ PutTableNames :
950 
951  Takes the names string in d->tablenames and puts it in the nblocks
952  pieces. Writes what has been changed to disk.
953 */
954 
955 int PutTableNames(DBASE *d)
956 {
957  NAMESBLOCK **nnew;
958  int i, j, firstdif;
959  MLONG m;
960  char *s, *t;
961 /*
962  Determine how many blocks are needed.
963 */
964  MLONG numblocks = d->tablenamefill/NAMETABLESIZE + 1;
965  if ( d->info.numberofnamesblocks < numblocks ) {
966 /*
967  We need more blocks. First make sure of the space for nblocks.
968 */
969  if ( ( nnew = (NAMESBLOCK **)Malloc1(sizeof(NAMESBLOCK *)*numblocks,
970  "new names block") ) == 0 ) {
971  return(-1);
972  }
973  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
974  nnew[i] = d->nblocks[i];
975  }
976  free(d->nblocks);
977  d->nblocks = nnew;
978  for ( ; i < numblocks; i++ ) {
979  if ( ( d->nblocks[i] = (NAMESBLOCK *)Malloc1(sizeof(NAMESBLOCK),
980  "additional names blocks ") ) == 0 ) {
981  FreeTableBase(d);
982  return(-1);
983  }
984  d->nblocks[i]->previousblock = -1;
985  d->nblocks[i]->position = -1;
986  s = d->nblocks[i]->names;
987  for ( j = 0; j < NAMETABLESIZE; j++ ) *s++ = 0;
988  }
989  d->info.numberofnamesblocks = numblocks;
990  }
991 /*
992  Now look till where the new contents agree with the old.
993 */
994  firstdif = 0;
995  i = 0; t = d->nblocks[i]->names; j = 0; s = d->tablenames;
996  for ( m = 0; m < d->tablenamefill; m++ ) {
997  if ( *s == *t ) {
998  s++; t++; j++;
999  if ( j >= NAMETABLESIZE ) {
1000  i++;
1001  t = d->nblocks[i]->names;
1002  j = 0;
1003  }
1004  }
1005  else {
1006  firstdif = i;
1007  for ( ; m < d->tablenamefill; m++ ) {
1008  *t++ = *s++; j++;
1009  if ( j >= NAMETABLESIZE ) {
1010  i++;
1011  t = d->nblocks[i]->names;
1012  j = 0;
1013  }
1014  }
1015  *t = 0;
1016  break;
1017  }
1018  }
1019  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
1020  if ( i == firstdif ) break;
1021  if ( d->nblocks[i]->position < 0 ) { firstdif = i; break; }
1022  }
1023 /*
1024  Now we have to (re)write the blocks, starting at firstdif.
1025 */
1026  for ( i = firstdif; i < d->info.numberofnamesblocks; i++ ) {
1027  if ( i > 0 ) d->nblocks[i]->previousblock = d->nblocks[i-1]->position;
1028  else d->nblocks[i]->previousblock = -1;
1029  if ( d->nblocks[i]->position < 0 ) {
1030  fseek(d->handle,0,SEEK_END);
1031  d->nblocks[i]->position = ftell(d->handle);
1032  }
1033  else fseek(d->handle,d->nblocks[i]->position,SEEK_SET);
1034  convertnamesblock(d->nblocks[i],&scratchnamesblock,TODISK);
1035  if ( minoswrite(d->handle,(char *)(&scratchnamesblock),sizeof(NAMESBLOCK)) ) {
1036  MesPrint("Error while writing names blocks\n");
1037  FreeTableBase(d);
1038  return(-1);
1039  }
1040  }
1041  d->info.lastnameblock = d->nblocks[d->info.numberofnamesblocks-1]->position;
1042  d->info.firstnameblock = d->nblocks[0]->position;
1043  return(WriteIniInfo(d));
1044 }
1045 
1046 /*
1047  #] PutTableNames :
1048  #[ AddToIndex :
1049 */
1050 
1051 int AddToIndex(DBASE *d,MLONG number)
1052 {
1053  MLONG i, oldnumofindexblocks = d->info.numberofindexblocks;
1054  MLONG j, newnumofindexblocks, jj;
1055  INDEXBLOCK **ib;
1056  MLONG t = (MLONG)(time(0));
1057  if ( number == 0 ) return(0);
1058  else if ( number < 0 ) {
1059  if ( d->info.entriesinindex < -number ) {
1060  MesPrint("There are only %ld entries in the index of file %s\n",
1061  d->info.entriesinindex,d->name);
1062  return(-1);
1063  }
1064  d->info.entriesinindex += number;
1065 dowrite:
1066  if ( WriteIniInfo(d) ) {
1067  d->info.entriesinindex -= number;
1068  MesPrint("File may be corrupted\n");
1069  return(-1);
1070  }
1071  }
1072  else if ( d->info.entriesinindex+number <=
1073  NUMOBJECTS*d->info.numberofindexblocks ) {
1074  d->info.entriesinindex += number;
1075  goto dowrite;
1076  }
1077  else {
1078  d->info.entriesinindex += number;
1079  newnumofindexblocks = d->info.numberofindexblocks + ((number -
1080  (NUMOBJECTS*d->info.numberofindexblocks - d->info.entriesinindex))
1081  +NUMOBJECTS-1)/NUMOBJECTS;
1082  if ( ( ib = (INDEXBLOCK **)Malloc1(sizeof(INDEXBLOCK *)*newnumofindexblocks,
1083  "index") ) == 0 ) return(-1);
1084  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1085  ib[i] = d->iblocks[i];
1086  }
1087  for ( i = d->info.numberofindexblocks; i < newnumofindexblocks; i++ ) {
1088  if ( ( ib[i] = (INDEXBLOCK *)Malloc1(sizeof(INDEXBLOCK),"index block") ) == 0 ) {
1089  FreeTableBase(d);
1090  return(-1);
1091  }
1092  if ( i > 0 ) ib[i]->previousblock = ib[i-1]->position;
1093  else ib[i]->previousblock = -1;
1094 /*
1095  Zero things properly. We don't want garbage in the file.
1096 */
1097  for ( j = 0; j < NUMOBJECTS; j++ ) {
1098  ib[i]->objects[j].date = t;
1099  ib[i]->objects[j].size = 0;
1100  ib[i]->objects[j].position = -1;
1101  ib[i]->objects[j].tablenumber = 0;
1102  ib[i]->objects[j].uncompressed = 0;
1103  ib[i]->objects[j].spare1 = 0;
1104  ib[i]->objects[j].spare2 = 0;
1105  ib[i]->objects[j].spare3 = 0;
1106  for ( jj = 0; jj < ELEMENTSIZE; jj++ ) ib[i]->objects[j].element[jj] = 0;
1107  }
1108  fseek(d->handle,0,SEEK_END);
1109  ib[i]->position = ftell(d->handle);
1110  convertblock(ib[i],&scratchblock,TODISK);
1111  if ( minoswrite(d->handle,(char *)(&scratchblock),sizeof(INDEXBLOCK)) ) {
1112  MesPrint("Error while writing new index of file %s",d->name);
1113  FreeTableBase(d);
1114  return(-1);
1115  }
1116  }
1117  d->info.lastindexblock = ib[newnumofindexblocks-1]->position;
1118  d->info.firstindexblock = ib[0]->position;
1119  d->info.numberofindexblocks = newnumofindexblocks;
1120  if ( WriteIniInfo(d) ) {
1121  d->info.numberofindexblocks = oldnumofindexblocks;
1122  d->info.entriesinindex -= number;
1123  MesPrint("File may be corrupted\n");
1124  FreeTableBase(d);
1125  return(-1);
1126  }
1127  M_free(d->iblocks,"AddToIndex");
1128  d->iblocks = ib;
1129  }
1130  return(0);
1131 }
1132 
1133 /*
1134  #] AddToIndex :
1135  #[ AddObject :
1136 */
1137 
1138 MLONG AddObject(DBASE *d,MLONG tablenumber,char *arguments,char *rhs)
1139 {
1140  MLONG number;
1141  number = d->info.entriesinindex;
1142  if ( AddToIndex(d,1) ) return(-1);
1143  if ( WriteObject(d,tablenumber,arguments,rhs,number) ) return(-1);
1144  return(number);
1145 }
1146 
1147 /*
1148  #] AddObject :
1149  #[ FindTableNumber :
1150 */
1151 
1152 MLONG FindTableNumber(DBASE *d,char *name)
1153 {
1154  char *s = d->tablenames, *t, *ss;
1155  MLONG num = 0;
1156  ss = d->tablenames + d->tablenamefill;
1157  while ( s < ss ) {
1158  num++;
1159  t = name;
1160  while ( *s == *t && *t ) {
1161  s++; t++;
1162  }
1163  if ( *s == 0 && *t == 0 ) return(num);
1164  while ( *s ) s++;
1165  s++;
1166 /*
1167  Skip also the argument tail
1168 */
1169  while ( *s ) s++;
1170  s++;
1171  }
1172  return(-1); /* Name not found */
1173 }
1174 
1175 /*
1176  #] FindTableNumber :
1177  #[ WriteObject :
1178 */
1179 
1180 int WriteObject(DBASE *d,MLONG tablenumber,char *arguments,char *rhs,MLONG number)
1181 {
1182  char *s, *a;
1183 #ifdef WITHZLIB
1184  char *buffer = 0;
1185  uLongf newsize = 0, oldsize = 0;
1186  uLong ssize;
1187  int error = 0;
1188 #endif
1189  MLONG i, j, position, size, n;
1190  OBJECTS *obj;
1191  if ( ( d->mode & INPUTONLY ) == INPUTONLY ) {
1192  MesPrint("Not allowed to write to input\n");
1193  return(-1);
1194  }
1195  if ( number >= d->info.entriesinindex ) {
1196  MesPrint("Reference to non-existing object number %ld\n",number+1);
1197  return(0);
1198  }
1199  j = number/NUMOBJECTS;
1200  i = number%NUMOBJECTS;
1201  obj = &(d->iblocks[j]->objects[i]);
1202  a = arguments;
1203  while ( *a ) a++;
1204  a++; n = a - arguments;
1205  if ( n > ELEMENTSIZE ) {
1206  MesPrint("Table element %s has more than %ld characters.\n",arguments,
1207  (MLONG)ELEMENTSIZE);
1208  return(-1);
1209  }
1210  s = obj->element;
1211  a = arguments;
1212  while ( *a ) *s++ = *a++;
1213  *s++ = 0;
1214  while ( n < ELEMENTSIZE ) { *s++ = 0; n++; }
1215  obj->spare1 = obj->spare2 = obj->spare3 = 0;
1216 
1217  fseek(d->handle,0,SEEK_END);
1218  position = ftell(d->handle);
1219  s = rhs;
1220  while ( *s ) s++;
1221  s++;
1222  size = s - rhs;
1223 #ifdef WITHZLIB
1224  if ( ( d->mode & NOCOMPRESS ) == 0 ) {
1225  newsize = size + size/1000 + 20;
1226  if ( ( buffer = (char *)Malloc1(newsize*sizeof(char),"compress buffer") )
1227  == 0 ) {
1228  MesPrint("No compress used for element %s in file %s\n",arguments,d->name);
1229  }
1230  }
1231  else buffer = 0;
1232  if ( buffer ) {
1233  ssize = size;
1234  if ( ( error = compress((Bytef *)buffer,&newsize,(Bytef *)rhs,ssize) ) != Z_OK ) {
1235  MesPrint("Error = %d\n",error);
1236  MesPrint("Due to error no compress used for element %s in file %s\n",arguments,d->name);
1237  M_free(buffer,"tb,WriteObject");
1238  buffer = 0;
1239  }
1240  }
1241  if ( buffer ) {
1242  rhs = buffer;
1243  oldsize = size;
1244  size = newsize;
1245  }
1246 #endif
1247  if ( minoswrite(d->handle,rhs,size) ) {
1248  MesPrint("Error while writing rhs\n");
1249  return(-1);
1250  }
1251  obj->position = position;
1252  obj->size = size;
1253  obj->date = (MLONG)(time(0));
1254  obj->tablenumber = tablenumber;
1255 #ifdef WITHZLIB
1256  obj->uncompressed = oldsize;
1257  if ( buffer ) M_free(buffer,"tb,WriteObject");
1258 #else
1259  obj->uncompressed = 0;
1260 #endif
1261  return(WriteIndexBlock(d,j));
1262 }
1263 
1264 /*
1265  #] WriteObject :
1266  #[ ReadObject :
1267 
1268  Returns a pointer to the proper rhs
1269 */
1270 
1271 char *ReadObject(DBASE *d,MLONG tablenumber,char *arguments)
1272 {
1273  OBJECTS *obj;
1274  MLONG i, j;
1275  char *buffer1, *s, *t;
1276 #ifdef WITHZLIB
1277  char *buffer2 = 0;
1278  uLongf finallength = 0;
1279 #endif
1280  if ( tablenumber > d->topnumber ) {
1281  MesPrint("Reference to non-existing table number in tablebase %s: %ld\n",
1282  d->name,tablenumber);
1283  return(0);
1284  }
1285 /*
1286  Start looking for the object
1287 */
1288  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1289  for ( j = 0; j < NUMOBJECTS; j++ ) {
1290  if ( d->iblocks[i]->objects[j].tablenumber != tablenumber ) continue;
1291  s = arguments; t = d->iblocks[i]->objects[j].element;
1292  while ( *s == *t && *s ) { s++; t++; }
1293  if ( *t == 0 && *s == 0 ) goto foundelement;
1294  }
1295  }
1296  s = d->tablenames; i = 1;
1297  while ( *s ) {
1298  if ( i == tablenumber ) break;
1299  while ( *s ) s++;
1300  s++;
1301  while ( *s ) s++;
1302  s++;
1303  i++;
1304  }
1305  MesPrint("%s(%s) not found in tablebase %s\n",s,arguments,d->name);
1306  return(0);
1307 
1308 foundelement:;
1309  obj = &(d->iblocks[i]->objects[j]);
1310  fseek(d->handle,obj->position,SEEK_SET);
1311  if ( ( buffer1 = (char *)Malloc1(obj->size,"reading rhs buffer1") ) == 0 ) {
1312  return(0);
1313  }
1314 #ifdef WITHZLIB
1315  if ( obj->uncompressed > 0 ) {
1316  if ( ( buffer2 = (char *)Malloc1(obj->uncompressed,"reading rhs buffer2") ) == 0 ) {
1317  return(0);
1318  }
1319  }
1320  else buffer2 = 0;
1321 #endif
1322  if ( minosread(d->handle,buffer1,obj->size) ) {
1323  MesPrint("Could not read rhs %s in file %s\n",arguments,d->name);
1324  M_free(buffer1,"tb,ReadObject");
1325 #ifdef WITHZLIB
1326  if ( buffer2 ) M_free(buffer2,"tb,ReadObject");
1327 #endif
1328  return(0);
1329  }
1330 #ifdef WITHZLIB
1331  if ( buffer2 == 0 ) return(buffer1);
1332  finallength = obj->uncompressed;
1333  if ( uncompress((Bytef *)buffer2,&finallength,(Bytef *)buffer1,obj->size) != Z_OK ) {
1334  MesPrint("Cannot uncompress element %s in file %s\n",arguments,d->name);
1335  M_free(buffer1,"tb,ReadObject"); M_free(buffer2,"tb,ReadObject");
1336  return(0);
1337  }
1338  M_free(buffer1,"tb,ReadObject");
1339  return(buffer2);
1340 #else
1341  return(buffer1);
1342 #endif
1343 }
1344 
1345 /*
1346  #] ReadObject :
1347  #[ ReadijObject :
1348 
1349  Returns a pointer to the proper rhs
1350 */
1351 
1352 char *ReadijObject(DBASE *d,MLONG i,MLONG j,char *arguments)
1353 {
1354  OBJECTS *obj;
1355  char *buffer1;
1356 #ifdef WITHZLIB
1357  char *buffer2 = 0;
1358  uLongf finallength = 0;
1359 #endif
1360  obj = &(d->iblocks[i]->objects[j]);
1361  fseek(d->handle,obj->position,SEEK_SET);
1362  if ( ( buffer1 = (char *)Malloc1(obj->size,"reading rhs buffer1") ) == 0 ) {
1363  return(0);
1364  }
1365 #ifdef WITHZLIB
1366  if ( obj->uncompressed > 0 ) {
1367  if ( ( buffer2 = (char *)Malloc1(obj->uncompressed,"reading rhs buffer2") ) == 0 ) {
1368  return(0);
1369  }
1370  }
1371  else buffer2 = 0;
1372 #endif
1373  if ( minosread(d->handle,buffer1,obj->size) ) {
1374  MesPrint("Could not read rhs %s in file %s\n",arguments,d->name);
1375  if ( buffer1 ) M_free(buffer1,"rhs buffer1");
1376 #ifdef WITHZLIB
1377  if ( buffer2 ) M_free(buffer2,"rhs buffer2");
1378 #endif
1379  return(0);
1380  }
1381 #ifdef WITHZLIB
1382  if ( buffer2 == 0 ) return(buffer1);
1383  finallength = obj->uncompressed;
1384  if ( uncompress((Bytef *)buffer2,&finallength,(Bytef *)buffer1,obj->size) != Z_OK ) {
1385  MesPrint("Cannot uncompress element %s in file %s\n",arguments,d->name);
1386  if ( buffer1 ) M_free(buffer1,"rhs buffer1");
1387  if ( buffer2 ) M_free(buffer2,"rhs buffer2");
1388  return(0);
1389  }
1390  M_free(buffer1,"rhs buffer1");
1391  return(buffer2);
1392 #else
1393  return(buffer1);
1394 #endif
1395 }
1396 
1397 /*
1398  #] ReadijObject :
1399  #[ ExistsObject :
1400 
1401  Returns 1 if Object exists
1402 */
1403 
1404 int ExistsObject(DBASE *d,MLONG tablenumber,char *arguments)
1405 {
1406  MLONG i, j;
1407  char *s, *t;
1408  if ( tablenumber > d->topnumber ) {
1409  MesPrint("Reference to non-existing table number in tablebase %s: %ld\n",
1410  d->name,tablenumber);
1411  return(0);
1412  }
1413 /*
1414  Start looking for the object
1415 */
1416  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1417  for ( j = 0; j < NUMOBJECTS; j++ ) {
1418  if ( d->iblocks[i]->objects[j].tablenumber != tablenumber ) continue;
1419  s = arguments; t = d->iblocks[i]->objects[j].element;
1420  while ( *s == *t && *s ) { s++; t++; }
1421  if ( *t == 0 && *s == 0 ) return(1);
1422  }
1423  }
1424  return(0);
1425 }
1426 
1427 /*
1428  #] ExistsObject :
1429  #[ DeleteObject :
1430 
1431  Returns 1 if Object has been deleteted.
1432  We leave a hole. Actually the object is still there but has been
1433  inactivated. It can be reactivated by calling this routine again.
1434 */
1435 
1436 int DeleteObject(DBASE *d,MLONG tablenumber,char *arguments)
1437 {
1438  MLONG i, j;
1439  char *s, *t;
1440  if ( tablenumber > d->topnumber ) {
1441  MesPrint("Reference to non-existing table number in tablebase %s: %ld\n",
1442  d->name,tablenumber);
1443  return(0);
1444  }
1445 /*
1446  Start looking for the object
1447 */
1448  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1449  for ( j = 0; j < NUMOBJECTS; j++ ) {
1450  if ( d->iblocks[i]->objects[j].tablenumber != tablenumber ) continue;
1451  s = arguments; t = d->iblocks[i]->objects[j].element;
1452  while ( *s == *t && *s ) { s++; t++; }
1453  if ( *t == 0 && *s == 0 ) {
1454  d->iblocks[i]->objects[j].tablenumber =
1455  -d->iblocks[i]->objects[j].tablenumber - 1;
1456  return(1);
1457  }
1458  }
1459  }
1460  return(0);
1461 }
1462 
1463 /*
1464  #] DeleteObject :
1465 */
Definition: minos.h:82
int size
Definition: structs.h:209
Definition: minos.h:94
UBYTE * argtail
Definition: structs.h:361
Definition: minos.h:120
Definition: structs.h:204